aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/controls/universal/ApplicationWindow.qml3
-rw-r--r--src/templates/qquickcontrol.cpp48
-rw-r--r--src/templates/qquickcontrol_p.h4
-rw-r--r--tests/auto/focus/tst_focus.cpp34
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)