From c45f9ed4464bfa8be5eb95d578f35055a93ea06b Mon Sep 17 00:00:00 2001 From: Devin Lin Date: Fri, 15 Nov 2024 13:12:22 -0800 Subject: [PATCH] envmanager: Handle SSD toggling with kwin rules Replace the convergentwindows KWin script SSD toggling with KWin rules to ensure windows are maximized and have no window border (and toggle off for docked mode). KWin rules work immediately at window creation, which is more efficient than listening to window creation events and manually changing properties on them. Currently, window rules setting maximization don't seem to address all cases where a window gets unmaximized, so for the time being we will still need the logic in convergentwindows to handle any sidecases. --- envmanager/config.h | 44 ++++++++++++++++++- envmanager/settings.cpp | 35 +++++++++++++-- envmanager/settings.h | 7 ++- .../convergentwindows/contents/ui/main.qml | 40 +++++++++-------- 4 files changed, 101 insertions(+), 25 deletions(-) diff --git a/envmanager/config.h b/envmanager/config.h index 0d410173..b5dc14a9 100644 --- a/envmanager/config.h +++ b/envmanager/config.h @@ -72,5 +72,47 @@ QMap> getKwinrcSettings(KSharedConfig::Ptr m_mo const QList KWIN_EFFECTS = {"blur", "mobiletaskswitcher", "screenedge"}; const QList KWIN_SCRIPTS = {"convergentwindows"}; -//ksmserver +// ksmserver const QMap> KSMSERVER_SETTINGS = {{"General", {{"loginMode", "emptySession"}}}}; + +// kwinrulesrc +const QList KWIN_RULES = {"plasma-mobile-desktop", "plasma-mobile-maximized-no-border"}; + +QMap> getKwinrulesrcSettings(KSharedConfig::Ptr m_mobileConfig, bool isMobileSession) +{ + auto group = KConfigGroup{m_mobileConfig, QStringLiteral("General")}; + bool convergenceModeEnabled = group.readEntry("convergenceModeEnabled", false); + + if (convergenceModeEnabled || !isMobileSession) { + return {{"plasma-mobile-desktop", + { + {"Description", "Desktop windows (controlled by Plasma Mobile)"}, + {"maximizehoriz", true}, + {"maximizehorizrule", 1}, + {"maximizevert", true}, + {"maximizevertrule", 1}, + {"noborderrule", 2}, + }}, + {"General", + { + {"count", 1}, + {"rules", "plasma-mobile-desktop"}, + }}}; + } else { + return {{"plasma-mobile-maximized-no-border", + { + {"Description", "Mobile windows (controlled by Plasma Mobile)"}, + {"maximizehoriz", true}, + {"maximizehorizrule", 2}, + {"maximizevert", true}, + {"maximizevertrule", 2}, + {"noborder", true}, + {"noborderrule", 2}, + }}, + {"General", + { + {"count", 1}, + {"rules", "plasma-mobile-maximized-no-border"}, + }}}; + } +} diff --git a/envmanager/settings.cpp b/envmanager/settings.cpp index 136617e8..efa0c675 100644 --- a/envmanager/settings.cpp +++ b/envmanager/settings.cpp @@ -26,6 +26,7 @@ Settings::Settings(QObject *parent) , m_appBlacklistConfig{KSharedConfig::openConfig(u"applications-blacklistrc"_s, KConfig::SimpleConfig)} , m_kdeglobalsConfig{KSharedConfig::openConfig(u"kdeglobals"_s, KConfig::SimpleConfig)} , m_ksmServerConfig{KSharedConfig::openConfig(u"ksmserverrc"_s, KConfig::SimpleConfig)} + , m_kwinrulesrcConfig{KSharedConfig::openConfig(u"kwinrulesrc"_s, KConfig::SimpleConfig)} , m_configWatcher{KConfigWatcher::create(m_mobileConfig)} { } @@ -54,6 +55,14 @@ void Settings::loadSavedConfiguration() // kwinrc loadKeys(u"kwinrc"_s, m_kwinrcConfig, getKwinrcSettings(m_mobileConfig)); m_kwinrcConfig->sync(); + + // kwinrules + for (const auto &groupName : KWIN_RULES) { + m_kwinrulesrcConfig->deleteGroup(groupName); + } + writeKeys(u"kwinrulesrc"_s, m_kwinrulesrcConfig, getKwinrulesrcSettings(m_mobileConfig, false), false, false); + m_kwinrulesrcConfig->sync(); + reloadKWinConfig(); // applications-blacklistrc @@ -74,6 +83,14 @@ void Settings::applyMobileConfiguration() // kwinrc writeKeys(u"kwinrc"_s, m_kwinrcConfig, getKwinrcSettings(m_mobileConfig), false); m_kwinrcConfig->sync(); + + // kwinrules + for (const auto &groupName : KWIN_RULES) { + m_kwinrulesrcConfig->deleteGroup(groupName); + } + writeKeys(u"kwinrulesrc"_s, m_kwinrulesrcConfig, getKwinrulesrcSettings(m_mobileConfig, true), false, false); + m_kwinrulesrcConfig->sync(); + reloadKWinConfig(); // applications-blacklistrc @@ -97,7 +114,11 @@ void Settings::applyMobileConfiguration() m_mobileConfig->sync(); } -void Settings::writeKeys(const QString &fileName, KSharedConfig::Ptr &config, const QMap> &settings, bool overwriteOnlyIfEmpty) +void Settings::writeKeys(const QString &fileName, + KSharedConfig::Ptr &config, + const QMap> &settings, + bool overwriteOnlyIfEmpty, + bool saveSettings) { const auto groupNames = settings.keys(); for (const auto &groupName : groupNames) { @@ -107,7 +128,9 @@ void Settings::writeKeys(const QString &fileName, KSharedConfig::Ptr &config, co for (const auto &key : keys) { if (!group.hasKey(key) || !overwriteOnlyIfEmpty) { // save key - saveConfigSetting(fileName, groupName, key, group.readEntry(key)); + if (saveSettings) { + saveConfigSetting(fileName, groupName, key, group.readEntry(key)); + } // overwrite with mobile setting group.writeEntry(key, settings[groupName][key], KConfigGroup::Notify); @@ -207,6 +230,10 @@ void Settings::reloadKWinConfig() } // Call "start" to load enabled KWin scripts. - QDBusMessage message = QDBusMessage::createMethodCall(u"org.kde.KWin"_s, u"/Scripting"_s, u"org.kde.kwin.Scripting"_s, u"start"_s); - QDBusConnection::sessionBus().send(message); + QDBusMessage startScriptsMessage = QDBusMessage::createMethodCall(u"org.kde.KWin"_s, u"/Scripting"_s, u"org.kde.kwin.Scripting"_s, u"start"_s); + QDBusConnection::sessionBus().send(startScriptsMessage); + + // Call reconfigure + QDBusMessage reconfigureMessage = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reconfigure"); + QDBusConnection::sessionBus().send(reconfigureMessage); } diff --git a/envmanager/settings.h b/envmanager/settings.h index d8d9814a..f0b06e9b 100644 --- a/envmanager/settings.h +++ b/envmanager/settings.h @@ -28,7 +28,11 @@ private: // applies our mobile configuration void applyMobileConfiguration(); - void writeKeys(const QString &fileName, KSharedConfig::Ptr &config, const QMap> &settings, bool overwriteOnlyIfEmpty); + void writeKeys(const QString &fileName, + KSharedConfig::Ptr &config, + const QMap> &settings, + bool overwriteOnlyIfEmpty, + bool saveSettings = true); void loadKeys(const QString &fileName, KSharedConfig::Ptr &config, const QMap> &settings); void saveConfigSetting(const QString &fileName, const QString &group, const QString &key, const QVariant value); const QString loadSavedConfigSetting(KSharedConfig::Ptr &config, const QString &fileName, const QString &group, const QString &key, bool write = true); @@ -43,6 +47,7 @@ private: KSharedConfig::Ptr m_appBlacklistConfig; KSharedConfig::Ptr m_kdeglobalsConfig; KSharedConfig::Ptr m_ksmServerConfig; + KSharedConfig::Ptr m_kwinrulesrcConfig; KConfigWatcher::Ptr m_configWatcher; }; diff --git a/kwin/scripts/convergentwindows/contents/ui/main.qml b/kwin/scripts/convergentwindows/contents/ui/main.qml index 3eaf2a63..0733e54b 100644 --- a/kwin/scripts/convergentwindows/contents/ui/main.qml +++ b/kwin/scripts/convergentwindows/contents/ui/main.qml @@ -6,6 +6,11 @@ import QtQuick import org.kde.kwin as KWinComponents import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings +// This script ensures that windows stay maximized in the shell. +// +// We eventually want to replace this with the window rules implementation, +// but it seems that window maximize rules still don't work for all cases just yet +// (ex. unmaximizing fullscreen window) Loader { id: root @@ -23,29 +28,26 @@ Loader { } if (ShellSettings.Settings.convergenceModeEnabled) { - window.noBorder = false; - } else { - if (!window.fullScreen) { - const output = window.output; - const desktop = window.desktops[0]; // assume it's the first desktop that the window is on - if (desktop === undefined) { - return; - } - const maximizeRect = KWinComponents.Workspace.clientArea(KWinComponents.Workspace.MaximizeArea, output, desktop); + return; + } - // set the window to the maximized size and position instantly, avoiding race condition - // between maximizing and window decorations being turned off (changing window height) - // see: https://invent.kde.org/teams/plasma-mobile/issues/-/issues/256 - window.frameGeometry = maximizeRect; + if (!window.fullScreen) { + const output = window.output; + const desktop = window.desktops[0]; // assume it's the first desktop that the window is on + if (desktop === undefined) { + return; } + const maximizeRect = KWinComponents.Workspace.clientArea(KWinComponents.Workspace.MaximizeArea, output, desktop); - // turn off window decorations - window.noBorder = true; + // set the window to the maximized size and position instantly, avoiding race condition + // between maximizing and window decorations being turned off (changing window height) + // see: https://invent.kde.org/teams/plasma-mobile/issues/-/issues/256 + window.frameGeometry = maximizeRect; + } - if (!window.fullScreen) { - // run maximize after to ensure the state is maximized - window.setMaximize(true, true); - } + if (!window.fullScreen) { + // run maximize after to ensure the state is maximized + window.setMaximize(true, true); } }