Add Peek at Desktop to the convergence dock

Place a desktop toggle next to Home in the convergence dock and
shift the pager and task focus flow around it. This brings the
upstream show-desktop affordance into SHIFT without adding a new
panel surface.
This commit is contained in:
Marco Allegretti 2026-05-09 10:46:32 +02:00
parent c23d756596
commit 76da62dae9

View file

@ -13,6 +13,7 @@ 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
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import QtQuick.Controls as Controls import QtQuick.Controls as Controls
import QtQuick.Templates as T import QtQuick.Templates as T
@ -93,14 +94,16 @@ MouseArea {
property real pagerButtonWidth: showPager ? Math.min(root.height, Kirigami.Units.gridUnit * 2.5) : 0 property real pagerButtonWidth: showPager ? Math.min(root.height, Kirigami.Units.gridUnit * 2.5) : 0
readonly property int pagerLeftCount: showPager ? Math.ceil(virtualDesktopInfo.numberOfDesktops / 2) : 0 readonly property int pagerLeftCount: showPager ? Math.ceil(virtualDesktopInfo.numberOfDesktops / 2) : 0
readonly property int pagerRightCount: showPager ? virtualDesktopInfo.numberOfDesktops - pagerLeftCount : 0 readonly property int pagerRightCount: showPager ? virtualDesktopInfo.numberOfDesktops - pagerLeftCount : 0
property real desktopButtonWidth: convergenceMode ? root.height : 0
property real trashButtonWidth: convergenceMode ? root.height : 0 property real trashButtonWidth: convergenceMode ? root.height : 0
property real searchButtonWidth: convergenceMode ? root.height : 0 property real searchButtonWidth: convergenceMode ? root.height : 0
readonly property real leftControlsWidth: convergenceMode ? navButtonWidth + pagerLeftCount * pagerButtonWidth : 0 readonly property real leftControlsWidth: convergenceMode ? navButtonWidth + desktopButtonWidth + pagerLeftCount * pagerButtonWidth : 0
readonly property real rightControlsWidth: convergenceMode ? navButtonWidth + searchButtonWidth + trashButtonWidth + pagerRightCount * pagerButtonWidth : 0 readonly property real rightControlsWidth: convergenceMode ? navButtonWidth + searchButtonWidth + trashButtonWidth + pagerRightCount * pagerButtonWidth : 0
readonly property real dockCenterX: convergenceMode readonly property real dockCenterX: convergenceMode
? leftControlsWidth + (root.width - leftControlsWidth - rightControlsWidth) / 2 ? leftControlsWidth + (root.width - leftControlsWidth - rightControlsWidth) / 2
: root.width / 2 : root.width / 2
Behavior on pagerButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } } Behavior on pagerButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on desktopButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on trashButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } } Behavior on trashButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
Behavior on searchButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } } Behavior on searchButtonWidth { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutCubic } }
@ -144,7 +147,7 @@ MouseArea {
if (!showPager) return "" if (!showPager) return ""
let ids = virtualDesktopInfo.desktopIds let ids = virtualDesktopInfo.desktopIds
for (let i = 0; i < pagerLeftCount; ++i) { for (let i = 0; i < pagerLeftCount; ++i) {
let bx = navButtonWidth + i * pagerButtonWidth let bx = navButtonWidth + desktopButtonWidth + i * pagerButtonWidth
if (x >= bx && x < bx + pagerButtonWidth) if (x >= bx && x < bx + pagerButtonWidth)
return (ids && i < ids.length) ? String(ids[i]) : "" return (ids && i < ids.length) ? String(ids[i]) : ""
} }
@ -235,11 +238,7 @@ MouseArea {
Keys.onEnterPressed: MobileShellState.ShellDBusClient.openHomeScreen() Keys.onEnterPressed: MobileShellState.ShellDBusClient.openHomeScreen()
Keys.onSpacePressed: MobileShellState.ShellDBusClient.openHomeScreen() Keys.onSpacePressed: MobileShellState.ShellDBusClient.openHomeScreen()
Keys.onRightPressed: { Keys.onRightPressed: {
let first = repeater.itemAt(0) desktopButton.forceActiveFocus()
if (first) { first.keyboardFocus(); return }
let firstTask = taskRepeater.itemAt(0)
if (firstTask) { firstTask.forceActiveFocus(); return }
searchButton.forceActiveFocus()
} }
KeyboardHighlight { KeyboardHighlight {
@ -275,6 +274,81 @@ MouseArea {
} }
} }
// Peek at Desktop button (convergence mode, next to Home)
Rectangle {
id: desktopButton
visible: root.convergenceMode || opacity > 0
enabled: root.convergenceMode
opacity: root.convergenceMode ? 1 : 0
activeFocusOnTab: root.convergenceMode
x: root.navButtonWidth
y: 0
width: root.desktopButtonWidth
height: root.height
color: "transparent"
function toggleDesktop() {
WindowPlugin.WindowUtil.requestShowingDesktop(!WindowPlugin.WindowUtil.isShowingDesktop)
}
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad }
}
Accessible.role: Accessible.Button
Accessible.name: WindowPlugin.WindowUtil.isShowingDesktop ? i18n("Stop Peeking at Desktop") : i18n("Peek at Desktop")
Accessible.onPressAction: desktopButton.toggleDesktop()
Keys.onReturnPressed: desktopButton.toggleDesktop()
Keys.onEnterPressed: desktopButton.toggleDesktop()
Keys.onSpacePressed: desktopButton.toggleDesktop()
Keys.onLeftPressed: homeButton.forceActiveFocus()
Keys.onRightPressed: {
let first = repeater.itemAt(0)
if (first) { first.keyboardFocus(); return }
let firstTask = taskRepeater.itemAt(0)
if (firstTask) { firstTask.forceActiveFocus(); return }
searchButton.forceActiveFocus()
}
KeyboardHighlight {
anchors.fill: parent
visible: desktopButton.activeFocus
}
Rectangle {
anchors.fill: parent
anchors.margins: root.dockItemInset
radius: Kirigami.Units.cornerRadius
color: root.dockItemColor(desktopMouseArea.containsPress, desktopMouseArea.containsMouse, WindowPlugin.WindowUtil.isShowingDesktop)
Behavior on color {
ColorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.OutCubic }
}
}
Kirigami.Icon {
anchors.centerIn: parent
width: root.dockIconSize
height: width
source: "user-desktop"
active: desktopMouseArea.containsMouse || WindowPlugin.WindowUtil.isShowingDesktop
}
PC3.ToolTip {
visible: desktopMouseArea.containsMouse
text: desktopButton.Accessible.name
}
MouseArea {
id: desktopMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: root.convergenceMode ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: desktopButton.toggleDesktop()
}
}
// Overview button (convergence mode, right end) // Overview button (convergence mode, right end)
Rectangle { Rectangle {
id: overviewButton id: overviewButton
@ -365,7 +439,7 @@ MouseArea {
if (lastTask) { lastTask.forceActiveFocus(); return } if (lastTask) { lastTask.forceActiveFocus(); return }
let lastFav = repeater.itemAt(repeater.count - 1) let lastFav = repeater.itemAt(repeater.count - 1)
if (lastFav) { lastFav.keyboardFocus(); return } if (lastFav) { lastFav.keyboardFocus(); return }
homeButton.forceActiveFocus() desktopButton.forceActiveFocus()
} }
Keys.onRightPressed: overviewButton.forceActiveFocus() Keys.onRightPressed: overviewButton.forceActiveFocus()
@ -427,7 +501,7 @@ MouseArea {
return root.pagerButtonDesktopAt(cx) === desktopId return root.pagerButtonDesktopAt(cx) === desktopId
} }
x: root.navButtonWidth + index * root.pagerButtonWidth x: root.navButtonWidth + root.desktopButtonWidth + index * root.pagerButtonWidth
y: 0 y: 0
width: root.pagerButtonWidth width: root.pagerButtonWidth
height: root.height height: root.height
@ -800,7 +874,7 @@ MouseArea {
prevDelegate.keyboardFocus(); prevDelegate.keyboardFocus();
event.accepted = true; event.accepted = true;
} else if (root.convergenceMode) { } else if (root.convergenceMode) {
homeButton.forceActiveFocus(); desktopButton.forceActiveFocus();
event.accepted = true; event.accepted = true;
} }
} }
@ -1385,7 +1459,7 @@ MouseArea {
if (prev) { prev.forceActiveFocus(); return } if (prev) { prev.forceActiveFocus(); return }
let lastFav = repeater.itemAt(repeater.count - 1) let lastFav = repeater.itemAt(repeater.count - 1)
if (lastFav) { lastFav.keyboardFocus(); return } if (lastFav) { lastFav.keyboardFocus(); return }
homeButton.forceActiveFocus() desktopButton.forceActiveFocus()
} }
Keys.onRightPressed: { Keys.onRightPressed: {
let next = taskRepeater.itemAt(taskDelegate.index + 1) let next = taskRepeater.itemAt(taskDelegate.index + 1)