Notify about the focus reason
authorBerthold Krevert <berthold.krevert@basyskom.com>
Fri, 2 May 2014 13:18:25 +0000 (15:18 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 6 May 2014 16:39:03 +0000 (18:39 +0200)
KeyNavigation sets the focus reason always to Qt::OtherFocusReason. This
should be changed at least for tab and backtab navigation.

Change-Id: I27c654a202e2a80449dd5420460e413ca9cff75e
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Reviewed-by: Liang Qi <liang.qi@digia.com>
src/quick/items/qquickitem.cpp
src/quick/items/qquickitem_p.h
tests/auto/quick/qquickitem2/tst_qquickitem.cpp

index 7173ad3..1f505f8 100644 (file)
@@ -657,13 +657,13 @@ void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
         break;
     case Qt::Key_Tab:
         if (d->tab) {
-            setFocusNavigation(d->tab, "tab");
+            setFocusNavigation(d->tab, "tab", Qt::TabFocusReason);
             event->accept();
         }
         break;
     case Qt::Key_Backtab:
         if (d->backtab) {
-            setFocusNavigation(d->backtab, "backtab");
+            setFocusNavigation(d->backtab, "backtab", Qt::BacktabFocusReason);
             event->accept();
         }
         break;
@@ -725,14 +725,15 @@ void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
     if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
 }
 
-void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir)
+void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir,
+                                                     Qt::FocusReason reason)
 {
     QQuickItem *initialItem = currentItem;
     bool isNextItem = false;
     do {
         isNextItem = false;
         if (currentItem->isVisible() && currentItem->isEnabled()) {
-            currentItem->forceActiveFocus(Qt::OtherFocusReason);
+            currentItem->forceActiveFocus(reason);
         } else {
             QObject *attached =
                 qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(currentItem, false);
index 96cb9e8..1bd999e 100644 (file)
@@ -686,7 +686,8 @@ Q_SIGNALS:
 private:
     virtual void keyPressed(QKeyEvent *event, bool post);
     virtual void keyReleased(QKeyEvent *event, bool post);
-    void setFocusNavigation(QQuickItem *currentItem, const char *dir);
+    void setFocusNavigation(QQuickItem *currentItem, const char *dir,
+                            Qt::FocusReason reason = Qt::OtherFocusReason);
 };
 
 class QQuickLayoutMirroringAttached : public QObject
index 2de7fa1..10f4aa2 100644 (file)
@@ -88,6 +88,7 @@ private slots:
     void keyNavigation_RightToLeft();
     void keyNavigation_skipNotVisible();
     void keyNavigation_implicitSetting();
+    void keyNavigation_focusReason();
     void layoutMirroring();
     void layoutMirroringIllegalParent();
     void smooth();
@@ -214,6 +215,21 @@ public:
     int mKey;
 };
 
+class FocusEventFilter : public QObject
+{
+protected:
+    bool eventFilter(QObject *watched, QEvent *event) {
+        if ((event->type() == QEvent::FocusIn) ||  (event->type() == QEvent::FocusOut)) {
+            QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
+            lastFocusReason = focusEvent->reason();
+            return false;
+        } else
+            return QObject::eventFilter(watched, event);
+    }
+public:
+    Qt::FocusReason lastFocusReason;
+};
+
 QML_DECLARE_TYPE(KeyTestItem);
 
 class HollowTestItem : public QQuickItem
@@ -1754,6 +1770,62 @@ void tst_QQuickItem::keyNavigation_implicitSetting()
     delete window;
 }
 
+void tst_QQuickItem::keyNavigation_focusReason()
+{
+    QQuickView *window = new QQuickView(0);
+    window->setBaseSize(QSize(240,320));
+
+    FocusEventFilter focusEventFilter;
+
+    window->setSource(testFileUrl("keynavigationtest.qml"));
+    window->show();
+    window->requestActivate();
+
+    QVERIFY(QTest::qWaitForWindowActive(window));
+    QVERIFY(QGuiApplication::focusWindow() == window);
+
+    // install event filter on first item
+    QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
+    QVERIFY(item);
+    QVERIFY(item->hasActiveFocus());
+    item->installEventFilter(&focusEventFilter);
+
+    //install event filter on second item
+    item = findItem<QQuickItem>(window->rootObject(), "item2");
+    QVERIFY(item);
+    item->installEventFilter(&focusEventFilter);
+
+    //install event filter on third item
+    item = findItem<QQuickItem>(window->rootObject(), "item3");
+    QVERIFY(item);
+    item->installEventFilter(&focusEventFilter);
+
+    //install event filter on last item
+    item = findItem<QQuickItem>(window->rootObject(), "item4");
+    QVERIFY(item);
+    item->installEventFilter(&focusEventFilter);
+
+    // tab
+    QKeyEvent key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+    QGuiApplication::sendEvent(window, &key);
+    QVERIFY(key.isAccepted());
+    QCOMPARE(focusEventFilter.lastFocusReason, Qt::TabFocusReason);
+
+    // backtab
+    key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+    QGuiApplication::sendEvent(window, &key);
+    QVERIFY(key.isAccepted());
+    QCOMPARE(focusEventFilter.lastFocusReason, Qt::BacktabFocusReason);
+
+    // some arbitrary cursor key
+    key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+    QGuiApplication::sendEvent(window, &key);
+    QVERIFY(key.isAccepted());
+    QCOMPARE(focusEventFilter.lastFocusReason, Qt::OtherFocusReason);
+
+    delete window;
+}
+
 void tst_QQuickItem::smooth()
 {
     QQmlComponent component(&engine);