aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quicktemplates/qquickpopup.cpp23
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml27
-rw-r--r--tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp48
3 files changed, 96 insertions, 2 deletions
diff --git a/src/quicktemplates/qquickpopup.cpp b/src/quicktemplates/qquickpopup.cpp
index 43bf1f447a..f5db64bcfb 100644
--- a/src/quicktemplates/qquickpopup.cpp
+++ b/src/quicktemplates/qquickpopup.cpp
@@ -633,8 +633,27 @@ bool QQuickPopupPrivate::prepareExitTransition()
if (transitionState != ExitTransition) {
// The setFocus(false) call below removes any active focus before we're
// able to check it in finalizeExitTransition.
- if (!hadActiveFocusBeforeExitTransition)
- hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus();
+ if (!hadActiveFocusBeforeExitTransition) {
+ const auto hasFocusInRoot = [](QQuickItem *item) {
+ Q_ASSERT(item);
+ if (!item->window() || item->window()->isActive())
+ return item->hasActiveFocus();
+
+ // fallback for when there's no active window
+ const auto *da = QQuickItemPrivate::get(item)->deliveryAgentPrivate();
+ if (!da || !da->rootItem)
+ return false;
+
+ QQuickItem *focusItem = da->rootItem;
+ while (focusItem->isFocusScope() && focusItem->scopedFocusItem())
+ focusItem = focusItem->scopedFocusItem();
+
+ return focusItem == item;
+ };
+
+ hadActiveFocusBeforeExitTransition = hasFocusInRoot(popupItem);
+ }
+
if (focus)
popupItem->setFocus(false, Qt::PopupFocusReason);
transitionState = ExitTransition;
diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml
new file mode 100644
index 0000000000..1d4dc87e41
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias popup: popup
+ property alias button: button
+
+ Button {
+ id: button
+ text: "button"
+ focus: true
+ }
+
+ Popup {
+ id: popup
+ focus: true
+ width: 100
+ height: 100
+ anchors.centerIn: Overlay.overlay
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
index aec7391f63..e774d055e1 100644
--- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp
@@ -65,6 +65,7 @@ private slots:
void activeFocusAfterExit();
void activeFocusOnDelayedEnter();
void activeFocusDespiteLowerStackingOrder();
+ void activeFocusItemAfterWindowInactive();
void hover_data();
void hover();
void wheel_data();
@@ -954,6 +955,53 @@ void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder()
QVERIFY(!popup1->hasActiveFocus());
}
+void tst_QQuickPopup::activeFocusItemAfterWindowInactive()
+{
+ if (!hasWindowActivation())
+ QSKIP("Window activation is not supported");
+
+ QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterWindowInactive.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(window));
+
+ QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>();
+ QQuickButton *button = helper.appWindow->property("button").value<QQuickButton*>();
+ QVERIFY(popup);
+ QVERIFY(button);
+
+ popup->open();
+ QVERIFY(popup->isVisible());
+ QTRY_VERIFY(popup->isOpened());
+ QVERIFY(popup->hasActiveFocus());
+ QVERIFY(!button->hasActiveFocus());
+
+ popup->close();
+ QVERIFY(!popup->isVisible());
+ QTRY_VERIFY(!popup->isOpened());
+ QVERIFY(button->hasActiveFocus());
+ QCOMPARE(window->activeFocusItem(), button);
+
+ popup->open();
+ QVERIFY(popup->isVisible());
+ QTRY_VERIFY(popup->isOpened());
+
+ QQuickWindow newWindow;
+ newWindow.setTitle("newFocusWindow");
+ newWindow.show();
+ newWindow.requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(&newWindow));
+
+ popup->close();
+ QCOMPARE(QGuiApplication::focusWindow(), &newWindow);
+
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(window));
+ QCOMPARE(window->activeFocusItem(), button);
+}
+
void tst_QQuickPopup::hover_data()
{
QTest::addColumn<QString>("source");