From 611c29c14bd5b6b13671abf2c0faf4da4f07718f Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Mon, 12 Dec 2022 12:42:02 +0100 Subject: Implement touch event handling for SplitView Amend 80166d58a18370bd5a2c6c61d2519011cfd65721, which broke touch event handling in SplitView. Implement handling of TouchBegin/Update/End events equivalently to the mouse event handling. As a drive-by, rename the logging category from 'mouse' to 'pointer', and refactor the if/else sequence to a switch statement, reducing duplication of code that's common for all event types. Remove expectFail from the test that now passes. Fixes: QTBUG-105312 Change-Id: I156f55fa40b2afaaa115e59940d26187121fc16a Reviewed-by: Mitch Curtis Reviewed-by: Shawn Rutledge (cherry picked from commit 6de2397da24e8068282c2d2bda5d1637ac033bc6) Reviewed-by: Qt Cherry-pick Bot --- src/quicktemplates/qquicksplitview.cpp | 78 ++++++++++++++-------- .../quickcontrols/controls/data/tst_splitview.qml | 1 - 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/quicktemplates/qquicksplitview.cpp b/src/quicktemplates/qquicksplitview.cpp index 7bb4d4dc3d..16037569a5 100644 --- a/src/quicktemplates/qquicksplitview.cpp +++ b/src/quicktemplates/qquicksplitview.cpp @@ -222,7 +222,7 @@ QT_BEGIN_NAMESPACE */ Q_LOGGING_CATEGORY(qlcQQuickSplitView, "qt.quick.controls.splitview") -Q_LOGGING_CATEGORY(qlcQQuickSplitViewMouse, "qt.quick.controls.splitview.mouse") +Q_LOGGING_CATEGORY(qlcQQuickSplitViewPointer, "qt.quick.controls.splitview.pointer") Q_LOGGING_CATEGORY(qlcQQuickSplitViewState, "qt.quick.controls.splitview.state") void QQuickSplitViewPrivate::updateFillIndex() @@ -896,7 +896,7 @@ void QQuickSplitViewPrivate::updateHandleVisibilities() void QQuickSplitViewPrivate::updateHoveredHandle(QQuickItem *hoveredItem) { - qCDebug(qlcQQuickSplitViewMouse) << "updating hovered handle after" << hoveredItem << "was hovered"; + qCDebug(qlcQQuickSplitViewPointer) << "updating hovered handle after" << hoveredItem << "was hovered"; const int oldHoveredHandleIndex = m_hoveredHandleIndex; m_hoveredHandleIndex = m_handleItems.indexOf(hoveredItem); @@ -909,16 +909,16 @@ void QQuickSplitViewPrivate::updateHoveredHandle(QQuickItem *hoveredItem) QQuickSplitHandleAttached *oldHoveredHandleAttached = qobject_cast( qmlAttachedPropertiesObject(oldHoveredHandle, true)); QQuickSplitHandleAttachedPrivate::get(oldHoveredHandleAttached)->setHovered(false); - qCDebug(qlcQQuickSplitViewMouse) << "handle item at index" << oldHoveredHandleIndex << "is no longer hovered"; + qCDebug(qlcQQuickSplitViewPointer) << "handle item at index" << oldHoveredHandleIndex << "is no longer hovered"; } if (m_hoveredHandleIndex != -1) { QQuickSplitHandleAttached *handleAttached = qobject_cast( qmlAttachedPropertiesObject(hoveredItem, true)); QQuickSplitHandleAttachedPrivate::get(handleAttached)->setHovered(true); - qCDebug(qlcQQuickSplitViewMouse) << "handle item at index" << m_hoveredHandleIndex << "is now hovered"; + qCDebug(qlcQQuickSplitViewPointer) << "handle item at index" << m_hoveredHandleIndex << "is now hovered"; } else { - qCDebug(qlcQQuickSplitViewMouse) << "either there is no hovered item or" << hoveredItem << "is not a handle"; + qCDebug(qlcQQuickSplitViewPointer) << "either there is no hovered item or" << hoveredItem << "is not a handle"; } } @@ -987,7 +987,7 @@ bool QQuickSplitViewPrivate::handlePress(const QPointF &point, ulong timestamp) setResizing(true); - qCDebug(qlcQQuickSplitViewMouse).nospace() << "handled press -" + qCDebug(qlcQQuickSplitViewPointer).nospace() << "handled press -" << " left/top index=" << m_pressedHandleIndex << "," << " size before press=" << m_leftOrTopItemSizeBeforePress << "," << " item=" << leftOrTopItem @@ -1380,27 +1380,51 @@ void QQuickSplitView::hoverLeaveEvent(QHoverEvent *event) bool QQuickSplitView::childMouseEventFilter(QQuickItem *item, QEvent *event) { Q_D(QQuickSplitView); - qCDebug(qlcQQuickSplitViewMouse) << "childMouseEventFilter called with" << item << event; - - if (event->type() == QEvent::MouseButtonPress) { - QMouseEvent *mouseEvent = static_cast(event); - const QPointF point = mapFromItem(item, mouseEvent->position()); - d->handlePress(point, mouseEvent->timestamp()); - - // Keep the mouse grab if this item belongs to the handle, - // otherwise this event can be stolen e.g. Flickable if we're inside it. - if (d->m_pressedHandleIndex != -1) - item->setKeepMouseGrab(true); - } - else if (event->type() == QEvent::MouseButtonRelease) { - QMouseEvent *mouseEvent = static_cast(event); - const QPointF point = mapFromItem(item, mouseEvent->position()); - d->handleRelease(point, mouseEvent->timestamp()); - } - else if (event->type() == QEvent::MouseMove) { - QMouseEvent *mouseEvent = static_cast(event); - const QPointF point = mapFromItem(item, mouseEvent->position()); - d->handleMove(point, mouseEvent->timestamp()); + qCDebug(qlcQQuickSplitViewPointer) << "childMouseEventFilter called with" << item << event; + + if (Q_LIKELY(event->isPointerEvent())) { + auto *pointerEvent = static_cast(event); + const auto &eventPoint = pointerEvent->points().first(); + const QPointF point = mapFromItem(item, eventPoint.position()); + const auto timestamp = pointerEvent->timestamp(); + + switch (event->type()) { + case QEvent::MouseButtonPress: + d->handlePress(point, timestamp); + // Keep the mouse grab if this item belongs to the handle, + // otherwise this event can be stolen e.g. Flickable if we're inside it. + if (d->m_pressedHandleIndex != -1) + item->setKeepMouseGrab(true); + break; + case QEvent::MouseButtonRelease: + d->handleRelease(point, timestamp); + break; + case QEvent::MouseMove: + d->handleMove(point, timestamp); + break; + case QEvent::TouchBegin: + if (pointerEvent->pointCount() == 1) { + d->handlePress(point, timestamp); + // We filter the event on behalf of item, but we want the item + // to be the exclusive grabber so that we can continue to filter + // touch events for it. + if (d->m_pressedHandleIndex != -1) { + item->setKeepTouchGrab(true); + pointerEvent->setExclusiveGrabber(eventPoint, item); + } + } + break; + case QEvent::TouchEnd: + if (pointerEvent->pointCount() == 1) + d->handleRelease(point, timestamp); + break; + case QEvent::TouchUpdate: + if (pointerEvent->pointCount() == 1) + d->handleMove(point, timestamp); + break; + default: + break; + } } // If this event belongs to the handle, filter it. (d->m_pressedHandleIndex != -1) means that diff --git a/tests/auto/quickcontrols/controls/data/tst_splitview.qml b/tests/auto/quickcontrols/controls/data/tst_splitview.qml index 08119ec366..4cefd834cb 100644 --- a/tests/auto/quickcontrols/controls/data/tst_splitview.qml +++ b/tests/auto/quickcontrols/controls/data/tst_splitview.qml @@ -2597,7 +2597,6 @@ TestCase { touch.move(0, control, handleCenter.x + 100, handleCenter.y).commit() verify(firstHandle.SplitHandle.pressed) let firstItem = control.itemAt(0) - expectFail("", "broken, QTBUG-105312") compare(firstItem.width, 125) touch.release(0, control, handleCenter.x + 100, handleCenter.y).commit() -- cgit v1.2.3