diff --git a/internal_client.cpp b/internal_client.cpp
index b3dee3b1ad..4695914f46 100644
--- a/internal_client.cpp
+++ b/internal_client.cpp
@@ -31,6 +31,7 @@ along with this program. If not, see .
Q_DECLARE_METATYPE(NET::WindowType)
static const QByteArray s_skipClosePropertyName = QByteArrayLiteral("KWIN_SKIP_CLOSE_ANIMATION");
+static const QByteArray s_shadowEnabledPropertyName = QByteArrayLiteral("kwin_shadow_enabled");
namespace KWin
{
@@ -62,6 +63,7 @@ InternalClient::InternalClient(QWindow *window)
setOpacity(m_internalWindow->opacity());
setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool());
+ // Create scene window, effect window, and update server-side shadow.
setupCompositing();
updateColorScheme();
@@ -86,6 +88,9 @@ bool InternalClient::eventFilter(QObject *watched, QEvent *event)
if (pe->propertyName() == s_skipClosePropertyName) {
setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool());
}
+ if (pe->propertyName() == s_shadowEnabledPropertyName) {
+ updateShadow();
+ }
if (pe->propertyName() == "kwin_windowType") {
m_windowType = m_internalWindow->property("kwin_windowType").value();
workspace()->updateClientArea();
diff --git a/plugins/windowsystem/CMakeLists.txt b/plugins/windowsystem/CMakeLists.txt
index 68305c955a..bb27ea4df0 100644
--- a/plugins/windowsystem/CMakeLists.txt
+++ b/plugins/windowsystem/CMakeLists.txt
@@ -1,6 +1,7 @@
set(kwindowsystem_plugin_SRCS
plugin.cpp
windoweffects.cpp
+ windowshadow.cpp
windowsystem.cpp
)
diff --git a/plugins/windowsystem/plugin.cpp b/plugins/windowsystem/plugin.cpp
index e374ee1a76..6125f6a620 100644
--- a/plugins/windowsystem/plugin.cpp
+++ b/plugins/windowsystem/plugin.cpp
@@ -18,8 +18,9 @@
* along with this program. If not, see .
*/
#include "plugin.h"
-#include "windowsystem.h"
#include "windoweffects.h"
+#include "windowshadow.h"
+#include "windowsystem.h"
KWindowSystemKWinPlugin::KWindowSystemKWinPlugin(QObject *parent)
: KWindowSystemPluginInterface(parent)
@@ -39,3 +40,13 @@ KWindowSystemPrivate *KWindowSystemKWinPlugin::createWindowSystem()
{
return new KWin::WindowSystem();
}
+
+KWindowShadowTilePrivate *KWindowSystemKWinPlugin::createWindowShadowTile()
+{
+ return new KWin::WindowShadowTile();
+}
+
+KWindowShadowPrivate *KWindowSystemKWinPlugin::createWindowShadow()
+{
+ return new KWin::WindowShadow();
+}
diff --git a/plugins/windowsystem/plugin.h b/plugins/windowsystem/plugin.h
index c1de4950cd..04fd03e099 100644
--- a/plugins/windowsystem/plugin.h
+++ b/plugins/windowsystem/plugin.h
@@ -33,4 +33,6 @@ public:
KWindowEffectsPrivate *createEffects() override;
KWindowSystemPrivate *createWindowSystem() override;
+ KWindowShadowTilePrivate *createWindowShadowTile() override;
+ KWindowShadowPrivate *createWindowShadow() override;
};
diff --git a/plugins/windowsystem/windowshadow.cpp b/plugins/windowsystem/windowshadow.cpp
new file mode 100644
index 0000000000..556c70f8d2
--- /dev/null
+++ b/plugins/windowsystem/windowshadow.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2020 Vlad Zahorodnii
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 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 14 of version 3 of the license.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "windowshadow.h"
+
+#include
+
+Q_DECLARE_METATYPE(QMargins)
+
+namespace KWin
+{
+
+bool WindowShadowTile::create()
+{
+ return true;
+}
+
+void WindowShadowTile::destroy()
+{
+}
+
+bool WindowShadow::create()
+{
+ // TODO: Perhaps we set way too many properties here. Alternatively we could put all shadow tiles
+ // in one big image and attach it rather than 8 separate images.
+ if (leftTile) {
+ window->setProperty("kwin_shadow_left_tile", QVariant::fromValue(leftTile->image()));
+ }
+ if (topLeftTile) {
+ window->setProperty("kwin_shadow_top_left_tile", QVariant::fromValue(topLeftTile->image()));
+ }
+ if (topTile) {
+ window->setProperty("kwin_shadow_top_tile", QVariant::fromValue(topTile->image()));
+ }
+ if (topRightTile) {
+ window->setProperty("kwin_shadow_top_right_tile", QVariant::fromValue(topRightTile->image()));
+ }
+ if (rightTile) {
+ window->setProperty("kwin_shadow_right_tile", QVariant::fromValue(rightTile->image()));
+ }
+ if (bottomRightTile) {
+ window->setProperty("kwin_shadow_bottom_right_tile", QVariant::fromValue(bottomRightTile->image()));
+ }
+ if (bottomTile) {
+ window->setProperty("kwin_shadow_bottom_tile", QVariant::fromValue(bottomTile->image()));
+ }
+ if (bottomLeftTile) {
+ window->setProperty("kwin_shadow_bottom_left_tile", QVariant::fromValue(bottomLeftTile->image()));
+ }
+ window->setProperty("kwin_shadow_padding", QVariant::fromValue(padding));
+
+ // Notice that the enabled property must be set last.
+ window->setProperty("kwin_shadow_enabled", QVariant::fromValue(true));
+
+ return true;
+}
+
+void WindowShadow::destroy()
+{
+ // Attempting to uninstall the shadow after the decorated window has been destroyed. It's doomed.
+ if (!window) {
+ return;
+ }
+
+ // Remove relevant shadow properties.
+ window->setProperty("kwin_shadow_left_tile", {});
+ window->setProperty("kwin_shadow_top_left_tile", {});
+ window->setProperty("kwin_shadow_top_tile", {});
+ window->setProperty("kwin_shadow_top_right_tile", {});
+ window->setProperty("kwin_shadow_right_tile", {});
+ window->setProperty("kwin_shadow_bottom_right_tile", {});
+ window->setProperty("kwin_shadow_bottom_tile", {});
+ window->setProperty("kwin_shadow_bottom_left_tile", {});
+ window->setProperty("kwin_shadow_padding", {});
+ window->setProperty("kwin_shadow_enabled", {});
+}
+
+} // namespace KWin
diff --git a/plugins/windowsystem/windowshadow.h b/plugins/windowsystem/windowshadow.h
new file mode 100644
index 0000000000..2574341f63
--- /dev/null
+++ b/plugins/windowsystem/windowshadow.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Vlad Zahorodnii
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 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 14 of version 3 of the license.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include
+
+namespace KWin
+{
+
+class WindowShadowTile final : public KWindowShadowTilePrivate
+{
+public:
+ bool create() override;
+ void destroy() override;
+};
+
+class WindowShadow final : public KWindowShadowPrivate
+{
+public:
+ bool create() override;
+ void destroy() override;
+};
+
+} // namespace KWin
diff --git a/shadow.cpp b/shadow.cpp
index 5f1175bcd8..745c4bb689 100644
--- a/shadow.cpp
+++ b/shadow.cpp
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2011 Martin Gräßlin
+Copyright (C) 2020 Vlad Zahorodnii
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,6 +24,7 @@ along with this program. If not, see .
#include "abstract_client.h"
#include "composite.h"
#include "effects.h"
+#include "internal_client.h"
#include "toplevel.h"
#include "wayland_server.h"
@@ -33,6 +35,10 @@ along with this program. If not, see .
#include
#include
+#include
+
+Q_DECLARE_METATYPE(QMargins)
+
namespace KWin
{
@@ -60,6 +66,9 @@ Shadow *Shadow::createShadow(Toplevel *toplevel)
if (!shadow && kwinApp()->x11Connection()) {
shadow = createShadowFromX11(toplevel);
}
+ if (!shadow) {
+ shadow = createShadowFromInternalWindow(toplevel);
+ }
if (!shadow) {
return nullptr;
}
@@ -121,6 +130,24 @@ Shadow *Shadow::createShadowFromWayland(Toplevel *toplevel)
return shadow;
}
+Shadow *Shadow::createShadowFromInternalWindow(Toplevel *toplevel)
+{
+ const InternalClient *client = qobject_cast(toplevel);
+ if (!client) {
+ return nullptr;
+ }
+ const QWindow *window = client->internalWindow();
+ if (!window) {
+ return nullptr;
+ }
+ Shadow *shadow = Compositor::self()->scene()->createShadow(toplevel);
+ if (!shadow->init(window)) {
+ delete shadow;
+ return nullptr;
+ }
+ return shadow;
+}
+
QVector< uint32_t > Shadow::readX11ShadowProperty(xcb_window_t id)
{
QVector ret;
@@ -240,6 +267,49 @@ bool Shadow::init(const QPointer< KWayland::Server::ShadowInterface > &shadow)
return true;
}
+bool Shadow::init(const QWindow *window)
+{
+ const bool isEnabled = window->property("kwin_shadow_enabled").toBool();
+ if (!isEnabled) {
+ return false;
+ }
+
+ const QImage leftTile = window->property("kwin_shadow_left_tile").value();
+ const QImage topLeftTile = window->property("kwin_shadow_top_left_tile").value();
+ const QImage topTile = window->property("kwin_shadow_top_tile").value();
+ const QImage topRightTile = window->property("kwin_shadow_top_right_tile").value();
+ const QImage rightTile = window->property("kwin_shadow_right_tile").value();
+ const QImage bottomRightTile = window->property("kwin_shadow_bottom_right_tile").value();
+ const QImage bottomTile = window->property("kwin_shadow_bottom_tile").value();
+ const QImage bottomLeftTile = window->property("kwin_shadow_bottom_left_tile").value();
+
+ m_shadowElements[ShadowElementLeft] = QPixmap::fromImage(leftTile);
+ m_shadowElements[ShadowElementTopLeft] = QPixmap::fromImage(topLeftTile);
+ m_shadowElements[ShadowElementTop] = QPixmap::fromImage(topTile);
+ m_shadowElements[ShadowElementTopRight] = QPixmap::fromImage(topRightTile);
+ m_shadowElements[ShadowElementRight] = QPixmap::fromImage(rightTile);
+ m_shadowElements[ShadowElementBottomRight] = QPixmap::fromImage(bottomRightTile);
+ m_shadowElements[ShadowElementBottom] = QPixmap::fromImage(bottomTile);
+ m_shadowElements[ShadowElementBottomLeft] = QPixmap::fromImage(bottomLeftTile);
+
+ const QMargins padding = window->property("kwin_shadow_padding").value();
+
+ m_leftOffset = padding.left();
+ m_topOffset = padding.top();
+ m_rightOffset = padding.right();
+ m_bottomOffset = padding.bottom();
+
+ updateShadowRegion();
+
+ if (!prepareBackend()) {
+ return false;
+ }
+
+ buildQuads();
+
+ return true;
+}
+
void Shadow::updateShadowRegion()
{
const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset);
@@ -356,6 +426,12 @@ bool Shadow::updateShadow()
}
}
+ if (InternalClient *client = qobject_cast(m_topLevel)) {
+ if (init(client->internalWindow())) {
+ return true;
+ }
+ }
+
auto data = Shadow::readX11ShadowProperty(m_topLevel->window());
if (data.isEmpty()) {
return false;
diff --git a/shadow.h b/shadow.h
index 953f28f687..9214ef760f 100644
--- a/shadow.h
+++ b/shadow.h
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2011 Martin Gräßlin
+Copyright (C) 2020 Vlad Zahorodnii
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -168,10 +169,12 @@ private:
static Shadow *createShadowFromX11(Toplevel *toplevel);
static Shadow *createShadowFromDecoration(Toplevel *toplevel);
static Shadow *createShadowFromWayland(Toplevel *toplevel);
+ static Shadow *createShadowFromInternalWindow(Toplevel *toplevel);
static QVector readX11ShadowProperty(xcb_window_t id);
bool init(const QVector &data);
bool init(KDecoration2::Decoration *decoration);
bool init(const QPointer &shadow);
+ bool init(const QWindow *window);
Toplevel *m_topLevel;
// shadow pixmaps
QPixmap m_shadowElements[ShadowElementsCount];