diff --git a/shadow.cpp b/shadow.cpp index 9581290b10..21d21cd355 100644 --- a/shadow.cpp +++ b/shadow.cpp @@ -24,10 +24,19 @@ along with this program. If not, see . #include "composite.h" #include "effects.h" #include "toplevel.h" +#if HAVE_WAYLAND +#include "wayland_server.h" +#endif #include #include +#if HAVE_WAYLAND +#include +#include +#include +#endif + namespace KWin { @@ -49,6 +58,11 @@ Shadow *Shadow::createShadow(Toplevel *toplevel) return NULL; } Shadow *shadow = crateShadowFromDecoration(toplevel); +#if HAVE_WAYLAND + if (!shadow && waylandServer()) { + shadow = createShadowFromWayland(toplevel); + } +#endif if (!shadow) { shadow = createShadowFromX11(toplevel); } @@ -98,6 +112,26 @@ Shadow *Shadow::crateShadowFromDecoration(Toplevel *toplevel) return shadow; } +Shadow *Shadow::createShadowFromWayland(Toplevel *toplevel) +{ +#if HAVE_WAYLAND + auto surface = toplevel->surface(); + if (!surface) { + return nullptr; + } + const auto s = surface->shadow(); + if (!s) { + return nullptr; + } + Shadow *shadow = Compositor::self()->scene()->createShadow(toplevel); + if (!shadow->init(s)) { + delete shadow; + return nullptr; + } + return shadow; +#endif +} + QVector< uint32_t > Shadow::readX11ShadowProperty(xcb_window_t id) { QVector ret; @@ -187,6 +221,36 @@ bool Shadow::init(KDecoration2::Decoration *decoration) return true; } +bool Shadow::init(const QPointer< KWayland::Server::ShadowInterface > &shadow) +{ +#if HAVE_WAYLAND + if (!shadow) { + return false; + } + + m_shadowElements[ShadowElementTop] = shadow->top() ? QPixmap::fromImage(shadow->top()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementTopRight] = shadow->topRight() ? QPixmap::fromImage(shadow->topRight()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementRight] = shadow->right() ? QPixmap::fromImage(shadow->right()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementBottomRight] = shadow->bottomRight() ? QPixmap::fromImage(shadow->bottomRight()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementBottom] = shadow->bottom() ? QPixmap::fromImage(shadow->bottom()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementBottomLeft] = shadow->bottomLeft() ? QPixmap::fromImage(shadow->bottomLeft()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementLeft] = shadow->left() ? QPixmap::fromImage(shadow->left()->data().copy()) : QPixmap(); + m_shadowElements[ShadowElementTopLeft] = shadow->topLeft() ? QPixmap::fromImage(shadow->topLeft()->data().copy()) : QPixmap(); + + const QMarginsF &p = shadow->offset(); + m_topOffset = p.top(); + m_rightOffset = p.right(); + m_bottomOffset = p.bottom(); + m_leftOffset = p.left(); + updateShadowRegion(); + if (!prepareBackend()) { + return false; + } + buildQuads(); + return true; +#endif +} + void Shadow::updateShadowRegion() { const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset); @@ -299,6 +363,20 @@ bool Shadow::updateShadow() clear(); return false; } +#if HAVE_WAYLAND + if (waylandServer()) { + if (m_topLevel && m_topLevel->surface()) { + if (const auto &s = m_topLevel->surface()->shadow()) { + if (init(s)) { + if (m_topLevel->effectWindow()) { + m_topLevel->effectWindow()->buildQuads(true); + } + return true; + } + } + } + } +#endif auto data = Shadow::readX11ShadowProperty(m_topLevel->window()); if (data.isEmpty()) { clear(); diff --git a/shadow.h b/shadow.h index 78c156712b..d47ff88b99 100644 --- a/shadow.h +++ b/shadow.h @@ -31,6 +31,14 @@ class Decoration; class DecorationShadow; } +namespace KWayland +{ +namespace Server +{ +class ShadowInterface; +} +} + namespace KWin { class Toplevel; @@ -160,9 +168,11 @@ protected: private: static Shadow *createShadowFromX11(Toplevel *toplevel); static Shadow *crateShadowFromDecoration(Toplevel *toplevel); + static Shadow *createShadowFromWayland(Toplevel *toplevel); static QVector readX11ShadowProperty(xcb_window_t id); bool init(const QVector &data); bool init(KDecoration2::Decoration *decoration); + bool init(const QPointer &shadow); Toplevel *m_topLevel; // shadow pixmaps QPixmap m_shadowElements[ShadowElementsCount]; diff --git a/shell_client.cpp b/shell_client.cpp index e08fcb6001..90ec8dc5f7 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -31,6 +31,7 @@ along with this program. If not, see . #include #include #include +#include #include #include @@ -88,6 +89,10 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface) ); connect(surface, &ShellSurfaceInterface::windowClassChanged, this, &ShellClient::updateIcon); updateIcon(); + + // setup shadow integration + getShadow(); + connect(surface->surface(), &SurfaceInterface::shadowChanged, this, &Toplevel::getShadow); } ShellClient::~ShellClient() = default; diff --git a/wayland_server.cpp b/wayland_server.cpp index 97d1eaeadc..6ce5f6bcfc 100644 --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -39,6 +39,7 @@ along with this program. If not, see . #include #include #include +#include #include // Qt @@ -186,6 +187,8 @@ void WaylandServer::init(const QByteArray &socketName) workspace()->setShowingDesktop(set); } ); + auto shadowManager = m_display->createShadowManager(m_display); + shadowManager->create(); } void WaylandServer::initWorkspace()