Route Folio task actions through tiling

This commit is contained in:
Marco Allegretti 2026-05-22 09:39:28 +02:00
parent 5311dc8fe8
commit e951690c91
2 changed files with 124 additions and 12 deletions

View file

@ -179,6 +179,27 @@ MouseArea {
return result
}
function desktopIndexForId(desktopId) {
let ids = virtualDesktopInfo.desktopIds
if (!ids) {
return -1
}
for (let i = 0; i < ids.length; ++i) {
if (String(ids[i]) === String(desktopId)) {
return i
}
}
return -1
}
function dynamicTilingMoveToDesktopAction(desktopId) {
let index = root.desktopIndexForId(desktopId)
if (index < 0) {
return ""
}
return "move-to-desktop:" + String(desktopId) + "|" + String(index + 1)
}
function taskActivities(taskModel) {
let activities = taskModel.Activities
return activities ? activities : []
@ -1670,8 +1691,15 @@ MouseArea {
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 int dynamicTilingWindowStateSerial: ShellSettings.Settings.dynamicTilingWindowStateSerial
readonly property bool dynamicTilingMaximized: taskDelegate.canRequestDynamicTiling
&& taskDelegate.dynamicTilingWindowStateSerial >= 0
&& ShellSettings.Settings.isDynamicTilingWindowMaximized(root.taskWindowId(taskDelegate.model))
readonly property bool canChangeVirtualDesktops: taskDelegate.model.IsVirtualDesktopsChangeable === true
readonly property bool canChangeActivities: activityInfo.numberOfRunningActivities > 1 && !taskDelegate.isGroupParent
readonly property bool dynamicTilingAllActivities: taskDelegate.canRequestDynamicTiling && root.taskActivities(taskDelegate.model).length === 0
readonly property bool canShowActivityScopeAction: taskDelegate.canChangeActivities && (!taskDelegate.canRequestDynamicTiling || taskDelegate.dynamicTilingAllActivities)
readonly property bool canShowActivityMoveActions: taskDelegate.canChangeActivities && !taskDelegate.canRequestDynamicTiling
Accessible.role: Accessible.Button
Accessible.name: taskDelegate.model.display || ""
@ -1695,6 +1723,25 @@ MouseArea {
}
}
function requestMoveToDesktop(desktopId) {
if (taskDelegate.canRequestDynamicTiling) {
let action = root.dynamicTilingMoveToDesktopAction(desktopId)
if (action !== "") {
ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), action)
return
}
}
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index), [desktopId])
}
function requestMoveToNewDesktop() {
if (taskDelegate.canRequestDynamicTiling) {
ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "move-to-new-desktop")
return
}
tasksModel.requestNewVirtualDesktop(tasksModel.makeModelIndex(taskDelegate.index))
}
Keys.onReturnPressed: taskDelegate.activateTask()
Keys.onEnterPressed: taskDelegate.activateTask()
Keys.onSpacePressed: taskDelegate.activateTask()
@ -1754,6 +1801,22 @@ MouseArea {
active: taskMouseArea.containsMouse
}
Rectangle {
visible: opacity > 0
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: Kirigami.Units.smallSpacing
width: Kirigami.Units.smallSpacing * 3
height: Math.max(2, Math.round(Kirigami.Units.devicePixelRatio))
radius: height / 2
color: Kirigami.Theme.highlightColor
opacity: taskDelegate.dynamicTilingMaximized ? 0.95 : 0
Behavior on opacity {
MobileShell.MotionNumberAnimation { type: MobileShell.Motion.EffectsFast; duration: root.shortAnimationDuration }
}
}
DragHandler {
id: taskDragHandler
target: null
@ -1778,7 +1841,7 @@ MouseArea {
let finalCenterX = root.taskBaseX(taskDelegate.index) + root.dockCellWidth / 2 + root.taskPinDragOffset
let pagerDesktop = root.pagerButtonDesktopAt(finalCenterX)
if (pagerDesktop && taskDelegate.model.IsVirtualDesktopsChangeable === true) {
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index), [pagerDesktop])
taskDelegate.requestMoveToDesktop(pagerDesktop)
} else if (root.taskPinCanDrop && !folio.FavouritesModel.containsApplication(root.taskPinStorageId)) {
folio.FavouritesModel.addApplicationAt(root.taskPinTargetIndex, root.taskPinStorageId)
}
@ -1918,6 +1981,15 @@ MouseArea {
onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "tile")
}
PC3.MenuItem {
icon.name: taskDelegate.dynamicTilingMaximized ? "window-restore" : "window-maximize"
text: taskDelegate.dynamicTilingMaximized ? i18n("Restore") : i18n("Maximize")
visible: taskDelegate.canRequestDynamicTiling
height: visible ? implicitHeight : 0
enabled: taskDelegate.model.IsMaximizable === true
onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "maximize-toggle")
}
PC3.MenuItem {
icon.name: "transform-move"
text: i18n("Move")
@ -1988,19 +2060,26 @@ MouseArea {
PC3.MenuItem {
icon.name: "virtual-desktops"
text: taskDelegate.model.IsOnAllVirtualDesktops ? i18n("Show Only on Current Desktop") : i18n("Show on All Desktops")
visible: taskDelegate.canChangeVirtualDesktops && virtualDesktopInfo.numberOfDesktops > 1
visible: taskDelegate.canChangeVirtualDesktops
&& virtualDesktopInfo.numberOfDesktops > 1
&& (!taskDelegate.dynamicTilingActive || taskDelegate.model.IsOnAllVirtualDesktops === true)
height: visible ? implicitHeight : 0
onClicked: tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index),
onClicked: {
if (taskDelegate.dynamicTilingActive && taskDelegate.model.IsOnAllVirtualDesktops === true) {
taskDelegate.requestMoveToDesktop(virtualDesktopInfo.currentDesktop)
return
}
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index),
taskDelegate.model.IsOnAllVirtualDesktops ? [virtualDesktopInfo.currentDesktop] : [])
}
}
Instantiator {
model: root.showPager && taskDelegate.canChangeVirtualDesktops ? root.menuDesktopIds(taskDelegate.model.IsOnAllVirtualDesktops === true) : []
delegate: PC3.MenuItem {
required property var modelData
text: i18n("Move to %1", root.pagerDesktopNameForId(modelData))
onTriggered: tasksModel.requestVirtualDesktops(
tasksModel.makeModelIndex(taskDelegate.index), [modelData])
onTriggered: taskDelegate.requestMoveToDesktop(modelData)
}
onObjectAdded: (idx, obj) => taskContextMenu.insertItem(taskContextMenu.count, obj)
onObjectRemoved: (idx, obj) => taskContextMenu.removeItem(obj)
@ -2010,25 +2089,25 @@ MouseArea {
text: i18n("Move to New Desktop")
visible: taskDelegate.canChangeVirtualDesktops
height: visible ? implicitHeight : 0
onClicked: tasksModel.requestNewVirtualDesktop(tasksModel.makeModelIndex(taskDelegate.index))
onClicked: taskDelegate.requestMoveToNewDesktop()
}
Controls.MenuSeparator {
visible: taskDelegate.canChangeActivities
visible: taskDelegate.canShowActivityScopeAction || taskDelegate.canShowActivityMoveActions
height: visible ? implicitHeight : 0
}
PC3.MenuItem {
icon.name: "activities"
text: root.taskActivities(taskDelegate.model).length === 0 ? i18n("Show Only on Current Activity") : i18n("Show on All Activities")
visible: taskDelegate.canChangeActivities
visible: taskDelegate.canShowActivityScopeAction
height: visible ? implicitHeight : 0
onClicked: tasksModel.requestActivities(tasksModel.makeModelIndex(taskDelegate.index),
root.taskActivities(taskDelegate.model).length === 0 ? [activityInfo.currentActivity] : [])
}
Instantiator {
model: taskDelegate.canChangeActivities ? root.menuActivityIds(root.taskActivities(taskDelegate.model)) : []
model: taskDelegate.canShowActivityMoveActions ? root.menuActivityIds(root.taskActivities(taskDelegate.model)) : []
delegate: PC3.MenuItem {
required property var modelData
icon.name: activityInfo.activityIcon(modelData)

View file

@ -7,6 +7,7 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.taskmanager as TaskManager
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
@ -46,6 +47,18 @@ Item {
return String(taskModel ? taskModel.AppId || "" : "") + "|" + String(taskModel ? taskModel.display || "" : "")
}
function taskWindowId(taskModel) {
const winIds = taskModel && taskModel.WinIdList ? taskModel.WinIdList : []
return winIds.length === 1 ? String(winIds[0]) : ""
}
function dynamicTilingMoveToDesktopAction(desktopId, desktopIndex) {
if (String(desktopId).length === 0 || desktopIndex < 0) {
return ""
}
return "move-to-desktop:" + String(desktopId) + "|" + String(desktopIndex + 1)
}
function markTaskMove(taskKey, desktopIndex) {
pendingMoveTaskKey = taskKey
pendingMoveTargetName = desktopName(desktopIndex)
@ -373,11 +386,18 @@ Item {
readonly property int previewCount: Math.max(1, Math.min(2, winIds.length))
readonly property bool activeTask: model.IsActive === true
readonly property bool minimizedTask: model.IsMinimized === true
readonly property bool maximizedTask: model.IsMaximized === true
readonly property bool groupTask: model.IsGroupParent === true
readonly property bool desktopsChangeable: model.IsVirtualDesktopsChangeable === true
readonly property string storageId: root.taskStorageId(model)
readonly property string taskKey: root.taskKey(model)
readonly property string windowId: root.taskWindowId(model)
readonly property bool dynamicTilingActive: ShellSettings.Settings.convergenceModeEnabled && ShellSettings.Settings.dynamicTilingEnabled
readonly property bool canRequestDynamicTiling: dynamicTilingActive && !groupTask && windowId !== ""
readonly property int dynamicTilingWindowStateSerial: ShellSettings.Settings.dynamicTilingWindowStateSerial
readonly property bool dynamicTilingMaximized: canRequestDynamicTiling
&& dynamicTilingWindowStateSerial >= 0
&& ShellSettings.Settings.isDynamicTilingWindowMaximized(windowId)
readonly property bool maximizedTask: model.IsMaximized === true || dynamicTilingMaximized
readonly property bool pinned: storageId !== "" && root.folio.FavouritesModel.containsApplication(storageId)
readonly property bool pendingMove: root.pendingMoveTaskKey === taskKey
@ -405,6 +425,13 @@ Item {
}
root.markTaskMove(taskCard.taskKey, desktopIndex)
if (taskCard.canRequestDynamicTiling) {
const action = root.dynamicTilingMoveToDesktopAction(desktopId, desktopIndex)
if (action !== "") {
ShellSettings.Settings.requestDynamicTilingWindowAction(taskCard.windowId, action)
return
}
}
tasksModel.requestVirtualDesktops(taskCard.modelIndex, [desktopId])
}
@ -665,7 +692,13 @@ Item {
iconName: taskCard.maximizedTask ? "window-restore" : "window-maximize"
toolTipText: taskCard.maximizedTask ? i18n("Restore") : i18n("Maximize")
enabled: !taskCard.groupTask
onTriggered: tasksModel.requestToggleMaximized(taskCard.modelIndex)
onTriggered: {
if (taskCard.canRequestDynamicTiling) {
ShellSettings.Settings.requestDynamicTilingWindowAction(taskCard.windowId, "maximize-toggle")
return
}
tasksModel.requestToggleMaximized(taskCard.modelIndex)
}
}
RunningAppsPanelButton {