From 4c3aa31cd3ffb5a593da8a017fc5d846c19019a8 Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Wed, 26 Aug 2015 14:42:58 +0200 Subject: [PATCH] Blur protocol in KWayland a protocol to activate the blur behind windows and to optionally set a sub region of the window where to apply the blur to, in case the window is shaped REVIEW:125015 --- src/wayland/CMakeLists.txt | 7 + src/wayland/autotests/client/CMakeLists.txt | 11 + .../autotests/client/test_wayland_blur.cpp | 169 ++++++++++++++ .../client/test_wayland_registry.cpp | 8 + src/wayland/blur_interface.cpp | 217 ++++++++++++++++++ src/wayland/blur_interface.h | 73 ++++++ src/wayland/display.cpp | 8 + src/wayland/display.h | 2 + src/wayland/surface_interface.cpp | 21 ++ src/wayland/surface_interface.h | 13 ++ src/wayland/surface_interface_p.h | 3 + 11 files changed, 532 insertions(+) create mode 100644 src/wayland/autotests/client/test_wayland_blur.cpp create mode 100644 src/wayland/blur_interface.cpp create mode 100644 src/wayland/blur_interface.h diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index 1cf09d3ab6..9d99325907 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -21,6 +21,7 @@ set(SERVER_LIB_SRCS resource.cpp seat_interface.cpp shadow_interface.cpp + blur_interface.cpp shell_interface.cpp surface_interface.cpp subcompositor_interface.cpp @@ -57,6 +58,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS BASENAME shadow ) +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/blur.xml + BASENAME blur +) + add_library(KF5WaylandServer ${SERVER_LIB_SRCS}) generate_export_header(KF5WaylandServer BASE_NAME @@ -92,6 +98,7 @@ install(TARGETS KF5WaylandServer EXPORT KF5WaylandTargets ${KF5_INSTALL_TARGETS_ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KWayland/Server/kwaylandserver_export.h + blur_interface.h buffer_interface.h clientconnection.h compositor_interface.h diff --git a/src/wayland/autotests/client/CMakeLists.txt b/src/wayland/autotests/client/CMakeLists.txt index c2c1df29cc..acc1cc0a87 100644 --- a/src/wayland/autotests/client/CMakeLists.txt +++ b/src/wayland/autotests/client/CMakeLists.txt @@ -135,6 +135,17 @@ target_link_libraries( testRegion Qt5::Test Qt5::Gui KF5::WaylandClient KF5::Way add_test(kwayland-testRegion testRegion) ecm_mark_as_test(testRegion) +######################################################## +# Test Blur +######################################################## +set( testBlur_SRCS + test_wayland_blur.cpp + ) +add_executable(testBlur ${testBlur_SRCS}) +target_link_libraries( testBlur Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) +add_test(kwayland-testBlur testBlur) +ecm_mark_as_test(testBlur) + ######################################################## # Test DataSource ######################################################## diff --git a/src/wayland/autotests/client/test_wayland_blur.cpp b/src/wayland/autotests/client/test_wayland_blur.cpp new file mode 100644 index 0000000000..db20e516bf --- /dev/null +++ b/src/wayland/autotests/client/test_wayland_blur.cpp @@ -0,0 +1,169 @@ +/******************************************************************** +Copyright 2014 Martin Gräßlin + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*********************************************************************/ +// Qt +#include +// KWin +#include "../../src/client/compositor.h" +#include "../../src/client/connection_thread.h" +#include "../../src/client/event_queue.h" +#include "../../src/client/region.h" +#include "../../src/client/registry.h" +#include "../../src/client/surface.h" +#include "../../src/client/blur.h" +#include "../../src/server/display.h" +#include "../../src/server/compositor_interface.h" +#include "../../src/server/region_interface.h" +#include "../../src/server/blur_interface.h" + +class TestBlur : public QObject +{ + Q_OBJECT +public: + explicit TestBlur(QObject *parent = nullptr); +private Q_SLOTS: + void init(); + void cleanup(); + + void testCreate(); + +private: + KWayland::Server::Display *m_display; + KWayland::Server::CompositorInterface *m_compositorInterface; + KWayland::Server::BlurManagerInterface *m_blurManagerInterface; + KWayland::Client::ConnectionThread *m_connection; + KWayland::Client::Compositor *m_compositor; + KWayland::Client::BlurManager *m_blurManager; + KWayland::Client::EventQueue *m_queue; + QThread *m_thread; + KWayland::Client::Registry m_registry; +}; + +static const QString s_socketName = QStringLiteral("kwayland-test-wayland-blur-0"); + +TestBlur::TestBlur(QObject *parent) + : QObject(parent) + , m_display(nullptr) + , m_compositorInterface(nullptr) + , m_connection(nullptr) + , m_compositor(nullptr) + , m_queue(nullptr) + , m_thread(nullptr) +{ +} + +void TestBlur::init() +{ + using namespace KWayland::Server; + delete m_display; + m_display = new Display(this); + m_display->setSocketName(s_socketName); + m_display->start(); + QVERIFY(m_display->isRunning()); + + // setup connection + m_connection = new KWayland::Client::ConnectionThread; + QSignalSpy connectedSpy(m_connection, SIGNAL(connected())); + m_connection->setSocketName(s_socketName); + + m_thread = new QThread(this); + m_connection->moveToThread(m_thread); + m_thread->start(); + + m_connection->initConnection(); + QVERIFY(connectedSpy.wait()); + + m_queue = new KWayland::Client::EventQueue(this); + QVERIFY(!m_queue->isValid()); + m_queue->setup(m_connection); + QVERIFY(m_queue->isValid()); + + QSignalSpy compositorSpy(&m_registry, SIGNAL(compositorAnnounced(quint32,quint32))); + QVERIFY(compositorSpy.isValid()); + + QSignalSpy blurSpy(&m_registry, SIGNAL(blurAnnounced(quint32,quint32))); + QVERIFY(blurSpy.isValid()); + + QVERIFY(!m_registry.eventQueue()); + m_registry.setEventQueue(m_queue); + QCOMPARE(m_registry.eventQueue(), m_queue); + m_registry.create(m_connection->display()); + QVERIFY(m_registry.isValid()); + m_registry.setup(); + + m_compositorInterface = m_display->createCompositor(m_display); + m_compositorInterface->create(); + QVERIFY(m_compositorInterface->isValid()); + + QVERIFY(compositorSpy.wait()); + m_compositor = m_registry.createCompositor(compositorSpy.first().first().value(), compositorSpy.first().last().value(), this); + + m_blurManagerInterface = m_display->createBlurManager(m_display); + m_blurManagerInterface->create(); + QVERIFY(m_blurManagerInterface->isValid()); + + QVERIFY(blurSpy.wait()); + m_blurManager = m_registry.createBlurManager(blurSpy.first().first().value(), blurSpy.first().last().value(), this); +} + +void TestBlur::cleanup() +{ + if (m_compositor) { + delete m_compositor; + m_compositor = nullptr; + } + if (m_queue) { + delete m_queue; + m_queue = nullptr; + } + if (m_thread) { + m_thread->quit(); + m_thread->wait(); + delete m_thread; + m_thread = nullptr; + } + delete m_connection; + m_connection = nullptr; + + delete m_display; + m_display = nullptr; +} + +void TestBlur::testCreate() +{ + QSignalSpy serverSurfaceCreated(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*))); + QVERIFY(serverSurfaceCreated.isValid()); + + QScopedPointer surface(m_compositor->createSurface()); + QVERIFY(serverSurfaceCreated.wait()); + + auto serverSurface = serverSurfaceCreated.first().first().value(); + QSignalSpy blurChanged(serverSurface, SIGNAL(blurChanged())); + + auto blur = m_blurManager->createBlur(surface.data(), surface.data()); + blur->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr)); + blur->commit(); + surface->commit(KWayland::Client::Surface::CommitFlag::None); + + QVERIFY(blurChanged.wait()); + QCOMPARE(serverSurface->blur()->region(), QRegion(0, 0, 10, 20)); +} + +QTEST_MAIN(TestBlur) +#include "test_wayland_blur.moc" diff --git a/src/wayland/autotests/client/test_wayland_registry.cpp b/src/wayland/autotests/client/test_wayland_registry.cpp index a38066aecc..9cef0d46e2 100644 --- a/src/wayland/autotests/client/test_wayland_registry.cpp +++ b/src/wayland/autotests/client/test_wayland_registry.cpp @@ -34,6 +34,7 @@ License along with this library. If not, see . #include "../../src/server/output_interface.h" #include "../../src/server/seat_interface.h" #include "../../src/server/shell_interface.h" +#include "../../src/server/blur_interface.h" #include "../../src/server/subcompositor_interface.h" // Wayland #include @@ -55,6 +56,7 @@ private Q_SLOTS: void testBindSeat(); void testBindSubCompositor(); void testBindDataDeviceManager(); + void testBindBlurManager(); void testGlobalSync(); void testGlobalSyncThreaded(); void testRemoval(); @@ -103,6 +105,7 @@ void TestWaylandRegistry::init() m_subcompositor->create(); m_dataDeviceManager = m_display->createDataDeviceManager(); m_dataDeviceManager->create(); + m_display->createBlurManager(this)->create(); } void TestWaylandRegistry::cleanup() @@ -205,6 +208,11 @@ void TestWaylandRegistry::testBindDataDeviceManager() TEST_BIND(KWayland::Client::Registry::Interface::DataDeviceManager, SIGNAL(dataDeviceManagerAnnounced(quint32,quint32)), bindDataDeviceManager, wl_data_device_manager_destroy) } +void TestWaylandRegistry::testBindBlurManager() +{ + TEST_BIND(KWayland::Client::Registry::Interface::Blur, SIGNAL(blurAnnounced(quint32,quint32)), bindBlurManager, free) +} + #undef TEST_BIND void TestWaylandRegistry::testRemoval() diff --git a/src/wayland/blur_interface.cpp b/src/wayland/blur_interface.cpp new file mode 100644 index 0000000000..cdca04e6fe --- /dev/null +++ b/src/wayland/blur_interface.cpp @@ -0,0 +1,217 @@ +/******************************************************************** +Copyright 2015 Martin Gräßlin +Copyright 2015 Marco Martin + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*********************************************************************/ +#include "blur_interface.h" +#include "region_interface.h" +#include "display.h" +#include "global_p.h" +#include "resource_p.h" +#include "surface_interface_p.h" + +#include +#include + +namespace KWayland +{ +namespace Server +{ + +static const quint32 s_version = 1; + +class BlurManagerInterface::Private : public Global::Private +{ +public: + Private(BlurManagerInterface *q, Display *d); + +private: + void bind(wl_client *client, uint32_t version, uint32_t id) override; + void createBlur(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface); + + static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface); + static void unsetCallback(wl_client *client, wl_resource *resource, wl_resource *surface); + static void unbind(wl_resource *resource); + static Private *cast(wl_resource *r) { + return reinterpret_cast(wl_resource_get_user_data(r)); + } + + BlurManagerInterface *q; + static const struct org_kde_kwin_blur_manager_interface s_interface; +}; + +const struct org_kde_kwin_blur_manager_interface BlurManagerInterface::Private::s_interface = { + createCallback, + unsetCallback +}; + +BlurManagerInterface::Private::Private(BlurManagerInterface *q, Display *d) + : Global::Private(d, &org_kde_kwin_blur_manager_interface, s_version) + , q(q) +{ +} + +void BlurManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + auto c = display->getConnection(client); + wl_resource *resource = c->createResource(&org_kde_kwin_blur_manager_interface, qMin(version, s_version), id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &s_interface, this, unbind); + // TODO: should we track? +} + +void BlurManagerInterface::Private::unbind(wl_resource *resource) +{ + Q_UNUSED(resource) + // TODO: implement? +} + +void BlurManagerInterface::Private::createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface) +{ + cast(resource)->createBlur(client, resource, id, surface); +} + +void BlurManagerInterface::Private::createBlur(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface) +{ + SurfaceInterface *s = SurfaceInterface::get(surface); + if (!s) { + return; + } + + BlurInterface *blur = new BlurInterface(q, resource); + blur->create(display->getConnection(client), wl_resource_get_version(resource), id); + if (!blur->resource()) { + wl_resource_post_no_memory(resource); + delete blur; + return; + } + QObject::connect(s, &QObject::destroyed, blur, + [blur] { + if (blur->resource()) { + wl_resource_destroy(blur->resource()); + delete blur; + } + } + ); + s->d_func()->setBlur(QPointer(blur)); +} + +void BlurManagerInterface::Private::unsetCallback(wl_client *client, wl_resource *resource, wl_resource *surface) +{ + Q_UNUSED(client) + Q_UNUSED(resource) + SurfaceInterface *s = SurfaceInterface::get(surface); + if (!s) { + return; + } + s->d_func()->setBlur(QPointer()); +} + +BlurManagerInterface::BlurManagerInterface(Display *display, QObject *parent) + : Global(new Private(this, display), parent) +{ +} + +BlurManagerInterface::~BlurManagerInterface() = default; + +class BlurInterface::Private : public Resource::Private +{ +public: + Private(BlurInterface *q, BlurManagerInterface *c, wl_resource *parentResource); + ~Private(); + + QRegion pendingRegion; + QRegion currentRegion; + +private: + void commit(); + //TODO + BlurInterface *q_func() { + return reinterpret_cast(q); + } + + static void commitCallback(wl_client *client, wl_resource *resource); + static void setRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region); + + static const struct org_kde_kwin_blur_interface s_interface; +}; + +const struct org_kde_kwin_blur_interface BlurInterface::Private::s_interface = { + commitCallback, + setRegionCallback +}; + +void BlurInterface::Private::commitCallback(wl_client *client, wl_resource *resource) +{ + Q_UNUSED(client) + cast(resource)->commit(); +} + +void BlurInterface::Private::commit() +{ + currentRegion = pendingRegion; +} + +void BlurInterface::Private::setRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region) +{ + Q_UNUSED(client) + Private *p = cast(resource); + RegionInterface *r = RegionInterface::get(region); + if (r) { + p->pendingRegion = r->region(); + } else { + p->pendingRegion = QRegion(); + } +} + +BlurInterface::Private::Private(BlurInterface *q, BlurManagerInterface *c, wl_resource *parentResource) + : Resource::Private(q, c, parentResource, &org_kde_kwin_blur_interface, &s_interface) +{ +} + +BlurInterface::Private::~Private() +{ + if (resource) { + wl_resource_destroy(resource); + resource = nullptr; + } +} + +BlurInterface::BlurInterface(BlurManagerInterface *parent, wl_resource *parentResource) + : Resource(new Private(this, parent, parentResource)) +{ +} + +BlurInterface::~BlurInterface() = default; + +QRegion BlurInterface::region() +{ + Q_D(); + return d->currentRegion; +} + +BlurInterface::Private *BlurInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +} +} diff --git a/src/wayland/blur_interface.h b/src/wayland/blur_interface.h new file mode 100644 index 0000000000..01568a87c2 --- /dev/null +++ b/src/wayland/blur_interface.h @@ -0,0 +1,73 @@ +/******************************************************************** +Copyright 2015 Martin Gräßlin +Copyright 2015 Marco Martin + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +*********************************************************************/ +#ifndef KWAYLAND_SERVER_BLUR_INTERFACE_H +#define KWAYLAND_SERVER_BLUR_INTERFACE_H + +#include "global.h" +#include "resource.h" + +#include +#include + +#include + +struct wl_region; + +namespace KWayland +{ +namespace Server +{ + +class BufferInterface; +class Display; + +class KWAYLANDSERVER_EXPORT BlurManagerInterface : public Global +{ + Q_OBJECT +public: + virtual ~BlurManagerInterface(); + +private: + explicit BlurManagerInterface(Display *display, QObject *parent = nullptr); + friend class Display; + class Private; +}; + +class KWAYLANDSERVER_EXPORT BlurInterface : public Resource +{ + Q_OBJECT +public: + virtual ~BlurInterface(); + + QRegion region(); + +private: + explicit BlurInterface(BlurManagerInterface *parent, wl_resource *parentResource); + friend class BlurManagerInterface; + + class Private; + Private *d_func() const; +}; + +} +} + +#endif diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index 884d7ea2fe..75adc142a9 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -29,6 +29,7 @@ License along with this library. If not, see . #include "qtsurfaceextension_interface.h" #include "seat_interface.h" #include "shadow_interface.h" +#include "blur_interface.h" #include "shell_interface.h" #include "subcompositor_interface.h" @@ -271,6 +272,13 @@ ShadowManagerInterface *Display::createShadowManager(QObject *parent) return s; } +BlurManagerInterface *Display::createBlurManager(QObject *parent) +{ + auto b = new BlurManagerInterface(this, parent); + connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); + return b; +} + void Display::createShm() { Q_ASSERT(d->display); diff --git a/src/wayland/display.h b/src/wayland/display.h index 4c0e0c71ef..cd43b03069 100644 --- a/src/wayland/display.h +++ b/src/wayland/display.h @@ -46,6 +46,7 @@ class PlasmaWindowManagementInterface; class QtSurfaceExtensionInterface; class SeatInterface; class ShadowManagerInterface; +class BlurManagerInterface; class ShellInterface; class SubCompositorInterface; @@ -126,6 +127,7 @@ public: IdleInterface *createIdle(QObject *parent = nullptr); FakeInputInterface *createFakeInput(QObject *parent = nullptr); ShadowManagerInterface *createShadowManager(QObject *parent = nullptr); + BlurManagerInterface *createBlurManager(QObject *parent = nullptr); /** * Gets the ClientConnection for the given @p client. diff --git a/src/wayland/surface_interface.cpp b/src/wayland/surface_interface.cpp index be885bd362..0f62d13363 100644 --- a/src/wayland/surface_interface.cpp +++ b/src/wayland/surface_interface.cpp @@ -130,6 +130,12 @@ void SurfaceInterface::Private::setShadow(const QPointer &shado pending.shadowIsSet = true; } +void SurfaceInterface::Private::setBlur(const QPointer &blur) +{ + pending.blur = blur; + pending.blurIsSet = true; +} + const struct wl_surface_interface SurfaceInterface::Private::s_interface = { destroyCallback, attachCallback, @@ -186,6 +192,7 @@ void SurfaceInterface::Private::commit() const bool scaleFactorChanged = current.scale != pending.scale; const bool transformFactorChanged = current.transform != pending.transform; const bool shadowChanged = pending.shadowIsSet; + const bool blurChanged = pending.blurIsSet; bool sizeChanged = false; auto buffer = current.buffer; if (bufferChanged) { @@ -207,6 +214,10 @@ void SurfaceInterface::Private::commit() if (shadowChanged) { shadow = pending.shadow; } + auto blur = current.blur; + if (blurChanged) { + blur = pending.blur; + } QList callbacks = current.callbacks; callbacks.append(pending.callbacks); // copy values @@ -214,6 +225,7 @@ void SurfaceInterface::Private::commit() current.buffer = buffer; current.callbacks = callbacks; current.shadow = shadow; + current.blur = blur; pending = State{}; pending.children = current.children; pending.input = current.input; @@ -255,6 +267,9 @@ void SurfaceInterface::Private::commit() if (shadowChanged) { emit q->shadowChanged(); } + if (blurChanged) { + emit q->blurChanged(); + } } void SurfaceInterface::Private::damage(const QRect &rect) @@ -480,6 +495,12 @@ QPointer< ShadowInterface > SurfaceInterface::shadow() const return d->current.shadow; } +QPointer< BlurInterface > SurfaceInterface::blur() const +{ + Q_D(); + return d->current.blur; +} + SurfaceInterface::Private *SurfaceInterface::d_func() const { return reinterpret_cast(d.data()); diff --git a/src/wayland/surface_interface.h b/src/wayland/surface_interface.h index 4935ff675e..f8f9be7b12 100644 --- a/src/wayland/surface_interface.h +++ b/src/wayland/surface_interface.h @@ -33,6 +33,8 @@ namespace KWayland { namespace Server { +class BlurManagerInterface; +class BlurInterface; class BufferInterface; class CompositorInterface; class ShadowManagerInterface; @@ -82,6 +84,12 @@ public: **/ QPointer shadow() const; + /** + * @returns The Blur for this Surface. + * @since 5.5 + **/ + QPointer blur() const; + static SurfaceInterface *get(wl_resource *native); /** * @returns The SurfaceInterface with given @p id for @p client, if it exists, otherwise @c nullptr. @@ -107,11 +115,16 @@ Q_SIGNALS: * @since 5.4 **/ void shadowChanged(); + /** + * @since 5.5 + **/ + void blurChanged(); private: friend class CompositorInterface; friend class SubSurfaceInterface; friend class ShadowManagerInterface; + friend class BlurManagerInterface; explicit SurfaceInterface(CompositorInterface *parent, wl_resource *parentResource); class Private; diff --git a/src/wayland/surface_interface_p.h b/src/wayland/surface_interface_p.h index 062c7e7540..2b55f81363 100644 --- a/src/wayland/surface_interface_p.h +++ b/src/wayland/surface_interface_p.h @@ -41,6 +41,7 @@ public: bool opaqueIsSet = false; bool bufferIsSet = false; bool shadowIsSet = false; + bool blurIsSet = false; bool inputIsInfinite = true; qint32 scale = 1; OutputInterface::Transform transform = OutputInterface::Transform::Normal; @@ -50,6 +51,7 @@ public: // stacking order: bottom (first) -> top (last) QList> children; QPointer shadow; + QPointer blur; }; Private(SurfaceInterface *q, CompositorInterface *c, wl_resource *parentResource); ~Private(); @@ -61,6 +63,7 @@ public: bool raiseChild(QPointer subsurface, SurfaceInterface *sibling); bool lowerChild(QPointer subsurface, SurfaceInterface *sibling); void setShadow(const QPointer &shadow); + void setBlur(const QPointer &blur); State current; State pending;