diff --git a/autotests/integration/effects/slidingpopups_test.cpp b/autotests/integration/effects/slidingpopups_test.cpp --- a/autotests/integration/effects/slidingpopups_test.cpp +++ b/autotests/integration/effects/slidingpopups_test.cpp @@ -125,8 +125,8 @@ QTest::newRow("fade, slide") << QStringList{QStringLiteral("kwin4_effect_fade"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, fade") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_fade")}; - QTest::newRow("scale, slide") << QStringList{QStringLiteral("scale"), QStringLiteral("slidingpopups")}; - QTest::newRow("slide, scale") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("scale")}; + QTest::newRow("scale, slide") << QStringList{QStringLiteral("kwin4_effect_scale"), QStringLiteral("slidingpopups")}; + QTest::newRow("slide, scale") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_scale")}; if (effects->compositingType() & KWin::OpenGLCompositing) { QTest::newRow("glide, slide") << QStringList{QStringLiteral("glide"), QStringLiteral("slidingpopups")}; @@ -262,8 +262,8 @@ QTest::newRow("fade, slide") << QStringList{QStringLiteral("kwin4_effect_fade"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, fade") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_fade")}; - QTest::newRow("scale, slide") << QStringList{QStringLiteral("scale"), QStringLiteral("slidingpopups")}; - QTest::newRow("slide, scale") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("scale")}; + QTest::newRow("scale, slide") << QStringList{QStringLiteral("kwin4_effect_scale"), QStringLiteral("slidingpopups")}; + QTest::newRow("slide, scale") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_scale")}; if (effects->compositingType() & KWin::OpenGLCompositing) { QTest::newRow("glide, slide") << QStringList{QStringLiteral("glide"), QStringLiteral("slidingpopups")}; diff --git a/autotests/test_builtin_effectloader.cpp b/autotests/test_builtin_effectloader.cpp --- a/autotests/test_builtin_effectloader.cpp +++ b/autotests/test_builtin_effectloader.cpp @@ -103,7 +103,6 @@ QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true; QTest::newRow("Resize") << QStringLiteral("resize") << true; - QTest::newRow("Scale") << QStringLiteral("scale") << true; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true; QTest::newRow("Sheet") << QStringLiteral("sheet") << true; @@ -159,7 +158,6 @@ << QStringLiteral("mousemark") << QStringLiteral("presentwindows") << QStringLiteral("resize") - << QStringLiteral("scale") << QStringLiteral("screenedge") << QStringLiteral("screenshot") << QStringLiteral("sheet") @@ -237,7 +235,6 @@ QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc << true; QTest::newRow("Resize") << QStringLiteral("resize") << true << xc << true; - QTest::newRow("Scale") << QStringLiteral("scale") << true << xc << true; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc << true; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc << true; QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc << true; @@ -325,7 +322,6 @@ QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc; QTest::newRow("Resize") << QStringLiteral("resize") << true << xc; - QTest::newRow("Scale") << QStringLiteral("scale") << true << xc; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc; QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc; diff --git a/autotests/test_plugin_effectloader.cpp b/autotests/test_plugin_effectloader.cpp --- a/autotests/test_plugin_effectloader.cpp +++ b/autotests/test_plugin_effectloader.cpp @@ -94,7 +94,6 @@ QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false; QTest::newRow("Resize") << QStringLiteral("resize") << false; - QTest::newRow("Scale") << QStringLiteral("scale") << false; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << false; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << false; QTest::newRow("Sheet") << QStringLiteral("sheet") << false; @@ -118,6 +117,7 @@ QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << false; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << false; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << false; + QTest::newRow("Scale") << QStringLiteral("kwin4_effect_scale") << false; QTest::newRow("Squash") << QStringLiteral("kwin4_effect_squash") << false; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << false; // and the fake effects we use here diff --git a/autotests/test_scripted_effectloader.cpp b/autotests/test_scripted_effectloader.cpp --- a/autotests/test_scripted_effectloader.cpp +++ b/autotests/test_scripted_effectloader.cpp @@ -124,7 +124,6 @@ QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false; QTest::newRow("Resize") << QStringLiteral("resize") << false; - QTest::newRow("Scale") << QStringLiteral("scale") << false; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << false; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << false; QTest::newRow("Sheet") << QStringLiteral("sheet") << false; @@ -150,6 +149,7 @@ QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true; + QTest::newRow("Scale") << QStringLiteral("kwin4_effect_scale") << true; QTest::newRow("Squash") << QStringLiteral("kwin4_effect_squash") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } @@ -182,6 +182,7 @@ << QStringLiteral("kwin4_effect_login") << QStringLiteral("kwin4_effect_logout") << QStringLiteral("kwin4_effect_maximize") + << QStringLiteral("kwin4_effect_scale") << QStringLiteral("kwin4_effect_squash") << QStringLiteral("kwin4_effect_translucency"); @@ -209,6 +210,7 @@ QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true; + QTest::newRow("Scale") << QStringLiteral("kwin4_effect_scale") << true; QTest::newRow("Squash") << QStringLiteral("kwin4_effect_squash") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } @@ -361,6 +363,7 @@ plugins.writeEntry(kwin4 + QStringLiteral("loginEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("logoutEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("maximizeEnabled"), false); + plugins.writeEntry(kwin4 + QStringLiteral("scaleEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("squashEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("translucencyEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), false); diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -90,7 +90,6 @@ presentwindows/presentwindows.cpp presentwindows/presentwindows_proxy.cpp resize/resize.cpp - scale/scale.cpp showfps/showfps.cpp showpaint/showpaint.cpp slide/slide.cpp @@ -121,7 +120,6 @@ mousemark/mousemarkconfig.kcfgc presentwindows/presentwindowsconfig.kcfgc resize/resizeconfig.kcfgc - scale/scaleconfig.kcfgc showfps/showfpsconfig.kcfgc slide/slideconfig.kcfgc slidingpopups/slidingpopupsconfig.kcfgc @@ -142,6 +140,7 @@ add_subdirectory( logout ) add_subdirectory( maximize ) add_subdirectory( morphingpopups ) +add_subdirectory( scale ) add_subdirectory( squash ) add_subdirectory( translucency ) add_subdirectory( windowaperture ) @@ -182,7 +181,6 @@ add_subdirectory( magnifier ) add_subdirectory( mouseclick ) add_subdirectory( mousemark ) -add_subdirectory( scale ) include( screenshot/CMakeLists.txt ) include( sheet/CMakeLists.txt ) include( snaphelper/CMakeLists.txt ) diff --git a/effects/effect_builtins.h b/effects/effect_builtins.h --- a/effects/effect_builtins.h +++ b/effects/effect_builtins.h @@ -56,7 +56,6 @@ MouseMark, PresentWindows, Resize, - Scale, ScreenEdge, ScreenShot, Sheet, diff --git a/effects/effect_builtins.cpp b/effects/effect_builtins.cpp --- a/effects/effect_builtins.cpp +++ b/effects/effect_builtins.cpp @@ -36,7 +36,6 @@ #include "highlightwindow/highlightwindow.h" #include "magiclamp/magiclamp.h" #include "resize/resize.h" -#include "scale/scale.h" #include "showfps/showfps.h" #include "showpaint/showpaint.h" #include "slide/slide.h" @@ -428,21 +427,6 @@ nullptr, nullptr #endif -EFFECT_FALLBACK - }, { - QStringLiteral("scale"), - i18ndc("kwin_effects", "Name of a KWin Effect", "Scale"), - i18ndc("kwin_effects", "Comment describing the KWin Effect", "Make windows smoothly scale in and out when they are shown or hidden"), - QStringLiteral("Appearance"), - QString(), - QUrl(), - false, - false, -#ifdef EFFECT_BUILTINS - &createHelper, - &ScaleEffect::supported, - nullptr -#endif EFFECT_FALLBACK }, { QStringLiteral("screenedge"), diff --git a/effects/scale/CMakeLists.txt b/effects/scale/CMakeLists.txt --- a/effects/scale/CMakeLists.txt +++ b/effects/scale/CMakeLists.txt @@ -1,25 +1 @@ -####################################### -# Config -set(kwin_scale_config_SRCS scale_config.cpp) -ki18n_wrap_ui(kwin_scale_config_SRCS scale_config.ui) -qt5_add_dbus_interface(kwin_scale_config_SRCS ${kwin_effects_dbus_xml} kwineffects_interface) -kconfig_add_kcfg_files(kwin_scale_config_SRCS scaleconfig.kcfgc) - -add_library(kwin_scale_config MODULE ${kwin_scale_config_SRCS}) - -target_link_libraries(kwin_scale_config - Qt5::DBus - KF5::ConfigWidgets - KF5::I18n - KF5::Service -) - -kcoreaddons_desktop_to_json(kwin_scale_config scale_config.desktop SERVICE_TYPES kcmodule.desktop) - -install( - TARGETS - kwin_scale_config - DESTINATION - ${PLUGIN_INSTALL_DIR}/kwin/effects/configs -) - +add_subdirectory(package) diff --git a/effects/scale/package/CMakeLists.txt b/effects/scale/package/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/effects/scale/package/CMakeLists.txt @@ -0,0 +1,9 @@ +install(DIRECTORY contents + DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_scale) + +install(FILES metadata.desktop + DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_scale) + +install(FILES metadata.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/${KWIN_NAME} + RENAME kwin4_effect_scale.desktop) diff --git a/effects/scale/package/contents/code/main.js b/effects/scale/package/contents/code/main.js new file mode 100644 --- /dev/null +++ b/effects/scale/package/contents/code/main.js @@ -0,0 +1,181 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2018 Vlad Zagorodniy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +var blacklist = [ + // The logout screen has to be animated only by the logout effect. + "ksmserver ksmserver", + "ksmserver-logout-greeter ksmserver-logout-greeter", + + // KDE Plasma splash screen has to be animated only by the login effect. + "ksplashqml ksplashqml", + "ksplashsimple ksplashsimple", + "ksplashx ksplashx" +]; + +var scaleEffect = { + loadConfig: function (window) { + "use strict"; + var defaultDuration = 160; + var duration = effect.readConfig("Duration", defaultDuration) || defaultDuration; + scaleEffect.duration = animationTime(duration); + scaleEffect.inScale = effect.readConfig("InScale", 0.96); + scaleEffect.inOpacity = effect.readConfig("InOpacity", 0.4); + scaleEffect.outScale = effect.readConfig("OutScale", 0.96); + scaleEffect.outOpacity = effect.readConfig("OutOpacity", 0.0); + }, + isScaleWindow: function (window) { + "use strict"; + // We don't want to animate most of plasmashell's windows, yet, some + // of them we want to, for example, Task Manager Settings window. + // The problem is that all those window share single window class. + // So, the only way to decide whether a window should be animated is + // to use a heuristic: if a window has decoration, then it's most + // likely a dialog or a settings window so we have to animate it. + if (window.windowClass == "plasmashell plasmashell" + || window.windowClass == "plasmashell org.kde.plasmashell") { + return window.hasDecoration; + } + + if (blacklist.indexOf(window.windowClass) != -1) { + return false; + } + + if (window.hasDecoration) { + return true; + } + + // Don't animate combobox popups, tooltips, popup menus, etc. + if (window.popup) { + return false; + } + + // Override-redirect windows are usually used for user interface + // concepts that are not expected to be animated by this effect. + if (window.x11Client && !window.managed) { + return false; + } + + return window.normalWindow || window.dialog; + }, + setupForcedRoles: function (window) { + "use strict"; + window.setData(Effect.WindowForceBackgroundContrastRole, true); + window.setData(Effect.WindowForceBlurRole, true); + }, + cleanupForcedRoles: function (window) { + "use strict"; + window.setData(Effect.WindowForceBackgroundContrastRole, null); + window.setData(Effect.WindowForceBlurRole, null); + }, + slotWindowAdded: function (window) { + "use strict"; + if (effects.hasActiveFullScreenEffect) { + return; + } + if (!scaleEffect.isScaleWindow(window)) { + return; + } + if (!window.visible) { + return; + } + if (!effect.grab(window, Effect.WindowAddedGrabRole)) { + return; + } + scaleEffect.setupForcedRoles(window); + window.scaleInAnimation = animate({ + window: window, + curve: QEasingCurve.InOutSine, + duration: scaleEffect.duration, + animations: [ + { + type: Effect.Scale, + from: scaleEffect.inScale + }, + { + type: Effect.Opacity, + from: scaleEffect.inOpacity + } + ] + }); + }, + slotWindowClosed: function (window) { + "use strict"; + if (effects.hasActiveFullScreenEffect) { + return; + } + if (!scaleEffect.isScaleWindow(window)) { + return; + } + if (!window.visible) { + return; + } + if (!effect.grab(window, Effect.WindowClosedGrabRole)) { + return; + } + if (window.scaleInAnimation) { + cancel(window.scaleInAnimation); + delete window.scaleInAnimation; + } + scaleEffect.setupForcedRoles(window); + window.scaleOutAnimation = animate({ + window: window, + curve: QEasingCurve.InOutSine, + duration: scaleEffect.duration, + animations: [ + { + type: Effect.Scale, + to: scaleEffect.outScale + }, + { + type: Effect.Opacity, + to: scaleEffect.outOpacity + } + ] + }); + }, + slotWindowDataChanged: function (window, role) { + "use strict"; + if (role == Effect.WindowAddedGrabRole) { + if (window.scaleInAnimation && effect.isGrabbed(window, role)) { + cancel(window.scaleInAnimation); + delete window.scaleInAnimation; + scaleEffect.cleanupForcedRoles(window); + } + } else if (role == Effect.WindowClosedGrabRole) { + if (window.scaleOutAnimation && effect.isGrabbed(window, role)) { + cancel(window.scaleOutAnimation); + delete window.scaleOutAnimation; + scaleEffect.cleanupForcedRoles(window); + } + } + }, + init: function () { + "use strict"; + scaleEffect.loadConfig(); + + effect.configChanged.connect(scaleEffect.loadConfig); + effect.animationEnded.connect(scaleEffect.cleanupForcedRoles); + effects.windowAdded.connect(scaleEffect.slotWindowAdded); + effects.windowClosed.connect(scaleEffect.slotWindowClosed); + effects.windowDataChanged.connect(scaleEffect.slotWindowDataChanged); + } +}; + +scaleEffect.init(); diff --git a/effects/scale/scale.kcfg b/effects/scale/package/contents/config/main.xml rename from effects/scale/scale.kcfg rename to effects/scale/package/contents/config/main.xml --- a/effects/scale/scale.kcfg +++ b/effects/scale/package/contents/config/main.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > - - + + 0 diff --git a/effects/scale/scale_config.ui b/effects/scale/package/contents/ui/config.ui rename from effects/scale/scale_config.ui rename to effects/scale/package/contents/ui/config.ui diff --git a/effects/scale/package/metadata.desktop b/effects/scale/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/effects/scale/package/metadata.desktop @@ -0,0 +1,22 @@ +[Desktop Entry] +Name=Scale +Icon=preferences-system-windows-effect-scale +Comment=Make windows smoothly scale in and out when they are shown or hidden + +Type=Service +X-KDE-ServiceTypes=KWin/Effect,KCModule +X-KDE-PluginInfo-Author=Vlad Zagorodniy +X-KDE-PluginInfo-Email=vladzzag@gmail.com +X-KDE-PluginInfo-Name=kwin4_effect_scale +X-KDE-PluginInfo-Version=1 +X-KDE-PluginInfo-Category=Appearance +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +X-KDE-Ordering=60 +X-Plasma-API=javascript +X-Plasma-MainScript=code/main.js +X-KDE-PluginKeyword=kwin4_effect_scale +X-KDE-Library=kcm_kwin4_genericscripted +X-KDE-ParentComponents=kwin4_effect_scale +X-KWin-Config-TranslationDomain=kwin_effects diff --git a/effects/scale/scale.h b/effects/scale/scale.h deleted file mode 100644 --- a/effects/scale/scale.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - - Copyright (C) 2018 Vlad Zagorodniy - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*********************************************************************/ - -#ifndef KWIN_SCALE_H -#define KWIN_SCALE_H - -// kwineffects -#include - -namespace KWin -{ - -class ScaleEffect : public Effect -{ - Q_OBJECT - Q_PROPERTY(int duration READ duration) - Q_PROPERTY(qreal inScale READ inScale) - Q_PROPERTY(qreal inOpacity READ inOpacity) - Q_PROPERTY(qreal outScale READ outScale) - Q_PROPERTY(qreal outOpacity READ outOpacity) - -public: - ScaleEffect(); - ~ScaleEffect() override; - - void reconfigure(ReconfigureFlags flags) override; - - void prePaintScreen(ScreenPrePaintData &data, int time) override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; - void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; - void postPaintScreen() override; - - bool isActive() const override; - int requestedEffectChainPosition() const override; - - static bool supported(); - - int duration() const; - qreal inScale() const; - qreal inOpacity() const; - qreal outScale() const; - qreal outOpacity() const; - -private Q_SLOTS: - void windowAdded(EffectWindow *w); - void windowClosed(EffectWindow *w); - void windowDeleted(EffectWindow *w); - void windowDataChanged(EffectWindow *w, int role); - -private: - bool isScaleWindow(EffectWindow *w) const; - - std::chrono::milliseconds m_duration; - QHash m_animations; - - struct ScaleParams { - struct { - qreal from; - qreal to; - } scale, opacity; - }; - - ScaleParams m_inParams; - ScaleParams m_outParams; -}; - -inline int ScaleEffect::requestedEffectChainPosition() const -{ - return 50; -} - -inline int ScaleEffect::duration() const -{ - return m_duration.count(); -} - -inline qreal ScaleEffect::inScale() const -{ - return m_inParams.scale.from; -} - -inline qreal ScaleEffect::inOpacity() const -{ - return m_inParams.opacity.from; -} - -inline qreal ScaleEffect::outScale() const -{ - return m_outParams.scale.to; -} - -inline qreal ScaleEffect::outOpacity() const -{ - return m_outParams.opacity.to; -} - -} // namespace KWin - -#endif diff --git a/effects/scale/scale.cpp b/effects/scale/scale.cpp deleted file mode 100644 --- a/effects/scale/scale.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - - Copyright (C) 2018 Vlad Zagorodniy - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*********************************************************************/ - -// own -#include "scale.h" - -// KConfigSkeleton -#include "scaleconfig.h" - -// Qt -#include - -namespace KWin -{ - -static const QSet s_blacklist { - // The logout screen has to be animated only by the logout effect. - QStringLiteral("ksmserver ksmserver"), - QStringLiteral("ksmserver-logout-greeter ksmserver-logout-greeter"), - - // KDE Plasma splash screen has to be animated only by the login effect. - QStringLiteral("ksplashqml ksplashqml"), - QStringLiteral("ksplashsimple ksplashsimple"), - QStringLiteral("ksplashx ksplashx") -}; - -ScaleEffect::ScaleEffect() -{ - initConfig(); - reconfigure(ReconfigureAll); - - connect(effects, &EffectsHandler::windowAdded, this, &ScaleEffect::windowAdded); - connect(effects, &EffectsHandler::windowClosed, this, &ScaleEffect::windowClosed); - connect(effects, &EffectsHandler::windowDeleted, this, &ScaleEffect::windowDeleted); - connect(effects, &EffectsHandler::windowDataChanged, this, &ScaleEffect::windowDataChanged); -} - -ScaleEffect::~ScaleEffect() -{ -} - -void ScaleEffect::reconfigure(ReconfigureFlags flags) -{ - Q_UNUSED(flags) - - ScaleConfig::self()->read(); - m_duration = std::chrono::milliseconds(animationTime(160)); - - m_inParams.scale.from = ScaleConfig::inScale(); - m_inParams.scale.to = 1.0; - m_inParams.opacity.from = ScaleConfig::inOpacity(); - m_inParams.opacity.to = 1.0; - - m_outParams.scale.from = 1.0; - m_outParams.scale.to = ScaleConfig::outScale(); - m_outParams.opacity.from = 1.0; - m_outParams.opacity.to = ScaleConfig::outOpacity(); -} - -void ScaleEffect::prePaintScreen(ScreenPrePaintData &data, int time) -{ - const std::chrono::milliseconds delta(time); - - auto animationIt = m_animations.begin(); - while (animationIt != m_animations.end()) { - (*animationIt).update(delta); - ++animationIt; - } - - effects->prePaintScreen(data, time); -} - -void ScaleEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) -{ - if (m_animations.contains(w)) { - data.setTransformed(); - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); - } - - effects->prePaintWindow(w, data, time); -} - -void ScaleEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) -{ - auto animationIt = m_animations.constFind(w); - if (animationIt == m_animations.constEnd()) { - effects->paintWindow(w, mask, region, data); - return; - } - - const ScaleParams params = w->isDeleted() ? m_outParams : m_inParams; - const qreal t = (*animationIt).value(); - const qreal scale = interpolate(params.scale.from, params.scale.to, t); - - data.setXScale(scale); - data.setYScale(scale); - data.setXTranslation(0.5 * (1.0 - scale) * w->width()); - data.setYTranslation(0.5 * (1.0 - scale) * w->height()); - data.multiplyOpacity(interpolate(params.opacity.from, params.opacity.to, t)); - - effects->paintWindow(w, mask, region, data); -} - -void ScaleEffect::postPaintScreen() -{ - auto animationIt = m_animations.begin(); - while (animationIt != m_animations.end()) { - EffectWindow *w = animationIt.key(); - - const QRect geo = w->expandedGeometry(); - const ScaleParams params = w->isDeleted() ? m_outParams : m_inParams; - const qreal scale = qMax(params.scale.from, params.scale.to); - const QRect repaintRect( - geo.topLeft() + 0.5 * (1.0 - scale) * QPoint(geo.width(), geo.height()), - geo.size() * scale); - effects->addRepaint(repaintRect); - - if ((*animationIt).done()) { - if (w->isDeleted()) { - w->unrefWindow(); - } else { - w->setData(WindowForceBackgroundContrastRole, QVariant()); - w->setData(WindowForceBlurRole, QVariant()); - } - animationIt = m_animations.erase(animationIt); - } else { - ++animationIt; - } - } - - effects->postPaintScreen(); -} - -bool ScaleEffect::isActive() const -{ - return !m_animations.isEmpty(); -} - -bool ScaleEffect::supported() -{ - return effects->animationsSupported(); -} - -void ScaleEffect::windowAdded(EffectWindow *w) -{ - if (effects->activeFullScreenEffect()) { - return; - } - - if (!isScaleWindow(w)) { - return; - } - - if (!w->isVisible()) { - return; - } - - const void *addGrab = w->data(WindowAddedGrabRole).value(); - if (addGrab && addGrab != this) { - return; - } - - TimeLine &timeLine = m_animations[w]; - timeLine.reset(); - timeLine.setDirection(TimeLine::Forward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::InCurve); - - w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast(this))); - w->setData(WindowForceBackgroundContrastRole, QVariant(true)); - w->setData(WindowForceBlurRole, QVariant(true)); - - w->addRepaintFull(); -} - -void ScaleEffect::windowClosed(EffectWindow *w) -{ - if (effects->activeFullScreenEffect()) { - return; - } - - if (!isScaleWindow(w)) { - return; - } - - if (!w->isVisible()) { - return; - } - - const void *closeGrab = w->data(WindowClosedGrabRole).value(); - if (closeGrab && closeGrab != this) { - return; - } - - w->refWindow(); - - TimeLine &timeLine = m_animations[w]; - timeLine.reset(); - timeLine.setDirection(TimeLine::Forward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::OutCurve); - - w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast(this))); - w->setData(WindowForceBackgroundContrastRole, QVariant(true)); - w->setData(WindowForceBlurRole, QVariant(true)); - - w->addRepaintFull(); -} - -void ScaleEffect::windowDeleted(EffectWindow *w) -{ - m_animations.remove(w); -} - -void ScaleEffect::windowDataChanged(EffectWindow *w, int role) -{ - if (role != WindowAddedGrabRole && role != WindowClosedGrabRole) { - return; - } - - if (w->data(role).value() == this) { - return; - } - - auto animationIt = m_animations.find(w); - if (animationIt == m_animations.end()) { - return; - } - - if (w->isDeleted() && role == WindowClosedGrabRole) { - w->unrefWindow(); - } - - m_animations.erase(animationIt); - - w->setData(WindowForceBackgroundContrastRole, QVariant()); - w->setData(WindowForceBlurRole, QVariant()); -} - -bool ScaleEffect::isScaleWindow(EffectWindow *w) const -{ - // We don't want to animate most of plasmashell's windows, yet, some - // of them we want to, for example, Task Manager Settings window. - // The problem is that all those window share single window class. - // So, the only way to decide whether a window should be animated is - // to use a heuristic: if a window has decoration, then it's most - // likely a dialog or a settings window so we have to animate it. - if (w->windowClass() == QLatin1String("plasmashell plasmashell") - || w->windowClass() == QLatin1String("plasmashell org.kde.plasmashell")) { - return w->hasDecoration(); - } - - if (s_blacklist.contains(w->windowClass())) { - return false; - } - - if (w->hasDecoration()) { - return true; - } - - // Don't animate combobox popups, tooltips, popup menus, etc. - if (w->isPopupWindow()) { - return false; - } - - // Override-redirect windows are usually used for user interface - // concepts that are not expected to be animated by this effect. - if (w->isX11Client() && !w->isManaged()) { - return false; - } - - return w->isNormalWindow() - || w->isDialog(); -} - -} // namespace KWin diff --git a/effects/scale/scale_config.h b/effects/scale/scale_config.h deleted file mode 100644 --- a/effects/scale/scale_config.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - - Copyright (C) 2018 Vlad Zagorodniy - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*********************************************************************/ - -#ifndef SCALE_CONFIG_H -#define SCALE_CONFIG_H - -#include "ui_scale_config.h" - -#include - -namespace KWin -{ - -class ScaleEffectConfig : public KCModule -{ - Q_OBJECT - -public: - explicit ScaleEffectConfig(QWidget *parent = nullptr, const QVariantList &args = QVariantList()); - ~ScaleEffectConfig() override; - - void save() override; - -private: - ::Ui::ScaleEffectConfig ui; -}; - -} // namespace KWin - -#endif - diff --git a/effects/scale/scale_config.cpp b/effects/scale/scale_config.cpp deleted file mode 100644 --- a/effects/scale/scale_config.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - - Copyright (C) 2018 Vlad Zagorodniy - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*********************************************************************/ - -#include "scale_config.h" - -// KConfigSkeleton -#include "scaleconfig.h" -#include - -#include -#include -#include - -K_PLUGIN_FACTORY_WITH_JSON(ScaleEffectConfigFactory, - "scale_config.json", - registerPlugin();) - -namespace KWin -{ - -ScaleEffectConfig::ScaleEffectConfig(QWidget *parent, const QVariantList &args) - : KCModule(KAboutData::pluginData(QStringLiteral("scale")), parent, args) -{ - ui.setupUi(this); - ScaleConfig::instance(KWIN_CONFIG); - addConfig(ScaleConfig::self(), this); - load(); -} - -ScaleEffectConfig::~ScaleEffectConfig() -{ -} - -void ScaleEffectConfig::save() -{ - KCModule::save(); - OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), - QStringLiteral("/Effects"), - QDBusConnection::sessionBus()); - interface.reconfigureEffect(QStringLiteral("scale")); -} - -} // namespace KWin - -#include "scale_config.moc" diff --git a/effects/scale/scale_config.desktop b/effects/scale/scale_config.desktop deleted file mode 100644 --- a/effects/scale/scale_config.desktop +++ /dev/null @@ -1,34 +0,0 @@ -[Desktop Entry] -Type=Service -X-KDE-ServiceTypes=KCModule - -X-KDE-Library=kwin_scale_config -X-KDE-ParentComponents=scale - -Name=Scale -Name[ca]=Escala -Name[ca@valencia]=Escala -Name[cs]=Měřítko -Name[de]=Skalieren -Name[el]=Κλιμάκωση -Name[en_GB]=Scale -Name[es]=Escalar -Name[eu]=Eskalatu -Name[fi]=Skaalaa -Name[fr]=Échelle -Name[gl]=Cambiar as dimensións -Name[id]=Scale -Name[it]=Scala -Name[ko]=크기 조정 -Name[nl]=Schalen -Name[nn]=Skalering -Name[pl]=Skala -Name[pt]=Escala -Name[pt_BR]=Escala -Name[ru]=Масштабирование -Name[sk]=Škálovať -Name[sv]=Skala -Name[uk]=Масштабування -Name[x-test]=xxScalexx -Name[zh_CN]=缩放 -Name[zh_TW]=縮放 diff --git a/effects/scale/scaleconfig.kcfgc b/effects/scale/scaleconfig.kcfgc deleted file mode 100644 --- a/effects/scale/scaleconfig.kcfgc +++ /dev/null @@ -1,5 +0,0 @@ -File=scale.kcfg -ClassName=ScaleConfig -NameSpace=KWin -Singleton=true -Mutators=true diff --git a/kconf_update/kwin.upd b/kconf_update/kwin.upd --- a/kconf_update/kwin.upd +++ b/kconf_update/kwin.upd @@ -11,3 +11,11 @@ File=kwinrc Group=Plugins Key=minimizeanimationEnabled,kwin4_effect_squashEnabled + +# Port the Scale effect to JavaScript. +Id=port-scale-effect-to-js +File=kwinrc +Group=Effect-Scale,Effect-kwin4_effect_scale +AllKeys +Group=Plugins +Key=scaleEnabled,kwin4_effect_scaleEnabled