diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp
index bacdc2030a..a7075f4061 100644
--- a/autotests/integration/internal_window.cpp
+++ b/autotests/integration/internal_window.cpp
@@ -20,6 +20,7 @@ along with this program. If not, see .
#include "kwin_wayland_test.h"
#include "platform.h"
#include "cursor.h"
+#include "effects.h"
#include "shell_client.h"
#include "screens.h"
#include "wayland_server.h"
@@ -32,6 +33,7 @@ along with this program. If not, see .
#include
#include
#include
+#include
#include
@@ -39,6 +41,8 @@ along with this program. If not, see .
using namespace KWayland::Client;
+Q_DECLARE_METATYPE(NET::WindowType);
+
namespace KWin
{
@@ -67,6 +71,11 @@ private Q_SLOTS:
void testModifierScroll();
void testPopup();
void testScale();
+ void testWindowType_data();
+ void testWindowType();
+ void testChangeWindowType_data();
+ void testChangeWindowType();
+ void testEffectWindow();
};
class HelperWindow : public QRasterWindow
@@ -712,6 +721,98 @@ void InternalWindowTest::testScale()
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
}
+void InternalWindowTest::testWindowType_data()
+{
+ QTest::addColumn("windowType");
+
+ QTest::newRow("normal") << NET::Normal;
+ QTest::newRow("desktop") << NET::Desktop;
+ QTest::newRow("Dock") << NET::Dock;
+ QTest::newRow("Toolbar") << NET::Toolbar;
+ QTest::newRow("Menu") << NET::Menu;
+ QTest::newRow("Dialog") << NET::Dialog;
+ QTest::newRow("Utility") << NET::Utility;
+ QTest::newRow("Splash") << NET::Splash;
+ QTest::newRow("DropdownMenu") << NET::DropdownMenu;
+ QTest::newRow("PopupMenu") << NET::PopupMenu;
+ QTest::newRow("Tooltip") << NET::Tooltip;
+ QTest::newRow("Notification") << NET::Notification;
+ QTest::newRow("ComboBox") << NET::ComboBox;
+ QTest::newRow("OnScreenDisplay") << NET::OnScreenDisplay;
+}
+
+void InternalWindowTest::testWindowType()
+{
+ QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QVERIFY(clientAddedSpy.isValid());
+ HelperWindow win;
+ win.setGeometry(0, 0, 100, 100);
+ QFETCH(NET::WindowType, windowType);
+ KWindowSystem::setType(win.winId(), windowType);
+ win.show();
+ QVERIFY(clientAddedSpy.wait());
+ QTRY_COMPARE(clientAddedSpy.count(), 1);
+ auto internalClient = clientAddedSpy.first().first().value();
+ QVERIFY(internalClient);
+ QCOMPARE(internalClient->windowType(), windowType);
+}
+
+void InternalWindowTest::testChangeWindowType_data()
+{
+ QTest::addColumn("windowType");
+
+ QTest::newRow("desktop") << NET::Desktop;
+ QTest::newRow("Dock") << NET::Dock;
+ QTest::newRow("Toolbar") << NET::Toolbar;
+ QTest::newRow("Menu") << NET::Menu;
+ QTest::newRow("Dialog") << NET::Dialog;
+ QTest::newRow("Utility") << NET::Utility;
+ QTest::newRow("Splash") << NET::Splash;
+ QTest::newRow("DropdownMenu") << NET::DropdownMenu;
+ QTest::newRow("PopupMenu") << NET::PopupMenu;
+ QTest::newRow("Tooltip") << NET::Tooltip;
+ QTest::newRow("Notification") << NET::Notification;
+ QTest::newRow("ComboBox") << NET::ComboBox;
+ QTest::newRow("OnScreenDisplay") << NET::OnScreenDisplay;
+}
+
+void InternalWindowTest::testChangeWindowType()
+{
+ QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QVERIFY(clientAddedSpy.isValid());
+ HelperWindow win;
+ win.setGeometry(0, 0, 100, 100);
+ win.show();
+ QVERIFY(clientAddedSpy.wait());
+ QTRY_COMPARE(clientAddedSpy.count(), 1);
+ auto internalClient = clientAddedSpy.first().first().value();
+ QVERIFY(internalClient);
+ QCOMPARE(internalClient->windowType(), NET::Normal);
+
+ QFETCH(NET::WindowType, windowType);
+ KWindowSystem::setType(win.winId(), windowType);
+ QTRY_COMPARE(internalClient->windowType(), windowType);
+
+ KWindowSystem::setType(win.winId(), NET::Normal);
+ QTRY_COMPARE(internalClient->windowType(), NET::Normal);
+}
+
+void InternalWindowTest::testEffectWindow()
+{
+ QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QVERIFY(clientAddedSpy.isValid());
+ HelperWindow win;
+ win.setGeometry(0, 0, 100, 100);
+ win.show();
+ QVERIFY(clientAddedSpy.wait());
+ auto internalClient = clientAddedSpy.first().first().value();
+ QVERIFY(internalClient);
+ QVERIFY(internalClient->effectWindow());
+ QCOMPARE(internalClient->effectWindow()->internalWindow(), &win);
+
+ QCOMPARE(effects->findWindow(&win), internalClient->effectWindow());
+ QCOMPARE(effects->findWindow(&win)->internalWindow(), &win);
+}
}
diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp
index 186d566cb5..6ae4025594 100644
--- a/autotests/integration/shell_client_test.cpp
+++ b/autotests/integration/shell_client_test.cpp
@@ -184,6 +184,9 @@ void TestShellClient::testMapUnmapMap()
QVERIFY(client->property("moveable").toBool());
QVERIFY(client->property("moveableAcrossScreens").toBool());
QVERIFY(client->property("resizeable").toBool());
+ QCOMPARE(client->isInternal(), false);
+ QVERIFY(client->effectWindow());
+ QVERIFY(!client->effectWindow()->internalWindow());
QCOMPARE(client->internalId().isNull(), false);
const auto uuid = client->internalId();
QUuid deletedUuid;
diff --git a/autotests/mock_effectshandler.h b/autotests/mock_effectshandler.h
index bfed418403..3587ce86e0 100644
--- a/autotests/mock_effectshandler.h
+++ b/autotests/mock_effectshandler.h
@@ -134,6 +134,9 @@ public:
KWin::EffectWindow *findWindow(KWayland::Server::SurfaceInterface *) const override {
return nullptr;
}
+ KWin::EffectWindow *findWindow(QWindow *w) const override {
+ return nullptr;
+ }
void *getProxy(QString) override {
return nullptr;
}
diff --git a/autotests/test_window_paint_data.cpp b/autotests/test_window_paint_data.cpp
index 167b6d0a8b..7d78dca763 100644
--- a/autotests/test_window_paint_data.cpp
+++ b/autotests/test_window_paint_data.cpp
@@ -59,6 +59,9 @@ public:
void closeWindow() override;
void referencePreviousWindowPixmap() override {}
void unreferencePreviousWindowPixmap() override {}
+ QWindow *internalWindow() const override {
+ return nullptr;
+ }
bool isDeleted() const override {
return false;
}
diff --git a/effects.cpp b/effects.cpp
index 42a1efa358..3177bbd5f7 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -1086,6 +1086,19 @@ EffectWindow* EffectsHandlerImpl::findWindow(KWayland::Server::SurfaceInterface
return nullptr;
}
+EffectWindow *EffectsHandlerImpl::findWindow(QWindow *w) const
+{
+ if (waylandServer()) {
+ if (auto c = waylandServer()->findClient(w)) {
+ return c->effectWindow();
+ }
+ }
+ if (auto u = Workspace::self()->findUnmanaged(w->winId())) {
+ return u->effectWindow();
+ }
+ return nullptr;
+}
+
EffectWindowList EffectsHandlerImpl::stackingOrder() const
{
@@ -1936,6 +1949,15 @@ EffectWindow* EffectWindowImpl::findModal()
return nullptr;
}
+QWindow *EffectWindowImpl::internalWindow() const
+{
+ auto client = qobject_cast(toplevel);
+ if (!client) {
+ return nullptr;
+ }
+ return client->internalWindow();
+}
+
template
EffectWindowList getMainWindows(T *c)
{
diff --git a/effects.h b/effects.h
index 17db6c0205..92faaa1bef 100644
--- a/effects.h
+++ b/effects.h
@@ -134,6 +134,7 @@ public:
void stopMousePolling() override;
EffectWindow* findWindow(WId id) const override;
EffectWindow* findWindow(KWayland::Server::SurfaceInterface *surf) const override;
+ EffectWindow *findWindow(QWindow *w) const override;
EffectWindowList stackingOrder() const override;
void setElevatedWindow(KWin::EffectWindow* w, bool set) override;
@@ -474,6 +475,8 @@ public:
void referencePreviousWindowPixmap() override;
void unreferencePreviousWindowPixmap() override;
+ QWindow *internalWindow() const override;
+
const Toplevel* window() const;
Toplevel* window();
diff --git a/effects/backgroundcontrast/contrast.cpp b/effects/backgroundcontrast/contrast.cpp
index a6fbfa57df..71276e8d6c 100644
--- a/effects/backgroundcontrast/contrast.cpp
+++ b/effects/backgroundcontrast/contrast.cpp
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
@@ -140,6 +141,27 @@ void ContrastEffect::updateContrastRegion(EffectWindow *w)
m_colorMatrices[w] = colorMatrix(surf->contrast()->contrast(), surf->contrast()->intensity(), surf->contrast()->saturation());
}
+ if (auto internal = w->internalWindow()) {
+ const auto property = internal->property("kwin_background_region");
+ if (property.isValid()) {
+ region = property.value();
+ bool ok = false;
+ qreal contrast = internal->property("kwin_background_contrast").toReal(&ok);
+ if (!ok) {
+ contrast = 1.0;
+ }
+ qreal intensity = internal->property("kwin_background_intensity").toReal(&ok);
+ if (!ok) {
+ intensity = 1.0;
+ }
+ qreal saturation = internal->property("kwin_background_saturation").toReal(&ok);
+ if (!ok) {
+ saturation = 1.0;
+ }
+ m_colorMatrices[w] = colorMatrix(contrast, intensity, saturation);
+ }
+ }
+
//!value.isNull() full window in X11 case, surf->contrast()
//valid, full window in wayland case
if (region.isEmpty() && (!value.isNull() || (surf && surf->contrast()))) {
@@ -163,9 +185,31 @@ void ContrastEffect::slotWindowAdded(EffectWindow *w)
}
});
}
+
+ if (auto internal = w->internalWindow()) {
+ internal->installEventFilter(this);
+ }
+
updateContrastRegion(w);
}
+bool ContrastEffect::eventFilter(QObject *watched, QEvent *event)
+{
+ auto internal = qobject_cast(watched);
+ if (internal && event->type() == QEvent::DynamicPropertyChange) {
+ QDynamicPropertyChangeEvent *pe = static_cast(event);
+ if (pe->propertyName() == "kwin_background_region" ||
+ pe->propertyName() == "kwin_background_contrast" ||
+ pe->propertyName() == "kwin_background_intensity" ||
+ pe->propertyName() == "kwin_background_saturation") {
+ if (auto w = effects->findWindow(internal)) {
+ updateContrastRegion(w);
+ }
+ }
+ }
+ return false;
+}
+
void ContrastEffect::slotWindowDeleted(EffectWindow *w)
{
if (m_contrastChangedConnections.contains(w)) {
diff --git a/effects/backgroundcontrast/contrast.h b/effects/backgroundcontrast/contrast.h
index f847827b76..3785c81c43 100644
--- a/effects/backgroundcontrast/contrast.h
+++ b/effects/backgroundcontrast/contrast.h
@@ -64,6 +64,8 @@ public:
return 76;
}
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
public Q_SLOTS:
void slotWindowAdded(KWin::EffectWindow *w);
void slotWindowDeleted(KWin::EffectWindow *w);
diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp
index c0e771dc05..76f4d4e2c0 100644
--- a/effects/blur/blur.cpp
+++ b/effects/blur/blur.cpp
@@ -29,6 +29,7 @@
#include
#include // for QGuiApplication
#include
+#include
#include // for ceil()
#include
@@ -272,6 +273,13 @@ void BlurEffect::updateBlurRegion(EffectWindow *w) const
region = surf->blur()->region();
}
+ if (auto internal = w->internalWindow()) {
+ const auto property = internal->property("kwin_blur");
+ if (property.isValid()) {
+ region = property.value();
+ }
+ }
+
//!value.isNull() full window in X11 case, surf->blur()
//valid, full window in wayland case
if (region.isEmpty() && (!value.isNull() || (surf && surf->blur()))) {
@@ -294,6 +302,9 @@ void BlurEffect::slotWindowAdded(EffectWindow *w)
}
});
}
+ if (auto internal = w->internalWindow()) {
+ internal->installEventFilter(this);
+ }
updateBlurRegion(w);
}
@@ -315,6 +326,20 @@ void BlurEffect::slotPropertyNotify(EffectWindow *w, long atom)
}
}
+bool BlurEffect::eventFilter(QObject *watched, QEvent *event)
+{
+ auto internal = qobject_cast(watched);
+ if (internal && event->type() == QEvent::DynamicPropertyChange) {
+ QDynamicPropertyChangeEvent *pe = static_cast(event);
+ if (pe->propertyName() == "kwin_blur") {
+ if (auto w = effects->findWindow(internal)) {
+ updateBlurRegion(w);
+ }
+ }
+ }
+ return false;
+}
+
bool BlurEffect::enabledByDefault()
{
GLPlatform *gl = GLPlatform::instance();
diff --git a/effects/blur/blur.h b/effects/blur/blur.h
index b34964aa11..15c99fd4e4 100644
--- a/effects/blur/blur.h
+++ b/effects/blur/blur.h
@@ -67,6 +67,8 @@ public:
return 75;
}
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
public Q_SLOTS:
void slotWindowAdded(KWin::EffectWindow *w);
void slotWindowDeleted(KWin::EffectWindow *w);
diff --git a/effects/slidingpopups/slidingpopups.cpp b/effects/slidingpopups/slidingpopups.cpp
index 6231d16e34..503b8cddd3 100644
--- a/effects/slidingpopups/slidingpopups.cpp
+++ b/effects/slidingpopups/slidingpopups.cpp
@@ -24,11 +24,16 @@ along with this program. If not, see .
#include
#include
+#include
#include
#include
#include
+#include
+
+Q_DECLARE_METATYPE(KWindowEffects::SlideFromLocation)
+
namespace KWin
{
@@ -200,6 +205,11 @@ void SlidingPopupsEffect::slotWindowAdded(EffectWindow *w)
});
}
+ if (auto internal = w->internalWindow()) {
+ internal->installEventFilter(this);
+ setupInternalWindowSlide(w);
+ }
+
slideIn(w);
}
@@ -377,6 +387,62 @@ void SlidingPopupsEffect::slotWaylandSlideOnShowChanged(EffectWindow* w)
}
}
+void SlidingPopupsEffect::setupInternalWindowSlide(EffectWindow *w)
+{
+ if (!w) {
+ return;
+ }
+ auto internal = w->internalWindow();
+ if (!internal) {
+ return;
+ }
+ const QVariant slideProperty = internal->property("kwin_slide");
+ if (!slideProperty.isValid()) {
+ return;
+ }
+ AnimationData &animData = m_animationsData[w];
+ switch (slideProperty.value()) {
+ case KWindowEffects::BottomEdge:
+ animData.location = Location::Bottom;
+ break;
+ case KWindowEffects::TopEdge:
+ animData.location = Location::Top;
+ break;
+ case KWindowEffects::RightEdge:
+ animData.location = Location::Right;
+ break;
+ case KWindowEffects::LeftEdge:
+ animData.location = Location::Left;
+ break;
+ default:
+ return;
+ }
+ bool intOk = false;
+ animData.offset = internal->property("kwin_slide_offset").toInt(&intOk);
+ if (!intOk) {
+ animData.offset = -1;
+ }
+ animData.slideLength = 0;
+ animData.slideInDuration = m_slideInDuration;
+ animData.slideOutDuration = m_slideOutDuration;
+
+ setupAnimData(w);
+}
+
+bool SlidingPopupsEffect::eventFilter(QObject *watched, QEvent *event)
+{
+ auto internal = qobject_cast(watched);
+ if (internal && event->type() == QEvent::DynamicPropertyChange) {
+ QDynamicPropertyChangeEvent *pe = static_cast(event);
+ if (pe->propertyName() == "kwin_slide" || pe->propertyName() == "kwin_slide_offset") {
+ if (auto w = effects->findWindow(internal)) {
+ setupInternalWindowSlide(w);
+ }
+ }
+ }
+ return false;
+}
+
void SlidingPopupsEffect::slideIn(EffectWindow *w)
{
if (effects->activeFullScreenEffect()) {
diff --git a/effects/slidingpopups/slidingpopups.h b/effects/slidingpopups/slidingpopups.h
index 32e8fb5761..3008d23283 100644
--- a/effects/slidingpopups/slidingpopups.h
+++ b/effects/slidingpopups/slidingpopups.h
@@ -53,6 +53,8 @@ public:
int slideInDuration() const;
int slideOutDuration() const;
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
private Q_SLOTS:
void slotWindowAdded(EffectWindow *w);
void slotWindowDeleted(EffectWindow *w);
@@ -65,6 +67,7 @@ private Q_SLOTS:
private:
void setupAnimData(EffectWindow *w);
+ void setupInternalWindowSlide(EffectWindow *w);
long m_atom;
diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h
index 1713c2bd0e..1ca8da379c 100644
--- a/libkwineffects/kwineffects.h
+++ b/libkwineffects/kwineffects.h
@@ -1078,6 +1078,16 @@ public:
Q_SCRIPTABLE virtual KWin::EffectWindow* findWindow(WId id) const = 0;
Q_SCRIPTABLE virtual KWin::EffectWindow* findWindow(KWayland::Server::SurfaceInterface *surf) const = 0;
+ /**
+ * Finds the EffectWindow for the internal window @p w.
+ * If there is no such window @c null is returned.
+ *
+ * On Wayland this returns the internal window. On X11 it returns an Unamanged with the
+ * window id matching that of the provided window @p w.
+ *
+ * @since 5.16
+ **/
+ Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(QWindow *w) const = 0;
virtual EffectWindowList stackingOrder() const = 0;
// window will be temporarily painted as if being at the top of the stack
Q_SCRIPTABLE virtual void setElevatedWindow(KWin::EffectWindow* w, bool set) = 0;
@@ -2041,6 +2051,14 @@ class KWINEFFECTS_EXPORT EffectWindow : public QObject
**/
Q_PROPERTY(bool popupWindow READ isPopupWindow CONSTANT)
+ /**
+ * KWin internal window. Specific to Wayland platform.
+ *
+ * If the EffectWindow does not reference an internal window, this property is @c null.
+ * @since 5.16
+ **/
+ Q_PROPERTY(QWindow *internalWindow READ internalWindow CONSTANT)
+
public:
/** Flags explaining why painting should be disabled */
enum {
@@ -2324,6 +2342,11 @@ public:
**/
virtual bool isPopupWindow() const = 0;
+ /**
+ * @since 5.16
+ **/
+ virtual QWindow *internalWindow() const = 0;
+
/**
* Can be used to by effects to store arbitrary data in the EffectWindow.
*
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index da3eed351a..98b66cb35a 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -3,6 +3,7 @@ add_subdirectory(qpa)
add_subdirectory(idletime)
add_subdirectory(platforms)
add_subdirectory(scenes)
+add_subdirectory(windowsystem)
if(KWIN_BUILD_DECORATIONS)
add_subdirectory(kdecorations)
diff --git a/plugins/windowsystem/CMakeLists.txt b/plugins/windowsystem/CMakeLists.txt
new file mode 100644
index 0000000000..48474c3252
--- /dev/null
+++ b/plugins/windowsystem/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(kwindowsystem_plugin_SRCS
+ plugin.cpp
+ windoweffects.cpp
+ windowsystem.cpp
+)
+
+
+add_library(KF5WindowSystemKWinPrivatePlugin MODULE ${kwindowsystem_plugin_SRCS})
+set_target_properties(KF5WindowSystemKWinPrivatePlugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/org.kde.kwindowsystem.platforms/")
+target_link_libraries(KF5WindowSystemKWinPrivatePlugin
+ kwin
+)
+
+install(
+ TARGETS
+ KF5WindowSystemKWinPrivatePlugin
+ DESTINATION
+ ${PLUGIN_INSTALL_DIR}/kf5/org.kde.kwindowsystem.platforms/
+)
diff --git a/plugins/windowsystem/kwindowsystem.json b/plugins/windowsystem/kwindowsystem.json
new file mode 100644
index 0000000000..aaf6fd00dd
--- /dev/null
+++ b/plugins/windowsystem/kwindowsystem.json
@@ -0,0 +1,3 @@
+{
+ "platforms": ["wayland-org.kde.kwin.qpa"]
+}
diff --git a/plugins/windowsystem/plugin.cpp b/plugins/windowsystem/plugin.cpp
new file mode 100644
index 0000000000..e374ee1a76
--- /dev/null
+++ b/plugins/windowsystem/plugin.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019 Martin Flöser
+ *
+ * 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 "plugin.h"
+#include "windowsystem.h"
+#include "windoweffects.h"
+
+KWindowSystemKWinPlugin::KWindowSystemKWinPlugin(QObject *parent)
+ : KWindowSystemPluginInterface(parent)
+{
+}
+
+KWindowSystemKWinPlugin::~KWindowSystemKWinPlugin()
+{
+}
+
+KWindowEffectsPrivate *KWindowSystemKWinPlugin::createEffects()
+{
+ return new KWin::WindowEffects();
+}
+
+KWindowSystemPrivate *KWindowSystemKWinPlugin::createWindowSystem()
+{
+ return new KWin::WindowSystem();
+}
diff --git a/plugins/windowsystem/plugin.h b/plugins/windowsystem/plugin.h
new file mode 100644
index 0000000000..c1de4950cd
--- /dev/null
+++ b/plugins/windowsystem/plugin.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Martin Flöser
+ *
+ * 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
+
+class KWindowSystemKWinPlugin : public KWindowSystemPluginInterface
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.kde.kwindowsystem.KWindowSystemPluginInterface" FILE "kwindowsystem.json")
+ Q_INTERFACES(KWindowSystemPluginInterface)
+
+public:
+ explicit KWindowSystemKWinPlugin(QObject *parent = nullptr);
+ ~KWindowSystemKWinPlugin() override;
+
+ KWindowEffectsPrivate *createEffects() override;
+ KWindowSystemPrivate *createWindowSystem() override;
+};
diff --git a/plugins/windowsystem/windoweffects.cpp b/plugins/windowsystem/windoweffects.cpp
new file mode 100644
index 0000000000..eb90f6ee20
--- /dev/null
+++ b/plugins/windowsystem/windoweffects.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2019 Martin Flöser
+ *
+ * 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 "windoweffects.h"
+#include "effect_builtins.h"
+#include "../../effects.h"
+
+#include
+#include
+#include
+
+Q_DECLARE_METATYPE(KWindowEffects::SlideFromLocation)
+
+namespace KWin
+{
+
+WindowEffects::WindowEffects()
+ : QObject(),
+ KWindowEffectsPrivate()
+{
+}
+
+WindowEffects::~WindowEffects()
+{}
+
+namespace
+{
+QWindow *findWindow(WId win)
+{
+ const auto windows = qApp->allWindows();
+ auto it = std::find_if(windows.begin(), windows.end(), [win] (QWindow *w) { return w->winId() == win; });
+ if (it == windows.end()) {
+ return nullptr;
+ }
+ return *it;
+}
+}
+
+bool WindowEffects::isEffectAvailable(KWindowEffects::Effect effect)
+{
+ if (!effects) {
+ return false;
+ }
+ auto e = static_cast(effects);
+ switch (effect) {
+ case KWindowEffects::BackgroundContrast:
+ return e->isEffectLoaded(BuiltInEffects::nameForEffect(BuiltInEffect::Contrast));
+ case KWindowEffects::BlurBehind:
+ return e->isEffectLoaded(BuiltInEffects::nameForEffect(BuiltInEffect::Blur));
+ case KWindowEffects::Slide:
+ return e->isEffectLoaded(BuiltInEffects::nameForEffect(BuiltInEffect::SlidingPopups));
+ default:
+ // plugin does not provide integration for other effects
+ return false;
+ }
+}
+
+void WindowEffects::slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset)
+{
+ auto w = findWindow(id);
+ if (!w) {
+ return;
+ }
+ w->setProperty("kwin_slide", QVariant::fromValue(location));
+ w->setProperty("kwin_slide_offset", offset);
+}
+
+void WindowEffects::slideWindow(QWidget *widget, KWindowEffects::SlideFromLocation location)
+{
+ slideWindow(widget->winId(), location, 0);
+}
+
+QList WindowEffects::windowSizes(const QList &ids)
+{
+ Q_UNUSED(ids)
+ return {};
+}
+
+void WindowEffects::presentWindows(WId controller, const QList &ids)
+{
+ Q_UNUSED(controller)
+ Q_UNUSED(ids)
+}
+
+void WindowEffects::presentWindows(WId controller, int desktop)
+{
+ Q_UNUSED(controller)
+ Q_UNUSED(desktop)
+}
+
+void WindowEffects::highlightWindows(WId controller, const QList &ids)
+{
+ Q_UNUSED(controller)
+ Q_UNUSED(ids)
+}
+
+void WindowEffects::enableBlurBehind(WId window, bool enable, const QRegion ®ion)
+{
+ auto w = findWindow(window);
+ if (!w) {
+ return;
+ }
+ if (enable) {
+ w->setProperty("kwin_blur", region);
+ } else {
+ w->setProperty("kwin_blur", {});
+ }
+}
+
+void WindowEffects::enableBackgroundContrast(WId window, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion ®ion)
+{
+ auto w = findWindow(window);
+ if (!w) {
+ return;
+ }
+ if (enable) {
+ w->setProperty("kwin_background_region", region);
+ w->setProperty("kwin_background_contrast", contrast);
+ w->setProperty("kwin_background_intensity", intensity);
+ w->setProperty("kwin_background_saturation", saturation);
+ } else {
+ w->setProperty("kwin_background_region", {});
+ w->setProperty("kwin_background_contrast", {});
+ w->setProperty("kwin_background_intensity", {});
+ w->setProperty("kwin_background_saturation", {});
+ }
+}
+
+void WindowEffects::markAsDashboard(WId window)
+{
+ Q_UNUSED(window)
+}
+
+}
diff --git a/plugins/windowsystem/windoweffects.h b/plugins/windowsystem/windoweffects.h
new file mode 100644
index 0000000000..9f025dd87b
--- /dev/null
+++ b/plugins/windowsystem/windoweffects.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 Martin Flöser
+ *
+ * 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 WindowEffects : public QObject, public KWindowEffectsPrivate
+{
+public:
+ WindowEffects();
+ ~WindowEffects() override;
+
+ bool isEffectAvailable(KWindowEffects::Effect effect) override;
+ void slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset) override;
+ void slideWindow(QWidget *widget, KWindowEffects::SlideFromLocation location) override;
+ QList windowSizes(const QList &ids) override;
+ void presentWindows(WId controller, const QList &ids) override;
+ void presentWindows(WId controller, int desktop = NET::OnAllDesktops) override;
+ void highlightWindows(WId controller, const QList &ids) override;
+ void enableBlurBehind(WId window, bool enable = true, const QRegion ®ion = QRegion()) override;
+ void enableBackgroundContrast(WId window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion ®ion = QRegion()) override;
+ void markAsDashboard(WId window) override;
+};
+
+}
diff --git a/plugins/windowsystem/windowsystem.cpp b/plugins/windowsystem/windowsystem.cpp
new file mode 100644
index 0000000000..df4c55388c
--- /dev/null
+++ b/plugins/windowsystem/windowsystem.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2019 Martin Flöser
+ *
+ * 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 "windowsystem.h"
+
+#include
+
+#include
+#include
+
+Q_DECLARE_METATYPE(NET::WindowType)
+
+namespace KWin
+{
+
+WindowSystem::WindowSystem()
+ : QObject()
+ , KWindowSystemPrivate()
+{
+}
+
+void WindowSystem::activateWindow(WId win, long int time)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(time)
+ // KWin cannot activate own windows
+}
+
+void WindowSystem::forceActiveWindow(WId win, long int time)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(time)
+ // KWin cannot activate own windows
+}
+
+WId WindowSystem::activeWindow()
+{
+ // KWin internal should not use KWindowSystem to find active window
+ return 0;
+}
+
+bool WindowSystem::allowedActionsSupported()
+{
+ return false;
+}
+
+void WindowSystem::allowExternalProcessWindowActivation(int pid)
+{
+ Q_UNUSED(pid)
+}
+
+bool WindowSystem::compositingActive()
+{
+ // wayland is always composited
+ return true;
+}
+
+void WindowSystem::connectNotify(const QMetaMethod &signal)
+{
+ Q_UNUSED(signal)
+}
+
+QPoint WindowSystem::constrainViewportRelativePosition(const QPoint &pos)
+{
+ Q_UNUSED(pos)
+ return QPoint();
+}
+
+int WindowSystem::currentDesktop()
+{
+ // KWin internal should not use KWindowSystem to find current desktop
+ return 0;
+}
+
+void WindowSystem::demandAttention(WId win, bool set)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(set)
+}
+
+QString WindowSystem::desktopName(int desktop)
+{
+ Q_UNUSED(desktop)
+ return QString();
+}
+
+QPoint WindowSystem::desktopToViewport(int desktop, bool absolute)
+{
+ Q_UNUSED(desktop)
+ Q_UNUSED(absolute)
+ return QPoint();
+}
+
+#ifndef KWINDOWSYSTEM_NO_DEPRECATED
+WId WindowSystem::groupLeader(WId window)
+{
+ Q_UNUSED(window)
+ return 0;
+}
+#endif
+
+bool WindowSystem::icccmCompliantMappingState()
+{
+ return false;
+}
+
+QPixmap WindowSystem::icon(WId win, int width, int height, bool scale, int flags)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(width)
+ Q_UNUSED(height)
+ Q_UNUSED(scale)
+ Q_UNUSED(flags)
+ return QPixmap();
+}
+
+void WindowSystem::lowerWindow(WId win)
+{
+ Q_UNUSED(win)
+}
+
+bool WindowSystem::mapViewport()
+{
+ return false;
+}
+
+void WindowSystem::minimizeWindow(WId win)
+{
+ Q_UNUSED(win)
+}
+
+void WindowSystem::unminimizeWindow(WId win)
+{
+ Q_UNUSED(win)
+}
+
+int WindowSystem::numberOfDesktops()
+{
+ // KWin internal should not use KWindowSystem to find number of desktops
+ return 1;
+}
+
+void WindowSystem::raiseWindow(WId win)
+{
+ Q_UNUSED(win)
+}
+
+QString WindowSystem::readNameProperty(WId window, long unsigned int atom)
+{
+ Q_UNUSED(window)
+ Q_UNUSED(atom)
+ return QString();
+}
+
+void WindowSystem::setBlockingCompositing(WId window, bool active)
+{
+ Q_UNUSED(window)
+ Q_UNUSED(active)
+}
+
+void WindowSystem::setCurrentDesktop(int desktop)
+{
+ Q_UNUSED(desktop)
+ // KWin internal should not use KWindowSystem to set current desktop
+}
+
+void WindowSystem::setDesktopName(int desktop, const QString &name)
+{
+ Q_UNUSED(desktop)
+ Q_UNUSED(name)
+ // KWin internal should not use KWindowSystem to set desktop name
+}
+
+void WindowSystem::setExtendedStrut(WId win, int left_width, int left_start, int left_end, int right_width, int right_start, int right_end, int top_width, int top_start, int top_end, int bottom_width, int bottom_start, int bottom_end)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(left_width)
+ Q_UNUSED(left_start)
+ Q_UNUSED(left_end)
+ Q_UNUSED(right_width)
+ Q_UNUSED(right_start)
+ Q_UNUSED(right_end)
+ Q_UNUSED(top_width)
+ Q_UNUSED(top_start)
+ Q_UNUSED(top_end)
+ Q_UNUSED(bottom_width)
+ Q_UNUSED(bottom_start)
+ Q_UNUSED(bottom_end)
+}
+
+void WindowSystem::setStrut(WId win, int left, int right, int top, int bottom)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(left)
+ Q_UNUSED(right)
+ Q_UNUSED(top)
+ Q_UNUSED(bottom)
+}
+
+void WindowSystem::setIcons(WId win, const QPixmap &icon, const QPixmap &miniIcon)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(icon)
+ Q_UNUSED(miniIcon)
+}
+
+void WindowSystem::setOnActivities(WId win, const QStringList &activities)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(activities)
+}
+
+void WindowSystem::setOnAllDesktops(WId win, bool b)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(b)
+}
+
+void WindowSystem::setOnDesktop(WId win, int desktop)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(desktop)
+}
+
+void WindowSystem::setShowingDesktop(bool showing)
+{
+ Q_UNUSED(showing)
+ // KWin should not use KWindowSystem to set showing desktop state
+}
+
+void WindowSystem::clearState(WId win, NET::States state)
+{
+ // KWin's windows don't support state
+ Q_UNUSED(win)
+ Q_UNUSED(state)
+}
+
+void WindowSystem::setState(WId win, NET::States state)
+{
+ // KWin's windows don't support state
+ Q_UNUSED(win)
+ Q_UNUSED(state)
+}
+
+void WindowSystem::setType(WId win, NET::WindowType windowType)
+{
+ const auto windows = qApp->allWindows();
+ auto it = std::find_if(windows.begin(), windows.end(), [win] (QWindow *w) { return w->winId() == win; });
+ if (it == windows.end()) {
+ return;
+ }
+
+ (*it)->setProperty("kwin_windowType", QVariant::fromValue(windowType));
+}
+
+void WindowSystem::setUserTime(WId win, long int time)
+{
+ Q_UNUSED(win)
+ Q_UNUSED(time)
+}
+
+bool WindowSystem::showingDesktop()
+{
+ // KWin should not use KWindowSystem for showing desktop state
+ return false;
+}
+
+QList< WId > WindowSystem::stackingOrder()
+{
+ // KWin should not use KWindowSystem for stacking order
+ return {};
+}
+
+#ifndef KWINDOWSYSTEM_NO_DEPRECATED
+WId WindowSystem::transientFor(WId window)
+{
+ Q_UNUSED(window)
+ return 0;
+}
+#endif
+
+int WindowSystem::viewportToDesktop(const QPoint &pos)
+{
+ Q_UNUSED(pos)
+ return 0;
+}
+
+int WindowSystem::viewportWindowToDesktop(const QRect &r)
+{
+ Q_UNUSED(r)
+ return 0;
+}
+
+QList< WId > WindowSystem::windows()
+{
+ return {};
+}
+
+QRect WindowSystem::workArea(const QList< WId > &excludes, int desktop)
+{
+ Q_UNUSED(excludes)
+ Q_UNUSED(desktop)
+ return {};
+}
+
+QRect WindowSystem::workArea(int desktop)
+{
+ Q_UNUSED(desktop)
+ return {};
+}
+
+}
diff --git a/plugins/windowsystem/windowsystem.h b/plugins/windowsystem/windowsystem.h
new file mode 100644
index 0000000000..f2abf5c437
--- /dev/null
+++ b/plugins/windowsystem/windowsystem.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019 Martin Flöser
+ *
+ * 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
+
+#include
+
+namespace KWin
+{
+
+class WindowSystem : public QObject, public KWindowSystemPrivate
+{
+ Q_OBJECT
+public:
+ WindowSystem();
+ QList windows() override;
+ QList stackingOrder() override;
+ WId activeWindow() override;
+ void activateWindow(WId win, long time) override;
+ void forceActiveWindow(WId win, long time) override;
+ void demandAttention(WId win, bool set) override;
+ bool compositingActive() override;
+ int currentDesktop() override;
+ int numberOfDesktops() override;
+ void setCurrentDesktop(int desktop) override;
+ void setOnAllDesktops(WId win, bool b) override;
+ void setOnDesktop(WId win, int desktop) override;
+ void setOnActivities(WId win, const QStringList &activities) override;
+#ifndef KWINDOWSYSTEM_NO_DEPRECATED
+ WId transientFor(WId window) override;
+ WId groupLeader(WId window) override;
+#endif
+ QPixmap icon(WId win, int width, int height, bool scale, int flags) override;
+ void setIcons(WId win, const QPixmap &icon, const QPixmap &miniIcon) override;
+ void setType(WId win, NET::WindowType windowType) override;
+ void setState(WId win, NET::States state) override;
+ void clearState(WId win, NET::States state) override;
+ void minimizeWindow(WId win) override;
+ void unminimizeWindow(WId win) override;
+ void raiseWindow(WId win) override;
+ void lowerWindow(WId win) override;
+ bool icccmCompliantMappingState() override;
+ QRect workArea(int desktop) override;
+ QRect workArea(const QList &excludes, int desktop) override;
+ QString desktopName(int desktop) override;
+ void setDesktopName(int desktop, const QString &name) override;
+ bool showingDesktop() override;
+ void setShowingDesktop(bool showing) override;
+ void setUserTime(WId win, long time) override;
+ void setExtendedStrut(WId win, int left_width, int left_start, int left_end,
+ int right_width, int right_start, int right_end, int top_width, int top_start, int top_end,
+ int bottom_width, int bottom_start, int bottom_end) override;
+ void setStrut(WId win, int left, int right, int top, int bottom) override;
+ bool allowedActionsSupported() override;
+ QString readNameProperty(WId window, unsigned long atom) override;
+ void allowExternalProcessWindowActivation(int pid) override;
+ void setBlockingCompositing(WId window, bool active) override;
+ bool mapViewport() override;
+ int viewportToDesktop(const QPoint &pos) override;
+ int viewportWindowToDesktop(const QRect &r) override;
+ QPoint desktopToViewport(int desktop, bool absolute) override;
+ QPoint constrainViewportRelativePosition(const QPoint &pos) override;
+
+ void connectNotify(const QMetaMethod &signal) override;
+};
+
+}
diff --git a/shell_client.cpp b/shell_client.cpp
index 810aa2fc71..e336ac5e9e 100644
--- a/shell_client.cpp
+++ b/shell_client.cpp
@@ -60,6 +60,8 @@ along with this program. If not, see .
#include
#include
+Q_DECLARE_METATYPE(NET::WindowType)
+
using namespace KWayland::Server;
static const QByteArray s_skipClosePropertyName = QByteArrayLiteral("KWIN_SKIP_CLOSE_ANIMATION");
@@ -1143,11 +1145,9 @@ void ShellClient::findInternalWindow()
connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; });
connect(m_internalWindow, &QWindow::opacityChanged, this, &ShellClient::setOpacity);
- // Try reading the window type from the QWindow. PlasmaCore.Dialog provides a dynamic type property
- // let's check whether it exists, if it does it's our window type
- const QVariant windowType = m_internalWindow->property("type");
+ const QVariant windowType = m_internalWindow->property("kwin_windowType");
if (!windowType.isNull()) {
- m_windowType = static_cast(windowType.toInt());
+ m_windowType = windowType.value();
}
setOpacity(m_internalWindow->opacity());
@@ -1505,6 +1505,10 @@ bool ShellClient::eventFilter(QObject *watched, QEvent *event)
if (pe->propertyName() == s_skipClosePropertyName) {
setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool());
}
+ if (pe->propertyName() == "kwin_windowType") {
+ m_windowType = m_internalWindow->property("kwin_windowType").value();
+ workspace()->updateClientArea();
+ }
}
return false;
}