From 3f6916cafce54f8abaddacb1fa491c4bad74b326 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Sun, 10 May 2026 09:32:25 +0200 Subject: [PATCH] Add Dynamic Tiling task menu request bridge Expose a KConfig-backed request channel in MobileShellSettings and use it from the Folio task menu to request float/tile actions for a single window. --- .../mobileshellsettings.cpp | 35 +++++++++++++++++++ .../shellsettingsplugin/mobileshellsettings.h | 8 +++++ .../homescreens/folio/qml/FavouritesBar.qml | 27 ++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/components/shellsettingsplugin/mobileshellsettings.cpp b/components/shellsettingsplugin/mobileshellsettings.cpp index a26157b5..b04dae15 100644 --- a/components/shellsettingsplugin/mobileshellsettings.cpp +++ b/components/shellsettingsplugin/mobileshellsettings.cpp @@ -47,6 +47,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent) Q_EMIT gamingModeEnabledChanged(); Q_EMIT gamingDismissHintEnabledChanged(); Q_EMIT dynamicTilingEnabledChanged(); + Q_EMIT dynamicTilingWindowRequestChanged(); Q_EMIT snapLayoutsEnabledChanged(); Q_EMIT allowLogoutChanged(); } @@ -291,6 +292,40 @@ void MobileShellSettings::setDynamicTilingEnabled(bool enabled) m_config->sync(); } +QString MobileShellSettings::dynamicTilingWindowRequestAction() const +{ + auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP}; + return group.readEntry("dynamicTilingWindowRequestAction", QString{}); +} + +QString MobileShellSettings::dynamicTilingWindowRequestId() const +{ + auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP}; + return group.readEntry("dynamicTilingWindowRequestId", QString{}); +} + +int MobileShellSettings::dynamicTilingWindowRequestSerial() const +{ + auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP}; + return group.readEntry("dynamicTilingWindowRequestSerial", 0); +} + +void MobileShellSettings::requestDynamicTilingWindowAction(const QString &windowId, const QString &action) +{ + if (windowId.isEmpty() || action.isEmpty()) { + return; + } + + auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP}; + const int serial = group.readEntry("dynamicTilingWindowRequestSerial", 0) + 1; + group.writeEntry("dynamicTilingWindowRequestId", windowId, KConfigGroup::Notify); + group.writeEntry("dynamicTilingWindowRequestAction", action, KConfigGroup::Notify); + group.writeEntry("dynamicTilingWindowRequestSerial", serial, KConfigGroup::Notify); + m_config->sync(); + + Q_EMIT dynamicTilingWindowRequestChanged(); +} + bool MobileShellSettings::snapLayoutsEnabled() const { auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP}; diff --git a/components/shellsettingsplugin/mobileshellsettings.h b/components/shellsettingsplugin/mobileshellsettings.h index fe66e0ad..a6c75676 100644 --- a/components/shellsettingsplugin/mobileshellsettings.h +++ b/components/shellsettingsplugin/mobileshellsettings.h @@ -59,6 +59,9 @@ class MobileShellSettings : public QObject // Dynamic (BSP) window tiling — only meaningful in convergence mode. // When false, KWin's native quick-tile behaviour is used unmodified. Q_PROPERTY(bool dynamicTilingEnabled READ dynamicTilingEnabled WRITE setDynamicTilingEnabled NOTIFY dynamicTilingEnabledChanged) + Q_PROPERTY(QString dynamicTilingWindowRequestAction READ dynamicTilingWindowRequestAction NOTIFY dynamicTilingWindowRequestChanged) + Q_PROPERTY(QString dynamicTilingWindowRequestId READ dynamicTilingWindowRequestId NOTIFY dynamicTilingWindowRequestChanged) + Q_PROPERTY(int dynamicTilingWindowRequestSerial READ dynamicTilingWindowRequestSerial NOTIFY dynamicTilingWindowRequestChanged) // Snap layout picker — only meaningful in convergence mode when dynamic tiling is off. Q_PROPERTY(bool snapLayoutsEnabled READ snapLayoutsEnabled WRITE setSnapLayoutsEnabled NOTIFY snapLayoutsEnabledChanged) @@ -288,6 +291,10 @@ public: */ bool dynamicTilingEnabled() const; void setDynamicTilingEnabled(bool enabled); + QString dynamicTilingWindowRequestAction() const; + QString dynamicTilingWindowRequestId() const; + int dynamicTilingWindowRequestSerial() const; + Q_INVOKABLE void requestDynamicTilingWindowAction(const QString &windowId, const QString &action); /** * Whether the SHIFT snap layout picker is enabled. @@ -346,6 +353,7 @@ Q_SIGNALS: void gamingModeEnabledChanged(); void gamingDismissHintEnabledChanged(); void dynamicTilingEnabledChanged(); + void dynamicTilingWindowRequestChanged(); void snapLayoutsEnabledChanged(); void allowLogoutChanged(); void lockscreenLeftButtonActionChanged(); diff --git a/containments/homescreens/folio/qml/FavouritesBar.qml b/containments/homescreens/folio/qml/FavouritesBar.qml index 83ca17d5..5f28e711 100644 --- a/containments/homescreens/folio/qml/FavouritesBar.qml +++ b/containments/homescreens/folio/qml/FavouritesBar.qml @@ -182,6 +182,11 @@ MouseArea { return activities ? activities : [] } + function taskWindowId(taskModel) { + let winIds = taskModel.WinIdList + return winIds && winIds.length === 1 ? String(winIds[0]) : "" + } + function activityName(activityId) { let name = activityInfo.activityName(activityId) return name && name.length > 0 ? name : i18n("Activity") @@ -1649,6 +1654,7 @@ MouseArea { readonly property bool isGroupParent: taskDelegate.model.IsGroupParent === true readonly property bool dynamicTilingActive: root.convergenceMode && ShellSettings.Settings.dynamicTilingEnabled readonly property bool showFreeGeometryActions: !taskDelegate.isGroupParent && !taskDelegate.dynamicTilingActive + readonly property bool canRequestDynamicTiling: taskDelegate.dynamicTilingActive && !taskDelegate.isGroupParent && root.taskWindowId(taskDelegate.model) !== "" readonly property bool canChangeVirtualDesktops: taskDelegate.model.IsVirtualDesktopsChangeable === true readonly property bool canChangeActivities: activityInfo.numberOfRunningActivities > 1 && !taskDelegate.isGroupParent @@ -1876,6 +1882,27 @@ MouseArea { height: visible ? implicitHeight : 0 } + Controls.MenuSeparator { + visible: taskDelegate.canRequestDynamicTiling + height: visible ? implicitHeight : 0 + } + + PC3.MenuItem { + icon.name: "window" + text: i18n("Float Window") + visible: taskDelegate.canRequestDynamicTiling + height: visible ? implicitHeight : 0 + onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "float") + } + + PC3.MenuItem { + icon.name: "view-grid-symbolic" + text: i18n("Tile Window") + visible: taskDelegate.canRequestDynamicTiling + height: visible ? implicitHeight : 0 + onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "tile") + } + PC3.MenuItem { icon.name: "transform-move" text: i18n("Move")