From 7eb5f8a54bdcf0520a7aa0a2874a059060866097 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 1 Feb 2018 11:48:45 +0100 Subject: QQuickControl: respect click focus policy for focus scopes If a focus scope explicitly requests click focus, make it gain active focus by clearing the sub-focus child. Pane { focusPolicy: Qt.ClickFocus TextField { } } [ChangeLog][Controls][Control] Fixed focus scope controls, such as Frame, GroupBox, Page, and Pane, to respect click focus policy by clearing a potential sub-focus child. This makes it possible to close the virtual keyboard by clicking the background of a Pane that has Qt.ClickFocus set as its focusPolicy, for example. Task-number: QTBUG-66133 Change-Id: I582f3c66aa6f11e229d89c4f610fae3c6259104d Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickcontrol.cpp | 12 +++++- tests/auto/focus/tst_focus.cpp | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 8d571c34..020997b1 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -160,11 +160,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) @@ -181,7 +189,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; } diff --git a/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp index 3d4a8875..ad7578d0 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,75 @@ void tst_focus::visualFocus() QVERIFY(!button->property("showFocus").toBool()); } +void tst_focus::scope_data() +{ + QTest::addColumn("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 window(qobject_cast(component.create())); + QVERIFY2(window, qPrintable(component.errorString())); + + QQuickControl *control = qobject_cast(window->contentItem()->childItems().first()); + QVERIFY(control); + + control->setFocusPolicy(Qt::WheelFocus); + control->setAcceptedMouseButtons(Qt::LeftButton); + + QQuickItem *child = window->property("child").value(); + 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 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()); +} + QTEST_MAIN(tst_focus) #include "tst_focus.moc" -- cgit v1.2.3 From f301decbe39d253cc979774e2f32cde9c1212e4c Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 5 Feb 2018 16:17:31 +0100 Subject: Popup: fix restoring focus for popups that did not request focus When a popup closes, if it has active focus, it should restore focus back to where it was regardless of whether the popup originally requested focus. Even if a popup does not request focus on open, it may gain focus programmatically or when a control with click-focus is clicked, for example. Task-number: QTBUG-66113 Change-Id: I9a7c467abe781bbef390d74898d13b9a30b2695b Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickpopup.cpp | 9 ++++----- tests/auto/qquickpopup/tst_qquickpopup.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index bb5ce660..0ef4bd64 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -443,12 +443,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; emit q->aboutToHide(); } diff --git a/tests/auto/qquickpopup/tst_qquickpopup.cpp b/tests/auto/qquickpopup/tst_qquickpopup.cpp index 3f4b2d13..b113e5ec 100644 --- a/tests/auto/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/qquickpopup/tst_qquickpopup.cpp @@ -521,6 +521,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() -- cgit v1.2.3 From cf719053689c32967084fdac54b118e44d0b7b67 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 2 Feb 2018 12:03:45 +0100 Subject: QQuickControl: respect wheel focus policy for focus scopes [ChangeLog][Controls][Control] Fixed focus scope controls to respect wheel focus policy. Task-number: QTBUG-66133 Change-Id: If963feba4b6e59b87ca54af5f6606805093eb0cc Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickcontrol.cpp | 2 +- tests/auto/focus/tst_focus.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 020997b1..4bf0a867 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -1459,7 +1459,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/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp index ad7578d0..958b996b 100644 --- a/tests/auto/focus/tst_focus.cpp +++ b/tests/auto/focus/tst_focus.cpp @@ -396,6 +396,17 @@ void tst_focus::scope() 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) -- cgit v1.2.3 From 44d02e3f0cf4db7e6d426c75de459019c574500a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 7 Feb 2018 20:20:02 +0100 Subject: Bump version Change-Id: I441fd7bf775a5eb02037fb51bd49b2f8b9efde96 --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 8dc3e6e2..4518dc99 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ DEFINES += QT_NO_FOREACH QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 5.9.4 +MODULE_VERSION = 5.9.5 -- cgit v1.2.3