scene: Decouple SurfaceItem from Window

The main motivation is to allow SurfaceItem used to be to present non
window contents.
This commit is contained in:
Vlad Zahorodnii 2022-12-14 16:52:10 +02:00
parent 93f053b514
commit f8fb0feab8
12 changed files with 91 additions and 39 deletions

View file

@ -91,6 +91,8 @@ void Item::addChild(Item *item)
updateBoundingRect(); updateBoundingRect();
scheduleRepaint(item->boundingRect().translated(item->position())); scheduleRepaint(item->boundingRect().translated(item->position()));
Q_EMIT childAdded(item);
} }
void Item::removeChild(Item *item) void Item::removeChild(Item *item)

View file

@ -108,6 +108,7 @@ public:
virtual void preprocess(); virtual void preprocess();
Q_SIGNALS: Q_SIGNALS:
void childAdded(Item *item);
/** /**
* This signal is emitted when the position of this item has changed. * This signal is emitted when the position of this item has changed.
*/ */

View file

@ -5,26 +5,13 @@
*/ */
#include "surfaceitem.h" #include "surfaceitem.h"
#include "deleted.h"
namespace KWin namespace KWin
{ {
SurfaceItem::SurfaceItem(Window *window, Item *parent) SurfaceItem::SurfaceItem(Item *parent)
: Item(parent) : Item(parent)
, m_window(window)
{ {
connect(window, &Window::windowClosed, this, &SurfaceItem::handleWindowClosed);
}
Window *SurfaceItem::window() const
{
return m_window;
}
void SurfaceItem::handleWindowClosed(Window *original, Deleted *deleted)
{
m_window = deleted;
} }
QMatrix4x4 SurfaceItem::surfaceToBufferMatrix() const QMatrix4x4 SurfaceItem::surfaceToBufferMatrix() const
@ -41,8 +28,7 @@ void SurfaceItem::addDamage(const QRegion &region)
{ {
m_damage += region; m_damage += region;
scheduleRepaint(region); scheduleRepaint(region);
Q_EMIT damaged();
Q_EMIT m_window->damaged(m_window);
} }
void SurfaceItem::resetDamage() void SurfaceItem::resetDamage()

View file

@ -12,7 +12,6 @@
namespace KWin namespace KWin
{ {
class Deleted;
class SurfacePixmap; class SurfacePixmap;
class Window; class Window;
@ -27,8 +26,6 @@ public:
QMatrix4x4 surfaceToBufferMatrix() const; QMatrix4x4 surfaceToBufferMatrix() const;
void setSurfaceToBufferMatrix(const QMatrix4x4 &matrix); void setSurfaceToBufferMatrix(const QMatrix4x4 &matrix);
Window *window() const;
void addDamage(const QRegion &region); void addDamage(const QRegion &region);
void resetDamage(); void resetDamage();
QRegion damage() const; QRegion damage() const;
@ -44,16 +41,16 @@ public:
virtual ContentType contentType() const; virtual ContentType contentType() const;
Q_SIGNALS:
void damaged();
protected: protected:
explicit SurfaceItem(Window *window, Item *parent = nullptr); explicit SurfaceItem(Item *parent = nullptr);
virtual std::unique_ptr<SurfacePixmap> createPixmap() = 0; virtual std::unique_ptr<SurfacePixmap> createPixmap() = 0;
void preprocess() override; void preprocess() override;
WindowQuadList buildQuads() const override; WindowQuadList buildQuads() const override;
void handleWindowClosed(Window *original, Deleted *deleted);
Window *m_window;
QRegion m_damage; QRegion m_damage;
std::unique_ptr<SurfacePixmap> m_pixmap; std::unique_ptr<SurfacePixmap> m_pixmap;
std::unique_ptr<SurfacePixmap> m_previousPixmap; std::unique_ptr<SurfacePixmap> m_previousPixmap;

View file

@ -6,6 +6,7 @@
#include "surfaceitem_internal.h" #include "surfaceitem_internal.h"
#include "composite.h" #include "composite.h"
#include "deleted.h"
#include "internalwindow.h" #include "internalwindow.h"
#include "scene.h" #include "scene.h"
@ -15,10 +16,13 @@ namespace KWin
{ {
SurfaceItemInternal::SurfaceItemInternal(InternalWindow *window, Item *parent) SurfaceItemInternal::SurfaceItemInternal(InternalWindow *window, Item *parent)
: SurfaceItem(window, parent) : SurfaceItem(parent)
, m_window(window)
{ {
connect(window, &Window::bufferGeometryChanged, connect(window, &Window::bufferGeometryChanged,
this, &SurfaceItemInternal::handleBufferGeometryChanged); this, &SurfaceItemInternal::handleBufferGeometryChanged);
connect(window, &Window::windowClosed,
this, &SurfaceItemInternal::handleWindowClosed);
setSize(window->bufferGeometry().size()); setSize(window->bufferGeometry().size());
@ -28,6 +32,11 @@ SurfaceItemInternal::SurfaceItemInternal(InternalWindow *window, Item *parent)
setSurfaceToBufferMatrix(surfaceToBufferMatrix); setSurfaceToBufferMatrix(surfaceToBufferMatrix);
} }
Window *SurfaceItemInternal::window() const
{
return m_window;
}
QVector<QRectF> SurfaceItemInternal::shape() const QVector<QRectF> SurfaceItemInternal::shape() const
{ {
return {rect()}; return {rect()};
@ -46,6 +55,11 @@ void SurfaceItemInternal::handleBufferGeometryChanged(Window *window, const QRec
setSize(window->bufferGeometry().size()); setSize(window->bufferGeometry().size());
} }
void SurfaceItemInternal::handleWindowClosed(Window *original, Deleted *deleted)
{
m_window = deleted;
}
SurfacePixmapInternal::SurfacePixmapInternal(SurfaceItemInternal *item, QObject *parent) SurfacePixmapInternal::SurfacePixmapInternal(SurfaceItemInternal *item, QObject *parent)
: SurfacePixmap(Compositor::self()->scene()->createSurfaceTextureInternal(this), parent) : SurfacePixmap(Compositor::self()->scene()->createSurfaceTextureInternal(this), parent)
, m_item(item) , m_item(item)

View file

@ -13,6 +13,7 @@ class QOpenGLFramebufferObject;
namespace KWin namespace KWin
{ {
class Deleted;
class InternalWindow; class InternalWindow;
/** /**
@ -25,13 +26,19 @@ class KWIN_EXPORT SurfaceItemInternal : public SurfaceItem
public: public:
explicit SurfaceItemInternal(InternalWindow *window, Item *parent = nullptr); explicit SurfaceItemInternal(InternalWindow *window, Item *parent = nullptr);
Window *window() const;
QVector<QRectF> shape() const override; QVector<QRectF> shape() const override;
private Q_SLOTS: private Q_SLOTS:
void handleBufferGeometryChanged(Window *window, const QRectF &old); void handleBufferGeometryChanged(Window *window, const QRectF &old);
void handleWindowClosed(Window *original, Deleted *deleted);
protected: protected:
std::unique_ptr<SurfacePixmap> createPixmap() override; std::unique_ptr<SurfacePixmap> createPixmap() override;
private:
Window *m_window;
}; };
class KWIN_EXPORT SurfacePixmapInternal final : public SurfacePixmap class KWIN_EXPORT SurfacePixmapInternal final : public SurfacePixmap

View file

@ -6,6 +6,7 @@
#include "surfaceitem_wayland.h" #include "surfaceitem_wayland.h"
#include "composite.h" #include "composite.h"
#include "deleted.h"
#include "scene.h" #include "scene.h"
#include "wayland/clientbuffer.h" #include "wayland/clientbuffer.h"
#include "wayland/subcompositor_interface.h" #include "wayland/subcompositor_interface.h"
@ -14,9 +15,8 @@
namespace KWin namespace KWin
{ {
SurfaceItemWayland::SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface, SurfaceItemWayland::SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface, Item *parent)
Window *window, Item *parent) : SurfaceItem(parent)
: SurfaceItem(window, parent)
, m_surface(surface) , m_surface(surface)
{ {
connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged, connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged,
@ -94,7 +94,7 @@ SurfaceItemWayland *SurfaceItemWayland::getOrCreateSubSurfaceItem(KWaylandServer
{ {
SurfaceItemWayland *&item = m_subsurfaces[child]; SurfaceItemWayland *&item = m_subsurfaces[child];
if (!item) { if (!item) {
item = new SurfaceItemWayland(child->surface(), window()); item = new SurfaceItemWayland(child->surface());
item->setParent(this); item->setParent(this);
item->setParentItem(this); item->setParentItem(this);
} }
@ -203,15 +203,17 @@ void SurfacePixmapWayland::setBuffer(KWaylandServer::ClientBuffer *buffer)
} }
SurfaceItemXwayland::SurfaceItemXwayland(Window *window, Item *parent) SurfaceItemXwayland::SurfaceItemXwayland(Window *window, Item *parent)
: SurfaceItemWayland(window->surface(), window, parent) : SurfaceItemWayland(window->surface(), parent)
, m_window(window)
{ {
connect(window, &Window::geometryShapeChanged, this, &SurfaceItemXwayland::discardQuads); connect(window, &Window::geometryShapeChanged, this, &SurfaceItemXwayland::discardQuads);
connect(window, &Window::windowClosed, this, &SurfaceItemXwayland::handleWindowClosed);
} }
QVector<QRectF> SurfaceItemXwayland::shape() const QVector<QRectF> SurfaceItemXwayland::shape() const
{ {
const QRectF clipRect = rect() & window()->clientGeometry().translated(-window()->bufferGeometry().topLeft()); const QRectF clipRect = rect() & m_window->clientGeometry().translated(-m_window->bufferGeometry().topLeft());
QVector<QRectF> shape = window()->shapeRegion(); QVector<QRectF> shape = m_window->shapeRegion();
// bounded to clipRect // bounded to clipRect
for (QRectF &shapePart : shape) { for (QRectF &shapePart : shape) {
@ -220,4 +222,9 @@ QVector<QRectF> SurfaceItemXwayland::shape() const
return shape; return shape;
} }
void SurfaceItemXwayland::handleWindowClosed(Window *original, Deleted *deleted)
{
m_window = deleted;
}
} // namespace KWin } // namespace KWin

View file

@ -18,6 +18,8 @@ class SurfaceInterface;
namespace KWin namespace KWin
{ {
class Deleted;
/** /**
* The SurfaceItemWayland class represents a Wayland surface in the scene. * The SurfaceItemWayland class represents a Wayland surface in the scene.
*/ */
@ -26,8 +28,7 @@ class KWIN_EXPORT SurfaceItemWayland : public SurfaceItem
Q_OBJECT Q_OBJECT
public: public:
explicit SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface, explicit SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface, Item *parent = nullptr);
Window *window, Item *parent = nullptr);
QVector<QRectF> shape() const override; QVector<QRectF> shape() const override;
QRegion opaque() const override; QRegion opaque() const override;
@ -89,6 +90,11 @@ public:
explicit SurfaceItemXwayland(Window *window, Item *parent = nullptr); explicit SurfaceItemXwayland(Window *window, Item *parent = nullptr);
QVector<QRectF> shape() const override; QVector<QRectF> shape() const override;
private:
void handleWindowClosed(Window *original, Deleted *deleted);
Window *m_window;
}; };
} // namespace KWin } // namespace KWin

View file

@ -6,6 +6,7 @@
#include "surfaceitem_x11.h" #include "surfaceitem_x11.h"
#include "composite.h" #include "composite.h"
#include "deleted.h"
#include "scene.h" #include "scene.h"
#include "x11syncmanager.h" #include "x11syncmanager.h"
@ -13,12 +14,15 @@ namespace KWin
{ {
SurfaceItemX11::SurfaceItemX11(Window *window, Item *parent) SurfaceItemX11::SurfaceItemX11(Window *window, Item *parent)
: SurfaceItem(window, parent) : SurfaceItem(parent)
, m_window(window)
{ {
connect(window, &Window::bufferGeometryChanged, connect(window, &Window::bufferGeometryChanged,
this, &SurfaceItemX11::handleBufferGeometryChanged); this, &SurfaceItemX11::handleBufferGeometryChanged);
connect(window, &Window::geometryShapeChanged, connect(window, &Window::geometryShapeChanged,
this, &SurfaceItemX11::handleGeometryShapeChanged); this, &SurfaceItemX11::handleGeometryShapeChanged);
connect(window, &Window::windowClosed,
this, &SurfaceItemX11::handleWindowClosed);
m_damageHandle = xcb_generate_id(kwinApp()->x11Connection()); m_damageHandle = xcb_generate_id(kwinApp()->x11Connection());
xcb_damage_create(kwinApp()->x11Connection(), m_damageHandle, window->frameId(), xcb_damage_create(kwinApp()->x11Connection(), m_damageHandle, window->frameId(),
@ -40,6 +44,16 @@ SurfaceItemX11::~SurfaceItemX11()
// destroyDamage() will be called by the associated Window. // destroyDamage() will be called by the associated Window.
} }
Window *SurfaceItemX11::window() const
{
return m_window;
}
void SurfaceItemX11::handleWindowClosed(Window *original, Deleted *deleted)
{
m_window = deleted;
}
void SurfaceItemX11::preprocess() void SurfaceItemX11::preprocess()
{ {
if (!damage().isEmpty()) { if (!damage().isEmpty()) {
@ -140,8 +154,8 @@ void SurfaceItemX11::handleGeometryShapeChanged()
QVector<QRectF> SurfaceItemX11::shape() const QVector<QRectF> SurfaceItemX11::shape() const
{ {
const QRectF clipRect = window()->clientGeometry().translated(-window()->bufferGeometry().topLeft()); const QRectF clipRect = m_window->clientGeometry().translated(-m_window->bufferGeometry().topLeft());
QVector<QRectF> shape = window()->shapeRegion(); QVector<QRectF> shape = m_window->shapeRegion();
// bounded to clipRect // bounded to clipRect
for (QRectF &shapePart : shape) { for (QRectF &shapePart : shape) {
shapePart = shapePart.intersected(clipRect); shapePart = shapePart.intersected(clipRect);
@ -155,10 +169,10 @@ QRegion SurfaceItemX11::opaque() const
for (const QRectF &shapePart : shape()) { for (const QRectF &shapePart : shape()) {
shapeRegion |= shapePart.toRect(); shapeRegion |= shapePart.toRect();
} }
if (!window()->hasAlpha()) { if (!m_window->hasAlpha()) {
return shapeRegion; return shapeRegion;
} else { } else {
return window()->opaqueRegion() & shapeRegion; return m_window->opaqueRegion() & shapeRegion;
} }
return QRegion(); return QRegion();
} }

View file

@ -14,6 +14,8 @@
namespace KWin namespace KWin
{ {
class Deleted;
/** /**
* The SurfaceItemX11 class represents an X11 surface in the scene. * The SurfaceItemX11 class represents an X11 surface in the scene.
*/ */
@ -25,6 +27,8 @@ public:
explicit SurfaceItemX11(Window *window, Item *parent = nullptr); explicit SurfaceItemX11(Window *window, Item *parent = nullptr);
~SurfaceItemX11() override; ~SurfaceItemX11() override;
Window *window() const;
void preprocess() override; void preprocess() override;
void processDamage(); void processDamage();
@ -38,11 +42,13 @@ public:
private Q_SLOTS: private Q_SLOTS:
void handleBufferGeometryChanged(Window *window, const QRectF &old); void handleBufferGeometryChanged(Window *window, const QRectF &old);
void handleGeometryShapeChanged(); void handleGeometryShapeChanged();
void handleWindowClosed(Window *original, Deleted *deleted);
protected: protected:
std::unique_ptr<SurfacePixmap> createPixmap() override; std::unique_ptr<SurfacePixmap> createPixmap() override;
private: private:
Window *m_window;
xcb_damage_damage_t m_damageHandle = XCB_NONE; xcb_damage_damage_t m_damageHandle = XCB_NONE;
xcb_xfixes_fetch_region_cookie_t m_damageCookie; xcb_xfixes_fetch_region_cookie_t m_damageCookie;
bool m_isDamaged = false; bool m_isDamaged = false;

View file

@ -176,6 +176,12 @@ void WindowItem::updateSurfaceItem(SurfaceItem *surfaceItem)
connect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition); connect(m_window, &Window::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition);
connect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition); connect(m_window, &Window::frameGeometryChanged, this, &WindowItem::updateSurfacePosition);
connect(surfaceItem, &SurfaceItem::damaged, this, &WindowItem::markDamaged);
connect(surfaceItem, &SurfaceItem::childAdded, this, [this](Item *item) {
auto surfaceItem = static_cast<SurfaceItem *>(item);
connect(surfaceItem, &SurfaceItem::damaged, this, &WindowItem::markDamaged);
});
updateSurfacePosition(); updateSurfacePosition();
updateSurfaceVisibility(); updateSurfaceVisibility();
} else { } else {
@ -237,6 +243,11 @@ void WindowItem::updateOpacity()
setOpacity(m_window->opacity()); setOpacity(m_window->opacity());
} }
void WindowItem::markDamaged()
{
Q_EMIT m_window->damaged(m_window);
}
WindowItemX11::WindowItemX11(Window *window, Item *parent) WindowItemX11::WindowItemX11(Window *window, Item *parent)
: WindowItem(window, parent) : WindowItem(window, parent)
{ {
@ -267,7 +278,7 @@ void WindowItemX11::initialize()
WindowItemWayland::WindowItemWayland(Window *window, Item *parent) WindowItemWayland::WindowItemWayland(Window *window, Item *parent)
: WindowItem(window, parent) : WindowItem(window, parent)
{ {
updateSurfaceItem(new SurfaceItemWayland(window->surface(), window, this)); updateSurfaceItem(new SurfaceItemWayland(window->surface(), this));
} }
WindowItemInternal::WindowItemInternal(InternalWindow *window, Item *parent) WindowItemInternal::WindowItemInternal(InternalWindow *window, Item *parent)

View file

@ -68,6 +68,7 @@ private Q_SLOTS:
private: private:
bool computeVisibility() const; bool computeVisibility() const;
void updateVisibility(); void updateVisibility();
void markDamaged();
Window *m_window; Window *m_window;
std::unique_ptr<SurfaceItem> m_surfaceItem; std::unique_ptr<SurfaceItem> m_surfaceItem;