/* SPDX-FileCopyrightText: 2021 Vlad Zahorodnii SPDX-License-Identifier: GPL-2.0-or-later */ #include "scene/surfaceitem_wayland.h" #include "compositor.h" #include "core/graphicsbuffer.h" #include "core/renderbackend.h" #include "wayland/subcompositor.h" #include "wayland/surface.h" #include "window.h" #include "x11window.h" namespace KWin { SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Scene *scene, Item *parent) : SurfaceItem(scene, parent) , m_surface(surface) { connect(surface, &SurfaceInterface::surfaceToBufferMatrixChanged, this, &SurfaceItemWayland::handleSurfaceToBufferMatrixChanged); connect(surface, &SurfaceInterface::sizeChanged, this, &SurfaceItemWayland::handleSurfaceSizeChanged); connect(surface, &SurfaceInterface::bufferSizeChanged, this, &SurfaceItemWayland::handleBufferSizeChanged); connect(surface, &SurfaceInterface::bufferSourceBoxChanged, this, &SurfaceItemWayland::handleBufferSourceBoxChanged); connect(surface, &SurfaceInterface::bufferTransformChanged, this, &SurfaceItemWayland::handleBufferTransformChanged); connect(surface, &SurfaceInterface::childSubSurfacesChanged, this, &SurfaceItemWayland::handleChildSubSurfacesChanged); connect(surface, &SurfaceInterface::committed, this, &SurfaceItemWayland::handleSurfaceCommitted); connect(surface, &SurfaceInterface::damaged, this, &SurfaceItemWayland::addDamage); connect(surface, &SurfaceInterface::childSubSurfaceRemoved, this, &SurfaceItemWayland::handleChildSubSurfaceRemoved); SubSurfaceInterface *subsurface = surface->subSurface(); if (subsurface) { connect(surface, &SurfaceInterface::mapped, this, &SurfaceItemWayland::handleSubSurfaceMappedChanged); connect(surface, &SurfaceInterface::unmapped, this, &SurfaceItemWayland::handleSubSurfaceMappedChanged); connect(subsurface, &SubSurfaceInterface::positionChanged, this, &SurfaceItemWayland::handleSubSurfacePositionChanged); setVisible(surface->isMapped()); setPosition(subsurface->position()); } handleChildSubSurfacesChanged(); setSize(surface->size()); setBufferTransform(surface->bufferTransform()); setBufferSourceBox(surface->bufferSourceBox()); setBufferSize(surface->bufferSize()); setSurfaceToBufferMatrix(surface->surfaceToBufferMatrix()); } QVector SurfaceItemWayland::shape() const { return {rect()}; } QRegion SurfaceItemWayland::opaque() const { if (m_surface) { return m_surface->opaque(); } return QRegion(); } SurfaceInterface *SurfaceItemWayland::surface() const { return m_surface; } void SurfaceItemWayland::handleSurfaceToBufferMatrixChanged() { setSurfaceToBufferMatrix(m_surface->surfaceToBufferMatrix()); discardQuads(); discardPixmap(); } void SurfaceItemWayland::handleSurfaceSizeChanged() { setSize(m_surface->size()); } void SurfaceItemWayland::handleBufferSizeChanged() { setBufferSize(m_surface->bufferSize()); discardPixmap(); } void SurfaceItemWayland::handleBufferSourceBoxChanged() { setBufferSourceBox(m_surface->bufferSourceBox()); } void SurfaceItemWayland::handleBufferTransformChanged() { setBufferTransform(m_surface->bufferTransform()); } void SurfaceItemWayland::handleSurfaceCommitted() { if (m_surface->hasFrameCallbacks()) { scheduleFrame(); } } SurfaceItemWayland *SurfaceItemWayland::getOrCreateSubSurfaceItem(SubSurfaceInterface *child) { auto &item = m_subsurfaces[child]; if (!item) { item = std::make_unique(child->surface(), scene()); item->setParentItem(this); } return item.get(); } void SurfaceItemWayland::handleChildSubSurfaceRemoved(SubSurfaceInterface *child) { m_subsurfaces.erase(child); } void SurfaceItemWayland::handleChildSubSurfacesChanged() { const QList below = m_surface->below(); const QList above = m_surface->above(); for (int i = 0; i < below.count(); ++i) { SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(below[i]); subsurfaceItem->setZ(i - below.count()); } for (int i = 0; i < above.count(); ++i) { SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(above[i]); subsurfaceItem->setZ(i); } } void SurfaceItemWayland::handleSubSurfacePositionChanged() { setPosition(m_surface->subSurface()->position()); } void SurfaceItemWayland::handleSubSurfaceMappedChanged() { setVisible(m_surface->isMapped()); } std::unique_ptr SurfaceItemWayland::createPixmap() { return std::make_unique(this); } ContentType SurfaceItemWayland::contentType() const { return m_surface->contentType(); } SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent) : SurfacePixmap(Compositor::self()->backend()->createSurfaceTextureWayland(this), parent) , m_item(item) { } void SurfacePixmapWayland::create() { update(); } void SurfacePixmapWayland::update() { SurfaceInterface *surface = m_item->surface(); if (surface) { setBuffer(surface->buffer()); } } bool SurfacePixmapWayland::isValid() const { return m_bufferRef; } SurfaceItemXwayland::SurfaceItemXwayland(X11Window *window, Scene *scene, Item *parent) : SurfaceItemWayland(window->surface(), scene, parent) , m_window(window) { connect(window, &X11Window::shapeChanged, this, &SurfaceItemXwayland::discardQuads); } QVector SurfaceItemXwayland::shape() const { const QRectF clipRect = rect() & m_window->clientGeometry().translated(-m_window->bufferGeometry().topLeft()); QVector shape = m_window->shapeRegion(); // bounded to clipRect for (QRectF &shapePart : shape) { shapePart = shapePart.intersected(clipRect); } return shape; } } // namespace KWin #include "moc_surfaceitem_wayland.cpp"