mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-29 15:03:09 +00:00
Enable keyboard control in convergence dock
Make the convergence dock fully usable from the keyboard. Tab now reaches Home, favorites, running tasks, and Overview. Left and right move across section boundaries, and Enter/Space triggers the same actions as mouse clicks. Also add accessible role/name/press actions for these controls so screen readers expose meaningful button semantics.
This commit is contained in:
parent
e72beb7296
commit
e9dbfa5ea1
1 changed files with 102 additions and 19 deletions
|
|
@ -125,6 +125,7 @@ MouseArea {
|
|||
Rectangle {
|
||||
id: homeButton
|
||||
visible: root.convergenceMode
|
||||
activeFocusOnTab: root.convergenceMode
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
@ -134,6 +135,26 @@ MouseArea {
|
|||
: (homeMouseArea.containsMouse ? Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.1) : "transparent")
|
||||
radius: Kirigami.Units.cornerRadius
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: i18n("Home")
|
||||
Accessible.onPressAction: MobileShellState.ShellDBusClient.openHomeScreen()
|
||||
|
||||
Keys.onReturnPressed: MobileShellState.ShellDBusClient.openHomeScreen()
|
||||
Keys.onEnterPressed: MobileShellState.ShellDBusClient.openHomeScreen()
|
||||
Keys.onSpacePressed: MobileShellState.ShellDBusClient.openHomeScreen()
|
||||
Keys.onRightPressed: {
|
||||
let first = repeater.itemAt(0)
|
||||
if (first) { first.keyboardFocus(); return }
|
||||
let firstTask = taskRepeater.itemAt(0)
|
||||
if (firstTask) { firstTask.forceActiveFocus(); return }
|
||||
overviewButton.forceActiveFocus()
|
||||
}
|
||||
|
||||
KeyboardHighlight {
|
||||
anchors.fill: parent
|
||||
visible: homeButton.activeFocus
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn: parent
|
||||
width: Math.min(parent.width, parent.height) * 0.75
|
||||
|
|
@ -155,6 +176,7 @@ MouseArea {
|
|||
Rectangle {
|
||||
id: overviewButton
|
||||
visible: root.convergenceMode
|
||||
activeFocusOnTab: root.convergenceMode
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
@ -164,6 +186,26 @@ MouseArea {
|
|||
: (overviewMouseArea.containsMouse ? Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.1) : "transparent")
|
||||
radius: Kirigami.Units.cornerRadius
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: i18n("Overview")
|
||||
Accessible.onPressAction: root.folio.triggerOverview()
|
||||
|
||||
Keys.onReturnPressed: root.folio.triggerOverview()
|
||||
Keys.onEnterPressed: root.folio.triggerOverview()
|
||||
Keys.onSpacePressed: root.folio.triggerOverview()
|
||||
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 }
|
||||
homeButton.forceActiveFocus()
|
||||
}
|
||||
|
||||
KeyboardHighlight {
|
||||
anchors.fill: parent
|
||||
visible: overviewButton.activeFocus
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn: parent
|
||||
width: Math.min(parent.width, parent.height) * 0.75
|
||||
|
|
@ -320,9 +362,12 @@ MouseArea {
|
|||
break;
|
||||
case Qt.Key_Left:
|
||||
if (isLocationBottom) {
|
||||
let nextDelegate = repeater.itemAt(delegate.index - 1);
|
||||
if (nextDelegate) {
|
||||
nextDelegate.keyboardFocus();
|
||||
let prevDelegate = repeater.itemAt(delegate.index - 1);
|
||||
if (prevDelegate) {
|
||||
prevDelegate.keyboardFocus();
|
||||
event.accepted = true;
|
||||
} else if (root.convergenceMode) {
|
||||
homeButton.forceActiveFocus();
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -333,6 +378,14 @@ MouseArea {
|
|||
if (nextDelegate) {
|
||||
nextDelegate.keyboardFocus();
|
||||
event.accepted = true;
|
||||
} else if (root.convergenceMode) {
|
||||
let firstTask = taskRepeater.itemAt(0);
|
||||
if (firstTask) {
|
||||
firstTask.forceActiveFocus();
|
||||
} else {
|
||||
overviewButton.forceActiveFocus();
|
||||
}
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -852,9 +905,49 @@ MouseArea {
|
|||
required property int index
|
||||
required property var model
|
||||
|
||||
activeFocusOnTab: root.convergenceMode
|
||||
|
||||
readonly property bool isLocationBottom: folio.HomeScreenState.favouritesBarLocation === Folio.HomeScreenState.Bottom
|
||||
readonly property string taskStorageId: root.runningTaskStorageId(taskDelegate.model)
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: taskDelegate.model.display || ""
|
||||
Accessible.onPressAction: taskDelegate.activateTask()
|
||||
|
||||
function activateTask() {
|
||||
var winIds = taskDelegate.model.WinIdList
|
||||
if (winIds && winIds.length > 1) {
|
||||
if (thumbnailPopup.opened && thumbnailPopup.taskIndex === taskDelegate.index) {
|
||||
thumbnailPopup.close()
|
||||
} else {
|
||||
thumbnailPopup.targetDelegate = taskDelegate
|
||||
thumbnailPopup.taskIndex = taskDelegate.index
|
||||
thumbnailPopup.windowIds = winIds
|
||||
thumbnailPopup.isGroup = taskDelegate.model.IsGroupParent === true
|
||||
thumbnailPopup.open()
|
||||
}
|
||||
} else {
|
||||
thumbnailPopup.close()
|
||||
tasksModel.requestActivate(tasksModel.makeModelIndex(taskDelegate.index))
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: taskDelegate.activateTask()
|
||||
Keys.onEnterPressed: taskDelegate.activateTask()
|
||||
Keys.onSpacePressed: taskDelegate.activateTask()
|
||||
Keys.onLeftPressed: {
|
||||
let prev = taskRepeater.itemAt(taskDelegate.index - 1)
|
||||
if (prev) { prev.forceActiveFocus(); return }
|
||||
let lastFav = repeater.itemAt(repeater.count - 1)
|
||||
if (lastFav) { lastFav.keyboardFocus(); return }
|
||||
homeButton.forceActiveFocus()
|
||||
}
|
||||
Keys.onRightPressed: {
|
||||
let next = taskRepeater.itemAt(taskDelegate.index + 1)
|
||||
if (next) { next.forceActiveFocus(); return }
|
||||
overviewButton.forceActiveFocus()
|
||||
}
|
||||
|
||||
// Position after all favourites
|
||||
property double fromCenterValue: (repeater.count + taskDelegate.index) - (root.totalItemCount / 2)
|
||||
Behavior on fromCenterValue {
|
||||
|
|
@ -881,6 +974,11 @@ MouseArea {
|
|||
: (taskMouseArea.containsMouse ? Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.1) : "transparent")
|
||||
}
|
||||
|
||||
KeyboardHighlight {
|
||||
anchors.fill: parent
|
||||
visible: taskDelegate.activeFocus
|
||||
}
|
||||
|
||||
// Task icon
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn: parent
|
||||
|
|
@ -970,22 +1068,7 @@ MouseArea {
|
|||
thumbnailShowTimer.stop()
|
||||
taskContextMenu.open();
|
||||
} else {
|
||||
var winIds = taskDelegate.model.WinIdList
|
||||
if (winIds && winIds.length > 1) {
|
||||
// Multiple windows: toggle thumbnail popup
|
||||
if (thumbnailPopup.opened && thumbnailPopup.taskIndex === taskDelegate.index) {
|
||||
thumbnailPopup.close()
|
||||
} else {
|
||||
thumbnailPopup.targetDelegate = taskDelegate
|
||||
thumbnailPopup.taskIndex = taskDelegate.index
|
||||
thumbnailPopup.windowIds = winIds
|
||||
thumbnailPopup.isGroup = taskDelegate.model.IsGroupParent === true
|
||||
thumbnailPopup.open()
|
||||
}
|
||||
} else {
|
||||
thumbnailPopup.close()
|
||||
tasksModel.requestActivate(tasksModel.makeModelIndex(taskDelegate.index));
|
||||
}
|
||||
taskDelegate.activateTask()
|
||||
}
|
||||
}
|
||||
onContainsMouseChanged: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue