Focus reason
authorCaroline Chao <caroline.chao@digia.com>
Tue, 5 Mar 2013 11:00:19 +0000 (12:00 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 7 Mar 2013 10:58:50 +0000 (11:58 +0100)
When trying to do for example text handling it becomes
obvious that focus handling is not proper.

A mouse click focus should de-select text,
while a window change should preserve the selection.

Re-introduce focus reason.

Change-Id: I3322c976437cba68938d7c9188e549bdb499fa5a
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>

src/quick/items/qquickitem.cpp
src/quick/items/qquickitem.h
src/quick/items/qquicktextedit.cpp
src/quick/items/qquickwindow.cpp
src/quick/items/qquickwindow_p.h

index ad8a9d9..8f68f6f 100644 (file)
@@ -2083,7 +2083,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
             while (!scopeItem->isFocusScope() && scopeItem->parentItem())
                 scopeItem = scopeItem->parentItem();
             if (d->window) {
-                QQuickWindowPrivate::get(d->window)->clearFocusInScope(scopeItem, scopeFocusedItem,
+                QQuickWindowPrivate::get(d->window)->clearFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason,
                                                                 QQuickWindowPrivate::DontChangeFocusProperty);
                 if (scopeFocusedItem != this)
                     QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, true);
@@ -2146,7 +2146,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
                 emit scopeFocusedItem->focusChanged(false);
             } else {
                 if (d->window) {
-                    QQuickWindowPrivate::get(d->window)->setFocusInScope(scopeItem, scopeFocusedItem,
+                    QQuickWindowPrivate::get(d->window)->setFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason,
                                                                   QQuickWindowPrivate::DontChangeFocusProperty);
                 } else {
                     QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, true);
@@ -3772,29 +3772,44 @@ void QQuickItem::mapToItem(QQmlV8Function *args) const
 
 /*!
     \qmlmethod QtQuick2::Item::forceActiveFocus()
+    \overload
 
     Forces active focus on the item.
 
     This method sets focus on the item and ensures that all ancestor
     FocusScope objects in the object hierarchy are also given \l focus.
 
+    The reason for the focus change will be \a Qt::OtherFocusReason. Use
+    the overloaded method to specify the focus reason to enable better
+    handling of the focus change.
+
     \sa activeFocus
 */
+void QQuickItem::forceActiveFocus()
+{
+    forceActiveFocus(Qt::OtherFocusReason);
+}
+
 /*!
-    Forces active focus on the item.
+    \qmlmethod QtQuick2::Item::forceActiveFocus(Qt::FocusReason reason)
+
+    Forces active focus on the item with the given \a reason.
 
     This method sets focus on the item and ensures that all ancestor
     FocusScope objects in the object hierarchy are also given \l focus.
 
-    \sa activeFocus
+    \since 5.1
+
+    \sa activeFocus, Qt::FocusReason
 */
-void QQuickItem::forceActiveFocus()
+
+void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
 {
-    setFocus(true);
+    setFocus(true, reason);
     QQuickItem *parent = parentItem();
     while (parent) {
         if (parent->flags() & QQuickItem::ItemIsFocusScope) {
-            parent->setFocus(true);
+            parent->setFocus(true, reason);
         }
         parent = parent->parentItem();
     }
@@ -5081,7 +5096,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
             q->ungrabMouse();
         if (scope && !effectiveEnable && activeFocus) {
             windowPriv->clearFocusInScope(
-                    scope, q,  QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
+                    scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
         }
     }
 
@@ -5092,7 +5107,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
 
     if (window && scope && effectiveEnable && focus) {
         QQuickWindowPrivate::get(window)->setFocusInScope(
-                scope, q, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
+                scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
     }
 
     emit q->enabledChanged();
@@ -6006,6 +6021,11 @@ bool QQuickItem::hasFocus() const
 
 void QQuickItem::setFocus(bool focus)
 {
+    setFocus(focus, Qt::OtherFocusReason);
+}
+
+void QQuickItem::setFocus(bool focus, Qt::FocusReason reason)
+{
     Q_D(QQuickItem);
     if (d->focus == focus)
         return;
@@ -6017,9 +6037,9 @@ void QQuickItem::setFocus(bool focus)
             scope = scope->parentItem();
         if (d->window) {
             if (focus)
-                QQuickWindowPrivate::get(d->window)->setFocusInScope(scope, this);
+                QQuickWindowPrivate::get(d->window)->setFocusInScope(scope, this, reason);
             else
-                QQuickWindowPrivate::get(d->window)->clearFocusInScope(scope, this);
+                QQuickWindowPrivate::get(d->window)->clearFocusInScope(scope, this, reason);
         } else {
             // do the focus changes from setFocusInScope/clearFocusInScope that are
             // unrelated to a window
index e9c817a..7168169 100644 (file)
@@ -274,6 +274,7 @@ public:
     bool hasActiveFocus() const;
     bool hasFocus() const;
     void setFocus(bool);
+    void setFocus(bool focus, Qt::FocusReason reason);
     bool isFocusScope() const;
     QQuickItem *scopedFocusItem() const;
 
@@ -318,6 +319,7 @@ public:
     Q_INVOKABLE void mapFromItem(QQmlV8Function*) const;
     Q_INVOKABLE void mapToItem(QQmlV8Function*) const;
     Q_INVOKABLE void forceActiveFocus();
+    Q_INVOKABLE void forceActiveFocus(Qt::FocusReason reason);
     Q_INVOKABLE QQuickItem *childAt(qreal x, qreal y) const;
 
 #ifndef QT_NO_IM
index 015f52c..4ddb992 100644 (file)
@@ -1539,7 +1539,7 @@ void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
     d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
     if (d->focusOnPress){
         bool hadActiveFocus = hasActiveFocus();
-        forceActiveFocus();
+        forceActiveFocus(Qt::MouseFocusReason);
         // re-open input panel on press if already focused
 #ifndef QT_NO_IM
         if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
index 2e717a9..1732251 100644 (file)
@@ -224,17 +224,17 @@ void QQuickWindow::hideEvent(QHideEvent *)
 }
 
 /*! \reimp */
-void QQuickWindow::focusOutEvent(QFocusEvent *)
+void QQuickWindow::focusOutEvent(QFocusEvent *ev)
 {
     Q_D(QQuickWindow);
-    d->contentItem->setFocus(false);
+    d->contentItem->setFocus(false, ev->reason());
 }
 
 /*! \reimp */
-void QQuickWindow::focusInEvent(QFocusEvent *)
+void QQuickWindow::focusInEvent(QFocusEvent *ev)
 {
     Q_D(QQuickWindow);
-    d->contentItem->setFocus(true);
+    d->contentItem->setFocus(true, ev->reason());
     d->updateFocusItemTransform();
 }
 
@@ -608,7 +608,7 @@ void QQuickWindowPrivate::translateTouchEvent(QTouchEvent *touchEvent)
     touchEvent->setTouchPoints(touchPoints);
 }
 
-void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
+void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
 {
     Q_Q(QQuickWindow);
 
@@ -648,7 +648,7 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
 #endif
 
             activeFocusItem = 0;
-            QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
+            QFocusEvent event(QEvent::FocusOut, reason);
             q->sendEvent(oldActiveFocusItem, &event);
 
             QQuickItem *afi = oldActiveFocusItem;
@@ -695,7 +695,7 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
         }
         updateFocusItemTransform();
 
-        QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
+        QFocusEvent event(QEvent::FocusIn, reason);
         q->sendEvent(newActiveFocusItem, &event);
     }
 
@@ -705,7 +705,7 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
         notifyFocusChangesRecur(changed.data(), changed.count() - 1);
 }
 
-void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions options)
+void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
 {
     Q_Q(QQuickWindow);
 
@@ -745,7 +745,7 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
 #endif
 
         activeFocusItem = 0;
-        QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
+        QFocusEvent event(QEvent::FocusOut, reason);
         q->sendEvent(oldActiveFocusItem, &event);
 
         QQuickItem *afi = oldActiveFocusItem;
@@ -777,7 +777,7 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
         activeFocusItem = scope;
         updateFocusItemTransform();
 
-        QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
+        QFocusEvent event(QEvent::FocusIn, reason);
         q->sendEvent(newActiveFocusItem, &event);
     }
 
index f272f30..ab772ca 100644 (file)
@@ -163,8 +163,8 @@ public:
     };
     Q_DECLARE_FLAGS(FocusOptions, FocusOption)
 
-    void setFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
-    void clearFocusInScope(QQuickItem *scope, QQuickItem *item, FocusOptions = 0);
+    void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0);
+    void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0);
     static void notifyFocusChangesRecur(QQuickItem **item, int remaining);
 
     void updateFocusItemTransform();