From 15b47ce7fce5c5ec9639ad763f26db1898b16dac Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 15 Nov 2023 11:51:56 +0200 Subject: [PATCH] Merge EffectsHandlerImpl and EffectsHandler --- .../dont_crash_cancel_animation.cpp | 4 +- .../dont_crash_reinitialize_compositor.cpp | 20 +- .../desktop_switching_animation_test.cpp | 20 +- .../effects/maximize_animation_test.cpp | 20 +- .../effects/minimize_animation_test.cpp | 20 +- .../popup_open_close_animation_test.cpp | 45 +- .../effects/scripted_effects_test.cpp | 11 +- .../effects/slidingpopups_test.cpp | 29 +- .../toplevel_open_close_animation_test.cpp | 32 +- .../integration/effects/translucency_test.cpp | 19 +- .../integration/effects/wobbly_shade_test.cpp | 12 +- autotests/integration/inputmethod_test.cpp | 1 - autotests/integration/internal_window.cpp | 2 +- autotests/integration/kwin_wayland_test.cpp | 4 +- .../integration/move_resize_window_test.cpp | 1 - autotests/integration/x11_window_test.cpp | 1 - autotests/integration/xdgshellwindow_test.cpp | 1 - src/CMakeLists.txt | 3 +- .../x11/standalone/x11_standalone_backend.cpp | 2 +- .../x11/standalone/x11_standalone_effects.cpp | 22 +- .../x11/standalone/x11_standalone_effects.h | 8 +- ...e_effects_keyboard_interception_filter.cpp | 2 +- ...one_effects_keyboard_interception_filter.h | 6 +- ...lone_effects_mouse_interception_filter.cpp | 5 +- ...dalone_effects_mouse_interception_filter.h | 6 +- src/effectloader.h | 2 +- src/effects.cpp | 1593 ----------------- src/effects.h | 324 ---- src/events.cpp | 17 +- src/input.cpp | 27 +- src/layers.cpp | 4 +- src/libkwineffects/kwineffects.cpp | 1559 +++++++++++++++- src/libkwineffects/kwineffects.h | 355 ++-- src/main.cpp | 4 +- src/main_wayland.cpp | 4 +- src/main_x11.cpp | 6 +- src/plugins/screencast/screencastmanager.cpp | 1 - src/plugins/windowsystem/windoweffects.cpp | 9 +- src/pointer_input.cpp | 3 +- src/scene/workspacescene.cpp | 7 +- src/scene/workspacescene.h | 2 +- src/screenedge.cpp | 2 +- src/scripting/gesturehandler.cpp | 2 +- src/scripting/windowthumbnailitem.cpp | 1 - src/scripting/workspace_wrapper.cpp | 4 +- src/tabbox/tabbox.cpp | 8 +- src/tabbox/x11_filter.cpp | 4 +- src/useractions.cpp | 1 - src/window_property_notify_x11_filter.cpp | 4 +- src/window_property_notify_x11_filter.h | 6 +- src/workspace.cpp | 8 +- src/x11window.cpp | 4 +- src/xdgactivationv1.cpp | 2 +- 53 files changed, 1975 insertions(+), 2284 deletions(-) delete mode 100644 src/effects.cpp delete mode 100644 src/effects.h diff --git a/autotests/integration/dont_crash_cancel_animation.cpp b/autotests/integration/dont_crash_cancel_animation.cpp index 65fe229531..636daec233 100644 --- a/autotests/integration/dont_crash_cancel_animation.cpp +++ b/autotests/integration/dont_crash_cancel_animation.cpp @@ -10,7 +10,7 @@ #include "compositor.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "scripting/scriptedeffect.h" #include "wayland_server.h" #include "window.h" @@ -80,7 +80,7 @@ void DontCrashCancelAnimationFromAnimationEndedTest::testScript() QVERIFY(QMetaObject::invokeMethod(*it, "effectLoaded", Q_ARG(KWin::Effect *, effect), Q_ARG(QString, QStringLiteral("crashy")))); break; } - QVERIFY(static_cast(effects)->isEffectLoaded(QStringLiteral("crashy"))); + QVERIFY(effects->isEffectLoaded(QStringLiteral("crashy"))); // create a window std::unique_ptr surface{Test::createSurface()}; diff --git a/autotests/integration/dont_crash_reinitialize_compositor.cpp b/autotests/integration/dont_crash_reinitialize_compositor.cpp index 12f55d3374..9c460c9541 100644 --- a/autotests/integration/dont_crash_reinitialize_compositor.cpp +++ b/autotests/integration/dont_crash_reinitialize_compositor.cpp @@ -12,7 +12,7 @@ #include "compositor.h" #include "core/output.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "wayland_server.h" #include "window.h" #include "workspace.h" @@ -81,10 +81,8 @@ void DontCrashReinitializeCompositorTest::init() void DontCrashReinitializeCompositorTest::cleanup() { // Unload all effects. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); Test::destroyWaylandConnection(); } @@ -104,10 +102,6 @@ void DontCrashReinitializeCompositorTest::testReinitializeCompositor() // have been changed while a scripted effect animates the disappearing of // a window. - // Make sure that we have the right effects ptr. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - // Create the test window. std::unique_ptr surface(Test::createSurface()); QVERIFY(surface != nullptr); @@ -118,10 +112,10 @@ void DontCrashReinitializeCompositorTest::testReinitializeCompositor() // Make sure that only the test effect is loaded. QFETCH(QString, effectName); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); diff --git a/autotests/integration/effects/desktop_switching_animation_test.cpp b/autotests/integration/effects/desktop_switching_animation_test.cpp index 56964fbc3d..2cece77129 100644 --- a/autotests/integration/effects/desktop_switching_animation_test.cpp +++ b/autotests/integration/effects/desktop_switching_animation_test.cpp @@ -10,7 +10,7 @@ #include "kwin_wayland_test.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "virtualdesktops.h" #include "wayland_server.h" #include "window.h" @@ -74,10 +74,9 @@ void DesktopSwitchingAnimationTest::init() void DesktopSwitchingAnimationTest::cleanup() { - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + QVERIFY(effects); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); VirtualDesktopManager::self()->setCount(1); @@ -115,12 +114,11 @@ void DesktopSwitchingAnimationTest::testSwitchDesktops() // Load effect that will be tested. QFETCH(QString, effectName); - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); diff --git a/autotests/integration/effects/maximize_animation_test.cpp b/autotests/integration/effects/maximize_animation_test.cpp index 97819ba9c3..74cf9a8c13 100644 --- a/autotests/integration/effects/maximize_animation_test.cpp +++ b/autotests/integration/effects/maximize_animation_test.cpp @@ -11,7 +11,7 @@ #include "compositor.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "scene/workspacescene.h" #include "wayland_server.h" #include "window.h" @@ -74,10 +74,9 @@ void MaximizeAnimationTest::init() void MaximizeAnimationTest::cleanup() { - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + QVERIFY(effects); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); Test::destroyWaylandConnection(); } @@ -123,12 +122,11 @@ void MaximizeAnimationTest::testMaximizeRestore() // Load effect that will be tested. const QString effectName = QStringLiteral("maximize"); - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); diff --git a/autotests/integration/effects/minimize_animation_test.cpp b/autotests/integration/effects/minimize_animation_test.cpp index 76d575bdda..971c2f4ff7 100644 --- a/autotests/integration/effects/minimize_animation_test.cpp +++ b/autotests/integration/effects/minimize_animation_test.cpp @@ -10,7 +10,7 @@ #include "kwin_wayland_test.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "wayland_server.h" #include "window.h" #include "workspace.h" @@ -74,10 +74,9 @@ void MinimizeAnimationTest::init() void MinimizeAnimationTest::cleanup() { - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + QVERIFY(effects); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); Test::destroyWaylandConnection(); } @@ -134,12 +133,11 @@ void MinimizeAnimationTest::testMinimizeUnminimize() // Load effect that will be tested. QFETCH(QString, effectName); - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); diff --git a/autotests/integration/effects/popup_open_close_animation_test.cpp b/autotests/integration/effects/popup_open_close_animation_test.cpp index f292b532e2..458c4fcd39 100644 --- a/autotests/integration/effects/popup_open_close_animation_test.cpp +++ b/autotests/integration/effects/popup_open_close_animation_test.cpp @@ -10,8 +10,8 @@ #include "kwin_wayland_test.h" #include "effectloader.h" -#include "effects.h" #include "internalwindow.h" +#include "libkwineffects/kwineffects.h" #include "useractions.h" #include "wayland_server.h" #include "window.h" @@ -76,10 +76,9 @@ void PopupOpenCloseAnimationTest::init() void PopupOpenCloseAnimationTest::cleanup() { - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + QVERIFY(effects); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); Test::destroyWaylandConnection(); } @@ -89,10 +88,6 @@ void PopupOpenCloseAnimationTest::testAnimatePopups() // This test verifies that popup open/close animation effects try // to animate popups(e.g. popup menus, tooltips, etc). - // Make sure that we have the right effects ptr. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - // Create the main window. std::unique_ptr mainWindowSurface(Test::createSurface()); QVERIFY(mainWindowSurface != nullptr); @@ -103,10 +98,10 @@ void PopupOpenCloseAnimationTest::testAnimatePopups() // Load effect that will be tested. const QString effectName = QStringLiteral("fadingpopups"); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); @@ -149,10 +144,6 @@ void PopupOpenCloseAnimationTest::testAnimateUserActionsPopup() // This test verifies that popup open/close animation effects try // to animate the user actions popup. - // Make sure that we have the right effects ptr. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - // Create the test window. std::unique_ptr surface(Test::createSurface()); QVERIFY(surface != nullptr); @@ -163,10 +154,10 @@ void PopupOpenCloseAnimationTest::testAnimateUserActionsPopup() // Load effect that will be tested. const QString effectName = QStringLiteral("fadingpopups"); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); @@ -200,10 +191,6 @@ void PopupOpenCloseAnimationTest::testAnimateDecorationTooltips() // This test verifies that popup open/close animation effects try // to animate decoration tooltips. - // Make sure that we have the right effects ptr. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - // Create the test window. std::unique_ptr surface(Test::createSurface()); QVERIFY(surface != nullptr); @@ -224,10 +211,10 @@ void PopupOpenCloseAnimationTest::testAnimateDecorationTooltips() // Load effect that will be tested. const QString effectName = QStringLiteral("fadingpopups"); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); diff --git a/autotests/integration/effects/scripted_effects_test.cpp b/autotests/integration/effects/scripted_effects_test.cpp index 37487ad8d5..2b29d7081e 100644 --- a/autotests/integration/effects/scripted_effects_test.cpp +++ b/autotests/integration/effects/scripted_effects_test.cpp @@ -10,8 +10,8 @@ #include "kwin_wayland_test.h" #include "effectloader.h" -#include "effects.h" #include "libkwineffects/anidata_p.h" +#include "libkwineffects/kwineffects.h" #include "scripting/scriptedeffect.h" #include "virtualdesktops.h" #include "wayland_server.h" @@ -104,7 +104,7 @@ bool ScriptedEffectWithDebugSpy::load(const QString &name) return false; } - // inject our newly created effect to be registered with the EffectsHandlerImpl::loaded_effects + // inject our newly created effect to be registered with the EffectsHandler::loaded_effects // this is private API so some horrible code is used to find the internal effectloader // and register ourselves auto children = effects->children(); @@ -116,7 +116,7 @@ bool ScriptedEffectWithDebugSpy::load(const QString &name) break; } - return (static_cast(effects)->isEffectLoaded(name)); + return effects->isEffectLoaded(name); } void ScriptedEffectsTest::initTestCase() @@ -159,9 +159,8 @@ void ScriptedEffectsTest::cleanup() { Test::destroyWaylandConnection(); - auto effectsImpl = static_cast(effects); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); KWin::VirtualDesktopManager::self()->setCurrent(1); } diff --git a/autotests/integration/effects/slidingpopups_test.cpp b/autotests/integration/effects/slidingpopups_test.cpp index e739f6305e..5152a9ae96 100644 --- a/autotests/integration/effects/slidingpopups_test.cpp +++ b/autotests/integration/effects/slidingpopups_test.cpp @@ -7,8 +7,8 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "effectloader.h" -#include "effects.h" #include "kwin_wayland_test.h" +#include "libkwineffects/kwineffects.h" #include "wayland_server.h" #include "workspace.h" #include "x11window.h" @@ -85,11 +85,10 @@ void SlidingPopupsTest::init() void SlidingPopupsTest::cleanup() { Test::destroyWaylandConnection(); - EffectsHandlerImpl *e = static_cast(effects); - while (!e->loadedEffects().isEmpty()) { - const QString effect = e->loadedEffects().first(); - e->unloadEffect(effect); - QVERIFY(!e->isEffectLoaded(effect)); + while (!effects->loadedEffects().isEmpty()) { + const QString effect = effects->loadedEffects().first(); + effects->unloadEffect(effect); + QVERIFY(!effects->isEffectLoaded(effect)); } } @@ -117,9 +116,8 @@ void SlidingPopupsTest::testWithOtherEffect() // this test verifies that slidingpopups effect grabs the window added role // independently of the sequence how the effects are loaded. // see BUG 336866 - EffectsHandlerImpl *e = static_cast(effects); // find the effectsloader - auto effectloader = e->findChild(); + auto effectloader = effects->findChild(); QVERIFY(effectloader); QSignalSpy effectLoadedSpy(effectloader, &AbstractEffectLoader::effectLoaded); @@ -127,9 +125,9 @@ void SlidingPopupsTest::testWithOtherEffect() Effect *otherEffect = nullptr; QFETCH(QStringList, effectsToLoad); for (const QString &effectName : effectsToLoad) { - QVERIFY(!e->isEffectLoaded(effectName)); - QVERIFY(e->loadEffect(effectName)); - QVERIFY(e->isEffectLoaded(effectName)); + QVERIFY(!effects->isEffectLoaded(effectName)); + QVERIFY(effects->loadEffect(effectName)); + QVERIFY(effects->isEffectLoaded(effectName)); QCOMPARE(effectLoadedSpy.count(), 1); Effect *effect = effectLoadedSpy.first().first().value(); @@ -245,9 +243,8 @@ void SlidingPopupsTest::testWithOtherEffectWayland() // independently of the sequence how the effects are loaded. // see BUG 336866 // the test is like testWithOtherEffect, but simulates using a Wayland window - EffectsHandlerImpl *e = static_cast(effects); // find the effectsloader - auto effectloader = e->findChild(); + auto effectloader = effects->findChild(); QVERIFY(effectloader); QSignalSpy effectLoadedSpy(effectloader, &AbstractEffectLoader::effectLoaded); @@ -255,9 +252,9 @@ void SlidingPopupsTest::testWithOtherEffectWayland() Effect *otherEffect = nullptr; QFETCH(QStringList, effectsToLoad); for (const QString &effectName : effectsToLoad) { - QVERIFY(!e->isEffectLoaded(effectName)); - QVERIFY(e->loadEffect(effectName)); - QVERIFY(e->isEffectLoaded(effectName)); + QVERIFY(!effects->isEffectLoaded(effectName)); + QVERIFY(effects->loadEffect(effectName)); + QVERIFY(effects->isEffectLoaded(effectName)); QCOMPARE(effectLoadedSpy.count(), 1); Effect *effect = effectLoadedSpy.first().first().value(); diff --git a/autotests/integration/effects/toplevel_open_close_animation_test.cpp b/autotests/integration/effects/toplevel_open_close_animation_test.cpp index 932c0c9e30..78af0d6314 100644 --- a/autotests/integration/effects/toplevel_open_close_animation_test.cpp +++ b/autotests/integration/effects/toplevel_open_close_animation_test.cpp @@ -10,7 +10,7 @@ #include "kwin_wayland_test.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "wayland_server.h" #include "window.h" #include "workspace.h" @@ -75,10 +75,8 @@ void ToplevelOpenCloseAnimationTest::init() void ToplevelOpenCloseAnimationTest::cleanup() { - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); Test::destroyWaylandConnection(); } @@ -97,16 +95,12 @@ void ToplevelOpenCloseAnimationTest::testAnimateToplevels() // This test verifies that window open/close animation effects try to // animate the appearing and the disappearing of toplevel windows. - // Make sure that we have the right effects ptr. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - // Load effect that will be tested. QFETCH(QString, effectName); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); @@ -148,10 +142,6 @@ void ToplevelOpenCloseAnimationTest::testDontAnimatePopups() // This test verifies that window open/close animation effects don't try // to animate popups(e.g. popup menus, tooltips, etc). - // Make sure that we have the right effects ptr. - auto effectsImpl = qobject_cast(effects); - QVERIFY(effectsImpl); - // Create the main window. std::unique_ptr mainWindowSurface(Test::createSurface()); QVERIFY(mainWindowSurface != nullptr); @@ -162,10 +152,10 @@ void ToplevelOpenCloseAnimationTest::testDontAnimatePopups() // Load effect that will be tested. QFETCH(QString, effectName); - QVERIFY(effectsImpl->loadEffect(effectName)); - QCOMPARE(effectsImpl->loadedEffects().count(), 1); - QCOMPARE(effectsImpl->loadedEffects().first(), effectName); - Effect *effect = effectsImpl->findEffect(effectName); + QVERIFY(effects->loadEffect(effectName)); + QCOMPARE(effects->loadedEffects().count(), 1); + QCOMPARE(effects->loadedEffects().first(), effectName); + Effect *effect = effects->findEffect(effectName); QVERIFY(effect); QVERIFY(!effect->isActive()); diff --git a/autotests/integration/effects/translucency_test.cpp b/autotests/integration/effects/translucency_test.cpp index 7512706aed..8bb5750a78 100644 --- a/autotests/integration/effects/translucency_test.cpp +++ b/autotests/integration/effects/translucency_test.cpp @@ -10,7 +10,7 @@ #include "compositor.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "pointer_input.h" #include "virtualdesktops.h" #include "wayland_server.h" @@ -73,16 +73,14 @@ void TranslucencyTest::initTestCase() void TranslucencyTest::init() { - // load the translucency effect - EffectsHandlerImpl *e = static_cast(effects); // find the effectsloader - auto effectloader = e->findChild(); + auto effectloader = effects->findChild(); QVERIFY(effectloader); QSignalSpy effectLoadedSpy(effectloader, &AbstractEffectLoader::effectLoaded); - QVERIFY(!e->isEffectLoaded(QStringLiteral("translucency"))); - QVERIFY(e->loadEffect(QStringLiteral("translucency"))); - QVERIFY(e->isEffectLoaded(QStringLiteral("translucency"))); + QVERIFY(!effects->isEffectLoaded(QStringLiteral("translucency"))); + QVERIFY(effects->loadEffect(QStringLiteral("translucency"))); + QVERIFY(effects->isEffectLoaded(QStringLiteral("translucency"))); QCOMPARE(effectLoadedSpy.count(), 1); m_translucencyEffect = effectLoadedSpy.first().first().value(); @@ -91,11 +89,10 @@ void TranslucencyTest::init() void TranslucencyTest::cleanup() { - EffectsHandlerImpl *e = static_cast(effects); - if (e->isEffectLoaded(QStringLiteral("translucency"))) { - e->unloadEffect(QStringLiteral("translucency")); + if (effects->isEffectLoaded(QStringLiteral("translucency"))) { + effects->unloadEffect(QStringLiteral("translucency")); } - QVERIFY(!e->isEffectLoaded(QStringLiteral("translucency"))); + QVERIFY(!effects->isEffectLoaded(QStringLiteral("translucency"))); m_translucencyEffect = nullptr; } diff --git a/autotests/integration/effects/wobbly_shade_test.cpp b/autotests/integration/effects/wobbly_shade_test.cpp index 6947f5bd8b..d944fab9e9 100644 --- a/autotests/integration/effects/wobbly_shade_test.cpp +++ b/autotests/integration/effects/wobbly_shade_test.cpp @@ -10,7 +10,7 @@ #include "cursor.h" #include "effectloader.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "wayland_server.h" #include "workspace.h" #include "x11window.h" @@ -80,17 +80,15 @@ void WobblyWindowsShadeTest::cleanup() { Test::destroyWaylandConnection(); - auto effectsImpl = static_cast(effects); - effectsImpl->unloadAllEffects(); - QVERIFY(effectsImpl->loadedEffects().isEmpty()); + effects->unloadAllEffects(); + QVERIFY(effects->loadedEffects().isEmpty()); } void WobblyWindowsShadeTest::testShadeMove() { // this test simulates the condition from BUG 390953 - EffectsHandlerImpl *e = static_cast(effects); - QVERIFY(e->loadEffect(QStringLiteral("wobblywindows"))); - QVERIFY(e->isEffectLoaded(QStringLiteral("wobblywindows"))); + QVERIFY(effects->loadEffect(QStringLiteral("wobblywindows"))); + QVERIFY(effects->isEffectLoaded(QStringLiteral("wobblywindows"))); Test::XcbConnectionPtr c = Test::createX11Connection(); QVERIFY(!xcb_connection_has_error(c.get())); diff --git a/autotests/integration/inputmethod_test.cpp b/autotests/integration/inputmethod_test.cpp index 4f053f7af3..b5c7a5a34a 100644 --- a/autotests/integration/inputmethod_test.cpp +++ b/autotests/integration/inputmethod_test.cpp @@ -9,7 +9,6 @@ #include "kwin_wayland_test.h" #include "core/output.h" -#include "effects.h" #include "inputmethod.h" #include "keyboard_input.h" #include "pointer_input.h" diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp index 9ca52f2af7..c07fe24801 100644 --- a/autotests/integration/internal_window.cpp +++ b/autotests/integration/internal_window.cpp @@ -9,8 +9,8 @@ #include "kwin_wayland_test.h" #include "core/output.h" -#include "effects.h" #include "internalwindow.h" +#include "libkwineffects/kwineffects.h" #include "pointer_input.h" #include "wayland/surface.h" #include "wayland_server.h" diff --git a/autotests/integration/kwin_wayland_test.cpp b/autotests/integration/kwin_wayland_test.cpp index 7a3bfda8a1..add7f0d96c 100644 --- a/autotests/integration/kwin_wayland_test.cpp +++ b/autotests/integration/kwin_wayland_test.cpp @@ -11,8 +11,8 @@ #include "backends/virtual/virtual_backend.h" #include "compositor_wayland.h" #include "core/session.h" -#include "effects.h" #include "inputmethod.h" +#include "libkwineffects/kwineffects.h" #include "placement.h" #include "pluginmanager.h" #include "utils/xcbutils.h" @@ -82,7 +82,7 @@ WaylandTestApplication::~WaylandTestApplication() // need to unload all effects prior to destroying X connection as they might do X calls // also before destroy Workspace, as effects might call into Workspace if (effects) { - static_cast(effects)->unloadAllEffects(); + effects->unloadAllEffects(); } m_xwayland.reset(); destroyVirtualInputDevices(); diff --git a/autotests/integration/move_resize_window_test.cpp b/autotests/integration/move_resize_window_test.cpp index b1c0ca518e..5ddc5bba0d 100644 --- a/autotests/integration/move_resize_window_test.cpp +++ b/autotests/integration/move_resize_window_test.cpp @@ -12,7 +12,6 @@ #include "atoms.h" #include "core/output.h" #include "cursor.h" -#include "effects.h" #include "placement.h" #include "pointer_input.h" #include "wayland_server.h" diff --git a/autotests/integration/x11_window_test.cpp b/autotests/integration/x11_window_test.cpp index 17dfd20d60..49aaeaafde 100644 --- a/autotests/integration/x11_window_test.cpp +++ b/autotests/integration/x11_window_test.cpp @@ -12,7 +12,6 @@ #include "compositor.h" #include "cursor.h" #include "effectloader.h" -#include "effects.h" #include "wayland_server.h" #include "workspace.h" #include "x11window.h" diff --git a/autotests/integration/xdgshellwindow_test.cpp b/autotests/integration/xdgshellwindow_test.cpp index b21f55f696..ee16edb79d 100644 --- a/autotests/integration/xdgshellwindow_test.cpp +++ b/autotests/integration/xdgshellwindow_test.cpp @@ -12,7 +12,6 @@ #include "core/output.h" #include "decorations/decorationbridge.h" #include "decorations/settings.h" -#include "effects.h" #include "pointer_input.h" #include "virtualdesktops.h" #include "wayland/clientconnection.h" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6286de7d08..d1f4cc611c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -82,7 +82,6 @@ target_sources(kwin PRIVATE decorations/settings.cpp dpmsinputeventfilter.cpp effectloader.cpp - effects.cpp events.cpp focuschain.cpp ftrace.cpp @@ -295,7 +294,7 @@ set(kwin_dbus_SRCS) qt_add_dbus_adaptor(kwin_dbus_SRCS scripting/org.kde.kwin.Script.xml scripting/scripting.h KWin::AbstractScript) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterface) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.kwin.Compositing.xml dbusinterface.h KWin::CompositorDBusInterface) -qt_add_dbus_adaptor(kwin_dbus_SRCS ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl) +qt_add_dbus_adaptor(kwin_dbus_SRCS ${kwin_effects_dbus_xml} libkwineffects/kwineffects.h KWin::EffectsHandler) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Session.xml sm.h KWin::SessionManager) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Plugins.xml dbusinterface.h KWin::PluginManagerDBusInterface) diff --git a/src/backends/x11/standalone/x11_standalone_backend.cpp b/src/backends/x11/standalone/x11_standalone_backend.cpp index c4551af632..9a0670bcad 100644 --- a/src/backends/x11/standalone/x11_standalone_backend.cpp +++ b/src/backends/x11/standalone/x11_standalone_backend.cpp @@ -254,7 +254,7 @@ std::unique_ptr X11StandaloneBackend::createOutline(Outline *outl void X11StandaloneBackend::createEffectsHandler(Compositor *compositor, WorkspaceScene *scene) { - new EffectsHandlerImplX11(compositor, scene); + new EffectsHandlerX11(compositor, scene); } QList X11StandaloneBackend::supportedCompositors() const diff --git a/src/backends/x11/standalone/x11_standalone_effects.cpp b/src/backends/x11/standalone/x11_standalone_effects.cpp index 0b1eee3f10..98816de803 100644 --- a/src/backends/x11/standalone/x11_standalone_effects.cpp +++ b/src/backends/x11/standalone/x11_standalone_effects.cpp @@ -20,19 +20,19 @@ namespace KWin { -EffectsHandlerImplX11::EffectsHandlerImplX11(Compositor *compositor, WorkspaceScene *scene) - : EffectsHandlerImpl(compositor, scene) +EffectsHandlerX11::EffectsHandlerX11(Compositor *compositor, WorkspaceScene *scene) + : EffectsHandler(compositor, scene) { - connect(this, &EffectsHandlerImpl::virtualScreenGeometryChanged, this, [this]() { + connect(this, &EffectsHandler::virtualScreenGeometryChanged, this, [this]() { if (m_mouseInterceptionWindow.isValid()) { m_mouseInterceptionWindow.setGeometry(virtualScreenGeometry()); } }); } -EffectsHandlerImplX11::~EffectsHandlerImplX11() +EffectsHandlerX11::~EffectsHandlerX11() { - // EffectsHandlerImpl tries to unload all effects when it's destroyed. + // EffectsHandler tries to unload all effects when it's destroyed. // The routine that unloads effects makes some calls (indirectly) to // doUngrabKeyboard and doStopMouseInterception, which are virtual. // Given that any call to a virtual function in the destructor of a base @@ -42,7 +42,7 @@ EffectsHandlerImplX11::~EffectsHandlerImplX11() unloadAllEffects(); } -bool EffectsHandlerImplX11::doGrabKeyboard() +bool EffectsHandlerX11::doGrabKeyboard() { auto keyboard = static_cast(kwinApp()->outputBackend())->keyboard(); if (!keyboard->xkbKeymap()) { @@ -56,13 +56,13 @@ bool EffectsHandlerImplX11::doGrabKeyboard() return ret; } -void EffectsHandlerImplX11::doUngrabKeyboard() +void EffectsHandlerX11::doUngrabKeyboard() { ungrabXKeyboard(); m_x11KeyboardInterception.reset(); } -void EffectsHandlerImplX11::doStartMouseInterception(Qt::CursorShape shape) +void EffectsHandlerX11::doStartMouseInterception(Qt::CursorShape shape) { // NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h // The mouse grab is implemented by using a full screen input only window @@ -86,14 +86,14 @@ void EffectsHandlerImplX11::doStartMouseInterception(Qt::CursorShape shape) workspace()->screenEdges()->ensureOnTop(); } -void EffectsHandlerImplX11::doStopMouseInterception() +void EffectsHandlerX11::doStopMouseInterception() { m_mouseInterceptionWindow.unmap(); m_x11MouseInterception.reset(); Workspace::self()->stackScreenEdgesUnderOverrideRedirect(); } -void EffectsHandlerImplX11::defineCursor(Qt::CursorShape shape) +void EffectsHandlerX11::defineCursor(Qt::CursorShape shape) { const xcb_cursor_t c = Cursors::self()->mouse()->x11Cursor(shape); if (c != XCB_CURSOR_NONE) { @@ -101,7 +101,7 @@ void EffectsHandlerImplX11::defineCursor(Qt::CursorShape shape) } } -void EffectsHandlerImplX11::doCheckInputWindowStacking() +void EffectsHandlerX11::doCheckInputWindowStacking() { m_mouseInterceptionWindow.raise(); // Raise electric border windows above the input windows diff --git a/src/backends/x11/standalone/x11_standalone_effects.h b/src/backends/x11/standalone/x11_standalone_effects.h index 8bcc16dcf8..6c20ed5dd5 100644 --- a/src/backends/x11/standalone/x11_standalone_effects.h +++ b/src/backends/x11/standalone/x11_standalone_effects.h @@ -9,7 +9,7 @@ */ #pragma once -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "utils/xcbutils.h" #include @@ -19,12 +19,12 @@ namespace KWin class EffectsMouseInterceptionX11Filter; class EffectsKeyboardInterceptionX11Filter; -class EffectsHandlerImplX11 : public EffectsHandlerImpl +class EffectsHandlerX11 : public EffectsHandler { Q_OBJECT public: - explicit EffectsHandlerImplX11(Compositor *compositor, WorkspaceScene *scene); - ~EffectsHandlerImplX11() override; + explicit EffectsHandlerX11(Compositor *compositor, WorkspaceScene *scene); + ~EffectsHandlerX11() override; void defineCursor(Qt::CursorShape shape) override; diff --git a/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.cpp b/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.cpp index 100e0c59f7..403fea3642 100644 --- a/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.cpp +++ b/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.cpp @@ -15,7 +15,7 @@ namespace KWin { -EffectsKeyboardInterceptionX11Filter::EffectsKeyboardInterceptionX11Filter(EffectsHandlerImpl *effects, X11Keyboard *keyboard) +EffectsKeyboardInterceptionX11Filter::EffectsKeyboardInterceptionX11Filter(EffectsHandler *effects, X11Keyboard *keyboard) : X11EventFilter(QList{XCB_KEY_PRESS, XCB_KEY_RELEASE}) , m_effects(effects) , m_keyboard(keyboard) diff --git a/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.h b/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.h index a80545242e..cd1d6cc173 100644 --- a/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.h +++ b/src/backends/x11/standalone/x11_standalone_effects_keyboard_interception_filter.h @@ -11,20 +11,20 @@ namespace KWin { -class EffectsHandlerImpl; +class EffectsHandler; class X11Keyboard; class EffectsKeyboardInterceptionX11Filter : public X11EventFilter { public: - explicit EffectsKeyboardInterceptionX11Filter(EffectsHandlerImpl *effects, X11Keyboard *keyboard); + explicit EffectsKeyboardInterceptionX11Filter(EffectsHandler *effects, X11Keyboard *keyboard); bool event(xcb_generic_event_t *event) override; private: void processKey(bool press, xcb_keycode_t keycode, xcb_timestamp_t timestamp); - EffectsHandlerImpl *m_effects; + EffectsHandler *m_effects; X11Keyboard *m_keyboard; }; diff --git a/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.cpp b/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.cpp index db7fa12867..a38a1fb5c0 100644 --- a/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.cpp +++ b/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.cpp @@ -7,15 +7,16 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "x11_standalone_effects_mouse_interception_filter.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "utils/common.h" +#include #include namespace KWin { -EffectsMouseInterceptionX11Filter::EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandlerImpl *effects) +EffectsMouseInterceptionX11Filter::EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandler *effects) : X11EventFilter(QList{XCB_BUTTON_PRESS, XCB_BUTTON_RELEASE, XCB_MOTION_NOTIFY}) , m_effects(effects) , m_window(window) diff --git a/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.h b/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.h index 4d0728472d..bbe5eec218 100644 --- a/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.h +++ b/src/backends/x11/standalone/x11_standalone_effects_mouse_interception_filter.h @@ -12,17 +12,17 @@ namespace KWin { -class EffectsHandlerImpl; +class EffectsHandler; class EffectsMouseInterceptionX11Filter : public X11EventFilter { public: - explicit EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandlerImpl *effects); + explicit EffectsMouseInterceptionX11Filter(xcb_window_t window, EffectsHandler *effects); bool event(xcb_generic_event_t *event) override; private: - EffectsHandlerImpl *m_effects; + EffectsHandler *m_effects; xcb_window_t m_window; }; diff --git a/src/effectloader.h b/src/effectloader.h index 7d8c560cf2..e1cf69d311 100644 --- a/src/effectloader.h +++ b/src/effectloader.h @@ -43,7 +43,7 @@ Q_DECLARE_FLAGS(LoadEffectFlags, LoadEffectFlag) * * The AbstractEffectLoader specifies the methods a concrete loader has to implement and how * those methods are expected to perform. Also it provides an interface to the outside world - * (that is EffectsHandlerImpl). + * (that is EffectsHandler). * * The abstraction is used because there are multiple types of Effects which need to be loaded: * @li Built-In Effects diff --git a/src/effects.cpp b/src/effects.cpp deleted file mode 100644 index 9931e78362..0000000000 --- a/src/effects.cpp +++ /dev/null @@ -1,1593 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2006 Lubos Lunak - SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#include "effects.h" - -#include - -#include "core/output.h" -#include "effectloader.h" -#include "effectsadaptor.h" -#if KWIN_BUILD_ACTIVITIES -#include "activities.h" -#endif -#include "core/renderbackend.h" -#include "core/renderlayer.h" -#include "cursor.h" -#include "group.h" -#include "input_event.h" -#include "internalwindow.h" -#include "osd.h" -#include "pointer_input.h" -#include "scene/itemrenderer.h" -#include "scripting/scripting.h" -#include "x11window.h" -#if KWIN_BUILD_TABBOX -#include "tabbox/tabbox.h" -#endif -#include "screenedge.h" -#include "scripting/scriptedeffect.h" -#if KWIN_BUILD_SCREENLOCKER -#include "screenlockerwatcher.h" -#endif -#include "compositor.h" -#include "core/rendertarget.h" -#include "core/renderviewport.h" -#include "decorations/decorationbridge.h" -#include "inputmethod.h" -#include "inputpanelv1window.h" -#include "libkwineffects/kwinoffscreenquickview.h" -#include "opengl/glutils.h" -#include "scene/windowitem.h" -#include "utils/xcbutils.h" -#include "virtualdesktops.h" -#include "wayland_server.h" -#include "waylandwindow.h" -#include "window_property_notify_x11_filter.h" -#include "workspace.h" - -#include -#include - -#include -#include -#include -#include -#include - -namespace KWin -{ -//--------------------- -// Static - -static QByteArray readWindowProperty(xcb_window_t win, xcb_atom_t atom, xcb_atom_t type, int format) -{ - if (win == XCB_WINDOW_NONE) { - return QByteArray(); - } - uint32_t len = 32768; - for (;;) { - Xcb::Property prop(false, win, atom, XCB_ATOM_ANY, 0, len); - if (prop.isNull()) { - // get property failed - return QByteArray(); - } - if (prop->bytes_after > 0) { - len *= 2; - continue; - } - return prop.toByteArray(format, type); - } -} - -static xcb_atom_t registerSupportProperty(const QByteArray &propertyName) -{ - auto c = kwinApp()->x11Connection(); - if (!c) { - return XCB_ATOM_NONE; - } - // get the atom for the propertyName - UniqueCPtr atomReply(xcb_intern_atom_reply(c, - xcb_intern_atom_unchecked(c, false, propertyName.size(), propertyName.constData()), - nullptr)); - if (!atomReply) { - return XCB_ATOM_NONE; - } - // announce property on root window - unsigned char dummy = 0; - xcb_change_property(c, XCB_PROP_MODE_REPLACE, kwinApp()->x11RootWindow(), atomReply->atom, atomReply->atom, 8, 1, &dummy); - // TODO: add to _NET_SUPPORTED - return atomReply->atom; -} - -//--------------------- - -EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, WorkspaceScene *scene) - : EffectsHandler(Compositor::self()->backend()->compositingType()) - , keyboard_grab_effect(nullptr) - , fullscreen_effect(nullptr) - , m_compositor(compositor) - , m_scene(scene) - , m_effectLoader(new EffectLoader(this)) - , m_trackingCursorChanges(0) -{ - qRegisterMetaType>(); - qRegisterMetaType(); - connect(m_effectLoader, &AbstractEffectLoader::effectLoaded, this, [this](Effect *effect, const QString &name) { - effect_order.insert(effect->requestedEffectChainPosition(), EffectPair(name, effect)); - loaded_effects << EffectPair(name, effect); - effectsChanged(); - }); - m_effectLoader->setConfig(kwinApp()->config()); - new EffectsAdaptor(this); - QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject(QStringLiteral("/Effects"), this); - - connect(options, &Options::animationSpeedChanged, this, &EffectsHandlerImpl::reconfigureEffects); - - Workspace *ws = Workspace::self(); - VirtualDesktopManager *vds = VirtualDesktopManager::self(); - connect(ws, &Workspace::showingDesktopChanged, this, [this](bool showing, bool animated) { - if (animated) { - Q_EMIT showingDesktopChanged(showing); - } - }); - connect(ws, &Workspace::currentDesktopChanged, this, [this](VirtualDesktop *old, Window *window) { - VirtualDesktop *newDesktop = VirtualDesktopManager::self()->currentDesktop(); - Q_EMIT desktopChanged(old, newDesktop, window ? window->effectWindow() : nullptr); - }); - connect(ws, &Workspace::currentDesktopChanging, this, [this](VirtualDesktop *currentDesktop, QPointF offset, KWin::Window *window) { - Q_EMIT desktopChanging(currentDesktop, offset, window ? window->effectWindow() : nullptr); - }); - connect(ws, &Workspace::currentDesktopChangingCancelled, this, [this]() { - Q_EMIT desktopChangingCancelled(); - }); - connect(ws, &Workspace::windowAdded, this, [this](Window *window) { - setupWindowConnections(window); - Q_EMIT windowAdded(window->effectWindow()); - }); - connect(ws, &Workspace::windowActivated, this, [this](Window *window) { - Q_EMIT windowActivated(window ? window->effectWindow() : nullptr); - }); - connect(ws, &Workspace::deletedRemoved, this, [this](KWin::Window *d) { - Q_EMIT windowDeleted(d->effectWindow()); - }); - connect(ws->sessionManager(), &SessionManager::stateChanged, this, &KWin::EffectsHandler::sessionStateChanged); - connect(vds, &VirtualDesktopManager::layoutChanged, this, [this](int width, int height) { - Q_EMIT desktopGridSizeChanged(QSize(width, height)); - Q_EMIT desktopGridWidthChanged(width); - Q_EMIT desktopGridHeightChanged(height); - }); - connect(vds, &VirtualDesktopManager::desktopAdded, this, &EffectsHandler::desktopAdded); - connect(vds, &VirtualDesktopManager::desktopRemoved, this, &EffectsHandler::desktopRemoved); - connect(Cursors::self()->mouse(), &Cursor::mouseChanged, this, &EffectsHandler::mouseChanged); - connect(ws, &Workspace::geometryChanged, this, &EffectsHandler::virtualScreenSizeChanged); - connect(ws, &Workspace::geometryChanged, this, &EffectsHandler::virtualScreenGeometryChanged); -#if KWIN_BUILD_ACTIVITIES - if (Activities *activities = Workspace::self()->activities()) { - connect(activities, &Activities::added, this, &EffectsHandler::activityAdded); - connect(activities, &Activities::removed, this, &EffectsHandler::activityRemoved); - connect(activities, &Activities::currentChanged, this, &EffectsHandler::currentActivityChanged); - } -#endif - connect(ws, &Workspace::stackingOrderChanged, this, &EffectsHandler::stackingOrderChanged); -#if KWIN_BUILD_TABBOX - TabBox::TabBox *tabBox = workspace()->tabbox(); - connect(tabBox, &TabBox::TabBox::tabBoxAdded, this, &EffectsHandler::tabBoxAdded); - connect(tabBox, &TabBox::TabBox::tabBoxUpdated, this, &EffectsHandler::tabBoxUpdated); - connect(tabBox, &TabBox::TabBox::tabBoxClosed, this, &EffectsHandler::tabBoxClosed); - connect(tabBox, &TabBox::TabBox::tabBoxKeyEvent, this, &EffectsHandler::tabBoxKeyEvent); -#endif - connect(workspace()->screenEdges(), &ScreenEdges::approaching, this, &EffectsHandler::screenEdgeApproaching); -#if KWIN_BUILD_SCREENLOCKER - connect(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::locked, this, &EffectsHandler::screenLockingChanged); - connect(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::aboutToLock, this, &EffectsHandler::screenAboutToLock); -#endif - - connect(kwinApp(), &Application::x11ConnectionChanged, this, [this]() { - registered_atoms.clear(); - for (auto it = m_propertiesForEffects.keyBegin(); it != m_propertiesForEffects.keyEnd(); it++) { - const auto atom = registerSupportProperty(*it); - if (atom == XCB_ATOM_NONE) { - continue; - } - m_compositor->keepSupportProperty(atom); - m_managedProperties.insert(*it, atom); - registerPropertyType(atom, true); - } - if (kwinApp()->x11Connection()) { - m_x11WindowPropertyNotify = std::make_unique(this); - } else { - m_x11WindowPropertyNotify.reset(); - } - Q_EMIT xcbConnectionChanged(); - }); - - if (kwinApp()->x11Connection()) { - m_x11WindowPropertyNotify = std::make_unique(this); - } - - // connect all clients - for (Window *window : ws->windows()) { - setupWindowConnections(window); - } - - connect(ws, &Workspace::outputAdded, this, &EffectsHandlerImpl::screenAdded); - connect(ws, &Workspace::outputRemoved, this, &EffectsHandlerImpl::screenRemoved); - - if (auto inputMethod = kwinApp()->inputMethod()) { - connect(inputMethod, &InputMethod::panelChanged, this, &EffectsHandlerImpl::inputPanelChanged); - } - - reconfigure(); -} - -EffectsHandlerImpl::~EffectsHandlerImpl() -{ - unloadAllEffects(); -} - -void EffectsHandlerImpl::unloadAllEffects() -{ - for (const EffectPair &pair : std::as_const(loaded_effects)) { - destroyEffect(pair.second); - } - - effect_order.clear(); - m_effectLoader->clear(); - - effectsChanged(); -} - -void EffectsHandlerImpl::setupWindowConnections(Window *window) -{ - connect(window, &Window::closed, this, [this, window]() { - if (window->effectWindow()) { - Q_EMIT windowClosed(window->effectWindow()); - } - }); -} - -void EffectsHandlerImpl::reconfigure() -{ - m_effectLoader->queryAndLoadAll(); -} - -// the idea is that effects call this function again which calls the next one -void EffectsHandlerImpl::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) -{ - if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { - (*m_currentPaintScreenIterator++)->prePaintScreen(data, presentTime); - --m_currentPaintScreenIterator; - } - // no special final code -} - -void EffectsHandlerImpl::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) -{ - if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { - (*m_currentPaintScreenIterator++)->paintScreen(renderTarget, viewport, mask, region, screen); - --m_currentPaintScreenIterator; - } else { - m_scene->finalPaintScreen(renderTarget, viewport, mask, region, screen); - } -} - -void EffectsHandlerImpl::postPaintScreen() -{ - if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { - (*m_currentPaintScreenIterator++)->postPaintScreen(); - --m_currentPaintScreenIterator; - } - // no special final code -} - -void EffectsHandlerImpl::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) -{ - if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { - (*m_currentPaintWindowIterator++)->prePaintWindow(w, data, presentTime); - --m_currentPaintWindowIterator; - } - // no special final code -} - -void EffectsHandlerImpl::paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) -{ - if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { - (*m_currentPaintWindowIterator++)->paintWindow(renderTarget, viewport, w, mask, region, data); - --m_currentPaintWindowIterator; - } else { - m_scene->finalPaintWindow(renderTarget, viewport, w, mask, region, data); - } -} - -void EffectsHandlerImpl::postPaintWindow(EffectWindow *w) -{ - if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { - (*m_currentPaintWindowIterator++)->postPaintWindow(w); - --m_currentPaintWindowIterator; - } - // no special final code -} - -Effect *EffectsHandlerImpl::provides(Effect::Feature ef) -{ - for (int i = 0; i < loaded_effects.size(); ++i) { - if (loaded_effects.at(i).second->provides(ef)) { - return loaded_effects.at(i).second; - } - } - return nullptr; -} - -void EffectsHandlerImpl::drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) -{ - if (m_currentDrawWindowIterator != m_activeEffects.constEnd()) { - (*m_currentDrawWindowIterator++)->drawWindow(renderTarget, viewport, w, mask, region, data); - --m_currentDrawWindowIterator; - } else { - m_scene->finalDrawWindow(renderTarget, viewport, w, mask, region, data); - } -} - -void EffectsHandlerImpl::renderWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) -{ - m_scene->finalDrawWindow(renderTarget, viewport, w, mask, region, data); -} - -bool EffectsHandlerImpl::hasDecorationShadows() const -{ - return false; -} - -bool EffectsHandlerImpl::decorationsHaveAlpha() const -{ - return true; -} - -// start another painting pass -void EffectsHandlerImpl::startPaint() -{ - m_activeEffects.clear(); - m_activeEffects.reserve(loaded_effects.count()); - for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->isActive()) { - m_activeEffects << it->second; - } - } - m_currentDrawWindowIterator = m_activeEffects.constBegin(); - m_currentPaintWindowIterator = m_activeEffects.constBegin(); - m_currentPaintScreenIterator = m_activeEffects.constBegin(); -} - -void EffectsHandlerImpl::setActiveFullScreenEffect(Effect *e) -{ - if (fullscreen_effect == e) { - return; - } - const bool activeChanged = (e == nullptr || fullscreen_effect == nullptr); - fullscreen_effect = e; - Q_EMIT activeFullScreenEffectChanged(); - if (activeChanged) { - Q_EMIT hasActiveFullScreenEffectChanged(); - workspace()->screenEdges()->checkBlocking(); - } -} - -Effect *EffectsHandlerImpl::activeFullScreenEffect() const -{ - return fullscreen_effect; -} - -bool EffectsHandlerImpl::hasActiveFullScreenEffect() const -{ - return fullscreen_effect; -} - -bool EffectsHandlerImpl::grabKeyboard(Effect *effect) -{ - if (keyboard_grab_effect != nullptr) { - return false; - } - if (!doGrabKeyboard()) { - return false; - } - keyboard_grab_effect = effect; - return true; -} - -bool EffectsHandlerImpl::doGrabKeyboard() -{ - return true; -} - -void EffectsHandlerImpl::ungrabKeyboard() -{ - Q_ASSERT(keyboard_grab_effect != nullptr); - doUngrabKeyboard(); - keyboard_grab_effect = nullptr; -} - -void EffectsHandlerImpl::doUngrabKeyboard() -{ -} - -void EffectsHandlerImpl::grabbedKeyboardEvent(QKeyEvent *e) -{ - if (keyboard_grab_effect != nullptr) { - keyboard_grab_effect->grabbedKeyboardEvent(e); - } -} - -void EffectsHandlerImpl::startMouseInterception(Effect *effect, Qt::CursorShape shape) -{ - if (m_grabbedMouseEffects.contains(effect)) { - return; - } - m_grabbedMouseEffects.append(effect); - if (m_grabbedMouseEffects.size() != 1) { - return; - } - doStartMouseInterception(shape); -} - -void EffectsHandlerImpl::doStartMouseInterception(Qt::CursorShape shape) -{ - input()->pointer()->setEffectsOverrideCursor(shape); - - // We want to allow global shortcuts to be triggered when moving a - // window so it is possible to pick up a window and then move it to a - // different desktop by using the global shortcut to switch desktop. - // However, that means that some other things can also be triggered. If - // an effect that fill the screen gets triggered that way, we end up in a - // weird state where the move will restart after the effect closes. So to - // avoid that, abort move/resize if a full screen effect starts. - if (workspace()->moveResizeWindow()) { - workspace()->moveResizeWindow()->endInteractiveMoveResize(); - } -} - -void EffectsHandlerImpl::stopMouseInterception(Effect *effect) -{ - if (!m_grabbedMouseEffects.contains(effect)) { - return; - } - m_grabbedMouseEffects.removeAll(effect); - if (m_grabbedMouseEffects.isEmpty()) { - doStopMouseInterception(); - } -} - -void EffectsHandlerImpl::doStopMouseInterception() -{ - input()->pointer()->removeEffectsOverrideCursor(); -} - -bool EffectsHandlerImpl::isMouseInterception() const -{ - return m_grabbedMouseEffects.count() > 0; -} - -bool EffectsHandlerImpl::touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->touchDown(id, pos, time)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->touchMotion(id, pos, time)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::touchUp(qint32 id, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->touchUp(id, time)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::tabletToolEvent(TabletEvent *event) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->tabletToolEvent(event)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->tabletToolButtonEvent(button, pressed, tabletToolId.m_uniqueId)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->tabletPadButtonEvent(button, pressed, tabletPadId.data)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->tabletPadStripEvent(number, position, isFinger, tabletPadId.data)) { - return true; - } - } - return false; -} - -bool EffectsHandlerImpl::tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) -{ - // TODO: reverse call order? - for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if (it->second->tabletPadRingEvent(number, position, isFinger, tabletPadId.data)) { - return true; - } - } - return false; -} - -void EffectsHandlerImpl::registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) -{ - input()->registerPointerShortcut(modifiers, pointerButtons, action); -} - -void EffectsHandlerImpl::registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) -{ - input()->registerAxisShortcut(modifiers, axis, action); -} - -void EffectsHandlerImpl::registerTouchpadSwipeShortcut(SwipeDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback) -{ - input()->registerTouchpadSwipeShortcut(dir, fingerCount, onUp, progressCallback); -} - -void EffectsHandlerImpl::registerTouchpadPinchShortcut(PinchDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback) -{ - input()->registerTouchpadPinchShortcut(dir, fingerCount, onUp, progressCallback); -} - -void EffectsHandlerImpl::registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback) -{ - input()->registerTouchscreenSwipeShortcut(direction, fingerCount, action, progressCallback); -} - -void EffectsHandlerImpl::startMousePolling() -{ - if (Cursors::self()->mouse()) { - Cursors::self()->mouse()->startMousePolling(); - } -} - -void EffectsHandlerImpl::stopMousePolling() -{ - if (Cursors::self()->mouse()) { - Cursors::self()->mouse()->stopMousePolling(); - } -} - -bool EffectsHandlerImpl::hasKeyboardGrab() const -{ - return keyboard_grab_effect != nullptr; -} - -void EffectsHandlerImpl::registerPropertyType(long atom, bool reg) -{ - if (reg) { - ++registered_atoms[atom]; // initialized to 0 if not present yet - } else { - if (--registered_atoms[atom] == 0) { - registered_atoms.remove(atom); - } - } -} - -xcb_atom_t EffectsHandlerImpl::announceSupportProperty(const QByteArray &propertyName, Effect *effect) -{ - PropertyEffectMap::iterator it = m_propertiesForEffects.find(propertyName); - if (it != m_propertiesForEffects.end()) { - // property has already been registered for an effect - // just append Effect and return the atom stored in m_managedProperties - if (!it.value().contains(effect)) { - it.value().append(effect); - } - return m_managedProperties.value(propertyName, XCB_ATOM_NONE); - } - m_propertiesForEffects.insert(propertyName, QList() << effect); - const auto atom = registerSupportProperty(propertyName); - if (atom == XCB_ATOM_NONE) { - return atom; - } - m_compositor->keepSupportProperty(atom); - m_managedProperties.insert(propertyName, atom); - registerPropertyType(atom, true); - return atom; -} - -void EffectsHandlerImpl::removeSupportProperty(const QByteArray &propertyName, Effect *effect) -{ - PropertyEffectMap::iterator it = m_propertiesForEffects.find(propertyName); - if (it == m_propertiesForEffects.end()) { - // property is not registered - nothing to do - return; - } - if (!it.value().contains(effect)) { - // property is not registered for given effect - nothing to do - return; - } - it.value().removeAll(effect); - if (!it.value().isEmpty()) { - // property still registered for another effect - nothing further to do - return; - } - const xcb_atom_t atom = m_managedProperties.take(propertyName); - registerPropertyType(atom, false); - m_propertiesForEffects.remove(propertyName); - m_compositor->removeSupportProperty(atom); // delayed removal -} - -QByteArray EffectsHandlerImpl::readRootProperty(long atom, long type, int format) const -{ - if (!kwinApp()->x11Connection()) { - return QByteArray(); - } - return readWindowProperty(kwinApp()->x11RootWindow(), atom, type, format); -} - -void EffectsHandlerImpl::activateWindow(EffectWindow *effectWindow) -{ - auto window = effectWindow->window(); - if (window->isClient()) { - Workspace::self()->activateWindow(window, true); - } -} - -EffectWindow *EffectsHandlerImpl::activeWindow() const -{ - return Workspace::self()->activeWindow() ? Workspace::self()->activeWindow()->effectWindow() : nullptr; -} - -void EffectsHandlerImpl::moveWindow(EffectWindow *w, const QPoint &pos, bool snap, double snapAdjust) -{ - auto window = w->window(); - if (!window->isClient() || !window->isMovable()) { - return; - } - - if (snap) { - window->move(Workspace::self()->adjustWindowPosition(window, pos, true, snapAdjust)); - } else { - window->move(pos); - } -} - -void EffectsHandlerImpl::windowToDesktops(EffectWindow *w, const QList &desktops) -{ - auto window = w->window(); - if (!window->isClient() || window->isDesktop() || window->isDock()) { - return; - } - window->setDesktops(desktops); -} - -void EffectsHandlerImpl::windowToScreen(EffectWindow *w, Output *screen) -{ - auto window = w->window(); - if (window->isClient() && !window->isDesktop() && !window->isDock()) { - Workspace::self()->sendWindowToOutput(window, screen); - } -} - -void EffectsHandlerImpl::setShowingDesktop(bool showing) -{ - Workspace::self()->setShowingDesktop(showing); -} - -QString EffectsHandlerImpl::currentActivity() const -{ -#if KWIN_BUILD_ACTIVITIES - if (!Workspace::self()->activities()) { - return QString(); - } - return Workspace::self()->activities()->current(); -#else - return QString(); -#endif -} - -VirtualDesktop *EffectsHandlerImpl::currentDesktop() const -{ - return VirtualDesktopManager::self()->currentDesktop(); -} - -QList EffectsHandlerImpl::desktops() const -{ - return VirtualDesktopManager::self()->desktops(); -} - -void EffectsHandlerImpl::setCurrentDesktop(VirtualDesktop *desktop) -{ - VirtualDesktopManager::self()->setCurrent(desktop); -} - -QSize EffectsHandlerImpl::desktopGridSize() const -{ - return VirtualDesktopManager::self()->grid().size(); -} - -int EffectsHandlerImpl::desktopGridWidth() const -{ - return desktopGridSize().width(); -} - -int EffectsHandlerImpl::desktopGridHeight() const -{ - return desktopGridSize().height(); -} - -int EffectsHandlerImpl::workspaceWidth() const -{ - return desktopGridWidth() * Workspace::self()->geometry().width(); -} - -int EffectsHandlerImpl::workspaceHeight() const -{ - return desktopGridHeight() * Workspace::self()->geometry().height(); -} - -VirtualDesktop *EffectsHandlerImpl::desktopAtCoords(QPoint coords) const -{ - return VirtualDesktopManager::self()->grid().at(coords); -} - -QPoint EffectsHandlerImpl::desktopGridCoords(VirtualDesktop *desktop) const -{ - return VirtualDesktopManager::self()->grid().gridCoords(desktop); -} - -QPoint EffectsHandlerImpl::desktopCoords(VirtualDesktop *desktop) const -{ - QPoint coords = VirtualDesktopManager::self()->grid().gridCoords(desktop); - if (coords.x() == -1) { - return QPoint(-1, -1); - } - const QSize displaySize = Workspace::self()->geometry().size(); - return QPoint(coords.x() * displaySize.width(), coords.y() * displaySize.height()); -} - -VirtualDesktop *EffectsHandlerImpl::desktopAbove(VirtualDesktop *desktop, bool wrap) const -{ - return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Up, wrap); -} - -VirtualDesktop *EffectsHandlerImpl::desktopToRight(VirtualDesktop *desktop, bool wrap) const -{ - return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Right, wrap); -} - -VirtualDesktop *EffectsHandlerImpl::desktopBelow(VirtualDesktop *desktop, bool wrap) const -{ - return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Down, wrap); -} - -VirtualDesktop *EffectsHandlerImpl::desktopToLeft(VirtualDesktop *desktop, bool wrap) const -{ - return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Left, wrap); -} - -QString EffectsHandlerImpl::desktopName(VirtualDesktop *desktop) const -{ - return desktop->name(); -} - -bool EffectsHandlerImpl::optionRollOverDesktops() const -{ - return options->isRollOverDesktops(); -} - -double EffectsHandlerImpl::animationTimeFactor() const -{ - return options->animationTimeFactor(); -} - -EffectWindow *EffectsHandlerImpl::findWindow(WId id) const -{ - if (X11Window *w = Workspace::self()->findClient(Predicate::WindowMatch, id)) { - return w->effectWindow(); - } - if (X11Window *w = Workspace::self()->findUnmanaged(id)) { - return w->effectWindow(); - } - return nullptr; -} - -EffectWindow *EffectsHandlerImpl::findWindow(SurfaceInterface *surf) const -{ - if (waylandServer()) { - if (Window *w = waylandServer()->findWindow(surf)) { - return w->effectWindow(); - } - } - return nullptr; -} - -EffectWindow *EffectsHandlerImpl::findWindow(QWindow *w) const -{ - if (Window *window = workspace()->findInternal(w)) { - return window->effectWindow(); - } - return nullptr; -} - -EffectWindow *EffectsHandlerImpl::findWindow(const QUuid &id) const -{ - if (Window *window = workspace()->findWindow(id)) { - return window->effectWindow(); - } - return nullptr; -} - -EffectWindowList EffectsHandlerImpl::stackingOrder() const -{ - QList list = workspace()->stackingOrder(); - EffectWindowList ret; - for (Window *t : list) { - if (EffectWindow *w = t->effectWindow()) { - ret.append(w); - } - } - return ret; -} - -void EffectsHandlerImpl::setElevatedWindow(KWin::EffectWindow *w, bool set) -{ - WindowItem *item = w->windowItem(); - - if (set) { - item->elevate(); - } else { - item->deelevate(); - } -} - -void EffectsHandlerImpl::setTabBoxWindow(EffectWindow *w) -{ -#if KWIN_BUILD_TABBOX - auto window = w->window(); - if (window->isClient()) { - workspace()->tabbox()->setCurrentClient(window); - } -#endif -} - -EffectWindowList EffectsHandlerImpl::currentTabBoxWindowList() const -{ -#if KWIN_BUILD_TABBOX - const auto clients = workspace()->tabbox()->currentClientList(); - EffectWindowList ret; - ret.reserve(clients.size()); - std::transform(std::cbegin(clients), std::cend(clients), - std::back_inserter(ret), - [](auto client) { - return client->effectWindow(); - }); - return ret; -#else - return EffectWindowList(); -#endif -} - -void EffectsHandlerImpl::refTabBox() -{ -#if KWIN_BUILD_TABBOX - workspace()->tabbox()->reference(); -#endif -} - -void EffectsHandlerImpl::unrefTabBox() -{ -#if KWIN_BUILD_TABBOX - workspace()->tabbox()->unreference(); -#endif -} - -void EffectsHandlerImpl::closeTabBox() -{ -#if KWIN_BUILD_TABBOX - workspace()->tabbox()->close(); -#endif -} - -EffectWindow *EffectsHandlerImpl::currentTabBoxWindow() const -{ -#if KWIN_BUILD_TABBOX - if (auto c = workspace()->tabbox()->currentClient()) { - return c->effectWindow(); - } -#endif - return nullptr; -} - -void EffectsHandlerImpl::addRepaintFull() -{ - m_compositor->scene()->addRepaintFull(); -} - -void EffectsHandlerImpl::addRepaint(const QRect &r) -{ - m_compositor->scene()->addRepaint(r); -} - -void EffectsHandlerImpl::addRepaint(const QRectF &r) -{ - m_compositor->scene()->addRepaint(r.toAlignedRect()); -} - -void EffectsHandlerImpl::addRepaint(const QRegion &r) -{ - m_compositor->scene()->addRepaint(r); -} - -void EffectsHandlerImpl::addRepaint(int x, int y, int w, int h) -{ - m_compositor->scene()->addRepaint(x, y, w, h); -} - -Output *EffectsHandlerImpl::activeScreen() const -{ - return workspace()->activeOutput(); -} - -QRectF EffectsHandlerImpl::clientArea(clientAreaOption opt, const Output *screen, const VirtualDesktop *desktop) const -{ - return Workspace::self()->clientArea(opt, screen, desktop); -} - -QRectF EffectsHandlerImpl::clientArea(clientAreaOption opt, const EffectWindow *effectWindow) const -{ - const Window *window = effectWindow->window(); - return Workspace::self()->clientArea(opt, window); -} - -QRectF EffectsHandlerImpl::clientArea(clientAreaOption opt, const QPoint &p, const VirtualDesktop *desktop) const -{ - const Output *output = Workspace::self()->outputAt(p); - return Workspace::self()->clientArea(opt, output, desktop); -} - -QRect EffectsHandlerImpl::virtualScreenGeometry() const -{ - return Workspace::self()->geometry(); -} - -QSize EffectsHandlerImpl::virtualScreenSize() const -{ - return Workspace::self()->geometry().size(); -} - -void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape) -{ - input()->pointer()->setEffectsOverrideCursor(shape); -} - -bool EffectsHandlerImpl::checkInputWindowEvent(QMouseEvent *e) -{ - if (m_grabbedMouseEffects.isEmpty()) { - return false; - } - for (Effect *effect : std::as_const(m_grabbedMouseEffects)) { - effect->windowInputMouseEvent(e); - } - return true; -} - -bool EffectsHandlerImpl::checkInputWindowEvent(QWheelEvent *e) -{ - if (m_grabbedMouseEffects.isEmpty()) { - return false; - } - for (Effect *effect : std::as_const(m_grabbedMouseEffects)) { - effect->windowInputMouseEvent(e); - } - return true; -} - -void EffectsHandlerImpl::connectNotify(const QMetaMethod &signal) -{ - if (signal == QMetaMethod::fromSignal(&EffectsHandler::cursorShapeChanged)) { - if (!m_trackingCursorChanges) { - connect(Cursors::self()->mouse(), &Cursor::cursorChanged, this, &EffectsHandler::cursorShapeChanged); - Cursors::self()->mouse()->startCursorTracking(); - } - ++m_trackingCursorChanges; - } - EffectsHandler::connectNotify(signal); -} - -void EffectsHandlerImpl::disconnectNotify(const QMetaMethod &signal) -{ - if (signal == QMetaMethod::fromSignal(&EffectsHandler::cursorShapeChanged)) { - Q_ASSERT(m_trackingCursorChanges > 0); - if (!--m_trackingCursorChanges) { - Cursors::self()->mouse()->stopCursorTracking(); - disconnect(Cursors::self()->mouse(), &Cursor::cursorChanged, this, &EffectsHandler::cursorShapeChanged); - } - } - EffectsHandler::disconnectNotify(signal); -} - -void EffectsHandlerImpl::checkInputWindowStacking() -{ - if (m_grabbedMouseEffects.isEmpty()) { - return; - } - doCheckInputWindowStacking(); -} - -void EffectsHandlerImpl::doCheckInputWindowStacking() -{ -} - -QPointF EffectsHandlerImpl::cursorPos() const -{ - return Cursors::self()->mouse()->pos(); -} - -void EffectsHandlerImpl::reserveElectricBorder(ElectricBorder border, Effect *effect) -{ - workspace()->screenEdges()->reserve(border, effect, "borderActivated"); -} - -void EffectsHandlerImpl::unreserveElectricBorder(ElectricBorder border, Effect *effect) -{ - workspace()->screenEdges()->unreserve(border, effect); -} - -void EffectsHandlerImpl::registerTouchBorder(ElectricBorder border, QAction *action) -{ - workspace()->screenEdges()->reserveTouch(border, action); -} - -void EffectsHandlerImpl::registerRealtimeTouchBorder(ElectricBorder border, QAction *action, EffectsHandler::TouchBorderCallback progressCallback) -{ - workspace()->screenEdges()->reserveTouch(border, action, progressCallback); -} - -void EffectsHandlerImpl::unregisterTouchBorder(ElectricBorder border, QAction *action) -{ - workspace()->screenEdges()->unreserveTouch(border, action); -} - -QPainter *EffectsHandlerImpl::scenePainter() -{ - return m_scene->renderer()->painter(); -} - -void EffectsHandlerImpl::toggleEffect(const QString &name) -{ - if (isEffectLoaded(name)) { - unloadEffect(name); - } else { - loadEffect(name); - } -} - -QStringList EffectsHandlerImpl::loadedEffects() const -{ - QStringList listModules; - listModules.reserve(loaded_effects.count()); - std::transform(loaded_effects.constBegin(), loaded_effects.constEnd(), - std::back_inserter(listModules), - [](const EffectPair &pair) { - return pair.first; - }); - return listModules; -} - -QStringList EffectsHandlerImpl::listOfEffects() const -{ - return m_effectLoader->listOfKnownEffects(); -} - -bool EffectsHandlerImpl::loadEffect(const QString &name) -{ - makeOpenGLContextCurrent(); - m_compositor->scene()->addRepaintFull(); - - return m_effectLoader->loadEffect(name); -} - -void EffectsHandlerImpl::unloadEffect(const QString &name) -{ - auto it = std::find_if(effect_order.begin(), effect_order.end(), - [name](EffectPair &pair) { - return pair.first == name; - }); - if (it == effect_order.end()) { - qCDebug(KWIN_CORE) << "EffectsHandler::unloadEffect : Effect not loaded :" << name; - return; - } - - qCDebug(KWIN_CORE) << "EffectsHandler::unloadEffect : Unloading Effect :" << name; - destroyEffect((*it).second); - effect_order.erase(it); - effectsChanged(); - - m_compositor->scene()->addRepaintFull(); -} - -void EffectsHandlerImpl::destroyEffect(Effect *effect) -{ - makeOpenGLContextCurrent(); - - if (fullscreen_effect == effect) { - setActiveFullScreenEffect(nullptr); - } - - if (keyboard_grab_effect == effect) { - ungrabKeyboard(); - } - - stopMouseInterception(effect); - - const QList properties = m_propertiesForEffects.keys(); - for (const QByteArray &property : properties) { - removeSupportProperty(property, effect); - } - - delete effect; -} - -void EffectsHandlerImpl::reconfigureEffects() -{ - makeOpenGLContextCurrent(); - for (const EffectPair &pair : loaded_effects) { - pair.second->reconfigure(Effect::ReconfigureAll); - } -} - -void EffectsHandlerImpl::reconfigureEffect(const QString &name) -{ - for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if ((*it).first == name) { - kwinApp()->config()->reparseConfiguration(); - makeOpenGLContextCurrent(); - (*it).second->reconfigure(Effect::ReconfigureAll); - return; - } - } -} - -bool EffectsHandlerImpl::isEffectLoaded(const QString &name) const -{ - auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), - [&name](const EffectPair &pair) { - return pair.first == name; - }); - return it != loaded_effects.constEnd(); -} - -bool EffectsHandlerImpl::isEffectSupported(const QString &name) -{ - // If the effect is loaded, it is obviously supported. - if (isEffectLoaded(name)) { - return true; - } - - // next checks might require a context - makeOpenGLContextCurrent(); - - return m_effectLoader->isEffectSupported(name); -} - -QList EffectsHandlerImpl::areEffectsSupported(const QStringList &names) -{ - QList retList; - retList.reserve(names.count()); - std::transform(names.constBegin(), names.constEnd(), - std::back_inserter(retList), - [this](const QString &name) { - return isEffectSupported(name); - }); - return retList; -} - -void EffectsHandlerImpl::reloadEffect(Effect *effect) -{ - QString effectName; - for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if ((*it).second == effect) { - effectName = (*it).first; - break; - } - } - if (!effectName.isNull()) { - unloadEffect(effectName); - m_effectLoader->loadEffect(effectName); - } -} - -void EffectsHandlerImpl::effectsChanged() -{ - loaded_effects.clear(); - m_activeEffects.clear(); // it's possible to have a reconfigure and a quad rebuild between two paint cycles - bug #308201 - - loaded_effects.reserve(effect_order.count()); - std::copy(effect_order.constBegin(), effect_order.constEnd(), - std::back_inserter(loaded_effects)); - - m_activeEffects.reserve(loaded_effects.count()); - - m_currentPaintScreenIterator = m_activeEffects.constBegin(); - m_currentPaintWindowIterator = m_activeEffects.constBegin(); - m_currentDrawWindowIterator = m_activeEffects.constBegin(); -} - -QStringList EffectsHandlerImpl::activeEffects() const -{ - QStringList ret; - for (QList::const_iterator it = loaded_effects.constBegin(), - end = loaded_effects.constEnd(); - it != end; ++it) { - if (it->second->isActive()) { - ret << it->first; - } - } - return ret; -} - -bool EffectsHandlerImpl::isEffectActive(const QString &pluginId) const -{ - auto it = std::find_if(loaded_effects.cbegin(), loaded_effects.cend(), [&pluginId](const EffectPair &p) { - return p.first == pluginId; - }); - if (it == loaded_effects.cend()) { - return false; - } - return it->second->isActive(); -} - -bool EffectsHandlerImpl::blocksDirectScanout() const -{ - return std::any_of(m_activeEffects.constBegin(), m_activeEffects.constEnd(), [](const Effect *effect) { - return effect->blocksDirectScanout(); - }); -} - -Display *EffectsHandlerImpl::waylandDisplay() const -{ - if (waylandServer()) { - return waylandServer()->display(); - } - return nullptr; -} - -QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt) -{ - switch (kwopt) { - case CloseButtonCorner: { - // TODO: this could become per window and be derived from the actual position in the deco - const auto settings = Workspace::self()->decorationBridge()->settings(); - return settings && settings->decorationButtonsLeft().contains(KDecoration2::DecorationButtonType::Close) ? Qt::TopLeftCorner : Qt::TopRightCorner; - } - case SwitchDesktopOnScreenEdge: - return workspace()->screenEdges()->isDesktopSwitching(); - case SwitchDesktopOnScreenEdgeMovingWindows: - return workspace()->screenEdges()->isDesktopSwitchingMovingClients(); - default: - return QVariant(); // an invalid one - } -} - -QString EffectsHandlerImpl::supportInformation(const QString &name) const -{ - auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), - [name](const EffectPair &pair) { - return pair.first == name; - }); - if (it == loaded_effects.constEnd()) { - return QString(); - } - - QString support((*it).first + QLatin1String(":\n")); - const QMetaObject *metaOptions = (*it).second->metaObject(); - for (int i = 0; i < metaOptions->propertyCount(); ++i) { - const QMetaProperty property = metaOptions->property(i); - if (qstrcmp(property.name(), "objectName") == 0) { - continue; - } - support += QString::fromUtf8(property.name()) + QLatin1String(": ") + (*it).second->property(property.name()).toString() + QLatin1Char('\n'); - } - - return support; -} - -bool EffectsHandlerImpl::isScreenLocked() const -{ -#if KWIN_BUILD_SCREENLOCKER - return kwinApp()->screenLockerWatcher()->isLocked(); -#else - return false; -#endif -} - -QString EffectsHandlerImpl::debug(const QString &name, const QString ¶meter) const -{ - QString internalName = name.toLower(); - for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { - if ((*it).first == internalName) { - return it->second->debug(parameter); - } - } - return QString(); -} - -bool EffectsHandlerImpl::makeOpenGLContextCurrent() -{ - return m_scene->makeOpenGLContextCurrent(); -} - -void EffectsHandlerImpl::doneOpenGLContextCurrent() -{ - m_scene->doneOpenGLContextCurrent(); -} - -bool EffectsHandlerImpl::animationsSupported() const -{ - static const QByteArray forceEnvVar = qgetenv("KWIN_EFFECTS_FORCE_ANIMATIONS"); - if (!forceEnvVar.isEmpty()) { - static const int forceValue = forceEnvVar.toInt(); - return forceValue == 1; - } - return m_scene->animationsSupported(); -} - -void EffectsHandlerImpl::highlightWindows(const QList &windows) -{ - Effect *e = provides(Effect::HighlightWindows); - if (!e) { - return; - } - e->perform(Effect::HighlightWindows, QVariantList{QVariant::fromValue(windows)}); -} - -PlatformCursorImage EffectsHandlerImpl::cursorImage() const -{ - return kwinApp()->cursorImage(); -} - -void EffectsHandlerImpl::hideCursor() -{ - Cursors::self()->hideCursor(); -} - -void EffectsHandlerImpl::showCursor() -{ - Cursors::self()->showCursor(); -} - -void EffectsHandlerImpl::startInteractiveWindowSelection(std::function callback) -{ - kwinApp()->startInteractiveWindowSelection([callback](KWin::Window *window) { - if (window && window->effectWindow()) { - callback(window->effectWindow()); - } else { - callback(nullptr); - } - }); -} - -void EffectsHandlerImpl::startInteractivePositionSelection(std::function callback) -{ - kwinApp()->startInteractivePositionSelection(callback); -} - -void EffectsHandlerImpl::showOnScreenMessage(const QString &message, const QString &iconName) -{ - OSD::show(message, iconName); -} - -void EffectsHandlerImpl::hideOnScreenMessage(OnScreenMessageHideFlags flags) -{ - OSD::HideFlags osdFlags; - if (flags.testFlag(OnScreenMessageHideFlag::SkipsCloseAnimation)) { - osdFlags |= OSD::HideFlag::SkipCloseAnimation; - } - OSD::hide(osdFlags); -} - -KSharedConfigPtr EffectsHandlerImpl::config() const -{ - return kwinApp()->config(); -} - -KSharedConfigPtr EffectsHandlerImpl::inputConfig() const -{ - return kwinApp()->inputConfig(); -} - -Effect *EffectsHandlerImpl::findEffect(const QString &name) const -{ - auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), [name](const EffectPair &pair) { - return pair.first == name; - }); - if (it == loaded_effects.constEnd()) { - return nullptr; - } - return (*it).second; -} - -void EffectsHandlerImpl::renderOffscreenQuickView(const RenderTarget &renderTarget, const RenderViewport &viewport, OffscreenQuickView *w) const -{ - if (!w->isVisible()) { - return; - } - if (compositingType() == OpenGLCompositing) { - GLTexture *t = w->bufferAsTexture(); - if (!t) { - return; - } - - ShaderTraits traits = ShaderTrait::MapTexture | ShaderTrait::TransformColorspace; - const qreal a = w->opacity(); - if (a != 1.0) { - traits |= ShaderTrait::Modulate; - } - - GLShader *shader = ShaderManager::instance()->pushShader(traits); - const QRectF rect = scaledRect(w->geometry(), viewport.scale()); - - QMatrix4x4 mvp(viewport.projectionMatrix()); - mvp.translate(rect.x(), rect.y()); - shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - - if (a != 1.0) { - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); - - const bool alphaBlending = w->hasAlphaChannel() || (a != 1.0); - if (alphaBlending) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - - t->render(w->size(), viewport.scale()); - - if (alphaBlending) { - glDisable(GL_BLEND); - } - - ShaderManager::instance()->popShader(); - } else if (compositingType() == QPainterCompositing) { - QPainter *painter = effects->scenePainter(); - const QImage buffer = w->bufferAsImage(); - if (buffer.isNull()) { - return; - } - painter->save(); - painter->setOpacity(w->opacity()); - painter->drawImage(w->geometry(), buffer); - painter->restore(); - } -} - -SessionState EffectsHandlerImpl::sessionState() const -{ - return Workspace::self()->sessionManager()->state(); -} - -QList EffectsHandlerImpl::screens() const -{ - return Workspace::self()->outputs(); -} - -Output *EffectsHandlerImpl::screenAt(const QPoint &point) const -{ - return Workspace::self()->outputAt(point); -} - -Output *EffectsHandlerImpl::findScreen(const QString &name) const -{ - const auto outputs = Workspace::self()->outputs(); - for (Output *screen : outputs) { - if (screen->name() == name) { - return screen; - } - } - return nullptr; -} - -Output *EffectsHandlerImpl::findScreen(int screenId) const -{ - return Workspace::self()->outputs().value(screenId); -} - -void EffectsHandlerImpl::renderScreen(Output *output) -{ - RenderTarget renderTarget(GLFramebuffer::currentFramebuffer()); - - RenderLayer layer(output->renderLoop()); - SceneDelegate delegate(m_scene, output); - delegate.setLayer(&layer); - - m_scene->prePaint(&delegate); - m_scene->paint(renderTarget, output->geometry()); - m_scene->postPaint(); -} - -bool EffectsHandlerImpl::isCursorHidden() const -{ - return Cursors::self()->isCursorHidden(); -} - -KWin::EffectWindow *EffectsHandlerImpl::inputPanel() const -{ - if (!kwinApp()->inputMethod() || !kwinApp()->inputMethod()->isEnabled()) { - return nullptr; - } - - auto panel = kwinApp()->inputMethod()->panel(); - if (panel) { - return panel->effectWindow(); - } - return nullptr; -} - -bool EffectsHandlerImpl::isInputPanelOverlay() const -{ - if (!kwinApp()->inputMethod() || !kwinApp()->inputMethod()->isEnabled()) { - return true; - } - - auto panel = kwinApp()->inputMethod()->panel(); - if (panel) { - return panel->mode() == InputPanelV1Window::Mode::Overlay; - } - return true; -} - -QQmlEngine *EffectsHandlerImpl::qmlEngine() const -{ - return Scripting::self()->qmlEngine(); -} - -} // namespace - -#include "moc_effects.cpp" diff --git a/src/effects.h b/src/effects.h deleted file mode 100644 index 4e6c9e03d0..0000000000 --- a/src/effects.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2006 Lubos Lunak - SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#pragma once - -#include "libkwineffects/kwineffects.h" -#include "scene/workspacescene.h" - -#include - -#include - -class QMouseEvent; -class QWheelEvent; - -class QDBusPendingCallWatcher; -class QDBusServiceWatcher; - -namespace KWin -{ -class Display; -class Window; -class Compositor; -class EffectLoader; -class Unmanaged; -class WindowPropertyNotifyX11Filter; -class TabletEvent; -class TabletPadId; -class TabletToolId; - -class KWIN_EXPORT EffectsHandlerImpl : public EffectsHandler -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Effects") - Q_PROPERTY(QStringList activeEffects READ activeEffects) - Q_PROPERTY(QStringList loadedEffects READ loadedEffects) - Q_PROPERTY(QStringList listOfEffects READ listOfEffects) -public: - EffectsHandlerImpl(Compositor *compositor, WorkspaceScene *scene); - ~EffectsHandlerImpl() override; - void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; - void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) override; - void postPaintScreen() override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; - void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; - void postPaintWindow(EffectWindow *w) override; - - Effect *provides(Effect::Feature ef); - - void drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; - void renderWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; - - void activateWindow(EffectWindow *c) override; - EffectWindow *activeWindow() const override; - void moveWindow(EffectWindow *w, const QPoint &pos, bool snap = false, double snapAdjust = 1.0) override; - void windowToScreen(EffectWindow *w, Output *screen) override; - void setShowingDesktop(bool showing) override; - - QString currentActivity() const override; - VirtualDesktop *currentDesktop() const override; - QList desktops() const override; - void setCurrentDesktop(VirtualDesktop *desktop) override; - QSize desktopGridSize() const override; - int desktopGridWidth() const override; - int desktopGridHeight() const override; - int workspaceWidth() const override; - int workspaceHeight() const override; - VirtualDesktop *desktopAtCoords(QPoint coords) const override; - QPoint desktopGridCoords(VirtualDesktop *desktop) const override; - QPoint desktopCoords(VirtualDesktop *desktop) const override; - VirtualDesktop *desktopAbove(VirtualDesktop *desktop = nullptr, bool wrap = true) const override; - VirtualDesktop *desktopToRight(VirtualDesktop *desktop = nullptr, bool wrap = true) const override; - VirtualDesktop *desktopBelow(VirtualDesktop *desktop = nullptr, bool wrap = true) const override; - VirtualDesktop *desktopToLeft(VirtualDesktop *desktop = nullptr, bool wrap = true) const override; - QString desktopName(VirtualDesktop *desktop) const override; - bool optionRollOverDesktops() const override; - - QPointF cursorPos() const override; - bool grabKeyboard(Effect *effect) override; - void ungrabKeyboard() override; - // not performing XGrabPointer - void startMouseInterception(Effect *effect, Qt::CursorShape shape) override; - void stopMouseInterception(Effect *effect) override; - bool isMouseInterception() const; - void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) override; - void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) override; - void registerTouchpadSwipeShortcut(SwipeDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback) override; - void registerTouchpadPinchShortcut(PinchDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback) override; - void registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback) override; - void startMousePolling() override; - void stopMousePolling() override; - EffectWindow *findWindow(WId id) const override; - EffectWindow *findWindow(SurfaceInterface *surf) const override; - EffectWindow *findWindow(QWindow *w) const override; - EffectWindow *findWindow(const QUuid &id) const override; - EffectWindowList stackingOrder() const override; - void setElevatedWindow(KWin::EffectWindow *w, bool set) override; - - void setTabBoxWindow(EffectWindow *) override; - EffectWindowList currentTabBoxWindowList() const override; - void refTabBox() override; - void unrefTabBox() override; - void closeTabBox() override; - EffectWindow *currentTabBoxWindow() const override; - - void setActiveFullScreenEffect(Effect *e) override; - Effect *activeFullScreenEffect() const override; - bool hasActiveFullScreenEffect() const override; - - void addRepaintFull() override; - void addRepaint(const QRect &r) override; - void addRepaint(const QRectF &r) override; - - void addRepaint(const QRegion &r) override; - void addRepaint(int x, int y, int w, int h) override; - Output *activeScreen() const override; - QRectF clientArea(clientAreaOption, const Output *screen, const VirtualDesktop *desktop) const override; - QRectF clientArea(clientAreaOption, const EffectWindow *c) const override; - QRectF clientArea(clientAreaOption, const QPoint &p, const VirtualDesktop *desktop) const override; - QSize virtualScreenSize() const override; - QRect virtualScreenGeometry() const override; - double animationTimeFactor() const override; - - void defineCursor(Qt::CursorShape shape) override; - bool checkInputWindowEvent(QMouseEvent *e); - bool checkInputWindowEvent(QWheelEvent *e); - void checkInputWindowStacking(); - - void reserveElectricBorder(ElectricBorder border, Effect *effect) override; - void unreserveElectricBorder(ElectricBorder border, Effect *effect) override; - - void registerTouchBorder(ElectricBorder border, QAction *action) override; - void registerRealtimeTouchBorder(ElectricBorder border, QAction *action, EffectsHandler::TouchBorderCallback progressCallback) override; - void unregisterTouchBorder(ElectricBorder border, QAction *action) override; - - QPainter *scenePainter() override; - void reconfigure() override; - QByteArray readRootProperty(long atom, long type, int format) const override; - xcb_atom_t announceSupportProperty(const QByteArray &propertyName, Effect *effect) override; - void removeSupportProperty(const QByteArray &propertyName, Effect *effect) override; - - bool hasDecorationShadows() const override; - - bool decorationsHaveAlpha() const override; - - QVariant kwinOption(KWinOption kwopt) override; - bool isScreenLocked() const override; - - bool makeOpenGLContextCurrent() override; - void doneOpenGLContextCurrent() override; - - xcb_connection_t *xcbConnection() const override; - xcb_window_t x11RootWindow() const override; - - // internal (used by kwin core or compositing code) - void startPaint(); - void grabbedKeyboardEvent(QKeyEvent *e); - bool hasKeyboardGrab() const; - - void reloadEffect(Effect *effect) override; - QStringList loadedEffects() const; - QStringList listOfEffects() const; - void unloadAllEffects(); - QStringList activeEffects() const; - bool isEffectActive(const QString &pluginId) const; - - /** - * @returns whether or not any effect is currently active where KWin should not use direct scanout - */ - bool blocksDirectScanout() const; - - Display *waylandDisplay() const override; - - bool animationsSupported() const override; - - PlatformCursorImage cursorImage() const override; - - void hideCursor() override; - void showCursor() override; - - void startInteractiveWindowSelection(std::function callback) override; - void startInteractivePositionSelection(std::function callback) override; - - void showOnScreenMessage(const QString &message, const QString &iconName = QString()) override; - void hideOnScreenMessage(OnScreenMessageHideFlags flags = OnScreenMessageHideFlags()) override; - - KSharedConfigPtr config() const override; - KSharedConfigPtr inputConfig() const override; - - WorkspaceScene *scene() const - { - return m_scene; - } - - bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time); - bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time); - bool touchUp(qint32 id, std::chrono::microseconds time); - - bool tabletToolEvent(KWin::TabletEvent *event); - bool tabletToolButtonEvent(uint button, bool pressed, const KWin::TabletToolId &tabletToolId, std::chrono::microseconds time); - bool tabletPadButtonEvent(uint button, bool pressed, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time); - bool tabletPadStripEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time); - bool tabletPadRingEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time); - - void highlightWindows(const QList &windows); - - bool isPropertyTypeRegistered(xcb_atom_t atom) const - { - return registered_atoms.contains(atom); - } - - void windowToDesktops(EffectWindow *w, const QList &desktops) override; - - /** - * Finds an effect with the given name. - * - * @param name The name of the effect. - * @returns The effect with the given name @p name, or nullptr if there - * is no such effect loaded. - */ - Effect *findEffect(const QString &name) const; - - void renderOffscreenQuickView(const RenderTarget &renderTarget, const RenderViewport &viewport, OffscreenQuickView *effectQuickView) const override; - - SessionState sessionState() const override; - QList screens() const override; - Output *screenAt(const QPoint &point) const override; - Output *findScreen(const QString &name) const override; - Output *findScreen(int screenId) const override; - void renderScreen(Output *screen) override; - bool isCursorHidden() const override; - - KWin::EffectWindow *inputPanel() const override; - bool isInputPanelOverlay() const override; - - QQmlEngine *qmlEngine() const override; - -public Q_SLOTS: - // slots for D-Bus interface - Q_SCRIPTABLE void reconfigureEffect(const QString &name); - Q_SCRIPTABLE bool loadEffect(const QString &name); - Q_SCRIPTABLE void toggleEffect(const QString &name); - Q_SCRIPTABLE void unloadEffect(const QString &name); - Q_SCRIPTABLE bool isEffectLoaded(const QString &name) const; - Q_SCRIPTABLE bool isEffectSupported(const QString &name); - Q_SCRIPTABLE QList areEffectsSupported(const QStringList &names); - Q_SCRIPTABLE QString supportInformation(const QString &name) const; - Q_SCRIPTABLE QString debug(const QString &name, const QString ¶meter = QString()) const; - -protected: - void connectNotify(const QMetaMethod &signal) override; - void disconnectNotify(const QMetaMethod &signal) override; - void effectsChanged(); - void setupWindowConnections(KWin::Window *window); - - /** - * Default implementation does nothing and returns @c true. - */ - virtual bool doGrabKeyboard(); - /** - * Default implementation does nothing. - */ - virtual void doUngrabKeyboard(); - - /** - * Default implementation sets Effects override cursor on the PointerInputRedirection. - */ - virtual void doStartMouseInterception(Qt::CursorShape shape); - - /** - * Default implementation removes the Effects override cursor on the PointerInputRedirection. - */ - virtual void doStopMouseInterception(); - - /** - * Default implementation does nothing - */ - virtual void doCheckInputWindowStacking(); - - Effect *keyboard_grab_effect; - Effect *fullscreen_effect; - QMultiMap effect_order; - QHash registered_atoms; - -private: - void registerPropertyType(long atom, bool reg); - void destroyEffect(Effect *effect); - void reconfigureEffects(); - - typedef QList EffectsList; - typedef EffectsList::const_iterator EffectsIterator; - EffectsList m_activeEffects; - EffectsIterator m_currentDrawWindowIterator; - EffectsIterator m_currentPaintWindowIterator; - EffectsIterator m_currentPaintScreenIterator; - typedef QHash> PropertyEffectMap; - PropertyEffectMap m_propertiesForEffects; - QHash m_managedProperties; - Compositor *m_compositor; - WorkspaceScene *m_scene; - QList m_grabbedMouseEffects; - EffectLoader *m_effectLoader; - int m_trackingCursorChanges; - std::unique_ptr m_x11WindowPropertyNotify; -}; - -inline xcb_window_t EffectsHandlerImpl::x11RootWindow() const -{ - return kwinApp()->x11RootWindow(); -} - -inline xcb_connection_t *EffectsHandlerImpl::xcbConnection() const -{ - return kwinApp()->x11Connection(); -} - -} // namespace diff --git a/src/events.cpp b/src/events.cpp index 9e4d5824db..2ba20a4a25 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -17,14 +17,9 @@ #include "atoms.h" #include "cursor.h" #include "focuschain.h" -#include "netinfo.h" -#include "workspace.h" -#include "x11window.h" -#if KWIN_BUILD_TABBOX -#include "tabbox/tabbox.h" -#endif -#include "effects.h" #include "group.h" +#include "libkwineffects/kwineffects.h" +#include "netinfo.h" #include "rules.h" #include "screenedge.h" #include "useractions.h" @@ -32,6 +27,12 @@ #include "wayland/surface.h" #include "wayland/xwaylandshell_v1.h" #include "wayland_server.h" +#include "workspace.h" +#include "x11window.h" + +#if KWIN_BUILD_TABBOX +#include "tabbox/tabbox.h" +#endif #include @@ -678,7 +679,7 @@ void X11Window::clientMessageEvent(xcb_client_message_event_t *e) void X11Window::configureNotifyEvent(xcb_configure_notify_event_t *e) { if (effects) { - static_cast(effects)->checkInputWindowStacking(); // keep them on top + effects->checkInputWindowStacking(); // keep them on top } QRectF newgeom(Xcb::fromXNative(e->x), Xcb::fromXNative(e->y), Xcb::fromXNative(e->width), Xcb::fromXNative(e->height)); if (newgeom != m_frameGeometry) { diff --git a/src/input.cpp b/src/input.cpp index 814040926b..77f26fe42e 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -15,7 +15,6 @@ #include "backends/libinput/device.h" #include "core/inputbackend.h" #include "core/session.h" -#include "effects.h" #include "gestures.h" #include "globalshortcuts.h" #include "hide_cursor_spy.h" @@ -529,23 +528,23 @@ public: if (!effects) { return false; } - return static_cast(effects)->checkInputWindowEvent(event); + return effects->checkInputWindowEvent(event); } bool wheelEvent(WheelEvent *event) override { if (!effects) { return false; } - return static_cast(effects)->checkInputWindowEvent(event); + return effects->checkInputWindowEvent(event); } bool keyEvent(KeyEvent *event) override { - if (!effects || !static_cast(effects)->hasKeyboardGrab()) { + if (!effects || !effects->hasKeyboardGrab()) { return false; } waylandServer()->seat()->setFocusedKeyboardSurface(nullptr); passToWaylandServer(event); - static_cast(effects)->grabbedKeyboardEvent(event); + effects->grabbedKeyboardEvent(event); return true; } bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override @@ -553,56 +552,56 @@ public: if (!effects) { return false; } - return static_cast(effects)->touchDown(id, pos, time); + return effects->touchDown(id, pos, time); } bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override { if (!effects) { return false; } - return static_cast(effects)->touchMotion(id, pos, time); + return effects->touchMotion(id, pos, time); } bool touchUp(qint32 id, std::chrono::microseconds time) override { if (!effects) { return false; } - return static_cast(effects)->touchUp(id, time); + return effects->touchUp(id, time); } bool tabletToolEvent(TabletEvent *event) override { if (!effects) { return false; } - return static_cast(effects)->tabletToolEvent(event); + return effects->tabletToolEvent(event); } bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override { if (!effects) { return false; } - return static_cast(effects)->tabletToolButtonEvent(button, pressed, tabletToolId, time); + return effects->tabletToolButtonEvent(button, pressed, tabletToolId, time); } bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override { if (!effects) { return false; } - return static_cast(effects)->tabletPadButtonEvent(button, pressed, tabletPadId, time); + return effects->tabletPadButtonEvent(button, pressed, tabletPadId, time); } bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override { if (!effects) { return false; } - return static_cast(effects)->tabletPadStripEvent(number, position, isFinger, tabletPadId, time); + return effects->tabletPadStripEvent(number, position, isFinger, tabletPadId, time); } bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override { if (!effects) { return false; } - return static_cast(effects)->tabletPadRingEvent(number, position, isFinger, tabletPadId, time); + return effects->tabletPadRingEvent(number, position, isFinger, tabletPadId, time); } }; @@ -3249,7 +3248,7 @@ Window *InputRedirection::findToplevel(const QPointF &pos) const bool isScreenLocked = waylandServer() && waylandServer()->isScreenLocked(); if (!isScreenLocked) { // if an effect overrides the cursor we don't have a window to focus - if (effects && static_cast(effects)->isMouseInterception()) { + if (effects && effects->isMouseInterception()) { return nullptr; } } diff --git a/src/layers.cpp b/src/layers.cpp index 10a73905ac..19696b5455 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -65,10 +65,10 @@ */ #include "compositor.h" -#include "effects.h" #include "focuschain.h" #include "group.h" #include "internalwindow.h" +#include "libkwineffects/kwineffects.h" #include "netinfo.h" #include "rules.h" #include "screenedge.h" @@ -589,7 +589,7 @@ void Workspace::blockStackingUpdates(bool block) if (--m_blockStackingUpdates == 0) { updateStackingOrder(m_blockedPropagatingNewWindows); if (effects) { - static_cast(effects)->checkInputWindowStacking(); + effects->checkInputWindowStacking(); } } } diff --git a/src/libkwineffects/kwineffects.cpp b/src/libkwineffects/kwineffects.cpp index dcf6b134b9..cc10770c61 100644 --- a/src/libkwineffects/kwineffects.cpp +++ b/src/libkwineffects/kwineffects.cpp @@ -10,16 +10,54 @@ */ #include "libkwineffects/kwineffects.h" -#include "core/output.h" -#include "group.h" -#include "internalwindow.h" -#include "scene/windowitem.h" -#include "virtualdesktops.h" -#include "waylandwindow.h" -#include "x11window.h" #include "config-kwin.h" +#include "compositor.h" +#include "core/output.h" +#include "core/renderbackend.h" +#include "core/renderlayer.h" +#include "core/rendertarget.h" +#include "core/renderviewport.h" +#include "decorations/decorationbridge.h" +#include "effectloader.h" +#include "effectsadaptor.h" +#include "group.h" +#include "input.h" +#include "input_event.h" +#include "inputmethod.h" +#include "inputpanelv1window.h" +#include "internalwindow.h" +#include "libkwineffects/kwinoffscreenquickview.h" +#include "opengl/glutils.h" +#include "osd.h" +#include "pointer_input.h" +#include "scene/itemrenderer.h" +#include "scene/windowitem.h" +#include "scene/workspacescene.h" +#include "screenedge.h" +#include "scripting/scripting.h" +#include "sm.h" +#include "virtualdesktops.h" +#include "wayland_server.h" +#include "waylandwindow.h" +#include "window_property_notify_x11_filter.h" +#include "workspace.h" +#include "x11window.h" + +#if KWIN_BUILD_ACTIVITIES +#include "activities.h" +#endif +#if KWIN_BUILD_TABBOX +#include "tabbox/tabbox.h" +#endif +#if KWIN_BUILD_SCREENLOCKER +#include "screenlockerwatcher.h" +#endif + +#include +#include + #include #include #include @@ -62,26 +100,171 @@ static void deleteWindowProperty(xcb_window_t win, long int atom) xcb_delete_property(kwinApp()->x11Connection(), win, atom); } +static xcb_atom_t registerSupportProperty(const QByteArray &propertyName) +{ + auto c = kwinApp()->x11Connection(); + if (!c) { + return XCB_ATOM_NONE; + } + // get the atom for the propertyName + UniqueCPtr atomReply(xcb_intern_atom_reply(c, + xcb_intern_atom_unchecked(c, false, propertyName.size(), propertyName.constData()), + nullptr)); + if (!atomReply) { + return XCB_ATOM_NONE; + } + // announce property on root window + unsigned char dummy = 0; + xcb_change_property(c, XCB_PROP_MODE_REPLACE, kwinApp()->x11RootWindow(), atomReply->atom, atomReply->atom, 8, 1, &dummy); + // TODO: add to _NET_SUPPORTED + return atomReply->atom; +} + //**************************************** // EffectsHandler //**************************************** -EffectsHandler::EffectsHandler(CompositingType type) - : compositing_type(type) +EffectsHandler::EffectsHandler(Compositor *compositor, WorkspaceScene *scene) + : keyboard_grab_effect(nullptr) + , fullscreen_effect(nullptr) + , compositing_type(compositor->backend()->compositingType()) + , m_compositor(compositor) + , m_scene(scene) + , m_effectLoader(new EffectLoader(this)) + , m_trackingCursorChanges(0) { if (compositing_type == NoCompositing) { return; } KWin::effects = this; + + qRegisterMetaType>(); + qRegisterMetaType(); + connect(m_effectLoader, &AbstractEffectLoader::effectLoaded, this, [this](Effect *effect, const QString &name) { + effect_order.insert(effect->requestedEffectChainPosition(), EffectPair(name, effect)); + loaded_effects << EffectPair(name, effect); + effectsChanged(); + }); + m_effectLoader->setConfig(kwinApp()->config()); + new EffectsAdaptor(this); + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject(QStringLiteral("/Effects"), this); + + connect(options, &Options::animationSpeedChanged, this, &EffectsHandler::reconfigureEffects); + + Workspace *ws = Workspace::self(); + VirtualDesktopManager *vds = VirtualDesktopManager::self(); + connect(ws, &Workspace::showingDesktopChanged, this, [this](bool showing, bool animated) { + if (animated) { + Q_EMIT showingDesktopChanged(showing); + } + }); + connect(ws, &Workspace::currentDesktopChanged, this, [this](VirtualDesktop *old, Window *window) { + VirtualDesktop *newDesktop = VirtualDesktopManager::self()->currentDesktop(); + Q_EMIT desktopChanged(old, newDesktop, window ? window->effectWindow() : nullptr); + }); + connect(ws, &Workspace::currentDesktopChanging, this, [this](VirtualDesktop *currentDesktop, QPointF offset, KWin::Window *window) { + Q_EMIT desktopChanging(currentDesktop, offset, window ? window->effectWindow() : nullptr); + }); + connect(ws, &Workspace::currentDesktopChangingCancelled, this, [this]() { + Q_EMIT desktopChangingCancelled(); + }); + connect(ws, &Workspace::windowAdded, this, [this](Window *window) { + setupWindowConnections(window); + Q_EMIT windowAdded(window->effectWindow()); + }); + connect(ws, &Workspace::windowActivated, this, [this](Window *window) { + Q_EMIT windowActivated(window ? window->effectWindow() : nullptr); + }); + connect(ws, &Workspace::deletedRemoved, this, [this](KWin::Window *d) { + Q_EMIT windowDeleted(d->effectWindow()); + }); + connect(ws->sessionManager(), &SessionManager::stateChanged, this, &KWin::EffectsHandler::sessionStateChanged); + connect(vds, &VirtualDesktopManager::layoutChanged, this, [this](int width, int height) { + Q_EMIT desktopGridSizeChanged(QSize(width, height)); + Q_EMIT desktopGridWidthChanged(width); + Q_EMIT desktopGridHeightChanged(height); + }); + connect(vds, &VirtualDesktopManager::desktopAdded, this, &EffectsHandler::desktopAdded); + connect(vds, &VirtualDesktopManager::desktopRemoved, this, &EffectsHandler::desktopRemoved); + connect(Cursors::self()->mouse(), &Cursor::mouseChanged, this, &EffectsHandler::mouseChanged); + connect(ws, &Workspace::geometryChanged, this, &EffectsHandler::virtualScreenSizeChanged); + connect(ws, &Workspace::geometryChanged, this, &EffectsHandler::virtualScreenGeometryChanged); +#if KWIN_BUILD_ACTIVITIES + if (Activities *activities = Workspace::self()->activities()) { + connect(activities, &Activities::added, this, &EffectsHandler::activityAdded); + connect(activities, &Activities::removed, this, &EffectsHandler::activityRemoved); + connect(activities, &Activities::currentChanged, this, &EffectsHandler::currentActivityChanged); + } +#endif + connect(ws, &Workspace::stackingOrderChanged, this, &EffectsHandler::stackingOrderChanged); +#if KWIN_BUILD_TABBOX + TabBox::TabBox *tabBox = workspace()->tabbox(); + connect(tabBox, &TabBox::TabBox::tabBoxAdded, this, &EffectsHandler::tabBoxAdded); + connect(tabBox, &TabBox::TabBox::tabBoxUpdated, this, &EffectsHandler::tabBoxUpdated); + connect(tabBox, &TabBox::TabBox::tabBoxClosed, this, &EffectsHandler::tabBoxClosed); + connect(tabBox, &TabBox::TabBox::tabBoxKeyEvent, this, &EffectsHandler::tabBoxKeyEvent); +#endif + connect(workspace()->screenEdges(), &ScreenEdges::approaching, this, &EffectsHandler::screenEdgeApproaching); +#if KWIN_BUILD_SCREENLOCKER + connect(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::locked, this, &EffectsHandler::screenLockingChanged); + connect(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::aboutToLock, this, &EffectsHandler::screenAboutToLock); +#endif + + connect(kwinApp(), &Application::x11ConnectionChanged, this, [this]() { + registered_atoms.clear(); + for (auto it = m_propertiesForEffects.keyBegin(); it != m_propertiesForEffects.keyEnd(); it++) { + const auto atom = registerSupportProperty(*it); + if (atom == XCB_ATOM_NONE) { + continue; + } + m_compositor->keepSupportProperty(atom); + m_managedProperties.insert(*it, atom); + registerPropertyType(atom, true); + } + if (kwinApp()->x11Connection()) { + m_x11WindowPropertyNotify = std::make_unique(this); + } else { + m_x11WindowPropertyNotify.reset(); + } + Q_EMIT xcbConnectionChanged(); + }); + + if (kwinApp()->x11Connection()) { + m_x11WindowPropertyNotify = std::make_unique(this); + } + + // connect all clients + for (Window *window : ws->windows()) { + setupWindowConnections(window); + } + + connect(ws, &Workspace::outputAdded, this, &EffectsHandler::screenAdded); + connect(ws, &Workspace::outputRemoved, this, &EffectsHandler::screenRemoved); + + if (auto inputMethod = kwinApp()->inputMethod()) { + connect(inputMethod, &InputMethod::panelChanged, this, &EffectsHandler::inputPanelChanged); + } + + reconfigure(); } EffectsHandler::~EffectsHandler() { - // All effects should already be unloaded by Impl dtor - Q_ASSERT(loaded_effects.count() == 0); + unloadAllEffects(); KWin::effects = nullptr; } +xcb_window_t EffectsHandler::x11RootWindow() const +{ + return kwinApp()->x11RootWindow(); +} + +xcb_connection_t *EffectsHandler::xcbConnection() const +{ + return kwinApp()->x11Connection(); +} + CompositingType EffectsHandler::compositingType() const { return compositing_type; @@ -92,6 +275,1360 @@ bool EffectsHandler::isOpenGLCompositing() const return compositing_type & OpenGLCompositing; } +void EffectsHandler::unloadAllEffects() +{ + for (const EffectPair &pair : std::as_const(loaded_effects)) { + destroyEffect(pair.second); + } + + effect_order.clear(); + m_effectLoader->clear(); + + effectsChanged(); +} + +void EffectsHandler::setupWindowConnections(Window *window) +{ + connect(window, &Window::closed, this, [this, window]() { + if (window->effectWindow()) { + Q_EMIT windowClosed(window->effectWindow()); + } + }); +} + +void EffectsHandler::reconfigure() +{ + m_effectLoader->queryAndLoadAll(); +} + +// the idea is that effects call this function again which calls the next one +void EffectsHandler::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) +{ + if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { + (*m_currentPaintScreenIterator++)->prePaintScreen(data, presentTime); + --m_currentPaintScreenIterator; + } + // no special final code +} + +void EffectsHandler::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) +{ + if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { + (*m_currentPaintScreenIterator++)->paintScreen(renderTarget, viewport, mask, region, screen); + --m_currentPaintScreenIterator; + } else { + m_scene->finalPaintScreen(renderTarget, viewport, mask, region, screen); + } +} + +void EffectsHandler::postPaintScreen() +{ + if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { + (*m_currentPaintScreenIterator++)->postPaintScreen(); + --m_currentPaintScreenIterator; + } + // no special final code +} + +void EffectsHandler::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) +{ + if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { + (*m_currentPaintWindowIterator++)->prePaintWindow(w, data, presentTime); + --m_currentPaintWindowIterator; + } + // no special final code +} + +void EffectsHandler::paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) +{ + if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { + (*m_currentPaintWindowIterator++)->paintWindow(renderTarget, viewport, w, mask, region, data); + --m_currentPaintWindowIterator; + } else { + m_scene->finalPaintWindow(renderTarget, viewport, w, mask, region, data); + } +} + +void EffectsHandler::postPaintWindow(EffectWindow *w) +{ + if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { + (*m_currentPaintWindowIterator++)->postPaintWindow(w); + --m_currentPaintWindowIterator; + } + // no special final code +} + +Effect *EffectsHandler::provides(Effect::Feature ef) +{ + for (int i = 0; i < loaded_effects.size(); ++i) { + if (loaded_effects.at(i).second->provides(ef)) { + return loaded_effects.at(i).second; + } + } + return nullptr; +} + +void EffectsHandler::drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) +{ + if (m_currentDrawWindowIterator != m_activeEffects.constEnd()) { + (*m_currentDrawWindowIterator++)->drawWindow(renderTarget, viewport, w, mask, region, data); + --m_currentDrawWindowIterator; + } else { + m_scene->finalDrawWindow(renderTarget, viewport, w, mask, region, data); + } +} + +void EffectsHandler::renderWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) +{ + m_scene->finalDrawWindow(renderTarget, viewport, w, mask, region, data); +} + +bool EffectsHandler::hasDecorationShadows() const +{ + return false; +} + +bool EffectsHandler::decorationsHaveAlpha() const +{ + return true; +} + +// start another painting pass +void EffectsHandler::startPaint() +{ + m_activeEffects.clear(); + m_activeEffects.reserve(loaded_effects.count()); + for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->isActive()) { + m_activeEffects << it->second; + } + } + m_currentDrawWindowIterator = m_activeEffects.constBegin(); + m_currentPaintWindowIterator = m_activeEffects.constBegin(); + m_currentPaintScreenIterator = m_activeEffects.constBegin(); +} + +void EffectsHandler::setActiveFullScreenEffect(Effect *e) +{ + if (fullscreen_effect == e) { + return; + } + const bool activeChanged = (e == nullptr || fullscreen_effect == nullptr); + fullscreen_effect = e; + Q_EMIT activeFullScreenEffectChanged(); + if (activeChanged) { + Q_EMIT hasActiveFullScreenEffectChanged(); + workspace()->screenEdges()->checkBlocking(); + } +} + +Effect *EffectsHandler::activeFullScreenEffect() const +{ + return fullscreen_effect; +} + +bool EffectsHandler::hasActiveFullScreenEffect() const +{ + return fullscreen_effect; +} + +bool EffectsHandler::grabKeyboard(Effect *effect) +{ + if (keyboard_grab_effect != nullptr) { + return false; + } + if (!doGrabKeyboard()) { + return false; + } + keyboard_grab_effect = effect; + return true; +} + +bool EffectsHandler::doGrabKeyboard() +{ + return true; +} + +void EffectsHandler::ungrabKeyboard() +{ + Q_ASSERT(keyboard_grab_effect != nullptr); + doUngrabKeyboard(); + keyboard_grab_effect = nullptr; +} + +void EffectsHandler::doUngrabKeyboard() +{ +} + +void EffectsHandler::grabbedKeyboardEvent(QKeyEvent *e) +{ + if (keyboard_grab_effect != nullptr) { + keyboard_grab_effect->grabbedKeyboardEvent(e); + } +} + +void EffectsHandler::startMouseInterception(Effect *effect, Qt::CursorShape shape) +{ + if (m_grabbedMouseEffects.contains(effect)) { + return; + } + m_grabbedMouseEffects.append(effect); + if (m_grabbedMouseEffects.size() != 1) { + return; + } + doStartMouseInterception(shape); +} + +void EffectsHandler::doStartMouseInterception(Qt::CursorShape shape) +{ + input()->pointer()->setEffectsOverrideCursor(shape); + + // We want to allow global shortcuts to be triggered when moving a + // window so it is possible to pick up a window and then move it to a + // different desktop by using the global shortcut to switch desktop. + // However, that means that some other things can also be triggered. If + // an effect that fill the screen gets triggered that way, we end up in a + // weird state where the move will restart after the effect closes. So to + // avoid that, abort move/resize if a full screen effect starts. + if (workspace()->moveResizeWindow()) { + workspace()->moveResizeWindow()->endInteractiveMoveResize(); + } +} + +void EffectsHandler::stopMouseInterception(Effect *effect) +{ + if (!m_grabbedMouseEffects.contains(effect)) { + return; + } + m_grabbedMouseEffects.removeAll(effect); + if (m_grabbedMouseEffects.isEmpty()) { + doStopMouseInterception(); + } +} + +void EffectsHandler::doStopMouseInterception() +{ + input()->pointer()->removeEffectsOverrideCursor(); +} + +bool EffectsHandler::isMouseInterception() const +{ + return m_grabbedMouseEffects.count() > 0; +} + +bool EffectsHandler::touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->touchDown(id, pos, time)) { + return true; + } + } + return false; +} + +bool EffectsHandler::touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->touchMotion(id, pos, time)) { + return true; + } + } + return false; +} + +bool EffectsHandler::touchUp(qint32 id, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->touchUp(id, time)) { + return true; + } + } + return false; +} + +bool EffectsHandler::tabletToolEvent(TabletEvent *event) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->tabletToolEvent(event)) { + return true; + } + } + return false; +} + +bool EffectsHandler::tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->tabletToolButtonEvent(button, pressed, tabletToolId.m_uniqueId)) { + return true; + } + } + return false; +} + +bool EffectsHandler::tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->tabletPadButtonEvent(button, pressed, tabletPadId.data)) { + return true; + } + } + return false; +} + +bool EffectsHandler::tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->tabletPadStripEvent(number, position, isFinger, tabletPadId.data)) { + return true; + } + } + return false; +} + +bool EffectsHandler::tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) +{ + // TODO: reverse call order? + for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if (it->second->tabletPadRingEvent(number, position, isFinger, tabletPadId.data)) { + return true; + } + } + return false; +} + +void EffectsHandler::registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) +{ + input()->registerPointerShortcut(modifiers, pointerButtons, action); +} + +void EffectsHandler::registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) +{ + input()->registerAxisShortcut(modifiers, axis, action); +} + +void EffectsHandler::registerTouchpadSwipeShortcut(SwipeDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback) +{ + input()->registerTouchpadSwipeShortcut(dir, fingerCount, onUp, progressCallback); +} + +void EffectsHandler::registerTouchpadPinchShortcut(PinchDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback) +{ + input()->registerTouchpadPinchShortcut(dir, fingerCount, onUp, progressCallback); +} + +void EffectsHandler::registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback) +{ + input()->registerTouchscreenSwipeShortcut(direction, fingerCount, action, progressCallback); +} + +void EffectsHandler::startMousePolling() +{ + if (Cursors::self()->mouse()) { + Cursors::self()->mouse()->startMousePolling(); + } +} + +void EffectsHandler::stopMousePolling() +{ + if (Cursors::self()->mouse()) { + Cursors::self()->mouse()->stopMousePolling(); + } +} + +bool EffectsHandler::hasKeyboardGrab() const +{ + return keyboard_grab_effect != nullptr; +} + +void EffectsHandler::registerPropertyType(long atom, bool reg) +{ + if (reg) { + ++registered_atoms[atom]; // initialized to 0 if not present yet + } else { + if (--registered_atoms[atom] == 0) { + registered_atoms.remove(atom); + } + } +} + +xcb_atom_t EffectsHandler::announceSupportProperty(const QByteArray &propertyName, Effect *effect) +{ + PropertyEffectMap::iterator it = m_propertiesForEffects.find(propertyName); + if (it != m_propertiesForEffects.end()) { + // property has already been registered for an effect + // just append Effect and return the atom stored in m_managedProperties + if (!it.value().contains(effect)) { + it.value().append(effect); + } + return m_managedProperties.value(propertyName, XCB_ATOM_NONE); + } + m_propertiesForEffects.insert(propertyName, QList() << effect); + const auto atom = registerSupportProperty(propertyName); + if (atom == XCB_ATOM_NONE) { + return atom; + } + m_compositor->keepSupportProperty(atom); + m_managedProperties.insert(propertyName, atom); + registerPropertyType(atom, true); + return atom; +} + +void EffectsHandler::removeSupportProperty(const QByteArray &propertyName, Effect *effect) +{ + PropertyEffectMap::iterator it = m_propertiesForEffects.find(propertyName); + if (it == m_propertiesForEffects.end()) { + // property is not registered - nothing to do + return; + } + if (!it.value().contains(effect)) { + // property is not registered for given effect - nothing to do + return; + } + it.value().removeAll(effect); + if (!it.value().isEmpty()) { + // property still registered for another effect - nothing further to do + return; + } + const xcb_atom_t atom = m_managedProperties.take(propertyName); + registerPropertyType(atom, false); + m_propertiesForEffects.remove(propertyName); + m_compositor->removeSupportProperty(atom); // delayed removal +} + +QByteArray EffectsHandler::readRootProperty(long atom, long type, int format) const +{ + if (!kwinApp()->x11Connection()) { + return QByteArray(); + } + return readWindowProperty(kwinApp()->x11RootWindow(), atom, type, format); +} + +void EffectsHandler::activateWindow(EffectWindow *effectWindow) +{ + auto window = effectWindow->window(); + if (window->isClient()) { + Workspace::self()->activateWindow(window, true); + } +} + +EffectWindow *EffectsHandler::activeWindow() const +{ + return Workspace::self()->activeWindow() ? Workspace::self()->activeWindow()->effectWindow() : nullptr; +} + +void EffectsHandler::moveWindow(EffectWindow *w, const QPoint &pos, bool snap, double snapAdjust) +{ + auto window = w->window(); + if (!window->isClient() || !window->isMovable()) { + return; + } + + if (snap) { + window->move(Workspace::self()->adjustWindowPosition(window, pos, true, snapAdjust)); + } else { + window->move(pos); + } +} + +void EffectsHandler::windowToDesktops(EffectWindow *w, const QList &desktops) +{ + auto window = w->window(); + if (!window->isClient() || window->isDesktop() || window->isDock()) { + return; + } + window->setDesktops(desktops); +} + +void EffectsHandler::windowToScreen(EffectWindow *w, Output *screen) +{ + auto window = w->window(); + if (window->isClient() && !window->isDesktop() && !window->isDock()) { + Workspace::self()->sendWindowToOutput(window, screen); + } +} + +void EffectsHandler::setShowingDesktop(bool showing) +{ + Workspace::self()->setShowingDesktop(showing); +} + +QString EffectsHandler::currentActivity() const +{ +#if KWIN_BUILD_ACTIVITIES + if (!Workspace::self()->activities()) { + return QString(); + } + return Workspace::self()->activities()->current(); +#else + return QString(); +#endif +} + +VirtualDesktop *EffectsHandler::currentDesktop() const +{ + return VirtualDesktopManager::self()->currentDesktop(); +} + +QList EffectsHandler::desktops() const +{ + return VirtualDesktopManager::self()->desktops(); +} + +void EffectsHandler::setCurrentDesktop(VirtualDesktop *desktop) +{ + VirtualDesktopManager::self()->setCurrent(desktop); +} + +QSize EffectsHandler::desktopGridSize() const +{ + return VirtualDesktopManager::self()->grid().size(); +} + +int EffectsHandler::desktopGridWidth() const +{ + return desktopGridSize().width(); +} + +int EffectsHandler::desktopGridHeight() const +{ + return desktopGridSize().height(); +} + +int EffectsHandler::workspaceWidth() const +{ + return desktopGridWidth() * Workspace::self()->geometry().width(); +} + +int EffectsHandler::workspaceHeight() const +{ + return desktopGridHeight() * Workspace::self()->geometry().height(); +} + +VirtualDesktop *EffectsHandler::desktopAtCoords(QPoint coords) const +{ + return VirtualDesktopManager::self()->grid().at(coords); +} + +QPoint EffectsHandler::desktopGridCoords(VirtualDesktop *desktop) const +{ + return VirtualDesktopManager::self()->grid().gridCoords(desktop); +} + +QPoint EffectsHandler::desktopCoords(VirtualDesktop *desktop) const +{ + QPoint coords = VirtualDesktopManager::self()->grid().gridCoords(desktop); + if (coords.x() == -1) { + return QPoint(-1, -1); + } + const QSize displaySize = Workspace::self()->geometry().size(); + return QPoint(coords.x() * displaySize.width(), coords.y() * displaySize.height()); +} + +VirtualDesktop *EffectsHandler::desktopAbove(VirtualDesktop *desktop, bool wrap) const +{ + return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Up, wrap); +} + +VirtualDesktop *EffectsHandler::desktopToRight(VirtualDesktop *desktop, bool wrap) const +{ + return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Right, wrap); +} + +VirtualDesktop *EffectsHandler::desktopBelow(VirtualDesktop *desktop, bool wrap) const +{ + return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Down, wrap); +} + +VirtualDesktop *EffectsHandler::desktopToLeft(VirtualDesktop *desktop, bool wrap) const +{ + return VirtualDesktopManager::self()->inDirection(desktop, VirtualDesktopManager::Direction::Left, wrap); +} + +QString EffectsHandler::desktopName(VirtualDesktop *desktop) const +{ + return desktop->name(); +} + +bool EffectsHandler::optionRollOverDesktops() const +{ + return options->isRollOverDesktops(); +} + +double EffectsHandler::animationTimeFactor() const +{ + return options->animationTimeFactor(); +} + +EffectWindow *EffectsHandler::findWindow(WId id) const +{ + if (X11Window *w = Workspace::self()->findClient(Predicate::WindowMatch, id)) { + return w->effectWindow(); + } + if (X11Window *w = Workspace::self()->findUnmanaged(id)) { + return w->effectWindow(); + } + return nullptr; +} + +EffectWindow *EffectsHandler::findWindow(SurfaceInterface *surf) const +{ + if (waylandServer()) { + if (Window *w = waylandServer()->findWindow(surf)) { + return w->effectWindow(); + } + } + return nullptr; +} + +EffectWindow *EffectsHandler::findWindow(QWindow *w) const +{ + if (Window *window = workspace()->findInternal(w)) { + return window->effectWindow(); + } + return nullptr; +} + +EffectWindow *EffectsHandler::findWindow(const QUuid &id) const +{ + if (Window *window = workspace()->findWindow(id)) { + return window->effectWindow(); + } + return nullptr; +} + +EffectWindowList EffectsHandler::stackingOrder() const +{ + QList list = workspace()->stackingOrder(); + EffectWindowList ret; + for (Window *t : list) { + if (EffectWindow *w = t->effectWindow()) { + ret.append(w); + } + } + return ret; +} + +void EffectsHandler::setElevatedWindow(KWin::EffectWindow *w, bool set) +{ + WindowItem *item = w->windowItem(); + + if (set) { + item->elevate(); + } else { + item->deelevate(); + } +} + +void EffectsHandler::setTabBoxWindow(EffectWindow *w) +{ +#if KWIN_BUILD_TABBOX + auto window = w->window(); + if (window->isClient()) { + workspace()->tabbox()->setCurrentClient(window); + } +#endif +} + +EffectWindowList EffectsHandler::currentTabBoxWindowList() const +{ +#if KWIN_BUILD_TABBOX + const auto clients = workspace()->tabbox()->currentClientList(); + EffectWindowList ret; + ret.reserve(clients.size()); + std::transform(std::cbegin(clients), std::cend(clients), + std::back_inserter(ret), + [](auto client) { + return client->effectWindow(); + }); + return ret; +#else + return EffectWindowList(); +#endif +} + +void EffectsHandler::refTabBox() +{ +#if KWIN_BUILD_TABBOX + workspace()->tabbox()->reference(); +#endif +} + +void EffectsHandler::unrefTabBox() +{ +#if KWIN_BUILD_TABBOX + workspace()->tabbox()->unreference(); +#endif +} + +void EffectsHandler::closeTabBox() +{ +#if KWIN_BUILD_TABBOX + workspace()->tabbox()->close(); +#endif +} + +EffectWindow *EffectsHandler::currentTabBoxWindow() const +{ +#if KWIN_BUILD_TABBOX + if (auto c = workspace()->tabbox()->currentClient()) { + return c->effectWindow(); + } +#endif + return nullptr; +} + +void EffectsHandler::addRepaintFull() +{ + m_compositor->scene()->addRepaintFull(); +} + +void EffectsHandler::addRepaint(const QRect &r) +{ + m_compositor->scene()->addRepaint(r); +} + +void EffectsHandler::addRepaint(const QRectF &r) +{ + m_compositor->scene()->addRepaint(r.toAlignedRect()); +} + +void EffectsHandler::addRepaint(const QRegion &r) +{ + m_compositor->scene()->addRepaint(r); +} + +void EffectsHandler::addRepaint(int x, int y, int w, int h) +{ + m_compositor->scene()->addRepaint(x, y, w, h); +} + +Output *EffectsHandler::activeScreen() const +{ + return workspace()->activeOutput(); +} + +QRectF EffectsHandler::clientArea(clientAreaOption opt, const Output *screen, const VirtualDesktop *desktop) const +{ + return Workspace::self()->clientArea(opt, screen, desktop); +} + +QRectF EffectsHandler::clientArea(clientAreaOption opt, const EffectWindow *effectWindow) const +{ + const Window *window = effectWindow->window(); + return Workspace::self()->clientArea(opt, window); +} + +QRectF EffectsHandler::clientArea(clientAreaOption opt, const QPoint &p, const VirtualDesktop *desktop) const +{ + const Output *output = Workspace::self()->outputAt(p); + return Workspace::self()->clientArea(opt, output, desktop); +} + +QRect EffectsHandler::virtualScreenGeometry() const +{ + return Workspace::self()->geometry(); +} + +QSize EffectsHandler::virtualScreenSize() const +{ + return Workspace::self()->geometry().size(); +} + +void EffectsHandler::defineCursor(Qt::CursorShape shape) +{ + input()->pointer()->setEffectsOverrideCursor(shape); +} + +bool EffectsHandler::checkInputWindowEvent(QMouseEvent *e) +{ + if (m_grabbedMouseEffects.isEmpty()) { + return false; + } + for (Effect *effect : std::as_const(m_grabbedMouseEffects)) { + effect->windowInputMouseEvent(e); + } + return true; +} + +bool EffectsHandler::checkInputWindowEvent(QWheelEvent *e) +{ + if (m_grabbedMouseEffects.isEmpty()) { + return false; + } + for (Effect *effect : std::as_const(m_grabbedMouseEffects)) { + effect->windowInputMouseEvent(e); + } + return true; +} + +void EffectsHandler::connectNotify(const QMetaMethod &signal) +{ + if (signal == QMetaMethod::fromSignal(&EffectsHandler::cursorShapeChanged)) { + if (!m_trackingCursorChanges) { + connect(Cursors::self()->mouse(), &Cursor::cursorChanged, this, &EffectsHandler::cursorShapeChanged); + Cursors::self()->mouse()->startCursorTracking(); + } + ++m_trackingCursorChanges; + } + QObject::connectNotify(signal); +} + +void EffectsHandler::disconnectNotify(const QMetaMethod &signal) +{ + if (signal == QMetaMethod::fromSignal(&EffectsHandler::cursorShapeChanged)) { + Q_ASSERT(m_trackingCursorChanges > 0); + if (!--m_trackingCursorChanges) { + Cursors::self()->mouse()->stopCursorTracking(); + disconnect(Cursors::self()->mouse(), &Cursor::cursorChanged, this, &EffectsHandler::cursorShapeChanged); + } + } + QObject::disconnectNotify(signal); +} + +void EffectsHandler::checkInputWindowStacking() +{ + if (m_grabbedMouseEffects.isEmpty()) { + return; + } + doCheckInputWindowStacking(); +} + +void EffectsHandler::doCheckInputWindowStacking() +{ +} + +QPointF EffectsHandler::cursorPos() const +{ + return Cursors::self()->mouse()->pos(); +} + +void EffectsHandler::reserveElectricBorder(ElectricBorder border, Effect *effect) +{ + workspace()->screenEdges()->reserve(border, effect, "borderActivated"); +} + +void EffectsHandler::unreserveElectricBorder(ElectricBorder border, Effect *effect) +{ + workspace()->screenEdges()->unreserve(border, effect); +} + +void EffectsHandler::registerTouchBorder(ElectricBorder border, QAction *action) +{ + workspace()->screenEdges()->reserveTouch(border, action); +} + +void EffectsHandler::registerRealtimeTouchBorder(ElectricBorder border, QAction *action, EffectsHandler::TouchBorderCallback progressCallback) +{ + workspace()->screenEdges()->reserveTouch(border, action, progressCallback); +} + +void EffectsHandler::unregisterTouchBorder(ElectricBorder border, QAction *action) +{ + workspace()->screenEdges()->unreserveTouch(border, action); +} + +QPainter *EffectsHandler::scenePainter() +{ + return m_scene->renderer()->painter(); +} + +void EffectsHandler::toggleEffect(const QString &name) +{ + if (isEffectLoaded(name)) { + unloadEffect(name); + } else { + loadEffect(name); + } +} + +QStringList EffectsHandler::loadedEffects() const +{ + QStringList listModules; + listModules.reserve(loaded_effects.count()); + std::transform(loaded_effects.constBegin(), loaded_effects.constEnd(), + std::back_inserter(listModules), + [](const EffectPair &pair) { + return pair.first; + }); + return listModules; +} + +QStringList EffectsHandler::listOfEffects() const +{ + return m_effectLoader->listOfKnownEffects(); +} + +bool EffectsHandler::loadEffect(const QString &name) +{ + makeOpenGLContextCurrent(); + m_compositor->scene()->addRepaintFull(); + + return m_effectLoader->loadEffect(name); +} + +void EffectsHandler::unloadEffect(const QString &name) +{ + auto it = std::find_if(effect_order.begin(), effect_order.end(), + [name](EffectPair &pair) { + return pair.first == name; + }); + if (it == effect_order.end()) { + qCDebug(KWIN_CORE) << "EffectsHandler::unloadEffect : Effect not loaded :" << name; + return; + } + + qCDebug(KWIN_CORE) << "EffectsHandler::unloadEffect : Unloading Effect :" << name; + destroyEffect((*it).second); + effect_order.erase(it); + effectsChanged(); + + m_compositor->scene()->addRepaintFull(); +} + +void EffectsHandler::destroyEffect(Effect *effect) +{ + makeOpenGLContextCurrent(); + + if (fullscreen_effect == effect) { + setActiveFullScreenEffect(nullptr); + } + + if (keyboard_grab_effect == effect) { + ungrabKeyboard(); + } + + stopMouseInterception(effect); + + const QList properties = m_propertiesForEffects.keys(); + for (const QByteArray &property : properties) { + removeSupportProperty(property, effect); + } + + delete effect; +} + +void EffectsHandler::reconfigureEffects() +{ + makeOpenGLContextCurrent(); + for (const EffectPair &pair : loaded_effects) { + pair.second->reconfigure(Effect::ReconfigureAll); + } +} + +void EffectsHandler::reconfigureEffect(const QString &name) +{ + for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if ((*it).first == name) { + kwinApp()->config()->reparseConfiguration(); + makeOpenGLContextCurrent(); + (*it).second->reconfigure(Effect::ReconfigureAll); + return; + } + } +} + +bool EffectsHandler::isEffectLoaded(const QString &name) const +{ + auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), + [&name](const EffectPair &pair) { + return pair.first == name; + }); + return it != loaded_effects.constEnd(); +} + +bool EffectsHandler::isEffectSupported(const QString &name) +{ + // If the effect is loaded, it is obviously supported. + if (isEffectLoaded(name)) { + return true; + } + + // next checks might require a context + makeOpenGLContextCurrent(); + + return m_effectLoader->isEffectSupported(name); +} + +QList EffectsHandler::areEffectsSupported(const QStringList &names) +{ + QList retList; + retList.reserve(names.count()); + std::transform(names.constBegin(), names.constEnd(), + std::back_inserter(retList), + [this](const QString &name) { + return isEffectSupported(name); + }); + return retList; +} + +void EffectsHandler::reloadEffect(Effect *effect) +{ + QString effectName; + for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if ((*it).second == effect) { + effectName = (*it).first; + break; + } + } + if (!effectName.isNull()) { + unloadEffect(effectName); + m_effectLoader->loadEffect(effectName); + } +} + +void EffectsHandler::effectsChanged() +{ + loaded_effects.clear(); + m_activeEffects.clear(); // it's possible to have a reconfigure and a quad rebuild between two paint cycles - bug #308201 + + loaded_effects.reserve(effect_order.count()); + std::copy(effect_order.constBegin(), effect_order.constEnd(), + std::back_inserter(loaded_effects)); + + m_activeEffects.reserve(loaded_effects.count()); + + m_currentPaintScreenIterator = m_activeEffects.constBegin(); + m_currentPaintWindowIterator = m_activeEffects.constBegin(); + m_currentDrawWindowIterator = m_activeEffects.constBegin(); +} + +QStringList EffectsHandler::activeEffects() const +{ + QStringList ret; + for (QList::const_iterator it = loaded_effects.constBegin(), + end = loaded_effects.constEnd(); + it != end; ++it) { + if (it->second->isActive()) { + ret << it->first; + } + } + return ret; +} + +bool EffectsHandler::isEffectActive(const QString &pluginId) const +{ + auto it = std::find_if(loaded_effects.cbegin(), loaded_effects.cend(), [&pluginId](const EffectPair &p) { + return p.first == pluginId; + }); + if (it == loaded_effects.cend()) { + return false; + } + return it->second->isActive(); +} + +bool EffectsHandler::blocksDirectScanout() const +{ + return std::any_of(m_activeEffects.constBegin(), m_activeEffects.constEnd(), [](const Effect *effect) { + return effect->blocksDirectScanout(); + }); +} + +Display *EffectsHandler::waylandDisplay() const +{ + if (waylandServer()) { + return waylandServer()->display(); + } + return nullptr; +} + +QVariant EffectsHandler::kwinOption(KWinOption kwopt) +{ + switch (kwopt) { + case CloseButtonCorner: { + // TODO: this could become per window and be derived from the actual position in the deco + const auto settings = Workspace::self()->decorationBridge()->settings(); + return settings && settings->decorationButtonsLeft().contains(KDecoration2::DecorationButtonType::Close) ? Qt::TopLeftCorner : Qt::TopRightCorner; + } + case SwitchDesktopOnScreenEdge: + return workspace()->screenEdges()->isDesktopSwitching(); + case SwitchDesktopOnScreenEdgeMovingWindows: + return workspace()->screenEdges()->isDesktopSwitchingMovingClients(); + default: + return QVariant(); // an invalid one + } +} + +QString EffectsHandler::supportInformation(const QString &name) const +{ + auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), + [name](const EffectPair &pair) { + return pair.first == name; + }); + if (it == loaded_effects.constEnd()) { + return QString(); + } + + QString support((*it).first + QLatin1String(":\n")); + const QMetaObject *metaOptions = (*it).second->metaObject(); + for (int i = 0; i < metaOptions->propertyCount(); ++i) { + const QMetaProperty property = metaOptions->property(i); + if (qstrcmp(property.name(), "objectName") == 0) { + continue; + } + support += QString::fromUtf8(property.name()) + QLatin1String(": ") + (*it).second->property(property.name()).toString() + QLatin1Char('\n'); + } + + return support; +} + +bool EffectsHandler::isScreenLocked() const +{ +#if KWIN_BUILD_SCREENLOCKER + return kwinApp()->screenLockerWatcher()->isLocked(); +#else + return false; +#endif +} + +QString EffectsHandler::debug(const QString &name, const QString ¶meter) const +{ + QString internalName = name.toLower(); + for (QList::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) { + if ((*it).first == internalName) { + return it->second->debug(parameter); + } + } + return QString(); +} + +bool EffectsHandler::makeOpenGLContextCurrent() +{ + return m_scene->makeOpenGLContextCurrent(); +} + +void EffectsHandler::doneOpenGLContextCurrent() +{ + m_scene->doneOpenGLContextCurrent(); +} + +bool EffectsHandler::animationsSupported() const +{ + static const QByteArray forceEnvVar = qgetenv("KWIN_EFFECTS_FORCE_ANIMATIONS"); + if (!forceEnvVar.isEmpty()) { + static const int forceValue = forceEnvVar.toInt(); + return forceValue == 1; + } + return m_scene->animationsSupported(); +} + +void EffectsHandler::highlightWindows(const QList &windows) +{ + Effect *e = provides(Effect::HighlightWindows); + if (!e) { + return; + } + e->perform(Effect::HighlightWindows, QVariantList{QVariant::fromValue(windows)}); +} + +PlatformCursorImage EffectsHandler::cursorImage() const +{ + return kwinApp()->cursorImage(); +} + +void EffectsHandler::hideCursor() +{ + Cursors::self()->hideCursor(); +} + +void EffectsHandler::showCursor() +{ + Cursors::self()->showCursor(); +} + +void EffectsHandler::startInteractiveWindowSelection(std::function callback) +{ + kwinApp()->startInteractiveWindowSelection([callback](KWin::Window *window) { + if (window && window->effectWindow()) { + callback(window->effectWindow()); + } else { + callback(nullptr); + } + }); +} + +void EffectsHandler::startInteractivePositionSelection(std::function callback) +{ + kwinApp()->startInteractivePositionSelection(callback); +} + +void EffectsHandler::showOnScreenMessage(const QString &message, const QString &iconName) +{ + OSD::show(message, iconName); +} + +void EffectsHandler::hideOnScreenMessage(OnScreenMessageHideFlags flags) +{ + OSD::HideFlags osdFlags; + if (flags.testFlag(OnScreenMessageHideFlag::SkipsCloseAnimation)) { + osdFlags |= OSD::HideFlag::SkipCloseAnimation; + } + OSD::hide(osdFlags); +} + +KSharedConfigPtr EffectsHandler::config() const +{ + return kwinApp()->config(); +} + +KSharedConfigPtr EffectsHandler::inputConfig() const +{ + return kwinApp()->inputConfig(); +} + +Effect *EffectsHandler::findEffect(const QString &name) const +{ + auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), [name](const EffectPair &pair) { + return pair.first == name; + }); + if (it == loaded_effects.constEnd()) { + return nullptr; + } + return (*it).second; +} + +void EffectsHandler::renderOffscreenQuickView(const RenderTarget &renderTarget, const RenderViewport &viewport, OffscreenQuickView *w) const +{ + if (!w->isVisible()) { + return; + } + if (compositingType() == OpenGLCompositing) { + GLTexture *t = w->bufferAsTexture(); + if (!t) { + return; + } + + ShaderTraits traits = ShaderTrait::MapTexture | ShaderTrait::TransformColorspace; + const qreal a = w->opacity(); + if (a != 1.0) { + traits |= ShaderTrait::Modulate; + } + + GLShader *shader = ShaderManager::instance()->pushShader(traits); + const QRectF rect = scaledRect(w->geometry(), viewport.scale()); + + QMatrix4x4 mvp(viewport.projectionMatrix()); + mvp.translate(rect.x(), rect.y()); + shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); + + if (a != 1.0) { + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } + shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); + + const bool alphaBlending = w->hasAlphaChannel() || (a != 1.0); + if (alphaBlending) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + + t->render(w->size(), viewport.scale()); + + if (alphaBlending) { + glDisable(GL_BLEND); + } + + ShaderManager::instance()->popShader(); + } else if (compositingType() == QPainterCompositing) { + QPainter *painter = effects->scenePainter(); + const QImage buffer = w->bufferAsImage(); + if (buffer.isNull()) { + return; + } + painter->save(); + painter->setOpacity(w->opacity()); + painter->drawImage(w->geometry(), buffer); + painter->restore(); + } +} + +SessionState EffectsHandler::sessionState() const +{ + return Workspace::self()->sessionManager()->state(); +} + +QList EffectsHandler::screens() const +{ + return Workspace::self()->outputs(); +} + +Output *EffectsHandler::screenAt(const QPoint &point) const +{ + return Workspace::self()->outputAt(point); +} + +Output *EffectsHandler::findScreen(const QString &name) const +{ + const auto outputs = Workspace::self()->outputs(); + for (Output *screen : outputs) { + if (screen->name() == name) { + return screen; + } + } + return nullptr; +} + +Output *EffectsHandler::findScreen(int screenId) const +{ + return Workspace::self()->outputs().value(screenId); +} + +void EffectsHandler::renderScreen(Output *output) +{ + RenderTarget renderTarget(GLFramebuffer::currentFramebuffer()); + + RenderLayer layer(output->renderLoop()); + SceneDelegate delegate(m_scene, output); + delegate.setLayer(&layer); + + m_scene->prePaint(&delegate); + m_scene->paint(renderTarget, output->geometry()); + m_scene->postPaint(); +} + +bool EffectsHandler::isCursorHidden() const +{ + return Cursors::self()->isCursorHidden(); +} + +KWin::EffectWindow *EffectsHandler::inputPanel() const +{ + if (!kwinApp()->inputMethod() || !kwinApp()->inputMethod()->isEnabled()) { + return nullptr; + } + + auto panel = kwinApp()->inputMethod()->panel(); + if (panel) { + return panel->effectWindow(); + } + return nullptr; +} + +bool EffectsHandler::isInputPanelOverlay() const +{ + if (!kwinApp()->inputMethod() || !kwinApp()->inputMethod()->isEnabled()) { + return true; + } + + auto panel = kwinApp()->inputMethod()->panel(); + if (panel) { + return panel->mode() == InputPanelV1Window::Mode::Overlay; + } + return true; +} + +QQmlEngine *EffectsHandler::qmlEngine() const +{ + return Scripting::self()->qmlEngine(); +} + EffectsHandler *effects = nullptr; //**************************************** diff --git a/src/libkwineffects/kwineffects.h b/src/libkwineffects/kwineffects.h index 583f5a1bf6..66f055e9fe 100644 --- a/src/libkwineffects/kwineffects.h +++ b/src/libkwineffects/kwineffects.h @@ -40,6 +40,8 @@ class KConfigGroup; class QFont; class QKeyEvent; class QMatrix4x4; +class QMouseEvent; +class QWheelEvent; class QAction; class QTabletEvent; class QQmlEngine; @@ -63,16 +65,23 @@ class Display; class PaintDataPrivate; class WindowPaintDataPrivate; +class Compositor; +class EffectLoader; class EffectWindow; class EffectWindowGroup; class OffscreenQuickView; class Group; class Output; class Effect; +class TabletEvent; +class TabletPadId; +class TabletToolId; class Window; class WindowItem; +class WindowPropertyNotifyX11Filter; class WindowQuad; class WindowQuadList; +class WorkspaceScene; class VirtualDesktop; typedef QPair EffectPair; @@ -133,6 +142,12 @@ KWIN_EXPORT inline QPoint flooredPoint(const QPointF &point) class KWIN_EXPORT EffectsHandler : public QObject { Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Effects") + + Q_PROPERTY(QStringList activeEffects READ activeEffects) + Q_PROPERTY(QStringList loadedEffects READ loadedEffects) + Q_PROPERTY(QStringList listOfEffects READ listOfEffects) + Q_PROPERTY(KWin::VirtualDesktop *currentDesktop READ currentDesktop WRITE setCurrentDesktop NOTIFY desktopChanged) Q_PROPERTY(QString currentActivity READ currentActivity NOTIFY currentActivityChanged) Q_PROPERTY(KWin::EffectWindow *activeWindow READ activeWindow WRITE activateWindow NOTIFY windowActivated) @@ -176,27 +191,31 @@ class KWIN_EXPORT EffectsHandler : public QObject public: using TouchBorderCallback = std::function; - explicit EffectsHandler(CompositingType type); + EffectsHandler(Compositor *compositor, WorkspaceScene *scene); ~EffectsHandler() override; + + // internal (used by kwin core or compositing code) + void startPaint(); + // for use by effects - virtual void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) = 0; - virtual void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) = 0; - virtual void postPaintScreen() = 0; - virtual void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) = 0; - virtual void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) = 0; - virtual void postPaintWindow(EffectWindow *w) = 0; - virtual void drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) = 0; - virtual void renderWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) = 0; - virtual QVariant kwinOption(KWinOption kwopt) = 0; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime); + void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen); + void postPaintScreen(); + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime); + void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data); + void postPaintWindow(EffectWindow *w); + void drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data); + void renderWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data); + QVariant kwinOption(KWinOption kwopt); /** * Sets the cursor while the mouse is intercepted. * @see startMouseInterception * @since 4.11 */ - virtual void defineCursor(Qt::CursorShape shape) = 0; - virtual QPointF cursorPos() const = 0; - virtual bool grabKeyboard(Effect *effect) = 0; - virtual void ungrabKeyboard() = 0; + virtual void defineCursor(Qt::CursorShape shape); + QPointF cursorPos() const; + bool grabKeyboard(Effect *effect); + void ungrabKeyboard(); /** * Ensures that all mouse events are sent to the @p effect. * No window will get the mouse events. Only fullscreen effects providing a custom user interface should @@ -211,13 +230,21 @@ public: * @see Effect::windowInputMouseEvent * @since 4.11 */ - virtual void startMouseInterception(Effect *effect, Qt::CursorShape shape) = 0; + void startMouseInterception(Effect *effect, Qt::CursorShape shape); /** * Releases the hold mouse interception for @p effect * @see startMouseInterception * @since 4.11 */ - virtual void stopMouseInterception(Effect *effect) = 0; + void stopMouseInterception(Effect *effect); + bool isMouseInterception() const; + + bool checkInputWindowEvent(QMouseEvent *e); + bool checkInputWindowEvent(QWheelEvent *e); + void checkInputWindowStacking(); + + void grabbedKeyboardEvent(QKeyEvent *e); + bool hasKeyboardGrab() const; /** * @brief Registers a global pointer shortcut with the provided @p action. @@ -226,7 +253,7 @@ public: * @param pointerButtons The pointer buttons which need to be pressed * @param action The action which gets triggered when the shortcut matches */ - virtual void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) = 0; + void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action); /** * @brief Registers a global axis shortcut with the provided @p action. * @@ -234,7 +261,7 @@ public: * @param axis The direction in which the axis needs to be moved * @param action The action which gets triggered when the shortcut matches */ - virtual void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) = 0; + void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action); /** * @brief Registers a global touchpad swipe gesture shortcut with the provided @p action. @@ -243,9 +270,9 @@ public: * @param action The action which gets triggered when the gesture triggers * @since 5.10 */ - virtual void registerTouchpadSwipeShortcut(SwipeDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback = {}) = 0; + void registerTouchpadSwipeShortcut(SwipeDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback = {}); - virtual void registerTouchpadPinchShortcut(PinchDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback = {}) = 0; + void registerTouchpadPinchShortcut(PinchDirection dir, uint fingerCount, QAction *onUp, std::function progressCallback = {}); /** * @brief Registers a global touchscreen swipe gesture shortcut with the provided @p action. @@ -254,14 +281,14 @@ public: * @param action The action which gets triggered when the gesture triggers * @since 5.25 */ - virtual void registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback) = 0; + void registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback); // Mouse polling - virtual void startMousePolling() = 0; - virtual void stopMousePolling() = 0; + void startMousePolling(); + void stopMousePolling(); - virtual void reserveElectricBorder(ElectricBorder border, Effect *effect) = 0; - virtual void unreserveElectricBorder(ElectricBorder border, Effect *effect) = 0; + void reserveElectricBorder(ElectricBorder border, Effect *effect); + void unreserveElectricBorder(ElectricBorder border, Effect *effect); /** * Registers the given @p action for the given @p border to be activated through @@ -276,7 +303,7 @@ public: * @see unregisterTouchBorder * @since 5.10 */ - virtual void registerTouchBorder(ElectricBorder border, QAction *action) = 0; + void registerTouchBorder(ElectricBorder border, QAction *action); /** * Registers the given @p action for the given @p border to be activated through @@ -294,7 +321,7 @@ public: * @see unregisterTouchBorder * @since 5.25 */ - virtual void registerRealtimeTouchBorder(ElectricBorder border, QAction *action, TouchBorderCallback progressCallback) = 0; + void registerRealtimeTouchBorder(ElectricBorder border, QAction *action, TouchBorderCallback progressCallback); /** * Unregisters the given @p action for the given touch @p border. @@ -302,101 +329,101 @@ public: * @see registerTouchBorder * @since 5.10 */ - virtual void unregisterTouchBorder(ElectricBorder border, QAction *action) = 0; + void unregisterTouchBorder(ElectricBorder border, QAction *action); // functions that allow controlling windows/desktop - virtual void activateWindow(KWin::EffectWindow *c) = 0; - virtual KWin::EffectWindow *activeWindow() const = 0; - Q_SCRIPTABLE virtual void moveWindow(KWin::EffectWindow *w, const QPoint &pos, bool snap = false, double snapAdjust = 1.0) = 0; + void activateWindow(KWin::EffectWindow *c); + KWin::EffectWindow *activeWindow() const; + Q_SCRIPTABLE void moveWindow(KWin::EffectWindow *w, const QPoint &pos, bool snap = false, double snapAdjust = 1.0); /** * Moves a window to the given desktops * On X11, the window will end up on the last window in the list * Setting this to an empty list will set the window on all desktops */ - Q_SCRIPTABLE virtual void windowToDesktops(KWin::EffectWindow *w, const QList &desktops) = 0; + Q_SCRIPTABLE void windowToDesktops(KWin::EffectWindow *w, const QList &desktops); - Q_SCRIPTABLE virtual void windowToScreen(KWin::EffectWindow *w, Output *screen) = 0; - virtual void setShowingDesktop(bool showing) = 0; + Q_SCRIPTABLE void windowToScreen(KWin::EffectWindow *w, Output *screen); + void setShowingDesktop(bool showing); // Activities /** * @returns The ID of the current activity. */ - virtual QString currentActivity() const = 0; + QString currentActivity() const; // Desktops /** * @returns The current desktop. */ - virtual VirtualDesktop *currentDesktop() const = 0; + VirtualDesktop *currentDesktop() const; /** * @returns Total number of desktops currently in existence. */ - virtual QList desktops() const = 0; + QList desktops() const; /** * Set the current desktop to @a desktop. */ - virtual void setCurrentDesktop(KWin::VirtualDesktop *desktop) = 0; + void setCurrentDesktop(KWin::VirtualDesktop *desktop); /** * @returns The size of desktop layout in grid units. */ - virtual QSize desktopGridSize() const = 0; + QSize desktopGridSize() const; /** * @returns The width of desktop layout in grid units. */ - virtual int desktopGridWidth() const = 0; + int desktopGridWidth() const; /** * @returns The height of desktop layout in grid units. */ - virtual int desktopGridHeight() const = 0; + int desktopGridHeight() const; /** * @returns The width of desktop layout in pixels. */ - virtual int workspaceWidth() const = 0; + int workspaceWidth() const; /** * @returns The height of desktop layout in pixels. */ - virtual int workspaceHeight() const = 0; + int workspaceHeight() const; /** * @returns The desktop at the point @a coords or 0 if no desktop exists at that * point. @a coords is to be in grid units. */ - virtual VirtualDesktop *desktopAtCoords(QPoint coords) const = 0; + VirtualDesktop *desktopAtCoords(QPoint coords) const; /** * @returns The coords of the specified @a desktop in grid units. */ - virtual QPoint desktopGridCoords(VirtualDesktop *desktop) const = 0; + QPoint desktopGridCoords(VirtualDesktop *desktop) const; /** * @returns The coords of the top-left corner of @a desktop in pixels. */ - virtual QPoint desktopCoords(VirtualDesktop *desktop) const = 0; + QPoint desktopCoords(VirtualDesktop *desktop) const; /** * @returns The desktop above the given @a desktop. Wraps around to the bottom of * the layout if @a wrap is set. If @a id is not set use the current one. */ - Q_SCRIPTABLE virtual KWin::VirtualDesktop *desktopAbove(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const = 0; + Q_SCRIPTABLE KWin::VirtualDesktop *desktopAbove(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const; /** * @returns The desktop to the right of the given @a desktop. Wraps around to the * left of the layout if @a wrap is set. If @a id is not set use the current one. */ - Q_SCRIPTABLE virtual KWin::VirtualDesktop *desktopToRight(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const = 0; + Q_SCRIPTABLE KWin::VirtualDesktop *desktopToRight(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const; /** * @returns The desktop below the given @a desktop. Wraps around to the top of the * layout if @a wrap is set. If @a id is not set use the current one. */ - Q_SCRIPTABLE virtual KWin::VirtualDesktop *desktopBelow(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const = 0; + Q_SCRIPTABLE KWin::VirtualDesktop *desktopBelow(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const; /** * @returns The desktop to the left of the given @a desktop. Wraps around to the * right of the layout if @a wrap is set. If @a id is not set use the current one. */ - Q_SCRIPTABLE virtual KWin::VirtualDesktop *desktopToLeft(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const = 0; - Q_SCRIPTABLE virtual QString desktopName(KWin::VirtualDesktop *desktop) const = 0; - virtual bool optionRollOverDesktops() const = 0; + Q_SCRIPTABLE KWin::VirtualDesktop *desktopToLeft(KWin::VirtualDesktop *desktop = nullptr, bool wrap = true) const; + Q_SCRIPTABLE QString desktopName(KWin::VirtualDesktop *desktop) const; + bool optionRollOverDesktops() const; - virtual Output *activeScreen() const = 0; // Xinerama - virtual QRectF clientArea(clientAreaOption, const Output *screen, const VirtualDesktop *desktop) const = 0; - virtual QRectF clientArea(clientAreaOption, const EffectWindow *c) const = 0; - virtual QRectF clientArea(clientAreaOption, const QPoint &p, const VirtualDesktop *desktop) const = 0; + Output *activeScreen() const; // Xinerama + QRectF clientArea(clientAreaOption, const Output *screen, const VirtualDesktop *desktop) const; + QRectF clientArea(clientAreaOption, const EffectWindow *c) const; + QRectF clientArea(clientAreaOption, const QPoint &p, const VirtualDesktop *desktop) const; /** * The bounding size of all screens combined. Overlapping areas @@ -406,7 +433,7 @@ public: * @see virtualScreenSizeChanged() * @since 5.0 */ - virtual QSize virtualScreenSize() const = 0; + QSize virtualScreenSize() const; /** * The bounding geometry of all outputs combined. Always starts at (0,0) and has * virtualScreenSize as it's size. @@ -415,7 +442,7 @@ public: * @see virtualScreenGeometryChanged() * @since 5.0 */ - virtual QRect virtualScreenGeometry() const = 0; + QRect virtualScreenGeometry() const; /** * Factor by which animation speed in the effect should be modified (multiplied). * If configurable in the effect itself, the option should have also 'default' @@ -423,10 +450,10 @@ public: * Note: The factor can be also 0, so make sure your code can cope with 0ms time * if used manually. */ - virtual double animationTimeFactor() const = 0; + double animationTimeFactor() const; - Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(WId id) const = 0; - Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(SurfaceInterface *surf) const = 0; + Q_SCRIPTABLE KWin::EffectWindow *findWindow(WId id) const; + Q_SCRIPTABLE KWin::EffectWindow *findWindow(SurfaceInterface *surf) const; /** * Finds the EffectWindow for the internal window @p w. * If there is no such window @c null is returned. @@ -436,38 +463,38 @@ public: * * @since 5.16 */ - Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(QWindow *w) const = 0; + Q_SCRIPTABLE KWin::EffectWindow *findWindow(QWindow *w) const; /** * Finds the EffectWindow for the Window with KWin internal @p id. * If there is no such window @c null is returned. * * @since 5.16 */ - Q_SCRIPTABLE virtual KWin::EffectWindow *findWindow(const QUuid &id) const = 0; - virtual EffectWindowList stackingOrder() const = 0; + Q_SCRIPTABLE KWin::EffectWindow *findWindow(const QUuid &id) const; + EffectWindowList stackingOrder() const; // 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; + Q_SCRIPTABLE void setElevatedWindow(KWin::EffectWindow *w, bool set); - virtual void setTabBoxWindow(EffectWindow *) = 0; - virtual EffectWindowList currentTabBoxWindowList() const = 0; - virtual void refTabBox() = 0; - virtual void unrefTabBox() = 0; - virtual void closeTabBox() = 0; - virtual EffectWindow *currentTabBoxWindow() const = 0; + void setTabBoxWindow(EffectWindow *); + EffectWindowList currentTabBoxWindowList() const; + void refTabBox(); + void unrefTabBox(); + void closeTabBox(); + EffectWindow *currentTabBoxWindow() const; - virtual void setActiveFullScreenEffect(Effect *e) = 0; - virtual Effect *activeFullScreenEffect() const = 0; + void setActiveFullScreenEffect(Effect *e); + Effect *activeFullScreenEffect() const; /** * Schedules the entire workspace to be repainted next time. * If you call it during painting (including prepaint) then it does not * affect the current painting. */ - Q_SCRIPTABLE virtual void addRepaintFull() = 0; - Q_SCRIPTABLE virtual void addRepaint(const QRectF &r) = 0; - Q_SCRIPTABLE virtual void addRepaint(const QRect &r) = 0; - Q_SCRIPTABLE virtual void addRepaint(const QRegion &r) = 0; - Q_SCRIPTABLE virtual void addRepaint(int x, int y, int w, int h) = 0; + Q_SCRIPTABLE void addRepaintFull(); + Q_SCRIPTABLE void addRepaint(const QRectF &r); + Q_SCRIPTABLE void addRepaint(const QRect &r); + Q_SCRIPTABLE void addRepaint(const QRegion &r); + Q_SCRIPTABLE void addRepaint(int x, int y, int w, int h); CompositingType compositingType() const; /** @@ -484,10 +511,10 @@ public: * * @return QPainter* The Scene's QPainter or @c null. */ - virtual QPainter *scenePainter() = 0; - virtual void reconfigure() = 0; + QPainter *scenePainter(); + void reconfigure(); - virtual QByteArray readRootProperty(long atom, long type, int format) const = 0; + QByteArray readRootProperty(long atom, long type, int format) const; /** * @brief Announces support for the feature with the given name. If no other Effect * has announced support for this feature yet, an X11 property will be installed on @@ -505,7 +532,7 @@ public: * @see removeSupportProperty * @since 4.11 */ - virtual xcb_atom_t announceSupportProperty(const QByteArray &propertyName, Effect *effect) = 0; + xcb_atom_t announceSupportProperty(const QByteArray &propertyName, Effect *effect); /** * @brief Removes support for the feature with the given name. If there is no other Effect left * which has announced support for the given property, the property will be removed from the @@ -518,18 +545,18 @@ public: * @see announceSupportProperty * @since 4.11 */ - virtual void removeSupportProperty(const QByteArray &propertyName, Effect *effect) = 0; + void removeSupportProperty(const QByteArray &propertyName, Effect *effect); /** * Returns @a true if the active window decoration has shadow API hooks. */ - virtual bool hasDecorationShadows() const = 0; + bool hasDecorationShadows() const; /** * Returns @a true if the window decorations use the alpha channel, and @a false otherwise. * @since 4.5 */ - virtual bool decorationsHaveAlpha() const = 0; + bool decorationsHaveAlpha() const; /** * Allows an effect to trigger a reload of itself. @@ -539,7 +566,14 @@ public: * @param effect The effect to reload * @since 4.8 */ - virtual void reloadEffect(Effect *effect) = 0; + void reloadEffect(Effect *effect); + Effect *provides(Effect::Feature ef); + Effect *findEffect(const QString &name) const; + QStringList loadedEffects() const; + QStringList listOfEffects() const; + void unloadAllEffects(); + QStringList activeEffects() const; + bool isEffectActive(const QString &pluginId) const; /** * Whether the screen is currently considered as locked. @@ -551,7 +585,7 @@ public: * @see screenLockingChanged * @since 4.11 */ - virtual bool isScreenLocked() const = 0; + bool isScreenLocked() const; /** * @brief Makes the OpenGL compositing context current. @@ -560,7 +594,7 @@ public: * * @return bool @c true if the context became current, @c false otherwise. */ - virtual bool makeOpenGLContextCurrent() = 0; + bool makeOpenGLContextCurrent(); /** * @brief Makes a null OpenGL context current resulting in no context * being current. @@ -569,17 +603,17 @@ public: * * There is normally no reason for an Effect to call this method. */ - virtual void doneOpenGLContextCurrent() = 0; + void doneOpenGLContextCurrent(); - virtual xcb_connection_t *xcbConnection() const = 0; - virtual xcb_window_t x11RootWindow() const = 0; + xcb_connection_t *xcbConnection() const; + xcb_window_t x11RootWindow() const; /** * Interface to the Wayland display: this is relevant only * on Wayland, on X11 it will be nullptr * @since 5.5 */ - virtual Display *waylandDisplay() const = 0; + Display *waylandDisplay() const; /** * Whether animations are supported by the Scene. @@ -589,33 +623,33 @@ public: * @returns Whether the Scene can drive animations * @since 5.8 */ - virtual bool animationsSupported() const = 0; + bool animationsSupported() const; /** * The current cursor image of the Platform. * @see cursorPos * @since 5.9 */ - virtual PlatformCursorImage cursorImage() const = 0; + PlatformCursorImage cursorImage() const; /** * The cursor image should be hidden. * @see showCursor * @since 5.9 */ - virtual void hideCursor() = 0; + void hideCursor(); /** * The cursor image should be shown again after having been hidden. * @see hideCursor * @since 5.9 */ - virtual void showCursor() = 0; + void showCursor(); /** * @returns Whether or not the cursor is currently hidden */ - virtual bool isCursorHidden() const = 0; + bool isCursorHidden() const; /** * Starts an interactive window selection process. @@ -629,7 +663,7 @@ public: * @param callback The function to invoke once the interactive window selection ends * @since 5.9 */ - virtual void startInteractiveWindowSelection(std::function callback) = 0; + void startInteractiveWindowSelection(std::function callback); /** * Starts an interactive position selection process. @@ -644,7 +678,7 @@ public: * @param callback The function to invoke once the interactive position selection ends * @since 5.9 */ - virtual void startInteractivePositionSelection(std::function callback) = 0; + void startInteractivePositionSelection(std::function callback); /** * Shows an on-screen-message. To hide it again use hideOnScreenMessage. @@ -654,7 +688,7 @@ public: * @see hideOnScreenMessage * @since 5.9 */ - virtual void showOnScreenMessage(const QString &message, const QString &iconName = QString()) = 0; + void showOnScreenMessage(const QString &message, const QString &iconName = QString()); /** * Flags for how to hide a shown on-screen-message @@ -675,55 +709,82 @@ public: * @see showOnScreenMessage * @since 5.9 */ - virtual void hideOnScreenMessage(OnScreenMessageHideFlags flags = OnScreenMessageHideFlags()) = 0; + void hideOnScreenMessage(OnScreenMessageHideFlags flags = OnScreenMessageHideFlags()); /* * @returns The configuration used by the EffectsHandler. * @since 5.10 */ - virtual KSharedConfigPtr config() const = 0; + KSharedConfigPtr config() const; /** * @returns The global input configuration (kcminputrc) * @since 5.10 */ - virtual KSharedConfigPtr inputConfig() const = 0; + KSharedConfigPtr inputConfig() const; /** * Returns if activeFullScreenEffect is set */ - virtual bool hasActiveFullScreenEffect() const = 0; + bool hasActiveFullScreenEffect() const; /** * Render the supplied OffscreenQuickView onto the scene * It can be called at any point during the scene rendering * @since 5.18 */ - virtual void renderOffscreenQuickView(const RenderTarget &renderTarget, const RenderViewport &viewport, OffscreenQuickView *effectQuickView) const = 0; + void renderOffscreenQuickView(const RenderTarget &renderTarget, const RenderViewport &viewport, OffscreenQuickView *effectQuickView) const; /** * The status of the session i.e if the user is logging out * @since 5.18 */ - virtual SessionState sessionState() const = 0; + SessionState sessionState() const; /** * Returns the list of all the screens connected to the system. */ - virtual QList screens() const = 0; - virtual Output *screenAt(const QPoint &point) const = 0; - virtual Output *findScreen(const QString &name) const = 0; - virtual Output *findScreen(int screenId) const = 0; + QList screens() const; + Output *screenAt(const QPoint &point) const; + Output *findScreen(const QString &name) const; + Output *findScreen(int screenId) const; /** * Renders @p screen in the current render target */ - virtual void renderScreen(Output *screen) = 0; + void renderScreen(Output *screen); - virtual KWin::EffectWindow *inputPanel() const = 0; - virtual bool isInputPanelOverlay() const = 0; + KWin::EffectWindow *inputPanel() const; + bool isInputPanelOverlay() const; - virtual QQmlEngine *qmlEngine() const = 0; + QQmlEngine *qmlEngine() const; + + /** + * @returns whether or not any effect is currently active where KWin should not use direct scanout + */ + bool blocksDirectScanout() const; + + WorkspaceScene *scene() const + { + return m_scene; + } + + bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time); + bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time); + bool touchUp(qint32 id, std::chrono::microseconds time); + + bool tabletToolEvent(KWin::TabletEvent *event); + bool tabletToolButtonEvent(uint button, bool pressed, const KWin::TabletToolId &tabletToolId, std::chrono::microseconds time); + bool tabletPadButtonEvent(uint button, bool pressed, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time); + bool tabletPadStripEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time); + bool tabletPadRingEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time); + + void highlightWindows(const QList &windows); + + bool isPropertyTypeRegistered(xcb_atom_t atom) const + { + return registered_atoms.contains(atom); + } Q_SIGNALS: /** @@ -1009,10 +1070,74 @@ Q_SIGNALS: void inputPanelChanged(); +public Q_SLOTS: + // slots for D-Bus interface + Q_SCRIPTABLE void reconfigureEffect(const QString &name); + Q_SCRIPTABLE bool loadEffect(const QString &name); + Q_SCRIPTABLE void toggleEffect(const QString &name); + Q_SCRIPTABLE void unloadEffect(const QString &name); + Q_SCRIPTABLE bool isEffectLoaded(const QString &name) const; + Q_SCRIPTABLE bool isEffectSupported(const QString &name); + Q_SCRIPTABLE QList areEffectsSupported(const QStringList &names); + Q_SCRIPTABLE QString supportInformation(const QString &name) const; + Q_SCRIPTABLE QString debug(const QString &name, const QString ¶meter = QString()) const; + protected: + void connectNotify(const QMetaMethod &signal) override; + void disconnectNotify(const QMetaMethod &signal) override; + void effectsChanged(); + void setupWindowConnections(KWin::Window *window); + + /** + * Default implementation does nothing and returns @c true. + */ + virtual bool doGrabKeyboard(); + /** + * Default implementation does nothing. + */ + virtual void doUngrabKeyboard(); + + /** + * Default implementation sets Effects override cursor on the PointerInputRedirection. + */ + virtual void doStartMouseInterception(Qt::CursorShape shape); + + /** + * Default implementation removes the Effects override cursor on the PointerInputRedirection. + */ + virtual void doStopMouseInterception(); + + /** + * Default implementation does nothing + */ + virtual void doCheckInputWindowStacking(); + + void registerPropertyType(long atom, bool reg); + void destroyEffect(Effect *effect); + void reconfigureEffects(); + + typedef QList EffectsList; + typedef EffectsList::const_iterator EffectsIterator; + + Effect *keyboard_grab_effect; + Effect *fullscreen_effect; + QMultiMap effect_order; + QHash registered_atoms; QList loaded_effects; - // QHash< QString, EffectFactory* > effect_factories; CompositingType compositing_type; + EffectsList m_activeEffects; + EffectsIterator m_currentDrawWindowIterator; + EffectsIterator m_currentPaintWindowIterator; + EffectsIterator m_currentPaintScreenIterator; + typedef QHash> PropertyEffectMap; + PropertyEffectMap m_propertiesForEffects; + QHash m_managedProperties; + Compositor *m_compositor; + WorkspaceScene *m_scene; + QList m_grabbedMouseEffects; + EffectLoader *m_effectLoader; + int m_trackingCursorChanges; + std::unique_ptr m_x11WindowPropertyNotify; }; class EffectWindowVisibleRef; diff --git a/src/main.cpp b/src/main.cpp index a42c7a6700..7a65bff5c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,9 +19,9 @@ #include "core/session.h" #include "cursor.h" #include "cursorsource.h" -#include "effects.h" #include "input.h" #include "inputmethod.h" +#include "libkwineffects/kwineffects.h" #include "opengl/gltexture.h" #include "opengl/glutils.h" #include "options.h" @@ -355,7 +355,7 @@ std::unique_ptr Application::createOutline(Outline *outline) void Application::createEffectsHandler(Compositor *compositor, WorkspaceScene *scene) { - new EffectsHandlerImpl(compositor, scene); + new EffectsHandler(compositor, scene); } void Application::registerEventFilter(X11EventFilter *filter) diff --git a/src/main_wayland.cpp b/src/main_wayland.cpp index 5916984b0d..903e68fe93 100644 --- a/src/main_wayland.cpp +++ b/src/main_wayland.cpp @@ -17,8 +17,8 @@ #include "compositor_wayland.h" #include "core/outputbackend.h" #include "core/session.h" -#include "effects.h" #include "inputmethod.h" +#include "libkwineffects/kwineffects.h" #include "tabletmodemanager.h" #include "utils/realtime.h" #include "wayland/display.h" @@ -117,7 +117,7 @@ ApplicationWayland::~ApplicationWayland() // need to unload all effects prior to destroying X connection as they might do X calls if (effects) { - static_cast(effects)->unloadAllEffects(); + effects->unloadAllEffects(); } m_xwayland.reset(); destroyColorManager(); diff --git a/src/main_x11.cpp b/src/main_x11.cpp index 2a76002c63..7c4306e62d 100644 --- a/src/main_x11.cpp +++ b/src/main_x11.cpp @@ -17,7 +17,7 @@ #include "core/outputbackend.h" #include "core/session.h" #include "cursor.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "outline.h" #include "screenedge.h" #include "sm.h" @@ -184,7 +184,7 @@ ApplicationX11::~ApplicationX11() setTerminating(); // need to unload all effects before destroying Workspace, as effects might call into Workspace if (effects) { - static_cast(effects)->unloadAllEffects(); + effects->unloadAllEffects(); } destroyPlugins(); destroyColorManager(); @@ -245,7 +245,7 @@ void ApplicationX11::lostSelection() sendPostedEvents(); // need to unload all effects before destroying Workspace, as effects might call into Workspace if (effects) { - static_cast(effects)->unloadAllEffects(); + effects->unloadAllEffects(); } destroyPlugins(); destroyColorManager(); diff --git a/src/plugins/screencast/screencastmanager.cpp b/src/plugins/screencast/screencastmanager.cpp index bde7ac5fa0..ff0081aaca 100644 --- a/src/plugins/screencast/screencastmanager.cpp +++ b/src/plugins/screencast/screencastmanager.cpp @@ -10,7 +10,6 @@ #include "compositor.h" #include "core/output.h" #include "core/outputbackend.h" -#include "effects.h" #include "opengl/gltexture.h" #include "outputscreencastsource.h" #include "regionscreencastsource.h" diff --git a/src/plugins/windowsystem/windoweffects.cpp b/src/plugins/windowsystem/windoweffects.cpp index 9cbc401a4c..8be76c8177 100644 --- a/src/plugins/windowsystem/windoweffects.cpp +++ b/src/plugins/windowsystem/windoweffects.cpp @@ -4,7 +4,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL */ #include "windoweffects.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include #include @@ -30,14 +30,13 @@ bool WindowEffects::isEffectAvailable(KWindowEffects::Effect effect) if (!effects) { return false; } - auto e = static_cast(effects); switch (effect) { case KWindowEffects::BackgroundContrast: - return e->isEffectLoaded(QStringLiteral("contrast")); + return effects->isEffectLoaded(QStringLiteral("contrast")); case KWindowEffects::BlurBehind: - return e->isEffectLoaded(QStringLiteral("blur")); + return effects->isEffectLoaded(QStringLiteral("blur")); case KWindowEffects::Slide: - return e->isEffectLoaded(QStringLiteral("slidingpopups")); + return effects->isEffectLoaded(QStringLiteral("slidingpopups")); default: // plugin does not provide integration for other effects return false; diff --git a/src/pointer_input.cpp b/src/pointer_input.cpp index d5ff3c4e46..0dddf6039a 100644 --- a/src/pointer_input.cpp +++ b/src/pointer_input.cpp @@ -16,7 +16,6 @@ #include "core/output.h" #include "cursorsource.h" #include "decorations/decoratedclient.h" -#include "effects.h" #include "input_event.h" #include "input_event_spy.h" #include "mousebuttons.h" @@ -1076,7 +1075,7 @@ void CursorImage::reevaluteSource() setSource(m_windowSelectionCursor.get()); return; } - if (effects && static_cast(effects)->isMouseInterception()) { + if (effects && effects->isMouseInterception()) { setSource(m_effectsCursor.get()); return; } diff --git a/src/scene/workspacescene.cpp b/src/scene/workspacescene.cpp index 5e20895f11..b9391d8ec4 100644 --- a/src/scene/workspacescene.cpp +++ b/src/scene/workspacescene.cpp @@ -59,8 +59,8 @@ #include "core/renderlayer.h" #include "core/renderloop.h" #include "core/renderviewport.h" -#include "effects.h" #include "internalwindow.h" +#include "libkwineffects/kwineffects.h" #include "scene/dndiconitem.h" #include "scene/itemrenderer.h" #include "scene/shadowitem.h" @@ -156,7 +156,7 @@ SurfaceItem *WorkspaceScene::scanoutCandidate() const return nullptr; } SurfaceItem *candidate = nullptr; - if (!static_cast(effects)->blocksDirectScanout()) { + if (!effects->blocksDirectScanout()) { for (int i = stacking_order.count() - 1; i >= 0; i--) { WindowItem *windowItem = stacking_order[i]; Window *window = windowItem->window(); @@ -248,8 +248,7 @@ QRegion WorkspaceScene::prePaint(SceneDelegate *delegate) } // preparation step - auto effectsImpl = static_cast(effects); - effectsImpl->startPaint(); + effects->startPaint(); ScreenPrePaintData prePaintData; prePaintData.mask = 0; diff --git a/src/scene/workspacescene.h b/src/scene/workspacescene.h index c11af7503e..686ae1e0d9 100644 --- a/src/scene/workspacescene.h +++ b/src/scene/workspacescene.h @@ -88,7 +88,7 @@ Q_SIGNALS: protected: void createStackingOrder(); void clearStackingOrder(); - friend class EffectsHandlerImpl; + friend class EffectsHandler; // called after all effects had their paintScreen() called void finalPaintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen); // shared implementation of painting the screen in the generic diff --git a/src/screenedge.cpp b/src/screenedge.cpp index 9ff3c4f1f7..e434d16cae 100644 --- a/src/screenedge.cpp +++ b/src/screenedge.cpp @@ -22,8 +22,8 @@ #include "core/output.h" #include "cursor.h" -#include "effects.h" #include "gestures.h" +#include "libkwineffects/kwineffects.h" #include "main.h" #include "pointer_input.h" #include "utils/common.h" diff --git a/src/scripting/gesturehandler.cpp b/src/scripting/gesturehandler.cpp index 9346a6d195..07d55d2ee3 100644 --- a/src/scripting/gesturehandler.cpp +++ b/src/scripting/gesturehandler.cpp @@ -5,7 +5,7 @@ */ #include "gesturehandler.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include diff --git a/src/scripting/windowthumbnailitem.cpp b/src/scripting/windowthumbnailitem.cpp index 90e75b4c22..2b09a25c14 100644 --- a/src/scripting/windowthumbnailitem.cpp +++ b/src/scripting/windowthumbnailitem.cpp @@ -11,7 +11,6 @@ #include "core/renderbackend.h" #include "core/rendertarget.h" #include "core/renderviewport.h" -#include "effects.h" #include "scene/itemrenderer.h" #include "scene/windowitem.h" #include "scene/workspacescene.h" diff --git a/src/scripting/workspace_wrapper.cpp b/src/scripting/workspace_wrapper.cpp index 1f76ed8a75..530a15eeb3 100644 --- a/src/scripting/workspace_wrapper.cpp +++ b/src/scripting/workspace_wrapper.cpp @@ -12,7 +12,7 @@ #include "core/output.h" #include "core/outputbackend.h" #include "cursor.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "outline.h" #include "tiles/tilemanager.h" #include "virtualdesktops.h" @@ -333,7 +333,7 @@ bool WorkspaceWrapper::isEffectActive(const QString &pluginId) const if (!effects) { return false; } - return static_cast(effects)->isEffectActive(pluginId); + return effects->isEffectActive(pluginId); } QSize WorkspaceWrapper::desktopGridSize() const diff --git a/src/tabbox/tabbox.cpp b/src/tabbox/tabbox.cpp index b857db3794..f476349448 100644 --- a/src/tabbox/tabbox.cpp +++ b/src/tabbox/tabbox.cpp @@ -22,10 +22,10 @@ #include "activities.h" #endif #include "compositor.h" -#include "effects.h" #include "focuschain.h" #include "input.h" #include "keyboard_input.h" +#include "libkwineffects/kwineffects.h" #include "pointer_input.h" #include "screenedge.h" #include "utils/xcbutils.h" @@ -271,7 +271,7 @@ void TabBoxHandlerImpl::highlightWindows(Window *window, QWindow *controller) if (Window *t = workspace()->findInternal(controller)) { windows << t->effectWindow(); } - static_cast(effects)->highlightWindows(windows); + effects->highlightWindows(windows); } bool TabBoxHandlerImpl::noModifierGrab() const @@ -606,7 +606,7 @@ bool TabBox::handleMouseEvent(QMouseEvent *event) { if (!m_isShown && isDisplayed()) { // tabbox has been replaced, check effects - if (effects && static_cast(effects)->checkInputWindowEvent(event)) { + if (effects && effects->checkInputWindowEvent(event)) { return true; } } @@ -636,7 +636,7 @@ bool TabBox::handleWheelEvent(QWheelEvent *event) { if (!m_isShown && isDisplayed()) { // tabbox has been replaced, check effects - if (effects && static_cast(effects)->checkInputWindowEvent(event)) { + if (effects && effects->checkInputWindowEvent(event)) { return true; } } diff --git a/src/tabbox/x11_filter.cpp b/src/tabbox/x11_filter.cpp index 89bfc70f12..a7e781e364 100644 --- a/src/tabbox/x11_filter.cpp +++ b/src/tabbox/x11_filter.cpp @@ -8,7 +8,7 @@ */ #include "x11_filter.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "screenedge.h" #include "tabbox/tabbox.h" #include "utils/xcbutils.h" @@ -41,7 +41,7 @@ bool X11Filter::event(xcb_generic_event_t *event) auto e = reinterpret_cast(event); xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, XCB_CURRENT_TIME); if (!tab->isShown() && tab->isDisplayed()) { - if (effects && static_cast(effects)->isMouseInterception()) { + if (effects && effects->isMouseInterception()) { // pass on to effects, effects will filter out the event return false; } diff --git a/src/useractions.cpp b/src/useractions.cpp index 1386f3dd8f..557458f414 100644 --- a/src/useractions.cpp +++ b/src/useractions.cpp @@ -27,7 +27,6 @@ #include "core/output.h" #include "cursor.h" -#include "effects.h" #include "input.h" #include "options.h" #include "scripting/scripting.h" diff --git a/src/window_property_notify_x11_filter.cpp b/src/window_property_notify_x11_filter.cpp index 10f843211f..e0b0a5f207 100644 --- a/src/window_property_notify_x11_filter.cpp +++ b/src/window_property_notify_x11_filter.cpp @@ -7,14 +7,14 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "window_property_notify_x11_filter.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "workspace.h" #include "x11window.h" namespace KWin { -WindowPropertyNotifyX11Filter::WindowPropertyNotifyX11Filter(EffectsHandlerImpl *effects) +WindowPropertyNotifyX11Filter::WindowPropertyNotifyX11Filter(EffectsHandler *effects) : X11EventFilter(QList{XCB_PROPERTY_NOTIFY}) , m_effects(effects) { diff --git a/src/window_property_notify_x11_filter.h b/src/window_property_notify_x11_filter.h index e10ecedc33..e92919785c 100644 --- a/src/window_property_notify_x11_filter.h +++ b/src/window_property_notify_x11_filter.h @@ -12,17 +12,17 @@ namespace KWin { -class EffectsHandlerImpl; +class EffectsHandler; class WindowPropertyNotifyX11Filter : public X11EventFilter { public: - explicit WindowPropertyNotifyX11Filter(EffectsHandlerImpl *effects); + explicit WindowPropertyNotifyX11Filter(EffectsHandler *effects); bool event(xcb_generic_event_t *event) override; private: - EffectsHandlerImpl *m_effects; + EffectsHandler *m_effects; }; } diff --git a/src/workspace.cpp b/src/workspace.cpp index dbe3924f69..35b9ac21d2 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -24,12 +24,12 @@ #include "core/outputconfiguration.h" #include "cursor.h" #include "dbusinterface.h" -#include "effects.h" #include "focuschain.h" #include "group.h" #include "input.h" #include "internalwindow.h" #include "killwindow.h" +#include "libkwineffects/kwineffects.h" #include "moving_client_x11_filter.h" #include "netinfo.h" #include "outline.h" @@ -1842,20 +1842,20 @@ QString Workspace::supportInformation() const } support.append(QStringLiteral("\nLoaded Effects:\n")); support.append(QStringLiteral("---------------\n")); - const auto loadedEffects = static_cast(effects)->loadedEffects(); + const auto loadedEffects = effects->loadedEffects(); for (const QString &effect : loadedEffects) { support.append(effect + QStringLiteral("\n")); } support.append(QStringLiteral("\nCurrently Active Effects:\n")); support.append(QStringLiteral("-------------------------\n")); - const auto activeEffects = static_cast(effects)->activeEffects(); + const auto activeEffects = effects->activeEffects(); for (const QString &effect : activeEffects) { support.append(effect + QStringLiteral("\n")); } support.append(QStringLiteral("\nEffect Settings:\n")); support.append(QStringLiteral("----------------\n")); for (const QString &effect : loadedEffects) { - support.append(static_cast(effects)->supportInformation(effect)); + support.append(effects->supportInformation(effect)); support.append(QStringLiteral("\n")); } support.append(QLatin1String("\nLoaded Plugins:\n")); diff --git a/src/x11window.cpp b/src/x11window.cpp index 4179a93e01..62780a42ba 100644 --- a/src/x11window.cpp +++ b/src/x11window.cpp @@ -20,9 +20,9 @@ #include "cursor.h" #include "decorations/decoratedclient.h" #include "decorations/decorationbridge.h" -#include "effects.h" #include "focuschain.h" #include "group.h" +#include "libkwineffects/kwineffects.h" #include "netinfo.h" #include "placement.h" #include "scene/surfaceitem_x11.h" @@ -561,7 +561,7 @@ bool X11Window::track(xcb_window_t w) m_outline = internalWindow->property("__kwin_outline").toBool(); } if (effects) { - static_cast(effects)->checkInputWindowStacking(); + effects->checkInputWindowStacking(); } switch (kwinApp()->operationMode()) { diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp index c497fbe3df..77a0c75c48 100644 --- a/src/xdgactivationv1.cpp +++ b/src/xdgactivationv1.cpp @@ -8,7 +8,7 @@ */ #include "xdgactivationv1.h" -#include "effects.h" +#include "libkwineffects/kwineffects.h" #include "utils/common.h" #include "wayland/display.h" #include "wayland/plasmawindowmanagement.h"