File indexing completed on 2024-05-12 05:32:08

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 "compositor.h"
0009 #include "core/graphicsbuffer.h"
0010 #include "core/renderbackend.h"
0011 #include "wayland/subcompositor.h"
0012 #include "wayland/surface.h"
0013 #include "window.h"
0014 #include "x11window.h"
0015 
0016 namespace KWin
0017 {
0018 
0019 SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Scene *scene, Item *parent)
0020     : SurfaceItem(scene, parent)
0021     , m_surface(surface)
0022 {
0023     connect(surface, &SurfaceInterface::sizeChanged,
0024             this, &SurfaceItemWayland::handleSurfaceSizeChanged);
0025     connect(surface, &SurfaceInterface::bufferSizeChanged,
0026             this, &SurfaceItemWayland::handleBufferSizeChanged);
0027     connect(surface, &SurfaceInterface::bufferSourceBoxChanged,
0028             this, &SurfaceItemWayland::handleBufferSourceBoxChanged);
0029     connect(surface, &SurfaceInterface::bufferTransformChanged,
0030             this, &SurfaceItemWayland::handleBufferTransformChanged);
0031 
0032     connect(surface, &SurfaceInterface::childSubSurfacesChanged,
0033             this, &SurfaceItemWayland::handleChildSubSurfacesChanged);
0034     connect(surface, &SurfaceInterface::committed,
0035             this, &SurfaceItemWayland::handleSurfaceCommitted);
0036     connect(surface, &SurfaceInterface::damaged,
0037             this, &SurfaceItemWayland::addDamage);
0038     connect(surface, &SurfaceInterface::childSubSurfaceRemoved,
0039             this, &SurfaceItemWayland::handleChildSubSurfaceRemoved);
0040     connect(surface, &SurfaceInterface::colorDescriptionChanged,
0041             this, &SurfaceItemWayland::handleColorDescriptionChanged);
0042     connect(surface, &SurfaceInterface::presentationModeHintChanged,
0043             this, &SurfaceItemWayland::handlePresentationModeHintChanged);
0044 
0045     SubSurfaceInterface *subsurface = surface->subSurface();
0046     if (subsurface) {
0047         connect(surface, &SurfaceInterface::mapped,
0048                 this, &SurfaceItemWayland::handleSubSurfaceMappedChanged);
0049         connect(surface, &SurfaceInterface::unmapped,
0050                 this, &SurfaceItemWayland::handleSubSurfaceMappedChanged);
0051         connect(subsurface, &SubSurfaceInterface::positionChanged,
0052                 this, &SurfaceItemWayland::handleSubSurfacePositionChanged);
0053         setVisible(surface->isMapped());
0054         setPosition(subsurface->position());
0055     }
0056 
0057     handleChildSubSurfacesChanged();
0058     setDestinationSize(surface->size());
0059     setBufferTransform(surface->bufferTransform());
0060     setBufferSourceBox(surface->bufferSourceBox());
0061     setBufferSize(surface->bufferSize());
0062     setColorDescription(surface->colorDescription());
0063 }
0064 
0065 QList<QRectF> SurfaceItemWayland::shape() const
0066 {
0067     return {rect()};
0068 }
0069 
0070 QRegion SurfaceItemWayland::opaque() const
0071 {
0072     if (m_surface) {
0073         return m_surface->opaque();
0074     }
0075     return QRegion();
0076 }
0077 
0078 SurfaceInterface *SurfaceItemWayland::surface() const
0079 {
0080     return m_surface;
0081 }
0082 
0083 void SurfaceItemWayland::handleSurfaceSizeChanged()
0084 {
0085     setDestinationSize(m_surface->size());
0086 }
0087 
0088 void SurfaceItemWayland::handleBufferSizeChanged()
0089 {
0090     setBufferSize(m_surface->bufferSize());
0091 }
0092 
0093 void SurfaceItemWayland::handleBufferSourceBoxChanged()
0094 {
0095     setBufferSourceBox(m_surface->bufferSourceBox());
0096 }
0097 
0098 void SurfaceItemWayland::handleBufferTransformChanged()
0099 {
0100     setBufferTransform(m_surface->bufferTransform());
0101 }
0102 
0103 void SurfaceItemWayland::handleSurfaceCommitted()
0104 {
0105     if (m_surface->hasFrameCallbacks()) {
0106         scheduleFrame();
0107     }
0108 }
0109 
0110 SurfaceItemWayland *SurfaceItemWayland::getOrCreateSubSurfaceItem(SubSurfaceInterface *child)
0111 {
0112     auto &item = m_subsurfaces[child];
0113     if (!item) {
0114         item = std::make_unique<SurfaceItemWayland>(child->surface(), scene());
0115         item->setParentItem(this);
0116     }
0117     return item.get();
0118 }
0119 
0120 void SurfaceItemWayland::handleChildSubSurfaceRemoved(SubSurfaceInterface *child)
0121 {
0122     m_subsurfaces.erase(child);
0123 }
0124 
0125 void SurfaceItemWayland::handleChildSubSurfacesChanged()
0126 {
0127     const QList<SubSurfaceInterface *> below = m_surface->below();
0128     const QList<SubSurfaceInterface *> above = m_surface->above();
0129 
0130     for (int i = 0; i < below.count(); ++i) {
0131         SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(below[i]);
0132         subsurfaceItem->setZ(i - below.count());
0133     }
0134 
0135     for (int i = 0; i < above.count(); ++i) {
0136         SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(above[i]);
0137         subsurfaceItem->setZ(i);
0138     }
0139 }
0140 
0141 void SurfaceItemWayland::handleSubSurfacePositionChanged()
0142 {
0143     setPosition(m_surface->subSurface()->position());
0144 }
0145 
0146 void SurfaceItemWayland::handleSubSurfaceMappedChanged()
0147 {
0148     setVisible(m_surface->isMapped());
0149 }
0150 
0151 std::unique_ptr<SurfacePixmap> SurfaceItemWayland::createPixmap()
0152 {
0153     return std::make_unique<SurfacePixmapWayland>(this);
0154 }
0155 
0156 ContentType SurfaceItemWayland::contentType() const
0157 {
0158     return m_surface ? m_surface->contentType() : ContentType::None;
0159 }
0160 
0161 void SurfaceItemWayland::freeze()
0162 {
0163     if (!m_surface) {
0164         return;
0165     }
0166 
0167     m_surface->disconnect(this);
0168     if (auto subsurface = m_surface->subSurface()) {
0169         subsurface->disconnect(this);
0170     }
0171 
0172     for (auto &[subsurface, subsurfaceItem] : m_subsurfaces) {
0173         subsurfaceItem->freeze();
0174     }
0175 }
0176 
0177 void SurfaceItemWayland::handleColorDescriptionChanged()
0178 {
0179     setColorDescription(m_surface->colorDescription());
0180 }
0181 
0182 void SurfaceItemWayland::handlePresentationModeHintChanged()
0183 {
0184     setPresentationHint(m_surface->presentationModeHint());
0185 }
0186 
0187 SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent)
0188     : SurfacePixmap(Compositor::self()->backend()->createSurfaceTextureWayland(this), parent)
0189     , m_item(item)
0190 {
0191 }
0192 
0193 void SurfacePixmapWayland::create()
0194 {
0195     update();
0196 }
0197 
0198 void SurfacePixmapWayland::update()
0199 {
0200     SurfaceInterface *surface = m_item->surface();
0201     if (surface) {
0202         setBuffer(surface->buffer());
0203     }
0204 }
0205 
0206 bool SurfacePixmapWayland::isValid() const
0207 {
0208     return m_bufferRef;
0209 }
0210 
0211 SurfaceItemXwayland::SurfaceItemXwayland(X11Window *window, Scene *scene, Item *parent)
0212     : SurfaceItemWayland(window->surface(), scene, parent)
0213     , m_window(window)
0214 {
0215     connect(window, &X11Window::shapeChanged, this, &SurfaceItemXwayland::discardQuads);
0216 }
0217 
0218 QList<QRectF> SurfaceItemXwayland::shape() const
0219 {
0220     QList<QRectF> shape = m_window->shapeRegion();
0221     for (QRectF &shapePart : shape) {
0222         shapePart = shapePart.intersected(rect());
0223     }
0224     return shape;
0225 }
0226 
0227 QRegion SurfaceItemXwayland::opaque() const
0228 {
0229     QRegion shapeRegion;
0230     for (const QRectF &shapePart : shape()) {
0231         shapeRegion += shapePart.toRect();
0232     }
0233     if (!m_window->hasAlpha()) {
0234         return shapeRegion;
0235     } else {
0236         return m_window->opaqueRegion() & shapeRegion;
0237     }
0238     return QRegion();
0239 }
0240 
0241 } // namespace KWin
0242 
0243 #include "moc_surfaceitem_wayland.cpp"