diff --git a/autotests/mock_effectshandler.h b/autotests/mock_effectshandler.h --- a/autotests/mock_effectshandler.h +++ b/autotests/mock_effectshandler.h @@ -281,6 +281,9 @@ void renderEffectQuickView(KWin::EffectQuickView *quickView) const override { Q_UNUSED(quickView); } + KWin::SessionState sessionState() const override { + return KWin::SessionState::Normal; + } private: bool m_animationsSuported = true; diff --git a/effects.h b/effects.h --- a/effects.h +++ b/effects.h @@ -275,6 +275,8 @@ void renderEffectQuickView(EffectQuickView *effectQuickView) const override; + SessionState sessionState() const override; + public Q_SLOTS: void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to); void slotTabAdded(EffectWindow* from, EffectWindow* to); diff --git a/effects.cpp b/effects.cpp --- a/effects.cpp +++ b/effects.cpp @@ -196,6 +196,8 @@ elevated_windows.removeAll(d->effectWindow()); } ); + connect(ws->sessionManager(), &SessionManager::stateChanged, this, + &KWin::EffectsHandler::sessionStateChanged); connect(vds, &VirtualDesktopManager::countChanged, this, &EffectsHandler::numberDesktopsChanged); connect(Cursor::self(), &Cursor::mouseChanged, this, &EffectsHandler::mouseChanged); connect(screens(), &Screens::countChanged, this, &EffectsHandler::numberScreensChanged); @@ -1710,6 +1712,11 @@ scene()->paintEffectQuickView(w); } +SessionState EffectsHandlerImpl::sessionState() const +{ + return Workspace::self()->sessionManager()->state(); +} + //**************************************** // EffectWindowImpl //**************************************** diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -157,6 +157,7 @@ install_scripted_effect(squash) install_scripted_effect(translucency) install_scripted_effect(windowaperture) +install_scripted_effect(sessionquit) ############################################################################### # Built-in effects go here diff --git a/effects/sessionquit/package/contents/code/main.js b/effects/sessionquit/package/contents/code/main.js new file mode 100644 --- /dev/null +++ b/effects/sessionquit/package/contents/code/main.js @@ -0,0 +1,43 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2019 David Edmundson + +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"; + +var quitEffect = { + closed: function (window) { + if (!window.desktopWindow || effects.sessionState != Globals.Quitting) { + return; + } + if (!effect.grab(window, Effect.WindowClosedGrabRole)) { + return; + } + window.outAnimation = animate({ + window: window, + duration: 30 * 1000, // 30 seconds should be long enough for any shutdown + type: Effect.Generic, // do nothing, just hold a reference + from: 0.0, + to: 0.0 + }); + }, + init: function () { + effects.windowClosed.connect(quitEffect.closed); + } +}; +quitEffect.init(); diff --git a/effects/sessionquit/package/metadata.desktop b/effects/sessionquit/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/effects/sessionquit/package/metadata.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Name=Session Quit +Icon=preferences-system-windows-effect-logout +Comment=Keep the desktop background alive during logout until the end + +Type=Service +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=David Edmundson +X-KDE-PluginInfo-Email=davidedmundson@kde.org +X-KDE-PluginInfo-Name=kwin4_effect_sessionquit +X-KDE-PluginInfo-Version=0.2.0 +X-KDE-PluginInfo-Category=Appearance +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-Ordering=40 +X-Plasma-API=javascript +X-KWin-Internal=true +X-Plasma-MainScript=code/main.js diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -826,6 +826,13 @@ Q_PROPERTY(QSize virtualScreenSize READ virtualScreenSize NOTIFY virtualScreenSizeChanged) Q_PROPERTY(QRect virtualScreenGeometry READ virtualScreenGeometry NOTIFY virtualScreenGeometryChanged) Q_PROPERTY(bool hasActiveFullScreenEffect READ hasActiveFullScreenEffect NOTIFY hasActiveFullScreenEffectChanged) + + /** + * The status of the session i.e if the user is logging out + * @since 5.18 + */ + Q_PROPERTY(KWin::SessionState sessionState READ sessionState NOTIFY sessionStateChanged) + friend class Effect; public: explicit EffectsHandler(CompositingType type); @@ -1367,6 +1374,11 @@ */ virtual void renderEffectQuickView(EffectQuickView *effectQuickView) const = 0; + /** + * The status of the session i.e if the user is logging out + * @since 5.18 + */ + virtual SessionState sessionState() const = 0; Q_SIGNALS: /** * Signal emitted when the current desktop changed. @@ -1799,6 +1811,12 @@ */ void windowFullScreenChanged(KWin::EffectWindow *w); + /** + * This signal is emitted when the session state was changed + * @since 5.18 + */ + void sessionStateChanged(); + protected: QVector< EffectPair > loaded_effects; //QHash< QString, EffectFactory* > effect_factories; diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -1941,3 +1941,4 @@ } // namespace +#include "moc_kwinglobals.cpp" diff --git a/libkwineffects/kwinglobals.h b/libkwineffects/kwinglobals.h --- a/libkwineffects/kwinglobals.h +++ b/libkwineffects/kwinglobals.h @@ -36,7 +36,7 @@ namespace KWin { - +KWIN_EXPORT Q_NAMESPACE enum CompositingType { NoCompositing = 0, @@ -147,6 +147,7 @@ Saving, Quitting }; +Q_ENUM_NS(SessionState) inline KWIN_EXPORT xcb_connection_t *connection() diff --git a/scripting/scriptedeffect.h b/scripting/scriptedeffect.h --- a/scripting/scriptedeffect.h +++ b/scripting/scriptedeffect.h @@ -38,6 +38,7 @@ Q_ENUMS(Anchor) Q_ENUMS(MetaType) Q_ENUMS(EasingCurve) + Q_ENUMS(SessionState) /** * True if we are the active fullscreen effect */ diff --git a/scripting/scriptedeffect.cpp b/scripting/scriptedeffect.cpp --- a/scripting/scriptedeffect.cpp +++ b/scripting/scriptedeffect.cpp @@ -633,6 +633,8 @@ #ifndef KWIN_UNIT_TEST m_engine->globalObject().setProperty(QStringLiteral("KWin"), m_engine->newQMetaObject(&QtScriptWorkspaceWrapper::staticMetaObject)); #endif + m_engine->globalObject().setProperty(QStringLiteral("Globals"), m_engine->newQMetaObject(&KWin::staticMetaObject)); + m_engine->globalObject().setProperty(QStringLiteral("QEasingCurve"), m_engine->newQMetaObject(&QEasingCurve::staticMetaObject)); m_engine->globalObject().setProperty(QStringLiteral("effect"), m_engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater), QScriptValue::Undeletable); MetaScripting::registration(m_engine);