From df1146bfa63de6bebd044161fffbff20e31ba677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 15 Jul 2015 11:24:19 +0200 Subject: [PATCH] [wayland] Shadow gains support for a Wayland protocol For Wayland clients we now are able to get shadows. Internally this reuses large parts of the X11 implementation. This could be improved to make the Scene's better aware of the Wayland shadow, so that less memory is needed. --- shadow.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++ shadow.h | 10 ++++++ shell_client.cpp | 5 +++ wayland_server.cpp | 3 ++ 4 files changed, 96 insertions(+) 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()