diff --git a/scene.cpp b/scene.cpp
index 27da36e893..89eeeb9bb0 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -82,6 +82,7 @@ along with this program. If not, see .
#include "thumbnailitem.h"
#include
+#include
#include
namespace KWin
@@ -937,6 +938,15 @@ WindowPixmap::WindowPixmap(Scene::Window *window)
{
}
+WindowPixmap::WindowPixmap(const QPointer &subSurface, WindowPixmap *parent)
+ : m_window(parent->m_window)
+ , m_pixmap(XCB_PIXMAP_NONE)
+ , m_discarded(false)
+ , m_parent(parent)
+ , m_subSurface(subSurface)
+{
+}
+
WindowPixmap::~WindowPixmap()
{
if (isValid() && !kwinApp()->shouldUseWaylandForCompositing()) {
@@ -957,7 +967,7 @@ void WindowPixmap::create()
if (kwinApp()->shouldUseWaylandForCompositing()) {
// use Buffer
updateBuffer();
- if (m_buffer || !m_fbo.isNull()) {
+ if ((m_buffer || !m_fbo.isNull()) && m_subSurface.isNull()) {
m_window->unreferencePreviousPixmap();
}
return;
@@ -991,6 +1001,12 @@ void WindowPixmap::create()
m_window->unreferencePreviousPixmap();
}
+WindowPixmap *WindowPixmap::createChild(const QPointer &subSurface)
+{
+ Q_UNUSED(subSurface)
+ return nullptr;
+}
+
bool WindowPixmap::isValid() const
{
if (kwinApp()->shouldUseWaylandForCompositing()) {
@@ -1001,9 +1017,42 @@ bool WindowPixmap::isValid() const
void WindowPixmap::updateBuffer()
{
- if (auto s = toplevel()->surface()) {
+ using namespace KWayland::Server;
+ SurfaceInterface *s = nullptr;
+ if (!m_subSurface.isNull()) {
+ s = m_subSurface->surface().data();
+ } else {
+ s = toplevel()->surface();
+ }
+ if (s) {
+ QVector oldTree = m_children;
+ QVector children;
using namespace KWayland::Server;
+ const auto subSurfaces = s->childSubSurfaces();
+ for (const auto &subSurface : subSurfaces) {
+ if (subSurface.isNull()) {
+ continue;
+ }
+ auto it = std::find_if(oldTree.begin(), oldTree.end(), [subSurface] (WindowPixmap *p) { return p->m_subSurface == subSurface; });
+ if (it != oldTree.end()) {
+ children << *it;
+ (*it)->updateBuffer();
+ oldTree.erase(it);
+ } else {
+ WindowPixmap *p = createChild(subSurface);
+ if (p) {
+ p->create();
+ children << p;
+ }
+ }
+ }
+ setChildren(children);
+ qDeleteAll(oldTree);
if (auto b = s->buffer()) {
+ if (b == m_buffer) {
+ // no change
+ return;
+ }
if (m_buffer) {
QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
m_buffer->unref();
@@ -1011,6 +1060,12 @@ void WindowPixmap::updateBuffer()
m_buffer = b;
m_buffer->ref();
QObject::connect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
+ } else if (m_subSurface) {
+ if (m_buffer) {
+ QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
+ m_buffer->unref();
+ m_buffer.clear();
+ }
} else {
// might be an internal window
const auto &fbo = toplevel()->internalFramebufferObject();
@@ -1018,6 +1073,12 @@ void WindowPixmap::updateBuffer()
m_fbo = fbo;
}
}
+ } else {
+ if (m_buffer) {
+ QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
+ m_buffer->unref();
+ m_buffer.clear();
+ }
}
}
diff --git a/scene.h b/scene.h
index 279f71394d..7eb1347da7 100644
--- a/scene.h
+++ b/scene.h
@@ -35,6 +35,7 @@ namespace KWayland
namespace Server
{
class BufferInterface;
+class SubSurfaceInterface;
}
}
@@ -392,8 +393,31 @@ public:
*/
Toplevel *toplevel() const;
+ /**
+ * @returns the parent WindowPixmap in the sub-surface tree
+ **/
+ WindowPixmap *parent() const {
+ return m_parent;
+ }
+
+ /**
+ * @returns the current sub-surface tree
+ **/
+ QVector children() const {
+ return m_children;
+ }
+
+ /**
+ * @returns the subsurface this WindowPixmap is for if it is not for a root window
+ **/
+ QPointer subSurface() const {
+ return m_subSurface;
+ }
+
protected:
explicit WindowPixmap(Scene::Window *window);
+ explicit WindowPixmap(const QPointer &subSurface, WindowPixmap *parent);
+ virtual WindowPixmap *createChild(const QPointer &subSurface);
/**
* @return The Window this WindowPixmap belongs to
*/
@@ -403,7 +427,15 @@ protected:
* Should be called by the implementing subclasses when the Wayland Buffer changed and needs
* updating.
**/
- void updateBuffer();
+ virtual void updateBuffer();
+
+ /**
+ * Sets the sub-surface tree to @p children.
+ **/
+ void setChildren(const QVector &children) {
+ m_children = children;
+ }
+
private:
Scene::Window *m_window;
xcb_pixmap_t m_pixmap;
@@ -412,6 +444,9 @@ private:
QRect m_contentsRect;
QPointer m_buffer;
QSharedPointer m_fbo;
+ WindowPixmap *m_parent = nullptr;
+ QVector m_children;
+ QPointer m_subSurface;
};
class Scene::EffectFrame