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.
This commit is contained in:
Marco Allegretti 2026-05-10 09:32:25 +02:00
parent 3fde6cd173
commit 3f6916cafc
3 changed files with 70 additions and 0 deletions

View file

@ -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};

View file

@ -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();

View file

@ -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")