File indexing completed on 2024-05-19 16:34:47
0001 /* 0002 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "scene/surfaceitem_wayland.h" 0008 #include "composite.h" 0009 #include "core/renderbackend.h" 0010 #include "deleted.h" 0011 #include "wayland/clientbuffer.h" 0012 #include "wayland/subcompositor_interface.h" 0013 #include "wayland/surface_interface.h" 0014 0015 namespace KWin 0016 { 0017 0018 SurfaceItemWayland::SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface, Scene *scene, Item *parent) 0019 : SurfaceItem(scene, parent) 0020 , m_surface(surface) 0021 { 0022 connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged, 0023 this, &SurfaceItemWayland::handleSurfaceToBufferMatrixChanged); 0024 0025 connect(surface, &KWaylandServer::SurfaceInterface::sizeChanged, 0026 this, &SurfaceItemWayland::handleSurfaceSizeChanged); 0027 connect(surface, &KWaylandServer::SurfaceInterface::bufferSizeChanged, 0028 this, &SurfaceItemWayland::discardPixmap); 0029 0030 connect(surface, &KWaylandServer::SurfaceInterface::childSubSurfacesChanged, 0031 this, &SurfaceItemWayland::handleChildSubSurfacesChanged); 0032 connect(surface, &KWaylandServer::SurfaceInterface::committed, 0033 this, &SurfaceItemWayland::handleSurfaceCommitted); 0034 connect(surface, &KWaylandServer::SurfaceInterface::damaged, 0035 this, &SurfaceItemWayland::addDamage); 0036 connect(surface, &KWaylandServer::SurfaceInterface::childSubSurfaceRemoved, 0037 this, &SurfaceItemWayland::handleChildSubSurfaceRemoved); 0038 0039 KWaylandServer::SubSurfaceInterface *subsurface = surface->subSurface(); 0040 if (subsurface) { 0041 connect(surface, &KWaylandServer::SurfaceInterface::mapped, 0042 this, &SurfaceItemWayland::handleSubSurfaceMappedChanged); 0043 connect(surface, &KWaylandServer::SurfaceInterface::unmapped, 0044 this, &SurfaceItemWayland::handleSubSurfaceMappedChanged); 0045 connect(subsurface, &KWaylandServer::SubSurfaceInterface::positionChanged, 0046 this, &SurfaceItemWayland::handleSubSurfacePositionChanged); 0047 setVisible(surface->isMapped()); 0048 setPosition(subsurface->position()); 0049 } 0050 0051 handleChildSubSurfacesChanged(); 0052 setSize(surface->size()); 0053 setSurfaceToBufferMatrix(surface->surfaceToBufferMatrix()); 0054 } 0055 0056 QVector<QRectF> SurfaceItemWayland::shape() const 0057 { 0058 return {rect()}; 0059 } 0060 0061 QRegion SurfaceItemWayland::opaque() const 0062 { 0063 if (m_surface) { 0064 return m_surface->opaque(); 0065 } 0066 return QRegion(); 0067 } 0068 0069 KWaylandServer::SurfaceInterface *SurfaceItemWayland::surface() const 0070 { 0071 return m_surface; 0072 } 0073 0074 void SurfaceItemWayland::handleSurfaceToBufferMatrixChanged() 0075 { 0076 setSurfaceToBufferMatrix(m_surface->surfaceToBufferMatrix()); 0077 discardQuads(); 0078 discardPixmap(); 0079 } 0080 0081 void SurfaceItemWayland::handleSurfaceSizeChanged() 0082 { 0083 setSize(m_surface->size()); 0084 } 0085 0086 void SurfaceItemWayland::handleSurfaceCommitted() 0087 { 0088 if (m_surface->hasFrameCallbacks()) { 0089 scheduleFrame(); 0090 } 0091 } 0092 0093 SurfaceItemWayland *SurfaceItemWayland::getOrCreateSubSurfaceItem(KWaylandServer::SubSurfaceInterface *child) 0094 { 0095 SurfaceItemWayland *&item = m_subsurfaces[child]; 0096 if (!item) { 0097 item = new SurfaceItemWayland(child->surface(), scene()); 0098 item->setParent(this); 0099 item->setParentItem(this); 0100 } 0101 return item; 0102 } 0103 0104 void SurfaceItemWayland::handleChildSubSurfaceRemoved(KWaylandServer::SubSurfaceInterface *child) 0105 { 0106 delete m_subsurfaces.take(child); 0107 } 0108 0109 void SurfaceItemWayland::handleChildSubSurfacesChanged() 0110 { 0111 const QList<KWaylandServer::SubSurfaceInterface *> below = m_surface->below(); 0112 const QList<KWaylandServer::SubSurfaceInterface *> above = m_surface->above(); 0113 0114 for (int i = 0; i < below.count(); ++i) { 0115 SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(below[i]); 0116 subsurfaceItem->setZ(i - below.count()); 0117 } 0118 0119 for (int i = 0; i < above.count(); ++i) { 0120 SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(above[i]); 0121 subsurfaceItem->setZ(i); 0122 } 0123 } 0124 0125 void SurfaceItemWayland::handleSubSurfacePositionChanged() 0126 { 0127 setPosition(m_surface->subSurface()->position()); 0128 } 0129 0130 void SurfaceItemWayland::handleSubSurfaceMappedChanged() 0131 { 0132 setVisible(m_surface->isMapped()); 0133 } 0134 0135 std::unique_ptr<SurfacePixmap> SurfaceItemWayland::createPixmap() 0136 { 0137 return std::make_unique<SurfacePixmapWayland>(this); 0138 } 0139 0140 ContentType SurfaceItemWayland::contentType() const 0141 { 0142 return m_surface->contentType(); 0143 } 0144 0145 SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent) 0146 : SurfacePixmap(Compositor::self()->backend()->createSurfaceTextureWayland(this), parent) 0147 , m_item(item) 0148 { 0149 } 0150 0151 SurfacePixmapWayland::~SurfacePixmapWayland() 0152 { 0153 setBuffer(nullptr); 0154 } 0155 0156 SurfaceItemWayland *SurfacePixmapWayland::item() const 0157 { 0158 return m_item; 0159 } 0160 0161 KWaylandServer::SurfaceInterface *SurfacePixmapWayland::surface() const 0162 { 0163 return m_item->surface(); 0164 } 0165 0166 KWaylandServer::ClientBuffer *SurfacePixmapWayland::buffer() const 0167 { 0168 return m_buffer; 0169 } 0170 0171 void SurfacePixmapWayland::create() 0172 { 0173 update(); 0174 } 0175 0176 void SurfacePixmapWayland::update() 0177 { 0178 KWaylandServer::SurfaceInterface *surface = m_item->surface(); 0179 if (surface) { 0180 setBuffer(surface->buffer()); 0181 } 0182 } 0183 0184 bool SurfacePixmapWayland::isValid() const 0185 { 0186 return m_buffer; 0187 } 0188 0189 void SurfacePixmapWayland::setBuffer(KWaylandServer::ClientBuffer *buffer) 0190 { 0191 if (m_buffer == buffer) { 0192 return; 0193 } 0194 if (m_buffer) { 0195 m_buffer->unref(); 0196 } 0197 m_buffer = buffer; 0198 if (m_buffer) { 0199 m_buffer->ref(); 0200 m_hasAlphaChannel = m_buffer->hasAlphaChannel(); 0201 m_size = m_buffer->size(); 0202 } 0203 } 0204 0205 SurfaceItemXwayland::SurfaceItemXwayland(Window *window, Scene *scene, Item *parent) 0206 : SurfaceItemWayland(window->surface(), scene, parent) 0207 , m_window(window) 0208 { 0209 connect(window, &Window::geometryShapeChanged, this, &SurfaceItemXwayland::discardQuads); 0210 connect(window, &Window::windowClosed, this, &SurfaceItemXwayland::handleWindowClosed); 0211 } 0212 0213 QVector<QRectF> SurfaceItemXwayland::shape() const 0214 { 0215 const QRectF clipRect = rect() & m_window->clientGeometry().translated(-m_window->bufferGeometry().topLeft()); 0216 QVector<QRectF> shape = m_window->shapeRegion(); 0217 0218 // bounded to clipRect 0219 for (QRectF &shapePart : shape) { 0220 shapePart = shapePart.intersected(clipRect); 0221 } 0222 return shape; 0223 } 0224 0225 void SurfaceItemXwayland::handleWindowClosed(Window *original, Deleted *deleted) 0226 { 0227 m_window = deleted; 0228 } 0229 0230 } // namespace KWin