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 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) { function taskActivities(taskModel) {
let activities = taskModel.Activities let activities = taskModel.Activities
return activities ? activities : [] return activities ? activities : []
@ -1670,8 +1691,15 @@ MouseArea {
readonly property bool dynamicTilingActive: root.convergenceMode && ShellSettings.Settings.dynamicTilingEnabled readonly property bool dynamicTilingActive: root.convergenceMode && ShellSettings.Settings.dynamicTilingEnabled
readonly property bool showFreeGeometryActions: !taskDelegate.isGroupParent && !taskDelegate.dynamicTilingActive readonly property bool showFreeGeometryActions: !taskDelegate.isGroupParent && !taskDelegate.dynamicTilingActive
readonly property bool canRequestDynamicTiling: taskDelegate.dynamicTilingActive && !taskDelegate.isGroupParent && root.taskWindowId(taskDelegate.model) !== "" 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 canChangeVirtualDesktops: taskDelegate.model.IsVirtualDesktopsChangeable === true
readonly property bool canChangeActivities: activityInfo.numberOfRunningActivities > 1 && !taskDelegate.isGroupParent 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.role: Accessible.Button
Accessible.name: taskDelegate.model.display || "" 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.onReturnPressed: taskDelegate.activateTask()
Keys.onEnterPressed: taskDelegate.activateTask() Keys.onEnterPressed: taskDelegate.activateTask()
Keys.onSpacePressed: taskDelegate.activateTask() Keys.onSpacePressed: taskDelegate.activateTask()
@ -1754,6 +1801,22 @@ MouseArea {
active: taskMouseArea.containsMouse 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 { DragHandler {
id: taskDragHandler id: taskDragHandler
target: null target: null
@ -1778,7 +1841,7 @@ MouseArea {
let finalCenterX = root.taskBaseX(taskDelegate.index) + root.dockCellWidth / 2 + root.taskPinDragOffset let finalCenterX = root.taskBaseX(taskDelegate.index) + root.dockCellWidth / 2 + root.taskPinDragOffset
let pagerDesktop = root.pagerButtonDesktopAt(finalCenterX) let pagerDesktop = root.pagerButtonDesktopAt(finalCenterX)
if (pagerDesktop && taskDelegate.model.IsVirtualDesktopsChangeable === true) { 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)) { } else if (root.taskPinCanDrop && !folio.FavouritesModel.containsApplication(root.taskPinStorageId)) {
folio.FavouritesModel.addApplicationAt(root.taskPinTargetIndex, root.taskPinStorageId) folio.FavouritesModel.addApplicationAt(root.taskPinTargetIndex, root.taskPinStorageId)
} }
@ -1918,6 +1981,15 @@ MouseArea {
onClicked: ShellSettings.Settings.requestDynamicTilingWindowAction(root.taskWindowId(taskDelegate.model), "tile") 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 { PC3.MenuItem {
icon.name: "transform-move" icon.name: "transform-move"
text: i18n("Move") text: i18n("Move")
@ -1988,10 +2060,18 @@ MouseArea {
PC3.MenuItem { PC3.MenuItem {
icon.name: "virtual-desktops" icon.name: "virtual-desktops"
text: taskDelegate.model.IsOnAllVirtualDesktops ? i18n("Show Only on Current Desktop") : i18n("Show on All 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 height: visible ? implicitHeight : 0
onClicked: tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index), onClicked: {
taskDelegate.model.IsOnAllVirtualDesktops ? [virtualDesktopInfo.currentDesktop] : []) if (taskDelegate.dynamicTilingActive && taskDelegate.model.IsOnAllVirtualDesktops === true) {
taskDelegate.requestMoveToDesktop(virtualDesktopInfo.currentDesktop)
return
}
tasksModel.requestVirtualDesktops(tasksModel.makeModelIndex(taskDelegate.index),
taskDelegate.model.IsOnAllVirtualDesktops ? [virtualDesktopInfo.currentDesktop] : [])
}
} }
Instantiator { Instantiator {
@ -1999,8 +2079,7 @@ MouseArea {
delegate: PC3.MenuItem { delegate: PC3.MenuItem {
required property var modelData required property var modelData
text: i18n("Move to %1", root.pagerDesktopNameForId(modelData)) text: i18n("Move to %1", root.pagerDesktopNameForId(modelData))
onTriggered: tasksModel.requestVirtualDesktops( onTriggered: taskDelegate.requestMoveToDesktop(modelData)
tasksModel.makeModelIndex(taskDelegate.index), [modelData])
} }
onObjectAdded: (idx, obj) => taskContextMenu.insertItem(taskContextMenu.count, obj) onObjectAdded: (idx, obj) => taskContextMenu.insertItem(taskContextMenu.count, obj)
onObjectRemoved: (idx, obj) => taskContextMenu.removeItem(obj) onObjectRemoved: (idx, obj) => taskContextMenu.removeItem(obj)
@ -2010,25 +2089,25 @@ MouseArea {
text: i18n("Move to New Desktop") text: i18n("Move to New Desktop")
visible: taskDelegate.canChangeVirtualDesktops visible: taskDelegate.canChangeVirtualDesktops
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onClicked: tasksModel.requestNewVirtualDesktop(tasksModel.makeModelIndex(taskDelegate.index)) onClicked: taskDelegate.requestMoveToNewDesktop()
} }
Controls.MenuSeparator { Controls.MenuSeparator {
visible: taskDelegate.canChangeActivities visible: taskDelegate.canShowActivityScopeAction || taskDelegate.canShowActivityMoveActions
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
} }
PC3.MenuItem { PC3.MenuItem {
icon.name: "activities" icon.name: "activities"
text: root.taskActivities(taskDelegate.model).length === 0 ? i18n("Show Only on Current Activity") : i18n("Show on All 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 height: visible ? implicitHeight : 0
onClicked: tasksModel.requestActivities(tasksModel.makeModelIndex(taskDelegate.index), onClicked: tasksModel.requestActivities(tasksModel.makeModelIndex(taskDelegate.index),
root.taskActivities(taskDelegate.model).length === 0 ? [activityInfo.currentActivity] : []) root.taskActivities(taskDelegate.model).length === 0 ? [activityInfo.currentActivity] : [])
} }
Instantiator { Instantiator {
model: taskDelegate.canChangeActivities ? root.menuActivityIds(root.taskActivities(taskDelegate.model)) : [] model: taskDelegate.canShowActivityMoveActions ? root.menuActivityIds(root.taskActivities(taskDelegate.model)) : []
delegate: PC3.MenuItem { delegate: PC3.MenuItem {
required property var modelData required property var modelData
icon.name: activityInfo.activityIcon(modelData) icon.name: activityInfo.activityIcon(modelData)

View file

@ -7,6 +7,7 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.plasma.components 3.0 as PC3 import org.kde.plasma.components 3.0 as PC3
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.taskmanager as TaskManager import org.kde.taskmanager as TaskManager
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio 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 || "" : "") 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) { function markTaskMove(taskKey, desktopIndex) {
pendingMoveTaskKey = taskKey pendingMoveTaskKey = taskKey
pendingMoveTargetName = desktopName(desktopIndex) pendingMoveTargetName = desktopName(desktopIndex)
@ -373,11 +386,18 @@ Item {
readonly property int previewCount: Math.max(1, Math.min(2, winIds.length)) readonly property int previewCount: Math.max(1, Math.min(2, winIds.length))
readonly property bool activeTask: model.IsActive === true readonly property bool activeTask: model.IsActive === true
readonly property bool minimizedTask: model.IsMinimized === 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 groupTask: model.IsGroupParent === true
readonly property bool desktopsChangeable: model.IsVirtualDesktopsChangeable === true readonly property bool desktopsChangeable: model.IsVirtualDesktopsChangeable === true
readonly property string storageId: root.taskStorageId(model) readonly property string storageId: root.taskStorageId(model)
readonly property string taskKey: root.taskKey(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 pinned: storageId !== "" && root.folio.FavouritesModel.containsApplication(storageId)
readonly property bool pendingMove: root.pendingMoveTaskKey === taskKey readonly property bool pendingMove: root.pendingMoveTaskKey === taskKey
@ -405,6 +425,13 @@ Item {
} }
root.markTaskMove(taskCard.taskKey, desktopIndex) 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]) tasksModel.requestVirtualDesktops(taskCard.modelIndex, [desktopId])
} }
@ -665,7 +692,13 @@ Item {
iconName: taskCard.maximizedTask ? "window-restore" : "window-maximize" iconName: taskCard.maximizedTask ? "window-restore" : "window-maximize"
toolTipText: taskCard.maximizedTask ? i18n("Restore") : i18n("Maximize") toolTipText: taskCard.maximizedTask ? i18n("Restore") : i18n("Maximize")
enabled: !taskCard.groupTask 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 { RunningAppsPanelButton {