diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-07-22 09:56:04 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-07-23 21:02:45 +0200 |
commit | bbcbb7c78f2f07e6c5e380ec5c018ac2a7abf292 (patch) | |
tree | d09275a89f3924935b2acdf640209af17cf8cb3a /tests/auto/quick/qquicktextinput | |
parent | 66a5167dab35aedf1c7bef3e0f8deea903c12a5e (diff) |
Pass the focus reason through to the control on mouse press
Otherwise, a TextInput item will always receive OtherFocusReason when
clicking into it.
Add a test that simulates focus changes with mouse and keys, records
the incoming focus events and verifies the correct focus reason is set
in the event. Qt Quick provides no mechanism to access the focus reason
from within QML (onActiveFocusChange only has a bool parameter, the
focusReason property exists only in QtQuickControl).
Task-number: QTBUG-75862
Pick-to: 6.2 6.1 5.15
Change-Id: Ifea95c7ef2ac88c6c8e8bbdc8d2dbe5205ff922e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/quick/qquicktextinput')
-rw-r--r-- | tests/auto/quick/qquicktextinput/data/focusReason.qml | 39 | ||||
-rw-r--r-- | tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp | 80 |
2 files changed, 119 insertions, 0 deletions
diff --git a/tests/auto/quick/qquicktextinput/data/focusReason.qml b/tests/auto/quick/qquicktextinput/data/focusReason.qml new file mode 100644 index 0000000000..7ac913d363 --- /dev/null +++ b/tests/auto/quick/qquicktextinput/data/focusReason.qml @@ -0,0 +1,39 @@ +import QtQuick 2.2 + +Rectangle { + width: 400 + height: 400 + + Column { + spacing: 5 + TextInput { + id: first + objectName: "first" + width: 100 + Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 } + KeyNavigation.backtab: third + KeyNavigation.tab: second + KeyNavigation.down: second + } + TextInput { + id: second + objectName: "second" + width: 100 + Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 } + KeyNavigation.up: first + KeyNavigation.backtab: first + KeyNavigation.tab: third + } + TextInput { + objectName: "third" + id: third + width: 100 + Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 } + KeyNavigation.backtab: second + KeyNavigation.tab: first + } + Component.onCompleted: { + first.focus = true + } + } +} diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index eada215781..f61be67107 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -239,6 +239,8 @@ private slots: void QTBUG_77814_InsertRemoveNoSelection(); void checkCursorDelegateWhenPaddingChanged(); + + void focusReason(); private: void simulateKeys(QWindow *window, const QList<Key> &keys); #if QT_CONFIG(shortcut) @@ -7053,6 +7055,84 @@ void tst_qquicktextinput::checkCursorDelegateWhenPaddingChanged() QCOMPARE(cursorDelegate->y(), textInput->topPadding()); } +/*! + Verifies that TextInput items get focus in/out events with the + correct focus reason set. + + Up and Down keys translates to Backtab and Tab focus reasons. + + See QTBUG-75862. +*/ +void tst_qquicktextinput::focusReason() +{ + QQuickView view; + view.setSource(testFileUrl("focusReason.qml")); + + QQuickTextInput *first = view.rootObject()->findChild<QQuickTextInput *>("first"); + QQuickTextInput *second = view.rootObject()->findChild<QQuickTextInput *>("second"); + QQuickTextInput *third = view.rootObject()->findChild<QQuickTextInput *>("third"); + QVERIFY(first && second && third); + + class FocusEventFilter : public QObject + { + public: + using QObject::QObject; + + QHash<QObject*, Qt::FocusReason> lastFocusReason; + protected: + bool eventFilter(QObject *o, QEvent *e) + { + if (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut) { + QFocusEvent *fe = static_cast<QFocusEvent*>(e); + lastFocusReason[o] = fe->reason(); + } + return QObject::eventFilter(o, e); + } + } eventFilter; + first->installEventFilter(&eventFilter); + second->installEventFilter(&eventFilter); + third->installEventFilter(&eventFilter); + + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QCOMPARE(qApp->focusObject(), first); + // on some platforms we don't get ActiveWindowFocusReason; tolerate this, + // it's not what we are testing in this test + if (eventFilter.lastFocusReason[first] != Qt::ActiveWindowFocusReason) { + QEXPECT_FAIL("", qPrintable(QString("No window activation event on the %1 platform") + .arg(QGuiApplication::platformName())), + Continue); + } + QCOMPARE(eventFilter.lastFocusReason[first], Qt::ActiveWindowFocusReason); + + QTest::mouseClick(&view, Qt::LeftButton, {}, + (second->boundingRect().center() + second->position()).toPoint()); + QTRY_COMPARE(qApp->focusObject(), second); + QCOMPARE(eventFilter.lastFocusReason[first], Qt::MouseFocusReason); + QCOMPARE(eventFilter.lastFocusReason[second], Qt::MouseFocusReason); + + QTest::keyClick(&view, Qt::Key_Tab); + QCOMPARE(qApp->focusObject(), third); + QCOMPARE(eventFilter.lastFocusReason[second], Qt::TabFocusReason); + QCOMPARE(eventFilter.lastFocusReason[third], Qt::TabFocusReason); + + QTest::keyClick(&view, Qt::Key_Backtab); + QCOMPARE(qApp->focusObject(), second); + QCOMPARE(eventFilter.lastFocusReason[third], Qt::BacktabFocusReason); + QCOMPARE(eventFilter.lastFocusReason[second], Qt::BacktabFocusReason); + + QTest::keyClick(&view, Qt::Key_Up); + QCOMPARE(qApp->focusObject(), first); + QCOMPARE(eventFilter.lastFocusReason[second], Qt::BacktabFocusReason); + QCOMPARE(eventFilter.lastFocusReason[first], Qt::BacktabFocusReason); + + QTest::keyClick(&view, Qt::Key_Down); + QCOMPARE(qApp->focusObject(), second); + QCOMPARE(eventFilter.lastFocusReason[second], Qt::TabFocusReason); + QCOMPARE(eventFilter.lastFocusReason[first], Qt::TabFocusReason); +} + QTEST_MAIN(tst_qquicktextinput) #include "tst_qquicktextinput.moc" |