From 211014bfcac08ae763f8b8c8497425c48eac6a77 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 19 Apr 2017 14:02:32 +0200 Subject: QQuickControl: implement focus handling on touch QQuickControl::focusPolicy was only managed in mousePressEvent() and mouseReleaseEvent(). All controls call the base class implementations of these event handlers to get the focus policy handling "for free". Move focus policy handling to handlePress() and handleRelease() that can be re-used for touch events, and make sure that various controls call the base class implementation of touch event handlers. There's still a bit of duplication in QQuickControl::touchEvent() and the overridden handlers in sub-classes, but this will be improved step by step. QQuickControlPrivate::handlePress/Move/Release/Ungrab() are planned to be made virtual, overridden in subclasses, and only called from QQuickControl event handlers. Most mouse and touch event handlers in QQuickControl subclasses can be removed later when we get there. Task-number: QTBUG-58389 Change-Id: I7e82dc2ef49762a005c482ce1353e03cc841659f Reviewed-by: Mitch Curtis --- tests/auto/focus/tst_focus.cpp | 55 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'tests/auto/focus') diff --git a/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp index e423835c..c5c24233 100644 --- a/tests/auto/focus/tst_focus.cpp +++ b/tests/auto/focus/tst_focus.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "../shared/util.h" #include "../shared/visualtestutil.h" @@ -59,6 +60,7 @@ private slots: void navigation_data(); void navigation(); + void policy_data(); void policy(); void reason_data(); @@ -122,11 +124,24 @@ void tst_focus::navigation() QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusBehavior(-1)); } +void tst_focus::policy_data() +{ + QTest::addColumn("name"); + + QTest::newRow("Control") << "Control"; + QTest::newRow("ComboBox") << "ComboBox"; + QTest::newRow("Button") << "Button"; + QTest::newRow("Slider") << "Slider"; + QTest::newRow("ScrollBar") << "ScrollBar"; +} + void tst_focus::policy() { + QFETCH(QString, name); + QQmlEngine engine; QQmlComponent component(&engine); - component.setData("import QtQuick.Controls 2.1; ApplicationWindow { width: 100; height: 100; Control { anchors.fill: parent } }", QUrl()); + component.setData(QString("import QtQuick.Controls 2.1; ApplicationWindow { width: 100; height: 100; %1 { anchors.fill: parent } }").arg(name).toUtf8(), QUrl()); QScopedPointer window(qobject_cast(component.create())); QVERIFY(window); @@ -141,6 +156,22 @@ void tst_focus::policy() 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()); + + control->setFocusPolicy(Qt::NoFocus); + QCOMPARE(control->focusPolicy(), Qt::NoFocus); + // Qt::TabFocus vs. QQuickItem::activeFocusOnTab control->setActiveFocusOnTab(true); QCOMPARE(control->focusPolicy(), Qt::TabFocus); @@ -162,7 +193,8 @@ void tst_focus::policy() control->setFocus(false); QVERIFY(!control->hasActiveFocus()); - // Qt::ClickFocus + // Qt::ClickFocus (mouse) + control->setFocusPolicy(Qt::NoFocus); control->setAcceptedMouseButtons(Qt::LeftButton); QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(control->width() / 2, control->height() / 2)); QVERIFY(!control->hasActiveFocus()); @@ -178,6 +210,25 @@ void tst_focus::policy() control->setFocus(false); QVERIFY(!control->hasActiveFocus()); + // Qt::ClickFocus (touch) + control->setFocusPolicy(Qt::NoFocus); + 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(!control->hasActiveFocus()); + QVERIFY(!control->hasVisualFocus()); + + control->setFocusPolicy(Qt::ClickFocus); + QCOMPARE(control->focusPolicy(), Qt::ClickFocus); + 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)); + QEXPECT_FAIL("Control", "TODO: Control::touchEvent should set the touchId", Continue); + QVERIFY(control->hasActiveFocus()); + QVERIFY(!control->hasVisualFocus()); + + // reset + control->setFocus(false); + QVERIFY(!control->hasActiveFocus()); + // Qt::WheelFocus QWheelEvent wheelEvent(QPoint(control->width() / 2, control->height() / 2), 10, Qt::NoButton, Qt::NoModifier); QGuiApplication::sendEvent(control, &wheelEvent); -- cgit v1.2.3