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 @@ -99,7 +99,6 @@ QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << true; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << true; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true; - QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true; @@ -156,7 +155,6 @@ << QStringLiteral("lookingglass") << QStringLiteral("magiclamp") << QStringLiteral("magnifier") - << QStringLiteral("minimizeanimation") << QStringLiteral("mouseclick") << QStringLiteral("mousemark") << QStringLiteral("presentwindows") @@ -235,7 +233,6 @@ QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc << true; QTest::newRow("MagicLamp-GL-no-anim") << QStringLiteral("magiclamp") << false << oc << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc << true; - QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc << true; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc << true; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc << true; @@ -324,7 +321,6 @@ QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc; QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc; - QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc; @@ -509,7 +505,6 @@ plugins.writeEntry(QStringLiteral("desktopgridEnabled"), false); plugins.writeEntry(QStringLiteral("highlightwindowEnabled"), false); plugins.writeEntry(QStringLiteral("kscreenEnabled"), false); - plugins.writeEntry(QStringLiteral("minimizeanimationEnabled"), false); plugins.writeEntry(QStringLiteral("presentwindowsEnabled"), false); plugins.writeEntry(QStringLiteral("screenedgeEnabled"), false); plugins.writeEntry(QStringLiteral("screenshotEnabled"), false); 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 @@ -90,7 +90,6 @@ QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << false; - QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << false; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << false; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false; @@ -119,6 +118,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("Squash") << QStringLiteral("kwin4_effect_squash") << false; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << false; // and the fake effects we use here QTest::newRow("fakeeffectplugin") << QStringLiteral("fakeeffectplugin") << true; 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 @@ -120,7 +120,6 @@ QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << false; - QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << false; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << false; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false; @@ -151,6 +150,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("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_squash") << QStringLiteral("kwin4_effect_translucency"); KWin::ScriptedEffectLoader loader; @@ -208,6 +209,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("Squash") << QStringLiteral("kwin4_effect_squash") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } @@ -359,7 +361,7 @@ plugins.writeEntry(kwin4 + QStringLiteral("loginEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("logoutEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("maximizeEnabled"), false); - plugins.writeEntry(kwin4 + QStringLiteral("minimizeanimationEnabled"), false); + plugins.writeEntry(kwin4 + QStringLiteral("squashEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("translucencyEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("windowapertureEnabled"), false); diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -142,6 +142,7 @@ add_subdirectory( logout ) add_subdirectory( maximize ) add_subdirectory( morphingpopups ) +add_subdirectory( squash ) add_subdirectory( translucency ) add_subdirectory( windowaperture ) @@ -156,7 +157,6 @@ include( highlightwindow/CMakeLists.txt ) include( kscreen/CMakeLists.txt ) add_subdirectory( magiclamp ) -include( minimizeanimation/CMakeLists.txt ) add_subdirectory( presentwindows ) add_subdirectory( resize ) include( screenedge/CMakeLists.txt ) diff --git a/effects/effect_builtins.h b/effects/effect_builtins.h --- a/effects/effect_builtins.h +++ b/effects/effect_builtins.h @@ -52,7 +52,6 @@ LookingGlass, MagicLamp, Magnifier, - MinimizeAnimation, MouseClick, MouseMark, PresentWindows, diff --git a/effects/effect_builtins.cpp b/effects/effect_builtins.cpp --- a/effects/effect_builtins.cpp +++ b/effects/effect_builtins.cpp @@ -35,7 +35,6 @@ #include "fallapart/fallapart.h" #include "highlightwindow/highlightwindow.h" #include "magiclamp/magiclamp.h" -#include "minimizeanimation/minimizeanimation.h" #include "resize/resize.h" #include "scale/scale.h" #include "showfps/showfps.h" @@ -369,21 +368,6 @@ &MagnifierEffect::supported, nullptr #endif -EFFECT_FALLBACK - }, { - QStringLiteral("minimizeanimation"), - i18ndc("kwin_effects", "Name of a KWin Effect", "Minimize Animation"), - i18ndc("kwin_effects", "Comment describing the KWin Effect", "Animate the minimizing of windows"), - QStringLiteral("Appearance"), - QStringLiteral("minimize"), - QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/minimize.ogv")), - true, - false, -#ifdef EFFECT_BUILTINS - &createHelper, - &MinimizeAnimationEffect::supported, - nullptr -#endif EFFECT_FALLBACK }, { QStringLiteral("mouseclick"), diff --git a/effects/minimizeanimation/CMakeLists.txt b/effects/minimizeanimation/CMakeLists.txt deleted file mode 100644 --- a/effects/minimizeanimation/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -####################################### -# Effect - -# Source files -set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources} - minimizeanimation/minimizeanimation.cpp - ) diff --git a/effects/minimizeanimation/minimizeanimation.h b/effects/minimizeanimation/minimizeanimation.h deleted file mode 100644 --- a/effects/minimizeanimation/minimizeanimation.h +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2007 Rivo Laks - -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_MINIMIZEANIMATION_H -#define KWIN_MINIMIZEANIMATION_H - -// Include with base class for effects. -#include - -namespace KWin -{ - -/** - * Animates minimize/unminimize - **/ -class MinimizeAnimationEffect : public Effect -{ - Q_OBJECT - -public: - MinimizeAnimationEffect(); - - 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 { - return 50; - } - - static bool supported(); - -private Q_SLOTS: - void windowDeleted(EffectWindow *w); - void windowMinimized(EffectWindow *w); - void windowUnminimized(EffectWindow *w); - -private: - std::chrono::milliseconds m_duration; - QHash m_animations; -}; - -} // namespace - -#endif diff --git a/effects/minimizeanimation/minimizeanimation.cpp b/effects/minimizeanimation/minimizeanimation.cpp deleted file mode 100644 --- a/effects/minimizeanimation/minimizeanimation.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2007 Rivo Laks - -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 "minimizeanimation.h" - -#include - -namespace KWin -{ - -MinimizeAnimationEffect::MinimizeAnimationEffect() -{ - reconfigure(ReconfigureAll); - - connect(effects, &EffectsHandler::windowDeleted, this, &MinimizeAnimationEffect::windowDeleted); - connect(effects, &EffectsHandler::windowMinimized, this, &MinimizeAnimationEffect::windowMinimized); - connect(effects, &EffectsHandler::windowUnminimized, this, &MinimizeAnimationEffect::windowUnminimized); -} - -void MinimizeAnimationEffect::reconfigure(ReconfigureFlags flags) -{ - Q_UNUSED(flags) - - m_duration = std::chrono::milliseconds(static_cast(animationTime(250))); -} - -bool MinimizeAnimationEffect::supported() -{ - return effects->animationsSupported(); -} - -void MinimizeAnimationEffect::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; - } - - // We need to mark the screen windows as transformed. Otherwise the - // whole screen won't be repainted, resulting in artefacts. - data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; - - effects->prePaintScreen(data, time); -} - -void MinimizeAnimationEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) -{ - if (m_animations.contains(w)) { - data.setTransformed(); - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); - } - - effects->prePaintWindow(w, data, time); -} - -void MinimizeAnimationEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) -{ - const auto animationIt = m_animations.constFind(w); - if (animationIt != m_animations.constEnd()) { - // 0 = not minimized, 1 = fully minimized - const qreal progress = (*animationIt).value(); - - QRect geo = w->geometry(); - QRect icon = w->iconGeometry(); - // If there's no icon geometry, minimize to the center of the screen - if (!icon.isValid()) { - icon = QRect(effects->virtualScreenGeometry().center(), QSize(0, 0)); - } - - data *= QVector2D(interpolate(1.0, icon.width() / (double)geo.width(), progress), - interpolate(1.0, icon.height() / (double)geo.height(), progress)); - data.setXTranslation(interpolate(data.xTranslation(), icon.x() - geo.x(), progress)); - data.setYTranslation(interpolate(data.yTranslation(), icon.y() - geo.y(), progress)); - data.multiplyOpacity(interpolate(1.0, 0.1, progress)); - } - - effects->paintWindow(w, mask, region, data); -} - -void MinimizeAnimationEffect::postPaintScreen() -{ - auto animationIt = m_animations.begin(); - while (animationIt != m_animations.end()) { - if ((*animationIt).done()) { - animationIt = m_animations.erase(animationIt); - } else { - ++animationIt; - } - } - - effects->addRepaintFull(); - - effects->postPaintScreen(); -} - -void MinimizeAnimationEffect::windowDeleted(EffectWindow *w) -{ - m_animations.remove(w); -} - -void MinimizeAnimationEffect::windowMinimized(EffectWindow *w) -{ - if (effects->activeFullScreenEffect()) { - return; - } - - TimeLine &timeLine = m_animations[w]; - - if (timeLine.running()) { - timeLine.toggleDirection(); - } else { - timeLine.setDirection(TimeLine::Forward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::InOutSine); - } - - effects->addRepaintFull(); -} - -void MinimizeAnimationEffect::windowUnminimized(EffectWindow *w) -{ - if (effects->activeFullScreenEffect()) { - return; - } - - TimeLine &timeLine = m_animations[w]; - - if (timeLine.running()) { - timeLine.toggleDirection(); - } else { - timeLine.setDirection(TimeLine::Backward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::InOutSine); - } - - effects->addRepaintFull(); -} - -bool MinimizeAnimationEffect::isActive() const -{ - return !m_animations.isEmpty(); -} - -} // namespace - diff --git a/effects/squash/CMakeLists.txt b/effects/squash/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/effects/squash/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(package) diff --git a/effects/squash/package/CMakeLists.txt b/effects/squash/package/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/effects/squash/package/CMakeLists.txt @@ -0,0 +1,9 @@ +install(DIRECTORY contents + DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_squash) + +install(FILES metadata.desktop + DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_squash) + +install(FILES metadata.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/${KWIN_NAME} + RENAME kwin4_effect_squash.desktop) diff --git a/effects/squash/package/contents/code/main.js b/effects/squash/package/contents/code/main.js new file mode 100644 --- /dev/null +++ b/effects/squash/package/contents/code/main.js @@ -0,0 +1,150 @@ +/******************************************************************** + 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 squashEffect = { + duration: animationTime(250), + loadConfig: function () { + "use strict"; + squashEffect.duration = animationTime(250); + }, + slotWindowMinimized: function (window) { + "use strict"; + if (effects.hasActiveFullScreenEffect) { + return; + } + + // If the window doesn't have an icon in the task manager, + // don't animate it. + var iconRect = window.iconGeometry; + if (iconRect.width == 0 || iconRect.height == 0) { + return; + } + + if (window.unminimizeAnimation) { + // TODO: Try to reverse it instead. + cancel(window.unminimizeAnimation); + delete window.unminimizeAnimation; + } + + var windowRect = window.geometry; + + window.minimizeAnimation = animate({ + window: window, + curve: QEasingCurve.InOutSine, + duration: squashEffect.duration, + animations: [ + { + type: Effect.Size, + from: { + value1: windowRect.width, + value2: windowRect.height + }, + to: { + value1: iconRect.width, + value2: iconRect.height + } + }, + { + type: Effect.Translation, + from: { + value1: 0.0, + value2: 0.0 + }, + to: { + value1: iconRect.x - windowRect.x - + (windowRect.width - iconRect.width) / 2, + value2: iconRect.y - windowRect.y - + (windowRect.height - iconRect.height) / 2, + } + }, + { + type: Effect.Opacity, + from: 1.0, + to: 0.0 + } + ] + }); + }, + slotWindowUnminimized: function (window) { + "use strict"; + if (effects.hasActiveFullScreenEffect) { + return; + } + + // If the window doesn't have an icon in the task manager, + // don't animate it. + var iconRect = window.iconGeometry; + if (iconRect.width == 0 || iconRect.height == 0) { + return; + } + + if (window.minimizeAnimation) { + // TODO: Try to reverse it instead. + cancel(window.minimizeAnimation); + delete window.minimizeAnimation; + } + + var windowRect = window.geometry; + + window.unminimizeAnimation = animate({ + window: window, + curve: QEasingCurve.InOutSine, + duration: squashEffect.duration, + animations: [ + { + type: Effect.Size, + from: { + value1: iconRect.width, + value2: iconRect.height + }, + to: { + value1: windowRect.width, + value2: windowRect.height + } + }, + { + type: Effect.Translation, + from: { + value1: iconRect.x - windowRect.x - + (windowRect.width - iconRect.width) / 2, + value2: iconRect.y - windowRect.y - + (windowRect.height - iconRect.height) / 2, + }, + to: { + value1: 0.0, + value2: 0.0 + } + }, + { + type: Effect.Opacity, + from: 0.0, + to: 1.0 + } + ] + }); + }, + init: function () { + "use strict"; + effect.configChanged.connect(squashEffect.loadConfig); + effects.windowMinimized.connect(squashEffect.slotWindowMinimized); + effects.windowUnminimized.connect(squashEffect.slotWindowUnminimized); + } +}; + +squashEffect.init(); diff --git a/effects/squash/package/metadata.desktop b/effects/squash/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/effects/squash/package/metadata.desktop @@ -0,0 +1,21 @@ +[Desktop Entry] +Comment=Squash windows when they are minimized +Icon=preferences-system-windows-effect-squash +Name=Squash + +Type=Service +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Rivo Laks, Vlad Zagorodniy +X-KDE-PluginInfo-Category=Appearance +X-KDE-PluginInfo-Email=rivolaks@hot.ee, vladzzag@gmail.com +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=kwin4_effect_squash +X-KDE-PluginInfo-Version=1 +X-KDE-PluginInfo-Website= +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-Ordering=60 +X-Plasma-API=javascript +X-Plasma-MainScript=code/main.js +X-KWin-Exclusive-Category=minimize +X-KWin-Video-Url=http://files.kde.org/plasma/kwin/effect-videos/minimize.ogv diff --git a/kconf_update/kwin.upd b/kconf_update/kwin.upd --- a/kconf_update/kwin.upd +++ b/kconf_update/kwin.upd @@ -5,3 +5,9 @@ File=kwinrc Group=Plugins Key=kwin4_effect_scaleinEnabled,scaleEnabled + +# Port the Minimize Animation effect to JavaScript. +Id=port-minimizeanimation-effect-to-js +File=kwinrc +Group=Plugins +Key=minimizeanimationEnabled,kwin4_effect_squashEnabled