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();
scheduleRepaint(item->boundingRect().translated(item->position()));
Q_EMIT childAdded(item);
}
void Item::removeChild(Item *item)

View file

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

View file

@ -5,26 +5,13 @@
*/
#include "surfaceitem.h"
#include "deleted.h"
namespace KWin
{
SurfaceItem::SurfaceItem(Window *window, Item *parent)
SurfaceItem::SurfaceItem(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
@ -41,8 +28,7 @@ void SurfaceItem::addDamage(const QRegion &region)
{
m_damage += region;
scheduleRepaint(region);
Q_EMIT m_window->damaged(m_window);
Q_EMIT damaged();
}
void SurfaceItem::resetDamage()

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,6 +14,8 @@
namespace KWin
{
class Deleted;
/**
* The SurfaceItemX11 class represents an X11 surface in the scene.
*/
@ -25,6 +27,8 @@ public:
explicit SurfaceItemX11(Window *window, Item *parent = nullptr);
~SurfaceItemX11() override;
Window *window() const;
void preprocess() override;
void processDamage();
@ -38,11 +42,13 @@ public:
private Q_SLOTS:
void handleBufferGeometryChanged(Window *window, const QRectF &old);
void handleGeometryShapeChanged();
void handleWindowClosed(Window *original, Deleted *deleted);
protected:
std::unique_ptr<SurfacePixmap> createPixmap() override;
private:
Window *m_window;
xcb_damage_damage_t m_damageHandle = XCB_NONE;
xcb_xfixes_fetch_region_cookie_t m_damageCookie;
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::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();
updateSurfaceVisibility();
} else {
@ -237,6 +243,11 @@ void WindowItem::updateOpacity()
setOpacity(m_window->opacity());
}
void WindowItem::markDamaged()
{
Q_EMIT m_window->damaged(m_window);
}
WindowItemX11::WindowItemX11(Window *window, Item *parent)
: WindowItem(window, parent)
{
@ -267,7 +278,7 @@ void WindowItemX11::initialize()
WindowItemWayland::WindowItemWayland(Window *window, Item *parent)
: WindowItem(window, parent)
{
updateSurfaceItem(new SurfaceItemWayland(window->surface(), window, this));
updateSurfaceItem(new SurfaceItemWayland(window->surface(), this));
}
WindowItemInternal::WindowItemInternal(InternalWindow *window, Item *parent)

View file

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