File indexing completed on 2024-11-10 04:57:16
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"