From 7e768dde39f9365a4e1fc45afc492b74744a44e6 Mon Sep 17 00:00:00 2001 From: Christoph Schleifenbaum Date: Sat, 16 Nov 2013 17:17:15 +0100 Subject: [PATCH] Widgets: Never revoke focus by click on focused widget. When clicking on a widget currently focused, w/o having Qt::ClickFocus set as focus policy, the focus should stay on the widget and not get propagated to the widget's parent. Task-number: QTBUG-34042 Change-Id: I53f1153829cc7228de02a90e38125b5cf4ee5008 Reviewed-by: Marc Mutz --- src/widgets/kernel/qapplication.cpp | 10 ++++ .../kernel/qapplication/tst_qapplication.cpp | 58 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 4e3ecf144a..9056ffe461 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3761,6 +3761,16 @@ void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEven } if (focusWidget->isWindow()) break; + + // find out whether this widget (or its proxy) already has focus + QWidget *f = focusWidget; + if (focusWidget->d_func()->extra && focusWidget->d_func()->extra->focus_proxy) + f = focusWidget->d_func()->extra->focus_proxy; + // if it has, stop here. + // otherwise a click on the focused widget would remove its focus if ClickFocus isn't set + if (f->hasFocus()) + break; + localPos += focusWidget->pos(); focusWidget = focusWidget->parentWidget(); } diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 8d75298673..091927abe4 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -153,6 +153,7 @@ private slots: void focusChanged(); void focusOut(); + void focusMouseClick(); void execAfterExit(); @@ -1771,6 +1772,63 @@ void tst_QApplication::focusOut() QTest::qWait(2000); } +class SpontaneousEvent +{ + Q_GADGET + QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) + Q_ENUMS(Type) +public: + enum Type { + Void + }; + + virtual ~SpontaneousEvent() {} + + QEventPrivate *d; + ushort t; + + ushort posted : 1; + ushort spont : 1; +}; + +void tst_QApplication::focusMouseClick() +{ + int argc = 1; + QApplication app(argc, &argv0); + + QWidget w; + w.setFocusPolicy(Qt::StrongFocus); + QWidget w2(&w); + w2.setFocusPolicy(Qt::TabFocus); + w.show(); + w.setFocus(); + QTRY_COMPARE(QApplication::focusWidget(), &w); + + // front most widget has Qt::TabFocus, parent widget accepts clicks as well + // now send a mouse button press event and check what happens with the focus + // it should be given to the parent widget + QMouseEvent ev(QEvent::MouseButtonPress, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + reinterpret_cast(&ev)->spont = 1; + QVERIFY(ev.spontaneous()); + qApp->notify(&w2, &ev); + QCOMPARE(QApplication::focusWidget(), &w); + + // then we give the inner widget strong focus -> it should get focus + w2.setFocusPolicy(Qt::StrongFocus); + reinterpret_cast(&ev)->spont = 1; + QVERIFY(ev.spontaneous()); + qApp->notify(&w2, &ev); + QTRY_COMPARE(QApplication::focusWidget(), &w2); + + // now back to tab focus and click again (it already had focus) -> focus should stay + // (focus was revoked as of QTBUG-34042) + w2.setFocusPolicy(Qt::TabFocus); + reinterpret_cast(&ev)->spont = 1; + QVERIFY(ev.spontaneous()); + qApp->notify(&w2, &ev); + QCOMPARE(QApplication::focusWidget(), &w2); +} + void tst_QApplication::execAfterExit() { int argc = 1;