diff options
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton.cpp | 9 | ||||
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton_p_p.h | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcombobox.cpp | 7 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol.cpp | 104 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol_p.h | 3 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol_p_p.h | 6 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdial.cpp | 9 | ||||
-rw-r--r-- | src/quicktemplates2/qquickscrollbar.cpp | 6 | ||||
-rw-r--r-- | src/quicktemplates2/qquickscrollbar_p_p.h | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickslider.cpp | 7 | ||||
-rw-r--r-- | src/quicktemplates2/qquickspinbox.cpp | 7 | ||||
-rw-r--r-- | tests/auto/focus/tst_focus.cpp | 55 |
12 files changed, 172 insertions, 43 deletions
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 7c2ced66..de954570 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -121,7 +121,6 @@ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() autoExclusive(false), autoRepeat(false), wasHeld(false), - touchId(-1), holdTimer(0), delayTimer(0), repeatTimer(0), @@ -165,7 +164,6 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) Q_Q(QQuickAbstractButton); bool wasPressed = pressed; q->setPressed(false); - touchId = -1; if (!wasHeld && (keepPressed || q->contains(point))) q->nextCheckState(); @@ -191,7 +189,6 @@ void QQuickAbstractButtonPrivate::handleCancel() return; q->setPressed(false); - touchId = -1; stopPressRepeat(); stopPressAndHold(); emit q->canceled(); @@ -579,7 +576,8 @@ void QQuickAbstractButton::focusOutEvent(QFocusEvent *event) { Q_D(QQuickAbstractButton); QQuickControl::focusOutEvent(event); - d->handleCancel(); + if (d->touchId == -1) // don't ungrab on multi-touch if another control gets focused + d->handleCancel(); } void QQuickAbstractButton::keyPressEvent(QKeyEvent *event) @@ -713,9 +711,10 @@ void QQuickAbstractButton::touchEvent(QTouchEvent *event) break; default: - QQuickControl::touchEvent(event); break; } + + QQuickControl::touchEvent(event); } void QQuickAbstractButton::touchUngrabEvent() diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index e27f5c82..6d149b4f 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -95,7 +95,6 @@ public: bool autoExclusive; bool autoRepeat; bool wasHeld; - int touchId; int holdTimer; int delayTimer; int repeatTimer; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 09a5eede..5c763d21 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -257,7 +257,6 @@ public: bool hasCurrentIndex; int highlightedIndex; int currentIndex; - int touchId; QVariant model; QString textRole; QString currentText; @@ -296,7 +295,6 @@ QQuickComboBoxPrivate::QQuickComboBoxPrivate() hasCurrentIndex(false), highlightedIndex(-1), currentIndex(-1), - touchId(-1), delegateModel(nullptr), delegate(nullptr), indicator(nullptr), @@ -648,14 +646,12 @@ void QQuickComboBoxPrivate::handleRelease(const QPointF &) q->setPressed(false); togglePopup(false); } - touchId = -1; } void QQuickComboBoxPrivate::handleUngrab() { Q_Q(QQuickComboBox); q->setPressed(false); - touchId = -1; } QQuickComboBox::QQuickComboBox(QQuickItem *parent) @@ -1580,9 +1576,10 @@ void QQuickComboBox::touchEvent(QTouchEvent *event) break; default: - QQuickControl::touchEvent(event); break; } + + QQuickControl::touchEvent(event); } void QQuickComboBox::touchUngrabEvent() diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index eb66f313..b086f3ee 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -120,6 +120,7 @@ QQuickControlPrivate::QQuickControlPrivate() hovered(false), explicitHoverEnabled(false), #endif + touchId(-1), padding(0), topPadding(0), leftPadding(0), @@ -144,6 +145,36 @@ QQuickControlPrivate::~QQuickControlPrivate() #endif } +void QQuickControlPrivate::handlePress(const QPointF &) +{ + Q_Q(QQuickControl); + if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && !QGuiApplication::styleHints()->setFocusOnTouchRelease()) + q->forceActiveFocus(Qt::MouseFocusReason); +} + +void QQuickControlPrivate::handleMove(const QPointF &point) +{ +#if QT_CONFIG(quicktemplates2_hover) + Q_Q(QQuickControl); + q->setHovered(hoverEnabled && q->contains(point)); +#else + Q_UNUSED(point); +#endif +} + +void QQuickControlPrivate::handleRelease(const QPointF &) +{ + Q_Q(QQuickControl); + if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && QGuiApplication::styleHints()->setFocusOnTouchRelease()) + q->forceActiveFocus(Qt::MouseFocusReason); + touchId = -1; +} + +void QQuickControlPrivate::handleUngrab() +{ + touchId = -1; +} + void QQuickControlPrivate::mirrorChange() { Q_Q(QQuickControl); @@ -1287,30 +1318,85 @@ void QQuickControl::hoverLeaveEvent(QHoverEvent *event) void QQuickControl::mousePressEvent(QMouseEvent *event) { Q_D(QQuickControl); - if ((d->focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && !QGuiApplication::styleHints()->setFocusOnTouchRelease()) - forceActiveFocus(Qt::MouseFocusReason); - + d->handlePress(event->localPos()); event->accept(); } void QQuickControl::mouseMoveEvent(QMouseEvent *event) { -#if QT_CONFIG(quicktemplates2_hover) Q_D(QQuickControl); - setHovered(d->hoverEnabled && contains(event->pos())); -#endif + d->handleMove(event->localPos()); event->accept(); } void QQuickControl::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickControl); - if ((d->focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && QGuiApplication::styleHints()->setFocusOnTouchRelease()) - forceActiveFocus(Qt::MouseFocusReason); - + d->handleRelease(event->localPos()); event->accept(); } +void QQuickControl::mouseUngrabEvent() +{ + Q_D(QQuickControl); + d->handleUngrab(); +} + +void QQuickControl::touchEvent(QTouchEvent *event) +{ + Q_D(QQuickControl); + switch (event->type()) { + case QEvent::TouchBegin: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() == d->touchId) + d->handlePress(point.pos()); + } + break; + + case QEvent::TouchUpdate: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() != d->touchId) + continue; + + switch (point.state()) { + case Qt::TouchPointPressed: + d->handlePress(point.pos()); + break; + case Qt::TouchPointMoved: + d->handleMove(point.pos()); + break; + case Qt::TouchPointReleased: + d->handleRelease(point.pos()); + break; + default: + break; + } + } + break; + + case QEvent::TouchEnd: + for (const QTouchEvent::TouchPoint &point : event->touchPoints()) { + if (point.id() == d->touchId) + d->handleRelease(point.pos()); + } + break; + + case QEvent::TouchCancel: + d->handleUngrab(); + break; + + default: + QQuickItem::touchEvent(event); + break; + } +} + +void QQuickControl::touchUngrabEvent() +{ + Q_D(QQuickControl); + d->handleUngrab(); +} + #if QT_CONFIG(wheelevent) void QQuickControl::wheelEvent(QWheelEvent *event) { diff --git a/src/quicktemplates2/qquickcontrol_p.h b/src/quicktemplates2/qquickcontrol_p.h index a94ef01d..6ad89376 100644 --- a/src/quicktemplates2/qquickcontrol_p.h +++ b/src/quicktemplates2/qquickcontrol_p.h @@ -184,6 +184,9 @@ protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; + void mouseUngrabEvent() override; + void touchEvent(QTouchEvent *event) override; + void touchUngrabEvent() override; #if QT_CONFIG(wheelevent) void wheelEvent(QWheelEvent *event) override; #endif diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index 14a468f3..2c79c887 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -78,6 +78,11 @@ public: return control->d_func(); } + void handlePress(const QPointF &point); + void handleMove(const QPointF &point); + void handleRelease(const QPointF &point); + void handleUngrab(); + void mirrorChange() override; void setTopPadding(qreal value, bool reset = false); @@ -136,6 +141,7 @@ public: bool hovered; bool explicitHoverEnabled; #endif + int touchId; qreal padding; qreal topPadding; qreal leftPadding; diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index 5b98992b..285dda49 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -96,8 +96,7 @@ class QQuickDialPrivate : public QQuickControlPrivate public: QQuickDialPrivate() - : touchId(-1), - from(0), + : from(0), to(1), value(0), position(0), @@ -123,7 +122,6 @@ public: void handleRelease(const QPointF &point); void handleUngrab(); - int touchId; qreal from; qreal to; qreal value; @@ -242,14 +240,12 @@ void QQuickDialPrivate::handleRelease(const QPointF &point) q->setPressed(false); pressPoint = QPointF(); - touchId = -1; } void QQuickDialPrivate::handleUngrab() { Q_Q(QQuickDial); pressPoint = QPointF(); - touchId = -1; q->setPressed(false); } @@ -729,9 +725,10 @@ void QQuickDial::touchEvent(QTouchEvent *event) break; default: - QQuickControl::touchEvent(event); break; } + + QQuickControl::touchEvent(event); } void QQuickDial::touchUngrabEvent() diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index b0d55dfb..be97f071 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -165,7 +165,6 @@ QQuickScrollBarPrivate::QQuickScrollBarPrivate() moving(false), interactive(true), explicitInteractive(false), - touchId(-1), orientation(Qt::Vertical), snapMode(QQuickScrollBar::NoSnap), policy(QQuickScrollBar::AsNeeded) @@ -269,7 +268,6 @@ void QQuickScrollBarPrivate::handleRelease(const QPointF &point) pos = snapPosition(pos); q->setPosition(pos); offset = 0.0; - touchId = -1; q->setPressed(false); } @@ -277,7 +275,6 @@ void QQuickScrollBarPrivate::handleUngrab() { Q_Q(QQuickScrollBar); offset = 0.0; - touchId = -1; q->setPressed(false); } @@ -657,9 +654,10 @@ void QQuickScrollBar::touchEvent(QTouchEvent *event) break; default: - QQuickControl::touchEvent(event); break; } + + QQuickControl::touchEvent(event); } void QQuickScrollBar::touchUngrabEvent() diff --git a/src/quicktemplates2/qquickscrollbar_p_p.h b/src/quicktemplates2/qquickscrollbar_p_p.h index 409b952b..cbbef2c8 100644 --- a/src/quicktemplates2/qquickscrollbar_p_p.h +++ b/src/quicktemplates2/qquickscrollbar_p_p.h @@ -88,7 +88,6 @@ public: bool moving; bool interactive; bool explicitInteractive; - int touchId; Qt::Orientation orientation; QQuickScrollBar::SnapMode snapMode; QQuickScrollBar::Policy policy; diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index 77e5856c..ef074c73 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -96,7 +96,6 @@ public: stepSize(0), live(true), pressed(false), - touchId(-1), orientation(Qt::Horizontal), snapMode(QQuickSlider::NoSnap), handle(nullptr) @@ -120,7 +119,6 @@ public: qreal stepSize; bool live; bool pressed; - int touchId; QPointF pressPoint; Qt::Orientation orientation; QQuickSlider::SnapMode snapMode; @@ -209,7 +207,6 @@ void QQuickSliderPrivate::handleMove(const QPointF &point) void QQuickSliderPrivate::handleRelease(const QPointF &point) { Q_Q(QQuickSlider); - touchId = -1; pressPoint = QPointF(); const qreal oldPos = position; qreal pos = positionAt(point); @@ -230,7 +227,6 @@ void QQuickSliderPrivate::handleRelease(const QPointF &point) void QQuickSliderPrivate::handleUngrab() { Q_Q(QQuickSlider); - touchId = -1; pressPoint = QPointF(); q->setPressed(false); } @@ -693,9 +689,10 @@ void QQuickSlider::touchEvent(QTouchEvent *event) break; default: - QQuickControl::touchEvent(event); break; } + + QQuickControl::touchEvent(event); } void QQuickSlider::touchUngrabEvent() diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index b70366ea..9558cfc5 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -114,7 +114,6 @@ public: stepSize(1), delayTimer(0), repeatTimer(0), - touchId(-1), up(nullptr), down(nullptr), validator(nullptr), @@ -150,7 +149,6 @@ public: int stepSize; int delayTimer; int repeatTimer; - int touchId; QQuickSpinButton *up; QQuickSpinButton *down; QValidator *validator; @@ -323,7 +321,6 @@ bool QQuickSpinBoxPrivate::handleRelease(const QPointF &point) if (value != oldValue) emit q->valueModified(); - touchId = -1; q->setAccessibleProperty("pressed", false); stopPressRepeat(); return wasPressed; @@ -335,7 +332,6 @@ bool QQuickSpinBoxPrivate::handleUngrab() up->setPressed(false); down->setPressed(false); - touchId = -1; q->setAccessibleProperty("pressed", false); stopPressRepeat(); return false; @@ -870,9 +866,10 @@ void QQuickSpinBox::touchEvent(QTouchEvent *event) break; default: - QQuickControl::touchEvent(event); break; } + + QQuickControl::touchEvent(event); } void QQuickSpinBox::touchUngrabEvent() 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 <QtQuickTemplates2/private/qquickcontrol_p.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qstylehints.h> +#include <QtGui/qtouchdevice.h> #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<QString>("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<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(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<QTouchDevice, TouchDeviceDeleter> 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); |