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()