diff options
author | Robin Burchell <robin.burchell@viroteck.net> | 2015-02-09 01:16:51 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@theqtcompany.com> | 2016-05-23 07:12:40 +0000 |
commit | e7da97bf71108a0acd72629e383f884e2d756477 (patch) | |
tree | 2bd207a2440584a884ff0176f166c262f970f298 /src | |
parent | a82094b63b8993630c37f7a71dac19d3f96b2804 (diff) |
QQuickWindow: Only send focus events to items that actually gain focus
Sending focus events may result in further changes to which item actually has
focus, so we cannot blindly send the focus events without first checking that it
hasn't subsequently changed.
To accomplish this, we delay sending events as long as possible, ensuring that
all necessary bookkeeping is done first to ensure internal consistency.
Task-number: QTBUG-40145
Change-Id: I7d93b3f8e3fea2ecce2151c88c29601deda12453
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 31 |
1 files changed, 25 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); } |