From ef7290de7be9d36fc590956a32444bb8b1db384c Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 5 Aug 2020 21:23:45 +0200 Subject: Prevent against re-entering prepareExitTransition after a focus change When a popup is hidden, then it will trigger a prepareExitTransition which can cause the active focus to be lost. If the popup's visibility is tied to that fact then it can retrigger the transition which means the active focus does not go back to where it should. Therefore, we check if hadActiveFocusBeforeExitTransition is false before going through that process as then it will only be called the first time the popup is hidden. Fixes: QTBUG-85884 Change-Id: I68054aeb48447617b4235ce6467514a17f1073ba Reviewed-by: Mitch Curtis Reviewed-by: Qt CI Bot (cherry picked from commit 1a5a0a591c35dcf498a232a802087683f2244ecb) Reviewed-by: Qt Cherry-pick Bot --- src/quicktemplates2/qquickpopup.cpp | 2 +- tests/auto/controls/data/tst_dialog.qml | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index b5a6e992..3312c63e 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -451,7 +451,7 @@ bool QQuickPopupPrivate::prepareExitTransition() if (transitionState == ExitTransition && transitionManager.isRunning()) return false; - if (transitionState != ExitTransition) { + if (transitionState != ExitTransition && !hadActiveFocusBeforeExitTransition) { // The setFocus(false) call below removes any active focus before we're // able to check it in finalizeExitTransition. hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus(); diff --git a/tests/auto/controls/data/tst_dialog.qml b/tests/auto/controls/data/tst_dialog.qml index 1bfffc1d..79053c13 100644 --- a/tests/auto/controls/data/tst_dialog.qml +++ b/tests/auto/controls/data/tst_dialog.qml @@ -411,4 +411,40 @@ TestCase { button.clicked() compare(buttonSpy.count, 1) } + + Component { + id: qtbug85884 + ApplicationWindow { + property alias focusItemActiveFocus: item.activeFocus + property alias focusDialogVisible: dialog.visible + visible: true + Item { + id: item + focus: true + } + Dialog { + id: dialog + focus: true + visible: false + onActiveFocusChanged: { + if (!activeFocus) + visible = false + } + } + } + } + + function test_focusLeavingDialog(data) { + var window = createTemporaryObject(qtbug85884, testCase) + verify(window) + tryCompare(window, "focusItemActiveFocus", true) + + window.focusDialogVisible = true + tryCompare(window, "focusDialogVisible", true) + tryCompare(window, "focusItemActiveFocus", false) + + window.focusDialogVisible = false + tryCompare(window, "focusDialogVisible", false) + tryCompare(window, "focusItemActiveFocus", true) + } } -- cgit v1.2.3