[vlc-commits] [Git][videolan/vlc][master] 4 commits: qml: fix controlbar keyboard navigation regression

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Sat Jul 31 09:55:16 UTC 2021



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
dd8945e7 by Fatih Uzunoglu at 2021-07-31T09:07:08+00:00
qml: fix controlbar keyboard navigation regression

recent introduction of Loaders broke the navigation.
This patch intends to fix the regression.

fixes #25762.

- - - - -
78e0394a by Fatih Uzunoglu at 2021-07-31T09:07:08+00:00
qml: use attached navigation in progressbar

- - - - -
85e9a3b0 by Fatih Uzunoglu at 2021-07-31T09:07:08+00:00
qml: fix typo in MiniPlayer

- - - - -
829a188d by Fatih Uzunoglu at 2021-07-31T09:07:08+00:00
qml: better focus handling in player toolbar

fixes #25748

- - - - -


5 changed files:

- modules/gui/qt/player/qml/ButtonsLayout.qml
- modules/gui/qt/player/qml/ControlBar.qml
- modules/gui/qt/player/qml/MiniPlayer.qml
- modules/gui/qt/player/qml/PlayerButtonsLayout.qml
- modules/gui/qt/player/qml/VolumeWidget.qml


Changes:

=====================================
modules/gui/qt/player/qml/ButtonsLayout.qml
=====================================
@@ -49,14 +49,36 @@ FocusScope {
     property real extraWidth: 0
     property int expandableCount: 0 // widget count that can expand when extra width is available
 
+    Navigation.navigable: {
+        for (var i = 0; i < buttonsRepeater.count; ++i) {
+            if (buttonsRepeater.itemAt(i).item.focus) {
+                return true
+            }
+        }
+        return false
+    }
+
     implicitWidth: buttonrow.implicitWidth
     implicitHeight: buttonrow.implicitHeight
 
-    visible: model.count > 0
+    property var altFocusAction: Navigation.defaultNavigationUp
+
+    function _handleFocus() {
+        if (typeof activeFocus === "undefined")
+            return
+
+        if (activeFocus && (!visible || model.count === 0))
+            altFocusAction()
+    }
+
+    Component.onCompleted: {
+        visibleChanged.connect(_handleFocus)
+        activeFocusChanged.connect(_handleFocus)
+        model.countChanged.connect(_handleFocus)
+    }
 
     RowLayout {
         id: buttonrow
-        property bool _focusGiven: false
 
         anchors.fill: parent
 
@@ -66,12 +88,10 @@ FocusScope {
             id: buttonsRepeater
 
             onItemRemoved: {
-                if (item.focus) {
-                    buttonrow._focusGiven = false
-                }
-
                 if (item.item.extraWidth !== undefined)
                     buttonsLayout.expandableCount--
+
+                item.recoverFocus(index)
             }
 
             delegate: Loader {
@@ -79,12 +99,50 @@ FocusScope {
 
                 sourceComponent: controlmodelbuttons.returnbuttondelegate(model.id)
 
-                onLoaded: {
-                    if (!buttonrow._focusGiven) {
-                        buttonloader.focus = true
-                        buttonrow._focusGiven = true
+                focus: (index === 0)
+
+                function buildFocusChain() {
+                    // rebuild the focus chain:
+                    if (typeof buttonsRepeater === "undefined")
+                        return
+
+                    var rightItem = buttonsRepeater.itemAt(index + 1)
+                    var leftItem = buttonsRepeater.itemAt(index - 1)
+
+                    item.Navigation.rightItem = !!rightItem ? rightItem.item : null
+                    item.Navigation.leftItem = !!leftItem ? leftItem.item : null
+                }
+
+                Component.onCompleted: {
+                    buttonsRepeater.countChanged.connect(buttonloader.buildFocusChain)
+                    mainInterface.controlbarProfileModel.selectedProfileChanged.connect(buttonloader.buildFocusChain)
+                    mainInterface.controlbarProfileModel.currentModel.dirtyChanged.connect(buttonloader.buildFocusChain)
+                }
+
+                onActiveFocusChanged: {
+                    if (activeFocus && !item.focus) {
+                        recoverFocus()
                     }
-                    buttonloader.item.focus = true
+                }
+
+                Connections {
+                    target: item
+
+                    enabled: buttonloader.status === Loader.Ready
+
+                    onEnabledChanged: {
+                        if (activeFocus && !item.enabled) // Loader has focus but item is not enabled
+                            recoverFocus()
+                    }
+                }
+
+                onLoaded: {
+                    // control should not request focus if they are not enabled:
+                    item.focus = Qt.binding(function() { return item.enabled })
+
+                    // navigation parent of control is always buttonsLayout
+                    // so it can be set here unlike leftItem and rightItem:
+                    item.Navigation.parentItem = buttonsLayout
 
                     if (buttonloader.item instanceof Widgets.IconToolButton)
                         buttonloader.item.size = Qt.binding(function() { return defaultSize; })
@@ -94,12 +152,6 @@ FocusScope {
                         buttonloader.item.colors = Qt.binding(function() { return colors; })
                     }
 
-                    buttonloader.item.Navigation.parentItem = buttonsLayout
-                    if (index > 0) {
-                        buttonloader.item.Navigation.leftItem = buttonrow.children[index-1].item
-                        buttonrow.children[index-1].item.Navigation.rightItem = buttonloader.item
-                   }
-
                     if (buttonloader.item.extraWidth !== undefined && buttonsLayout.extraWidth !== undefined) {
                         buttonsLayout.expandableCount++
                         buttonloader.item.extraWidth = Qt.binding( function() {
@@ -107,6 +159,44 @@ FocusScope {
                         } )
                     }
                 }
+
+                function _focusIfFocusable(loader, reason) {
+                    if (!!loader && !!loader.item && loader.item.focus) {
+                        loader.item.forceActiveFocus(reason)
+                        return true
+                    } else {
+                        return false
+                    }
+                }
+
+                function recoverFocus(_index) {
+                    if (_index === undefined)
+                        _index = index
+
+                    for (var i = 1; i <= Math.max(_index, buttonsRepeater.count - (_index + 1)); ++i) {
+                         if (i <= _index) {
+                             var leftItem = buttonsRepeater.itemAt(_index - i)
+
+                             if (_focusIfFocusable(leftItem))
+                                 return
+                         }
+
+                         if (_index + i <= buttonsRepeater.count - 1) {
+                             var rightItem = buttonsRepeater.itemAt(_index + i)
+
+                             if (_focusIfFocusable(rightItem))
+                                 return
+                         }
+                    }
+
+                    // focus to other alignment if focusable control
+                    // in the same alignment is not found:
+                    if (_index > (buttonsRepeater.count + 1) / 2) {
+                        buttonsLayout.Navigation.defaultNavigationRight()
+                    } else {
+                        buttonsLayout.Navigation.defaultNavigationLeft()
+                    }
+                }
             }
         }
     }


=====================================
modules/gui/qt/player/qml/ControlBar.qml
=====================================
@@ -194,6 +194,11 @@ FocusScope {
         parentWindow: g_root
         colors: root.colors
 
-        Keys.onDownPressed: playerButtonsLayout.focus = true
+        Navigation.parentItem: root
+        Navigation.downItem: playerButtonsLayout
+
+        Keys.onPressed: {
+            Navigation.defaultKeyAction(event)
+        }
     }
 }


=====================================
modules/gui/qt/player/qml/MiniPlayer.qml
=====================================
@@ -86,10 +86,11 @@ FocusScope {
         Navigation.parentItem: root
 
         Keys.onPressed: {
-            if (!event.accepted)
-                controlbar.Navigation.defaultKeyAction(event)
-            if (!event.accepted)
-                mainInterface.sendHotkey(event.key, event.modifiers);
+            controlBar.Navigation.defaultKeyAction(event)
+
+            if (!event.accepted) {
+                mainInterface.sendHotkey(event.key, event.modifiers)
+            }
         }
     }
 }


=====================================
modules/gui/qt/player/qml/PlayerButtonsLayout.qml
=====================================
@@ -77,7 +77,10 @@ FocusScope {
             rightMargin: layoutSpacing
         }
 
-        active: !!playerButtonsLayout.model && !!playerButtonsLayout.model.left
+        active: !!playerButtonsLayout.model
+                && !!playerButtonsLayout.model.left
+
+        focus: true
 
         sourceComponent: ButtonsLayout {
             model: playerButtonsLayout.model.left
@@ -87,9 +90,11 @@ FocusScope {
             visible: extraWidth < 0 ? false : true // extraWidth < 0 means there is not even available space for minimumSize
 
             Navigation.parentItem: playerButtonsLayout
-            Navigation.rightItem: buttonrow_center
+            Navigation.rightItem: buttonrow_center.item
 
             focus: true
+
+            altFocusAction: Navigation.defaultNavigationRight
         }
     }
 
@@ -103,14 +108,19 @@ FocusScope {
             bottomMargin: playerButtonsLayout.marginBottom
         }
 
-        active: !!playerButtonsLayout.model && !!playerButtonsLayout.model.center
+        active: !!playerButtonsLayout.model
+                && !!playerButtonsLayout.model.center
 
         sourceComponent: ButtonsLayout {
             model: playerButtonsLayout.model.center
 
             Navigation.parentItem: playerButtonsLayout
-            Navigation.leftItem: buttonrow_left
-            Navigation.rightItem: buttonrow_right
+            Navigation.leftItem: buttonrow_left.item
+            Navigation.rightItem: buttonrow_right.item
+
+            focus: true
+
+            altFocusAction: Navigation.defaultNavigationUp
         }
     }
 
@@ -127,11 +137,10 @@ FocusScope {
             leftMargin: layoutSpacing
         }
 
-        active: !!playerButtonsLayout.model && !!playerButtonsLayout.model.right
+        active: !!playerButtonsLayout.model
+                && !!playerButtonsLayout.model.right
 
         sourceComponent: ButtonsLayout {
-
-
             model: playerButtonsLayout.model.right
 
             extraWidth: (playerButtonsLayout.width - (buttonrow_center.x + buttonrow_center.width) - minimumWidth - (2 * layoutSpacing))
@@ -139,7 +148,11 @@ FocusScope {
             visible: extraWidth < 0 ? false : true // extraWidth < 0 means there is not even available space for minimumSize
 
             Navigation.parentItem: playerButtonsLayout
-            Navigation.leftItem: buttonrow_center
+            Navigation.leftItem: buttonrow_center.item
+
+            focus: true
+
+            altFocusAction: Navigation.defaultNavigationLeft
         }
     }
 }


=====================================
modules/gui/qt/player/qml/VolumeWidget.qml
=====================================
@@ -39,11 +39,6 @@ FocusScope{
 
     property alias parentWindow: volumeTooltip.parentWindow
 
-    // these are uninitialized because they will be set by button loader
-    // not 'undefined' because the loader must know if they exist
-    property var leftAction: null
-    property var rightAction: null
-
     property VLCColors colors: VLCStyle.colors
 
     RowLayout{
@@ -72,15 +67,7 @@ FocusScope{
             onClicked: player.muted = !player.muted
 
             Navigation.parentItem: widgetfscope
-            Navigation.upAction: function() {
-                volControl.increase()
-                tooltipShower.restart()
-            }
-
-            Navigation.downAction: function() {
-                volControl.decrease()
-                tooltipShower.restart()
-            }
+            Navigation.rightItem: volControl
         }
 
         Slider
@@ -101,6 +88,8 @@ FocusScope{
             Keys.onPressed: {
                 if (KeyHelper.matchOk(event)) {
                     event.accepted = true
+                } else {
+                    Navigation.defaultKeyAction(event)
                 }
             }
 
@@ -125,6 +114,21 @@ FocusScope{
                 }
             }
 
+            Navigation.leftItem: volumeBtn
+            Navigation.parentItem: widgetfscope
+
+            Keys.onUpPressed: {
+                volControl.increase()
+                tooltipShower.restart()
+            }
+
+            Keys.onDownPressed: {
+                volControl.decrease()
+                tooltipShower.restart()
+            }
+
+            Keys.priority: Keys.BeforeItem
+
             property color sliderColor: (volControl.position > fullvolpos) ? colors.volmax : widgetfscope.color
             property int maxvol: 125
             property double fullvolpos: 100 / maxvol



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6cb1e6a236c901e1f101bb1e4ef2719fbe1a7839...829a188d96a0f7776f9e4c8f123bda939c6872f3

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6cb1e6a236c901e1f101bb1e4ef2719fbe1a7839...829a188d96a0f7776f9e4c8f123bda939c6872f3
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list