aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Eftevaag <[email protected]>2024-05-07 13:24:37 +0200
committerOliver Eftevaag <[email protected]>2024-05-29 14:01:24 +0200
commit2393c588bc9a5368c013952a4fb195c5b4017543 (patch)
tree1e29ba686b1faf9853fabf3fb7d77beec78f36cf
parent523b6a5eb0aef0e4b0ca86eca99161c2e9619871 (diff)
Forward keyboard events to the active popup window
Popup windows will never become the focus window of the application. Meaning that window system events will be send directly to the "main" window, and then forwarded to any potential popup windows, if any. But since popup windows don't become "active", they won't receive the focus in event, and thus never call setFocus on their contentItem. This could cause setFocusInScope() to skip assigning the activeFocusItem to be the new focus item. Effectively breaking keyboard navigation for things like menus that are inside a menubar. Change-Id: Id1345aee09ed4dd31017781f5e0e6f5f925551e6 Reviewed-by: Richard Moe Gustavsen <[email protected]>
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml1
-rw-r--r--tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp40
3 files changed, 42 insertions, 1 deletions
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp
index 34032d4801..ed2112fa0d 100644
--- a/src/quick/util/qquickdeliveryagent.cpp
+++ b/src/quick/util/qquickdeliveryagent.cpp
@@ -428,7 +428,7 @@ void QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *
}
}
- if (newActiveFocusItem && rootItem->hasFocus()) {
+ if (newActiveFocusItem && (rootItem->hasFocus() || (rootItem->window()->type() == Qt::Popup))) {
activeFocusItem = newActiveFocusItem;
QQuickItemPrivate::get(newActiveFocusItem)->activeFocus = true;
diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml b/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml
index 60033d34a3..1477db047e 100644
--- a/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml
+++ b/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml
@@ -19,6 +19,7 @@ Window {
Popup {
id: simplepopup
+ popupType: Popup.Window
TextField {
id: innerTextField
focus: true
diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
index 8b9e8aa976..f5a4212d91 100644
--- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
@@ -120,6 +120,7 @@ private slots:
void popupWindowModality();
void popupWindowClosesOnParentWindowClosing();
void popupWindowChangingParent();
+ void popupWindowFocus();
private:
QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
@@ -2639,6 +2640,45 @@ void tst_QQuickPopup::popupWindowChangingParent()
VERIFY_LOCAL_POS(popup, initialPos);
}
+void tst_QQuickPopup::popupWindowFocus()
+{
+ QSKIP("Enable this test once the PopupType property has been merged");
+ QQuickApplicationHelper helper(this, "popupWindowFocusHandling.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickWindow *window = helper.window;
+ QVERIFY(window);
+ auto *popup = window->contentItem()->findChild<QQuickPopup *>();
+ QVERIFY(popup);
+ auto *popupPrivate = QQuickPopupPrivate::get(popup);
+ QVERIFY(popupPrivate);
+ QQuickTextInput *textField1 = window->property("textField1").value<QQuickTextInput *>();
+ QVERIFY(textField1);
+ QQuickTextInput *textField2 = window->property("textField2").value<QQuickTextInput *>();
+ QVERIFY(textField2);
+ if (!popupPrivate->usePopupWindow())
+ QSKIP("The platform doesn't support native popup windows. Skipping test.");
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowFocused(window));
+ QVERIFY(QGuiApplication::focusObject() == textField1);
+ QTest::keyClick(helper.window, Qt::Key_Q);
+ QTRY_COMPARE(textField1->text(), "q");
+ popup->open();
+ QTRY_VERIFY(popup->isVisible());
+ auto *popupWindow = popupPrivate->popupWindow;
+ QVERIFY(popupWindow);
+ QVERIFY(popupWindow->isVisible());
+ // The focusWindow should still be the main window,
+ // the popup window should get its event forwarded via the delivery agent
+ QVERIFY(QGuiApplication::focusWindow() == helper.window);
+ QVERIFY(popupWindow->focusObject() == textField2);
+ QTest::keyClick(popupWindow, Qt::Key_T);
+ QTRY_COMPARE(textField2->text(), "t");
+ popup->close();
+ QTRY_VERIFY(!popup->isVisible());
+ QVERIFY(QGuiApplication::focusObject() == textField1);
+}
+
QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup)
#include "tst_qquickpopup.moc"