Fix setting active window as application's focus widget
When setting the application's focus widget we search for the next child widget that can hold the focus and call its setFocus() method, which also updates focus widgets of all its parent wigets. In case if the focus widget is the active window itself, we only set it as the application's focus widget, but we don't update the focus widget of the active window itself. Because of this the focusWidget() method always results nullptr for the active window. This prevents from setting the focus back to active window after the focus has changed (for example after a context menu is closed, as in the bugreport). Transfer the focus to active window by calling the setFocus() method, as it is done in case of transferring the focus to any other widget. Pick-to: 6.0 5.15 Fixes: QTBUG-85846 Change-Id: I91ebf182fd5bb7d451a1186e2f3e38c8d48acc4e Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
20e364e00c
commit
154573929a
@ -1869,17 +1869,18 @@ void QApplication::setActiveWindow(QWidget* act)
|
||||
if (w) {
|
||||
w->setFocus(Qt::ActiveWindowFocusReason);
|
||||
} else {
|
||||
// If the focus widget is not in the activate_window, clear the focus
|
||||
w = QApplicationPrivate::focus_widget;
|
||||
if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus)
|
||||
QApplicationPrivate::setFocusWidget(QApplicationPrivate::active_window, Qt::ActiveWindowFocusReason);
|
||||
else if (!QApplicationPrivate::active_window->isAncestorOf(w))
|
||||
if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus) {
|
||||
QApplicationPrivate::active_window->setFocus(Qt::ActiveWindowFocusReason);
|
||||
} else if (!QApplicationPrivate::active_window->isAncestorOf(w)) {
|
||||
// If the focus widget is not in the activate_window, clear the focus
|
||||
QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QWidget *qt_tlw_for_window(QWindow *wnd)
|
||||
{
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include <QtWidgets/private/qapplication_p.h>
|
||||
#include <QtWidgets/QStyle>
|
||||
#include <QtWidgets/qproxystyle.h>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <qpa/qwindowsysteminterface_p.h>
|
||||
@ -125,6 +126,7 @@ private slots:
|
||||
|
||||
void setActiveWindow();
|
||||
|
||||
void focusWidget();
|
||||
void focusChanged();
|
||||
void focusOut();
|
||||
void focusMouseClick();
|
||||
@ -1556,6 +1558,44 @@ void tst_QApplication::setActiveWindow()
|
||||
delete w;
|
||||
}
|
||||
|
||||
void tst_QApplication::focusWidget()
|
||||
{
|
||||
int argc = 0;
|
||||
QApplication app(argc, nullptr);
|
||||
|
||||
// The focus widget is the active window itself
|
||||
{
|
||||
QTextEdit te;
|
||||
te.show();
|
||||
|
||||
QApplication::setActiveWindow(&te);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&te));
|
||||
|
||||
const auto focusWidget = QApplication::focusWidget();
|
||||
QVERIFY(focusWidget);
|
||||
QVERIFY(focusWidget->hasFocus());
|
||||
QVERIFY(te.hasFocus());
|
||||
QCOMPARE(focusWidget, te.focusWidget());
|
||||
}
|
||||
|
||||
// The focus widget is a child of the active window
|
||||
{
|
||||
QWidget w;
|
||||
QTextEdit te(&w);
|
||||
w.show();
|
||||
|
||||
QApplication::setActiveWindow(&w);
|
||||
QVERIFY(QTest::qWaitForWindowActive(&w));
|
||||
|
||||
const auto focusWidget = QApplication::focusWidget();
|
||||
QVERIFY(focusWidget);
|
||||
QVERIFY(focusWidget->hasFocus());
|
||||
QVERIFY(!w.hasFocus());
|
||||
QVERIFY(te.hasFocus());
|
||||
QCOMPARE(te.focusWidget(), w.focusWidget());
|
||||
QCOMPARE(focusWidget, w.focusWidget());
|
||||
}
|
||||
}
|
||||
|
||||
/* This might fail on some X11 window managers? */
|
||||
void tst_QApplication::focusChanged()
|
||||
|
Loading…
Reference in New Issue
Block a user