[Development] [Qt Quick] Automatically restoring focus to last focused item

Mitch Curtis mitch.curtis at qt.io
Thu May 5 16:08:33 CEST 2016


Consider the example below (requires Qt 5.7):

    import QtQuick 2.6
    import QtQuick.Layouts 1.1
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.0
    
    ApplicationWindow {
        width: 400
        height: 200
        visible: true
    
        onActiveFocusItemChanged: print("activeFocusItem", activeFocusItem)
    
        header: ToolBar {
            RowLayout {
                focus: false
                implicitWidth: children[0].implicitWidth
                implicitHeight: children[0].implicitHeight
    
                ToolButton {
                    text: qsTr("File")
                    onClicked: fileMenu.open()
    
                    Menu {
                        id: fileMenu
                        y: parent.height
    
                        MenuItem {
                            text: qsTr("New")
                        }
                        MenuItem {
                            text: qsTr("open")
                        }
                        MenuItem {
                            text: qsTr("Close")
                        }
                    }
                }
            }
        }
    
        FocusScope {
            id: focusScope
            focus: true
            anchors.fill: parent
    
            property bool toggled: false
            onToggledChanged: print("toggled", toggled)
    
            Keys.onPressed: {
                if (event.modifiers === Qt.AltModifier) {
                    focusScope.toggled = true;
                }
            }
            Keys.onReleased: {
                if ((event.modifiers === Qt.AltModifier || event.key === Qt.Key_Alt) && !event.isAutoRepeat) {
                    focusScope.toggled = false;
                }
            }
    
            RowLayout {
                anchors.centerIn: parent
    
                Button {
                    id: penButton
                    text: qsTr("Pen")
                    highlighted: !focusScope.toggled
                }
                Button {
                    id: eyedropperButton
                    text: qsTr("Eyedropper")
                    highlighted: focusScope.toggled
                }
            }
        }
    }
    
The idea is that holding the Alt key down will toggle between two "modes". The mode is indicated by a highlighted button.

Try switching between the buttons. Now open the menu by clicking the "File" button. The menu will receive focus and the focus scope will lose it. If you then close the menu and try to switch between the buttons again, it won't work because the focus scope never regained focus (the root item now has it). This is explained here [1]:

"When a QML Item explicitly relinquishes focus (by setting its focus property to false while it has active focus), the system does not automatically select another type to receive focus. That is, it is possible for there to be no currently active focus."

I'm not sure if "explicitly relinquishes focus" is exactly what's happening here, though. The FocusScope loses focus because something else was open temporarily. So now the developer has no other option than to listen to e.g. the menu visibility changes and explicitly set focus on the FocusScope accordingly. That's pretty gross if you ask me. I think we can do better. Specifically, I think that we should remember the last focused item, and give that focus, rather than give it to the root item. The question is, would it be an acceptable change for Qt 5? I'd assume that users are already working around this anyway, and so the fix wouldn't hurt.

[1] http://doc.qt.io/qt-5/qtquick-input-focus.html


More information about the Development mailing list