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