summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/kernel/qwidget.cpp11
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp94
2 files changed, 99 insertions, 6 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 8afacb9dab..06080a0f42 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6197,18 +6197,17 @@ void QWidget::setFocusProxy(QWidget * w)
}
}
- QWidget *oldDeepestFocusProxy = d_func()->deepestFocusProxy();
+ QWidget *oldDeepestFocusProxy = d->deepestFocusProxy();
if (!oldDeepestFocusProxy)
oldDeepestFocusProxy = this;
- const bool changingAppFocusWidget = (QApplicationPrivate::focus_widget == oldDeepestFocusProxy);
+
+ const bool focusProxyHadFocus = (QApplicationPrivate::focus_widget == oldDeepestFocusProxy);
d->createExtra();
d->extra->focus_proxy = w;
- if (changingAppFocusWidget) {
- QWidget *newDeepestFocusProxy = d_func()->deepestFocusProxy();
- QApplicationPrivate::setFocusWidget(newDeepestFocusProxy ? newDeepestFocusProxy : this, Qt::NoFocusReason);
- }
+ if (focusProxyHadFocus)
+ setFocus(Qt::OtherFocusReason);
}
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 5ffbbdd400..833111644e 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -373,6 +373,7 @@ private slots:
void openModal_taskQTBUG_5804();
+ void focusProxy();
void focusProxyAndInputMethods();
#ifdef QT_BUILD_INTERNAL
void scrollWithoutBackingStore();
@@ -10078,6 +10079,99 @@ void tst_QWidget::openModal_taskQTBUG_5804()
QVERIFY(QTest::qWaitForWindowExposed(win.data()));
}
+/*!
+ Test that the focus proxy receives focus, and that changing the
+ focus proxy of a widget that has focus passes focus on correctly.
+
+ The test uses a single window, so we can rely on the window's focus
+ widget and the QApplication focus widget to be the same.
+*/
+void tst_QWidget::focusProxy()
+{
+ QWidget window;
+ class Container : public QWidget
+ {
+ public:
+ Container()
+ {
+ edit = new QLineEdit;
+ edit->installEventFilter(this);
+ setFocusProxy(edit);
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(edit);
+ setLayout(layout);
+ }
+
+ QLineEdit *edit;
+ int focusInCount = 0;
+ int focusOutCount = 0;
+
+ protected:
+ bool eventFilter(QObject *receiver, QEvent *event)
+ {
+ if (receiver == edit) {
+ switch (event->type()) {
+ case QEvent::FocusIn:
+ ++focusInCount;
+ break;
+ case QEvent::FocusOut:
+ ++focusOutCount;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QWidget::eventFilter(receiver, event);
+ }
+ };
+
+ auto container1 = new Container;
+ container1->edit->setObjectName("edit1");
+ auto container2 = new Container;
+ container2->edit->setObjectName("edit2");
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(container1);
+ layout->addWidget(container2);
+ window.setLayout(layout);
+
+ window.show();
+ window.activateWindow();
+ if (!QTest::qWaitForWindowExposed(&window) || !QTest::qWaitForWindowActive(&window))
+ QSKIP("Window activation failed");
+
+ QCOMPARE(container1->focusInCount, 1);
+ QCOMPARE(container1->focusOutCount, 0);
+
+ // given a widget with a nested focus proxy
+ window.setFocusProxy(container1);
+ QCOMPARE(window.focusWidget(), container1->edit);
+ QCOMPARE(window.focusWidget(), QApplication::focusWidget());
+ QVERIFY(container1->edit->hasFocus());
+ QCOMPARE(container1->focusInCount, 1);
+
+ // changing the focus proxy should move focus to the new proxy
+ window.setFocusProxy(container2);
+ QCOMPARE(window.focusWidget(), container2->edit);
+ QCOMPARE(window.focusWidget(), QApplication::focusWidget());
+ QVERIFY(!container1->edit->hasFocus());
+ QVERIFY(container2->edit->hasFocus());
+ QCOMPARE(container1->focusInCount, 1);
+ QCOMPARE(container1->focusOutCount, 1);
+ QCOMPARE(container2->focusInCount, 1);
+ QCOMPARE(container2->focusOutCount, 0);
+
+ // clearing the focus proxy moves focus
+ window.setFocusProxy(nullptr);
+ QCOMPARE(window.focusWidget(), &window);
+ QCOMPARE(window.focusWidget(), QApplication::focusWidget());
+ QCOMPARE(container1->focusInCount, 1);
+ QCOMPARE(container1->focusOutCount, 1);
+ QCOMPARE(container2->focusInCount, 1);
+ QCOMPARE(container2->focusOutCount, 1);
+}
+
void tst_QWidget::focusProxyAndInputMethods()
{
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))