aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quicktemplates2/qquickcontrol.cpp14
-rw-r--r--src/quicktemplates2/qquickpopup.cpp9
-rw-r--r--tests/auto/focus/tst_focus.cpp83
-rw-r--r--tests/auto/qquickpopup/tst_qquickpopup.cpp10
4 files changed, 108 insertions, 8 deletions
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index 67c89729..1c9bcfd5 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -159,11 +159,19 @@ bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point)
}
#endif
+static void setActiveFocus(QQuickControl *control, Qt::FocusReason reason)
+{
+ QQuickControlPrivate *d = QQuickControlPrivate::get(control);
+ if (d->subFocusItem && d->window && d->flags & QQuickItem::ItemIsFocusScope)
+ QQuickWindowPrivate::get(d->window)->clearFocusInScope(control, d->subFocusItem, reason);
+ control->forceActiveFocus(reason);
+}
+
void QQuickControlPrivate::handlePress(const QPointF &)
{
Q_Q(QQuickControl);
if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && !QGuiApplication::styleHints()->setFocusOnTouchRelease())
- q->forceActiveFocus(Qt::MouseFocusReason);
+ setActiveFocus(q, Qt::MouseFocusReason);
}
void QQuickControlPrivate::handleMove(const QPointF &point)
@@ -180,7 +188,7 @@ void QQuickControlPrivate::handleRelease(const QPointF &)
{
Q_Q(QQuickControl);
if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && QGuiApplication::styleHints()->setFocusOnTouchRelease())
- q->forceActiveFocus(Qt::MouseFocusReason);
+ setActiveFocus(q, Qt::MouseFocusReason);
touchId = -1;
}
@@ -1582,7 +1590,7 @@ void QQuickControl::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickControl);
if ((d->focusPolicy & Qt::WheelFocus) == Qt::WheelFocus)
- forceActiveFocus(Qt::MouseFocusReason);
+ setActiveFocus(this, Qt::MouseFocusReason);
event->setAccepted(d->wheelEnabled);
}
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index 1a4c90a4..207a886b 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -450,12 +450,11 @@ bool QQuickPopupPrivate::prepareExitTransition()
return false;
if (transitionState != ExitTransition) {
- if (focus) {
- // The setFocus(false) call below removes any active focus before we're
- // able to check it in finalizeExitTransition.
- hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus();
+ // The setFocus(false) call below removes any active focus before we're
+ // able to check it in finalizeExitTransition.
+ hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus();
+ if (focus)
popupItem->setFocus(false);
- }
transitionState = ExitTransition;
hideOverlay();
emit q->aboutToHide();
diff --git a/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp
index 3d4a8875..958b996b 100644
--- a/tests/auto/focus/tst_focus.cpp
+++ b/tests/auto/focus/tst_focus.cpp
@@ -67,6 +67,9 @@ private slots:
void reason();
void visualFocus();
+
+ void scope_data();
+ void scope();
};
void tst_focus::initTestCase()
@@ -326,6 +329,86 @@ void tst_focus::visualFocus()
QVERIFY(!button->property("showFocus").toBool());
}
+void tst_focus::scope_data()
+{
+ QTest::addColumn<QString>("name");
+
+ QTest::newRow("Frame") << "Frame";
+ QTest::newRow("GroupBox") << "Frame";
+ QTest::newRow("Page") << "Page";
+ QTest::newRow("Pane") << "Pane";
+ QTest::newRow("StackView") << "StackView";
+}
+
+void tst_focus::scope()
+{
+ QFETCH(QString, name);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(QString("import QtQuick 2.9; import QtQuick.Controls 2.2; ApplicationWindow { property alias child: child; width: 100; height: 100; %1 { anchors.fill: parent; Item { id: child; width: 10; height: 10 } } }").arg(name).toUtf8(), QUrl());
+
+ QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(component.create()));
+ QVERIFY2(window, qPrintable(component.errorString()));
+
+ QQuickControl *control = qobject_cast<QQuickControl *>(window->contentItem()->childItems().first());
+ QVERIFY(control);
+
+ control->setFocusPolicy(Qt::WheelFocus);
+ control->setAcceptedMouseButtons(Qt::LeftButton);
+
+ QQuickItem *child = window->property("child").value<QQuickItem *>();
+ QVERIFY(child);
+
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ struct TouchDeviceDeleter
+ {
+ static inline void cleanup(QTouchDevice *device)
+ {
+ QWindowSystemInterface::unregisterTouchDevice(device);
+ delete device;
+ }
+ };
+
+ QScopedPointer<QTouchDevice, TouchDeviceDeleter> device(new QTouchDevice);
+ device->setType(QTouchDevice::TouchScreen);
+ QWindowSystemInterface::registerTouchDevice(device.data());
+
+ child->forceActiveFocus();
+ QVERIFY(child->hasActiveFocus());
+ QVERIFY(control->hasActiveFocus());
+
+ // Qt::ClickFocus (mouse)
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(control->width() / 2, control->height() / 2));
+ QVERIFY(!child->hasActiveFocus());
+ QVERIFY(control->hasActiveFocus());
+
+ // reset
+ child->forceActiveFocus();
+ QVERIFY(child->hasActiveFocus());
+ QVERIFY(control->hasActiveFocus());
+
+ // Qt::ClickFocus (touch)
+ QTest::touchEvent(window.data(), device.data()).press(0, QPoint(control->width() / 2, control->height() / 2));
+ QTest::touchEvent(window.data(), device.data()).release(0, QPoint(control->width() / 2, control->height() / 2));
+ QVERIFY(!child->hasActiveFocus());
+ QVERIFY(control->hasActiveFocus());
+
+ // reset
+ child->forceActiveFocus();
+ QVERIFY(child->hasActiveFocus());
+ QVERIFY(control->hasActiveFocus());
+
+ // Qt::WheelFocus
+ QWheelEvent wheelEvent(QPoint(control->width() / 2, control->height() / 2), 10, Qt::NoButton, Qt::NoModifier);
+ QGuiApplication::sendEvent(control, &wheelEvent);
+ QVERIFY(!child->hasActiveFocus());
+ QVERIFY(control->hasActiveFocus());
+}
+
QTEST_MAIN(tst_focus)
#include "tst_focus.moc"
diff --git a/tests/auto/qquickpopup/tst_qquickpopup.cpp b/tests/auto/qquickpopup/tst_qquickpopup.cpp
index a1e5e246..550655ef 100644
--- a/tests/auto/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/qquickpopup/tst_qquickpopup.cpp
@@ -565,6 +565,16 @@ void tst_QQuickPopup::activeFocusOnClose1()
nonFocusedPopup->close();
QVERIFY(!nonFocusedPopup->isVisible());
QVERIFY(focusedPopup->hasActiveFocus());
+
+ // QTBUG-66113: force active focus on a popup that did not request focus
+ nonFocusedPopup->open();
+ nonFocusedPopup->forceActiveFocus();
+ QVERIFY(nonFocusedPopup->isVisible());
+ QVERIFY(nonFocusedPopup->hasActiveFocus());
+
+ nonFocusedPopup->close();
+ QVERIFY(!nonFocusedPopup->isVisible());
+ QVERIFY(focusedPopup->hasActiveFocus());
}
void tst_QQuickPopup::activeFocusOnClose2()