aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickwindow.cpp31
-rw-r--r--tests/auto/quick/qquicktextinput/data/focusOnlyOneOnPress.qml32
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp41
3 files changed, 98 insertions, 6 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index ef534fe35d..14e7915dba 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -785,8 +785,10 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ QQuickItem *oldActiveFocusItem = 0;
QQuickItem *currentActiveFocusItem = activeFocusItem;
QQuickItem *newActiveFocusItem = 0;
+ bool sendFocusIn = false;
lastFocusReason = reason;
@@ -794,7 +796,6 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
// Does this change the active focus?
if (item == contentItem || scopePrivate->activeFocus) {
- QQuickItem *oldActiveFocusItem = 0;
oldActiveFocusItem = activeFocusItem;
if (item->isEnabled()) {
newActiveFocusItem = item;
@@ -813,8 +814,6 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
#endif
activeFocusItem = 0;
- QFocusEvent event(QEvent::FocusOut, reason);
- q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
while (afi && afi != scope) {
@@ -859,7 +858,19 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
afi = afi->parentItem();
}
updateFocusItemTransform();
+ sendFocusIn = true;
+ }
+
+ // Now that all the state is changed, emit signals & events
+ // We must do this last, as this process may result in further changes to
+ // focus.
+ if (oldActiveFocusItem) {
+ QFocusEvent event(QEvent::FocusOut, reason);
+ q->sendEvent(oldActiveFocusItem, &event);
+ }
+ // Make sure that the FocusOut didn't result in another focus change.
+ if (sendFocusIn && activeFocusItem == newActiveFocusItem) {
QFocusEvent event(QEvent::FocusIn, reason);
q->sendEvent(newActiveFocusItem, &event);
}
@@ -912,9 +923,6 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
activeFocusItem = 0;
if (oldActiveFocusItem) {
- QFocusEvent event(QEvent::FocusOut, reason);
- q->sendEvent(oldActiveFocusItem, &event);
-
QQuickItem *afi = oldActiveFocusItem;
while (afi && afi != scope) {
if (QQuickItemPrivate::get(afi)->activeFocus) {
@@ -944,7 +952,18 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
Q_ASSERT(newActiveFocusItem == scope);
activeFocusItem = scope;
updateFocusItemTransform();
+ }
+
+ // Now that all the state is changed, emit signals & events
+ // We must do this last, as this process may result in further changes to
+ // focus.
+ if (oldActiveFocusItem) {
+ QFocusEvent event(QEvent::FocusOut, reason);
+ q->sendEvent(oldActiveFocusItem, &event);
+ }
+ // Make sure that the FocusOut didn't result in another focus change.
+ if (newActiveFocusItem && activeFocusItem == newActiveFocusItem) {
QFocusEvent event(QEvent::FocusIn, reason);
q->sendEvent(newActiveFocusItem, &event);
}
diff --git a/tests/auto/quick/qquicktextinput/data/focusOnlyOneOnPress.qml b/tests/auto/quick/qquicktextinput/data/focusOnlyOneOnPress.qml
new file mode 100644
index 0000000000..037b36c8ff
--- /dev/null
+++ b/tests/auto/quick/qquicktextinput/data/focusOnlyOneOnPress.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 400
+ height: 400
+
+ Column {
+ spacing: 5
+ TextInput {
+ objectName: "first"
+ onEditingFinished: second.focus = true
+ width: 100
+ Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 }
+ }
+ TextInput {
+ id: second
+ objectName: "second"
+ onEditingFinished: third.focus = true
+ width: 100
+ Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 }
+ }
+ TextInput {
+ objectName: "third"
+ id: third
+ width: 100
+ Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 }
+ }
+ Component.onCompleted: {
+ second.focus = true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 70d3906ff3..e57a95184c 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -158,6 +158,7 @@ private slots:
#endif
void readOnly();
void focusOnPress();
+ void focusOnPressOnlyOneItem();
void openInputPanel();
void setHAlignClearCache();
@@ -3457,6 +3458,46 @@ void tst_qquicktextinput::focusOnPress()
QTest::mouseRelease(&window, Qt::LeftButton, noModifiers);
}
+void tst_qquicktextinput::focusOnPressOnlyOneItem()
+{
+ QQuickView window(testFileUrl("focusOnlyOneOnPress.qml"));
+ window.show();
+ window.requestActivate();
+ QTest::qWaitForWindowActive(&window);
+
+ QQuickTextInput *first = window.rootObject()->findChild<QQuickTextInput*>("first");
+ QQuickTextInput *second = window.rootObject()->findChild<QQuickTextInput*>("second");
+ QQuickTextInput *third = window.rootObject()->findChild<QQuickTextInput*>("third");
+
+ // second is focused onComplete
+ QVERIFY(second->hasActiveFocus());
+
+ // and first will try focus when we press it
+ QVERIFY(first->focusOnPress());
+
+ // write some text to start editing
+ QTest::keyClick(&window, Qt::Key_A);
+
+ // click the first input. naturally, we are giving focus on press, but
+ // second's editingFinished also attempts to assign focus. lastly, focus
+ // should bounce back to second from first's editingFinished signal.
+ //
+ // this is a contrived example to be sure, but at the end of this, the
+ // important thing is that only one thing should have activeFocus.
+ Qt::KeyboardModifiers noModifiers = 0;
+ QTest::mousePress(&window, Qt::LeftButton, noModifiers, QPoint(10, 10));
+
+ // make sure the press is processed.
+ QGuiApplication::processEvents();
+
+ QVERIFY(second->hasActiveFocus()); // make sure it's still there
+ QVERIFY(!third->hasActiveFocus()); // make sure it didn't end up anywhere else
+ QVERIFY(!first->hasActiveFocus()); // make sure it didn't end up anywhere else
+
+ // reset state
+ QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, QPoint(10, 10));
+}
+
void tst_qquicktextinput::openInputPanel()
{
PlatformInputContext platformInputContext;