From b80c87848750e33d5f6bb3e0768be29d7a230a63 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Fri, 29 May 2026 11:11:59 +0200 Subject: [PATCH] Make dock pager follow keyboard focus order Keep keyboard navigation aligned with the compact desktop pager group. Right from the Desktop button now enters the pager, pager buttons expose accessible activation, and focus continues into dock content after the last desktop. --- .../homescreens/folio/qml/FavouritesBar.qml | 74 +++++++++++++++---- tests/check-convergence-dock-invariant.sh | 6 ++ 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/containments/homescreens/folio/qml/FavouritesBar.qml b/containments/homescreens/folio/qml/FavouritesBar.qml index 700c9ec6..96261281 100644 --- a/containments/homescreens/folio/qml/FavouritesBar.qml +++ b/containments/homescreens/folio/qml/FavouritesBar.qml @@ -299,6 +299,30 @@ MouseArea { return "" } + function focusFirstDockContent() { + let firstPager = leftPagerRepeater.itemAt(0) + if (firstPager) { firstPager.forceActiveFocus(); return } + root.focusAfterPager() + } + + function focusAfterPager() { + let first = repeater.itemAt(0) + if (first) { first.keyboardFocus(); return } + let firstTask = taskRepeater.itemAt(0) + if (firstTask) { firstTask.forceActiveFocus(); return } + searchButton.forceActiveFocus() + } + + function focusBeforeSearch() { + let lastTask = taskRepeater.itemAt(taskRepeater.count - 1) + if (lastTask) { lastTask.forceActiveFocus(); return } + let lastFav = repeater.itemAt(repeater.count - 1) + if (lastFav) { lastFav.keyboardFocus(); return } + let lastPager = leftPagerRepeater.itemAt(leftPagerRepeater.count - 1) + if (lastPager) { lastPager.forceActiveFocus(); return } + desktopButton.forceActiveFocus() + } + function runningTaskStorageId(taskModel) { var id = taskModel ? taskModel.AppId || "" : "" if (id && !id.endsWith(".desktop")) @@ -441,13 +465,7 @@ MouseArea { 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() - } + Keys.onRightPressed: root.focusFirstDockContent() KeyboardHighlight { anchors.fill: parent @@ -615,13 +633,7 @@ MouseArea { Keys.onReturnPressed: root.folio.HomeScreenState.openSearchWidget() Keys.onEnterPressed: root.folio.HomeScreenState.openSearchWidget() Keys.onSpacePressed: root.folio.HomeScreenState.openSearchWidget() - Keys.onLeftPressed: { - let lastTask = taskRepeater.itemAt(taskRepeater.count - 1) - if (lastTask) { lastTask.forceActiveFocus(); return } - let lastFav = repeater.itemAt(repeater.count - 1) - if (lastFav) { lastFav.keyboardFocus(); return } - desktopButton.forceActiveFocus() - } + Keys.onLeftPressed: root.focusBeforeSearch() Keys.onRightPressed: overviewButton.forceActiveFocus() KeyboardHighlight { @@ -701,6 +713,36 @@ MouseArea { y: 0 width: root.pagerButtonWidth height: root.height + activeFocusOnTab: root.showPager + + function activateDesktop() { + if (leftDesktopBtn.desktopId) { + root.folio.activateVirtualDesktop(leftDesktopBtn.desktopId) + } + } + + Accessible.role: Accessible.Button + Accessible.name: root.pagerDesktopName(leftDesktopBtn.index) + Accessible.onPressAction: leftDesktopBtn.activateDesktop() + + Keys.onReturnPressed: leftDesktopBtn.activateDesktop() + Keys.onEnterPressed: leftDesktopBtn.activateDesktop() + Keys.onSpacePressed: leftDesktopBtn.activateDesktop() + Keys.onLeftPressed: { + let previous = leftPagerRepeater.itemAt(index - 1) + if (previous) { previous.forceActiveFocus(); return } + desktopButton.forceActiveFocus() + } + Keys.onRightPressed: { + let next = leftPagerRepeater.itemAt(index + 1) + if (next) { next.forceActiveFocus(); return } + root.focusAfterPager() + } + + KeyboardHighlight { + anchors.fill: parent + visible: leftDesktopBtn.activeFocus + } MobileShell.MotionStateLayer { anchors.fill: parent @@ -738,8 +780,8 @@ MouseArea { root.hideDockToolTip(leftDesktopBtn) if (mouse.button === Qt.RightButton) { leftPagerContextMenu.open() - } else if (leftDesktopBtn.desktopId) { - root.folio.activateVirtualDesktop(leftDesktopBtn.desktopId) + } else { + leftDesktopBtn.activateDesktop() } } onPressAndHold: { diff --git a/tests/check-convergence-dock-invariant.sh b/tests/check-convergence-dock-invariant.sh index 9b6bb0c5..921ec3e1 100644 --- a/tests/check-convergence-dock-invariant.sh +++ b/tests/check-convergence-dock-invariant.sh @@ -92,6 +92,12 @@ require_line "$favourites_bar" "readonly property int pagerLeftCount: showPager require_line "$favourites_bar" "readonly property int pagerRightCount: 0" require_line "$favourites_bar" "readonly property real rightControlsWidth: convergenceMode ? navButtonWidth + searchButtonWidth + trashButtonWidth : 0" require_line "$favourites_bar" "Virtual desktop pager: compact group next to the Desktop button" +require_line "$favourites_bar" "function focusFirstDockContent()" +require_line "$favourites_bar" "Keys.onRightPressed: root.focusFirstDockContent()" +require_line "$favourites_bar" "Keys.onLeftPressed: root.focusBeforeSearch()" +require_line "$favourites_bar" "Accessible.name: root.pagerDesktopName(leftDesktopBtn.index)" +require_line "$favourites_bar" "Keys.onRightPressed: {" +require_line "$favourites_bar" "root.focusAfterPager()" if grep -Fq "Math.ceil(virtualDesktopInfo.numberOfDesktops / 2)" "$favourites_bar"; then echo "Desktop pager must not split virtual desktops between dock edges" >&2 exit 1