diff options
-rw-r--r-- | src/quicktemplates2/qquickcontrol.cpp | 14 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 9 | ||||
-rw-r--r-- | tests/auto/focus/tst_focus.cpp | 83 | ||||
-rw-r--r-- | tests/auto/qquickpopup/tst_qquickpopup.cpp | 10 |
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() |