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 @@ -113,6 +113,7 @@ // all the scripted effects should fail QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << false; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << false; + QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << false; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << false; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << false; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << false; 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 @@ -145,6 +145,7 @@ QTest::newRow("Fade + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << true; QTest::newRow("Fade + kwin4_effect + CS") << QStringLiteral("kwin4_eFfect_fAde") << true; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << true; + QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << true; QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; @@ -179,6 +180,7 @@ expectedEffects << QStringLiteral("kwin4_effect_dialogparent") << QStringLiteral("kwin4_effect_fade") << QStringLiteral("kwin4_effect_fadedesktop") + << QStringLiteral("kwin4_effect_fadingpopups") << QStringLiteral("kwin4_effect_frozenapp") << QStringLiteral("kwin4_effect_login") << QStringLiteral("kwin4_effect_logout") @@ -206,6 +208,7 @@ QTest::newRow("Fade + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << true; QTest::newRow("Fade + kwin4_effect + CS") << QStringLiteral("kwin4_eFfect_fAde") << true; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << true; + QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << true; QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; @@ -360,6 +363,7 @@ plugins.writeEntry(kwin4 + QStringLiteral("dialogparentEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("fadeEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("fadedesktopEnabled"), false); + plugins.writeEntry(kwin4 + QStringLiteral("fadingpopupsEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("frozenappEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("loginEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("logoutEnabled"), false); diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -135,6 +135,7 @@ add_subdirectory( eyeonscreen ) add_subdirectory( fade ) add_subdirectory( fadedesktop ) +add_subdirectory( fadingpopups ) add_subdirectory( frozenapp ) add_subdirectory( login ) add_subdirectory( logout ) diff --git a/effects/fade/package/contents/code/main.js b/effects/fade/package/contents/code/main.js --- a/effects/fade/package/contents/code/main.js +++ b/effects/fade/package/contents/code/main.js @@ -34,12 +34,21 @@ if (blacklist.indexOf(w.windowClass) != -1) { return false; } + if (w.popup) { + return false; + } + if (w.x11Client && !w.managed) { + return false; + } + if (!w.visible) { + return false; + } if (w.deleted && effect.isGrabbed(w, Effect.WindowClosedGrabRole)) { return false; } else if (!w.deleted && effect.isGrabbed(w, Effect.WindowAddedGrabRole)) { return false; } - return w.onCurrentDesktop && !w.desktopWindow && !w.utility && !w.minimized; + return w.normalWindow || w.dialog; } var fadeInTime, fadeOutTime, fadeWindows; diff --git a/effects/fadingpopups/CMakeLists.txt b/effects/fadingpopups/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/effects/fadingpopups/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(package) diff --git a/effects/fadingpopups/package/CMakeLists.txt b/effects/fadingpopups/package/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/effects/fadingpopups/package/CMakeLists.txt @@ -0,0 +1,12 @@ +install(DIRECTORY contents + DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_fadingpopups) + +install(FILES metadata.desktop + DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_fadingpopups) + +install(FILES metadata.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/${KWIN_NAME} + RENAME kwin4_effect_fadingpopups.desktop) + +file(COPY contents metadata.desktop + DESTINATION ${CMAKE_BINARY_DIR}/bin/kwin/effects/kwin4_effect_fadingpopups) diff --git a/effects/fadingpopups/package/contents/code/main.js b/effects/fadingpopups/package/contents/code/main.js new file mode 100644 --- /dev/null +++ b/effects/fadingpopups/package/contents/code/main.js @@ -0,0 +1,129 @@ +/******************************************************************** + 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 . +*********************************************************************/ + +"use strict"; + +function isPopupWindow(window) { + // Animate combo box popups, tooltips, popup menus, etc. + if (window.popupWindow) { + return true; + } + + // Override-redirect windows are usually used for user interface + // concepts that are expected to be animated by this effect, e.g. + // popups that contain window thumbnails on X11, etc. + if (window.x11Client && !window.managed) { + // Some utility windows can look like popup windows (e.g. the + // address bar dropdown in Firefox), but we don't want to fade + // them because the fade effect didn't do that. + if (window.utility) { + return false; + } + + return true; + } + + // Previously, there was a "monolithic" fade effect, which tried to + // animate almost every window that was shown or hidden. Then it was + // split into two effects: one that animates toplevel windows and + // this one. In addition to popups, this effect also animates some + // special windows(e.g. notifications) because the monolithic version + // was doing that. + if (window.dock || window.splash || window.toolbar + || window.notification || window.onScreenDisplay) { + return true; + } + + return false; +} + +var fadingPopupsEffect = { + loadConfig: function () { + fadingPopupsEffect.fadeInDuration = animationTime(150); + fadingPopupsEffect.fadeOutDuration = animationTime(150) * 4; + }, + slotWindowAdded: function (window) { + if (effects.hasActiveFullScreenEffect) { + return; + } + if (!isPopupWindow(window)) { + return; + } + if (!window.visible) { + return; + } + if (!effect.grab(window, Effect.WindowAddedGrabRole)) { + return; + } + window.fadeInAnimation = animate({ + window: window, + curve: QEasingCurve.Linear, + duration: fadingPopupsEffect.fadeInDuration, + type: Effect.Opacity, + from: 0.0, + to: 1.0 + }); + }, + slotWindowClosed: function (window) { + if (effects.hasActiveFullScreenEffect) { + return; + } + if (!isPopupWindow(window)) { + return; + } + if (!window.visible) { + return; + } + if (!effect.grab(window, Effect.WindowClosedGrabRole)) { + return; + } + window.fadeOutAnimation = animate({ + window: window, + curve: QEasingCurve.OutQuart, + duration: fadingPopupsEffect.fadeOutDuration, + type: Effect.Opacity, + from: 1.0, + to: 0.0 + }); + }, + slotWindowDataChanged: function (window, role) { + if (role == Effect.WindowAddedGrabRole) { + if (window.fadeInAnimation && effect.isGrabbed(window, role)) { + cancel(window.fadeInAnimation); + delete window.fadeInAnimation; + } + } else if (role == Effect.WindowClosedGrabRole) { + if (window.fadeOutAnimation && effect.isGrabbed(window, role)) { + cancel(window.fadeOutAnimation); + delete window.fadeOutAnimation; + } + } + }, + init: function () { + fadingPopupsEffect.loadConfig(); + + effect.configChanged.connect(fadingPopupsEffect.loadConfig); + effects.windowAdded.connect(fadingPopupsEffect.slotWindowAdded); + effects.windowClosed.connect(fadingPopupsEffect.slotWindowClosed); + effects.windowDataChanged.connect(fadingPopupsEffect.slotWindowDataChanged); + } +}; + +fadingPopupsEffect.init(); diff --git a/effects/fadingpopups/package/metadata.desktop b/effects/fadingpopups/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/effects/fadingpopups/package/metadata.desktop @@ -0,0 +1,18 @@ +[Desktop Entry] +Name=Fading Popups +Icon=preferences-system-windows-effect-fadingpopups +Comment=Make popups smoothly fade in and out when they are shown or hidden + +Type=Service +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=Vlad Zagorodniy +X-KDE-PluginInfo-Email=vladzzag@gmail.com +X-KDE-PluginInfo-Name=kwin4_effect_fadingpopups +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Category=Appearance +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-Ordering=60 +X-Plasma-API=javascript +X-Plasma-MainScript=code/main.js