diff options
-rw-r--r-- | src/imports/controls/universal/ApplicationWindow.qml | 3 | ||||
-rw-r--r-- | src/templates/qquickcontrol.cpp | 48 | ||||
-rw-r--r-- | src/templates/qquickcontrol_p.h | 4 | ||||
-rw-r--r-- | tests/auto/focus/tst_focus.cpp | 34 |
4 files changed, 82 insertions, 7 deletions
diff --git a/src/imports/controls/universal/ApplicationWindow.qml b/src/imports/controls/universal/ApplicationWindow.qml index 3113e748..3acc70db 100644 --- a/src/imports/controls/universal/ApplicationWindow.qml +++ b/src/imports/controls/universal/ApplicationWindow.qml @@ -52,7 +52,6 @@ T.ApplicationWindow { parent: window.activeFocusControl width: parent ? parent.width : 0 height: parent ? parent.height : 0 - visible: parent && !!parent.useSystemFocusVisuals - && (parent.focusReason === Qt.TabFocusReason || parent.focusReason === Qt.BacktabFocusReason) + visible: parent && !!parent.useSystemFocusVisuals && !!parent.activeKeyFocus } } diff --git a/src/templates/qquickcontrol.cpp b/src/templates/qquickcontrol.cpp index 71e783e7..2bee0ed2 100644 --- a/src/templates/qquickcontrol.cpp +++ b/src/templates/qquickcontrol.cpp @@ -73,6 +73,11 @@ QT_BEGIN_NAMESPACE \labs */ +static bool isKeyFocusReason(Qt::FocusReason reason) +{ + return reason == Qt::TabFocusReason || reason == Qt::BacktabFocusReason || reason == Qt::ShortcutFocusReason; +} + QQuickControlPrivate::QQuickControlPrivate() : hasTopPadding(false), hasLeftPadding(false), hasRightPadding(false), hasBottomPadding(false), hasLocale(false), hovered(false), wheelEnabled(false), padding(0), topPadding(0), leftPadding(0), rightPadding(0), bottomPadding(0), spacing(0), @@ -379,10 +384,20 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem:: { Q_D(QQuickControl); QQuickItem::itemChange(change, value); - if (change == ItemParentHasChanged && value.item) { - d->resolveFont(); - if (!d->hasLocale) - d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false + switch (change) { + case ItemParentHasChanged: + if (value.item) { + d->resolveFont(); + if (!d->hasLocale) + d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false + } + break; + case ItemActiveFocusHasChanged: + if (isKeyFocusReason(d->focusReason)) + emit activeKeyFocusChanged(); + break; + default: + break; } } @@ -786,7 +801,7 @@ void QQuickControl::setFocusPolicy(Qt::FocusPolicy policy) \value Qt.MenuBarFocusReason The menu bar took focus. \value Qt.OtherFocusReason Another reason, usually application-specific. - \sa Item::activeFocus + \sa activeKeyFocus, Item::activeFocus */ Qt::FocusReason QQuickControl::focusReason() const { @@ -800,8 +815,31 @@ void QQuickControl::setFocusReason(Qt::FocusReason reason) if (d->focusReason == reason) return; + Qt::FocusReason oldReason = d->focusReason; d->focusReason = reason; emit focusReasonChanged(); + if (d->activeFocus && isKeyFocusReason(oldReason) != isKeyFocusReason(reason)) + emit activeKeyFocusChanged(); +} + +/*! + \qmlproperty bool Qt.labs.controls::Control::activeKeyFocus + \readonly + + This property holds whether the control has active focus and the focus + reason is either \c Qt.TabFocusReason, \c Qt.BacktabFocusReason, or + \c Qt.ShortcutFocusReason. + + In general, for visualizing key focus, this property is preferred over + \l Item::activeFocus. This ensures that key focus is only visualized when + interacting with keys - not when interacting via touch or mouse. + + \sa focusReason, Item::activeFocus +*/ +bool QQuickControl::hasActiveKeyFocus() const +{ + Q_D(const QQuickControl); + return d->activeFocus && isKeyFocusReason(d->focusReason); } /*! diff --git a/src/templates/qquickcontrol_p.h b/src/templates/qquickcontrol_p.h index e393e827..4cd0b77c 100644 --- a/src/templates/qquickcontrol_p.h +++ b/src/templates/qquickcontrol_p.h @@ -72,6 +72,7 @@ class Q_QUICKTEMPLATES_EXPORT QQuickControl : public QQuickItem Q_PROPERTY(bool mirrored READ isMirrored NOTIFY mirroredChanged FINAL) Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy NOTIFY focusPolicyChanged FINAL) Q_PROPERTY(Qt::FocusReason focusReason READ focusReason WRITE setFocusReason NOTIFY focusReasonChanged FINAL) + Q_PROPERTY(bool activeKeyFocus READ hasActiveKeyFocus NOTIFY activeKeyFocusChanged FINAL) Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged FINAL) Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged FINAL) Q_PROPERTY(bool wheelEnabled READ isWheelEnabled WRITE setWheelEnabled NOTIFY wheelEnabledChanged FINAL) @@ -124,6 +125,8 @@ public: Qt::FocusReason focusReason() const; void setFocusReason(Qt::FocusReason reason); + bool hasActiveKeyFocus() const; + bool isHovered() const; void setHovered(bool hovered); @@ -153,6 +156,7 @@ Q_SIGNALS: void mirroredChanged(); void focusPolicyChanged(); void focusReasonChanged(); + void activeKeyFocusChanged(); void hoveredChanged(); void hoverEnabledChanged(); void wheelEnabledChanged(); diff --git a/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp index 18012a42..f058f137 100644 --- a/tests/auto/focus/tst_focus.cpp +++ b/tests/auto/focus/tst_focus.cpp @@ -132,6 +132,9 @@ void tst_focus::policy() QQuickControl *control = qobject_cast<QQuickControl *>(window->contentItem()->childItems().first()); QVERIFY(control); + QVERIFY(!control->hasActiveFocus()); + QVERIFY(!control->hasActiveKeyFocus()); + window->show(); window->requestActivate(); QVERIFY(QTest::qWaitForWindowActive(window.data())); @@ -146,14 +149,27 @@ void tst_focus::policy() QCOMPARE(control->focusPolicy(), Qt::TabFocus); QCOMPARE(control->activeFocusOnTab(), true); + // Qt::TabFocus + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); + QTest::keyClick(window.data(), Qt::Key_Tab); + QVERIFY(control->hasActiveFocus()); + QVERIFY(control->hasActiveKeyFocus()); + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusBehavior(-1)); + + // reset + control->setFocus(false); + QVERIFY(!control->hasActiveFocus()); + // Qt::ClickFocus QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(control->width() / 2, control->height() / 2)); QVERIFY(!control->hasActiveFocus()); + QVERIFY(!control->hasActiveKeyFocus()); control->setFocusPolicy(Qt::ClickFocus); QCOMPARE(control->focusPolicy(), Qt::ClickFocus); QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(control->width() / 2, control->height() / 2)); QVERIFY(control->hasActiveFocus()); + QVERIFY(!control->hasActiveKeyFocus()); // reset control->setFocus(false); @@ -163,12 +179,14 @@ void tst_focus::policy() QWheelEvent wheelEvent(QPoint(control->width() / 2, control->height() / 2), 10, Qt::NoButton, Qt::NoModifier); QGuiApplication::sendEvent(control, &wheelEvent); QVERIFY(!control->hasActiveFocus()); + QVERIFY(!control->hasActiveKeyFocus()); control->setFocusPolicy(Qt::WheelFocus); QCOMPARE(control->focusPolicy(), Qt::WheelFocus); QGuiApplication::sendEvent(control, &wheelEvent); QVERIFY(control->hasActiveFocus()); + QVERIFY(!control->hasActiveKeyFocus()); } void tst_focus::reason_data() @@ -205,9 +223,25 @@ void tst_focus::reason() QVERIFY(control->hasActiveFocus()); QCOMPARE(control->property("focusReason").toInt(), int(Qt::MouseFocusReason)); + QEXPECT_FAIL("TextArea", "TODO: TextArea::activeKeyFocus?", Continue); + QEXPECT_FAIL("TextField", "TODO: TextField::activeKeyFocus?", Continue); + QCOMPARE(control->property("activeKeyFocus"), QVariant(false)); + window->contentItem()->forceActiveFocus(Qt::TabFocusReason); QVERIFY(!control->hasActiveFocus()); QCOMPARE(control->property("focusReason").toInt(), int(Qt::TabFocusReason)); + + QEXPECT_FAIL("TextArea", "", Continue); + QEXPECT_FAIL("TextField", "", Continue); + QCOMPARE(control->property("activeKeyFocus"), QVariant(false)); + + control->forceActiveFocus(Qt::TabFocusReason); + QVERIFY(control->hasActiveFocus()); + QCOMPARE(control->property("focusReason").toInt(), int(Qt::TabFocusReason)); + + QEXPECT_FAIL("TextArea", "", Continue); + QEXPECT_FAIL("TextField", "", Continue); + QCOMPARE(control->property("activeKeyFocus"), QVariant(true)); } QTEST_MAIN(tst_focus) |