aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/handlers/qquicktaphandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/handlers/qquicktaphandler.cpp')
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp376
1 files changed, 267 insertions, 109 deletions
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 0a7cc7e075..accf307382 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -1,44 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquicktaphandler_p.h"
#include "qquicksinglepointhandler_p_p.h"
+#include <QtQuick/private/qquickdeliveryagent_p_p.h>
+#include <QtQuick/qquickwindow.h>
#include <qpa/qplatformtheme.h>
#include <private/qguiapplication_p.h>
#include <QtGui/qstylehints.h>
@@ -47,7 +13,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcTapHandler, "qt.quick.handler.tap")
-qreal QQuickTapHandler::m_multiTapInterval(0.0);
+quint64 QQuickTapHandler::m_multiTapInterval(0);
// single tap distance is the same as the drag threshold
int QQuickTapHandler::m_mouseMultiClickDistanceSquared(-1);
int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
@@ -77,19 +43,22 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
button in order to cancel the click. For this use case, set the
\l gesturePolicy to \c TapHandler.ReleaseWithinBounds.
+ \snippet pointerHandlers/tapHandlerButton.qml 0
+
For multi-tap gestures (double-tap, triple-tap etc.), the distance moved
must not exceed QStyleHints::mouseDoubleClickDistance() with mouse and
QStyleHints::touchDoubleTapDistance() with touch, and the time between
taps must not exceed QStyleHints::mouseDoubleClickInterval().
- \sa MouseArea
+ \sa MouseArea, {Qt Quick Examples - Pointer Handlers}
*/
QQuickTapHandler::QQuickTapHandler(QQuickItem *parent)
: QQuickSinglePointHandler(parent)
+ , m_longPressThreshold(QGuiApplication::styleHints()->mousePressAndHoldInterval())
{
if (m_mouseMultiClickDistanceSquared < 0) {
- m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval() / 1000.0;
+ m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval();
m_mouseMultiClickDistanceSquared = qApp->styleHints()->mouseDoubleClickDistance();
m_mouseMultiClickDistanceSquared *= m_mouseMultiClickDistanceSquared;
m_touchMultiTapDistanceSquared = qApp->styleHints()->touchDoubleTapDistance();
@@ -99,8 +68,9 @@ QQuickTapHandler::QQuickTapHandler(QQuickItem *parent)
bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
{
- if (!QQuickWindowPrivate::isMouseEvent(event) && !QQuickWindowPrivate::isTouchEvent(event) &&
- !QQuickWindowPrivate::isTabletEvent(event))
+ if (!QQuickDeliveryAgentPrivate::isMouseEvent(event) &&
+ !QQuickDeliveryAgentPrivate::isTouchEvent(event) &&
+ !QQuickDeliveryAgentPrivate::isTabletEvent(event))
return false;
// If the user has not violated any constraint, it could be a tap.
// Otherwise we want to give up the grab so that a competing handler
@@ -108,7 +78,9 @@ bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventP
// Don't forget to emit released in case of a cancel.
bool ret = false;
bool overThreshold = d_func()->dragOverThreshold(point);
- if (overThreshold) {
+ if (overThreshold && m_gesturePolicy != DragWithinBounds) {
+ if (m_longPressTimer.isActive())
+ qCDebug(lcTapHandler) << objectName() << "drag threshold exceeded";
m_longPressTimer.stop();
m_holdTimer.invalidate();
}
@@ -118,15 +90,17 @@ bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventP
ret = parentContains(point);
break;
case QEventPoint::Updated:
+ ret = point.id() == this->point().id();
switch (m_gesturePolicy) {
case DragThreshold:
- ret = !overThreshold && parentContains(point);
+ ret = ret && !overThreshold && parentContains(point);
break;
case WithinBounds:
- ret = parentContains(point);
+ case DragWithinBounds:
+ ret = ret && parentContains(point);
break;
case ReleaseWithinBounds:
- ret = point.id() == this->point().id();
+ // no change to ret: depends only whether it's the already-tracking point ID
break;
}
break;
@@ -149,13 +123,13 @@ bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventP
void QQuickTapHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point)
{
+ const bool isTouch = QQuickDeliveryAgentPrivate::isTouchEvent(event);
switch (point.state()) {
case QEventPoint::Pressed:
setPressed(true, false, event, point);
break;
case QEventPoint::Released: {
- if (QQuickWindowPrivate::isTouchEvent(event) ||
- (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton)
+ if (isTouch || (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton)
setPressed(false, false, event, point);
break;
}
@@ -164,24 +138,38 @@ void QQuickTapHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point
}
QQuickSinglePointHandler::handleEventPoint(event, point);
+
+ // If TapHandler only needs a passive grab, it should not block other items and handlers from reacting.
+ // If the point is accepted, QQuickItemPrivate::localizedTouchEvent() would skip it.
+ if (isTouch && m_gesturePolicy == DragThreshold)
+ point.setAccepted(false);
}
/*!
\qmlproperty real QtQuick::TapHandler::longPressThreshold
- The time in seconds that an event point must be pressed in order to
- trigger a long press gesture and emit the \l longPressed() signal.
- If the point is released before this time limit, a tap can be detected
- if the \l gesturePolicy constraint is satisfied. The default value is
- QStyleHints::mousePressAndHoldInterval() converted to seconds.
+ The time in seconds that an \l eventPoint must be pressed in order to
+ trigger a long press gesture and emit the \l longPressed() signal, if the
+ value is greater than \c 0. If the point is released before this time
+ limit, a tap can be detected if the \l gesturePolicy constraint is
+ satisfied. If \c longPressThreshold is \c 0, the timer is disabled and the
+ signal will not be emitted. If \c longPressThreshold is set to \c undefined,
+ the default value is used instead, and can be read back from this property.
+
+ The default value is QStyleHints::mousePressAndHoldInterval() converted to
+ seconds.
*/
qreal QQuickTapHandler::longPressThreshold() const
{
- return longPressThresholdMilliseconds() / 1000.0;
+ return m_longPressThreshold / qreal(1000);
}
void QQuickTapHandler::setLongPressThreshold(qreal longPressThreshold)
{
+ if (longPressThreshold < 0) {
+ resetLongPressThreshold();
+ return;
+ }
int ms = qRound(longPressThreshold * 1000);
if (m_longPressThreshold == ms)
return;
@@ -190,9 +178,14 @@ void QQuickTapHandler::setLongPressThreshold(qreal longPressThreshold)
emit longPressThresholdChanged();
}
-int QQuickTapHandler::longPressThresholdMilliseconds() const
+void QQuickTapHandler::resetLongPressThreshold()
{
- return (m_longPressThreshold < 0 ? QGuiApplication::styleHints()->mousePressAndHoldInterval() : m_longPressThreshold);
+ int ms = QGuiApplication::styleHints()->mousePressAndHoldInterval();
+ if (m_longPressThreshold == ms)
+ return;
+
+ m_longPressThreshold = ms;
+ emit longPressThresholdChanged();
}
void QQuickTapHandler::timerEvent(QTimerEvent *event)
@@ -200,7 +193,16 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
if (event->timerId() == m_longPressTimer.timerId()) {
m_longPressTimer.stop();
qCDebug(lcTapHandler) << objectName() << "longPressed";
+ m_longPressed = true;
emit longPressed();
+ } else if (event->timerId() == m_doubleTapTimer.timerId()) {
+ m_doubleTapTimer.stop();
+ qCDebug(lcTapHandler) << objectName() << "double-tap timer expired; taps:" << m_tapCount;
+ Q_ASSERT(m_exclusiveSignals == (SingleTap | DoubleTap));
+ if (m_tapCount == 1)
+ emit singleTapped(m_singleTapReleasedPoint, m_singleTapReleasedButton);
+ else if (m_tapCount == 2)
+ emit doubleTapped(m_singleTapReleasedPoint, m_singleTapReleasedButton);
}
}
@@ -214,31 +216,98 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
If the spatial constraint is violated, \l pressed transitions immediately
from true to false, regardless of the time held.
- \value TapHandler.DragThreshold
- (the default value) The event point must not move significantly.
- If the mouse, finger or stylus moves past the system-wide drag
- threshold (QStyleHints::startDragDistance), the tap gesture is
- canceled, even if the button or finger is still pressed. This policy
- can be useful whenever TapHandler needs to cooperate with other
- input handlers (for example \l DragHandler) or event-handling Items
- (for example QtQuick Controls), because in this case TapHandler
- will not take the exclusive grab, but merely a passive grab.
-
- \value TapHandler.WithinBounds
- If the event point leaves the bounds of the \c parent Item, the tap
- gesture is canceled. The TapHandler will take the exclusive grab on
- press, but will release the grab as soon as the boundary constraint
- is no longer satisfied.
-
- \value TapHandler.ReleaseWithinBounds
- At the time of release (the mouse button is released or the finger
- is lifted), if the event point is outside the bounds of the
- \c parent Item, a tap gesture is not recognized. This corresponds to
- typical behavior for button widgets: you can cancel a click by
- dragging outside the button, and you can also change your mind by
- dragging back inside the button before release. Note that it's
- necessary for TapHandler take the exclusive grab on press and retain
- it until release in order to detect this gesture.
+ The \c gesturePolicy also affects grab behavior as described below.
+
+ \table
+ \header
+ \li Constant
+ \li Description
+ \row
+ \li \c TapHandler.DragThreshold
+ \image pointerHandlers/tapHandlerOverlappingButtons.webp
+ Grab on press: \e passive
+ \li (the default value) The \l eventPoint must not move significantly.
+ If the mouse, finger or stylus moves past the system-wide drag
+ threshold (QStyleHints::startDragDistance), the tap gesture is
+ canceled, even if the device or finger is still pressed. This policy
+ can be useful whenever TapHandler needs to cooperate with other
+ input handlers (for example \l DragHandler) or event-handling Items
+ (for example \l {Qt Quick Controls}), because in this case TapHandler
+ will not take the exclusive grab, but merely a
+ \l {QPointerEvent::addPassiveGrabber()}{passive grab}.
+ That is, \c DragThreshold is especially useful to \e augment
+ existing behavior: it reacts to tap/click/long-press even when
+ another item or handler is already reacting, perhaps even in a
+ different layer of the UI. The following snippet shows one
+ TapHandler as used in one component; but if we stack up two
+ instances of the component, you will see the handlers in both of them
+ react simultaneously when a press occurs over both of them, because
+ the passive grab does not stop event propagation:
+ \quotefromfile pointerHandlers/tapHandlerOverlappingButtons.qml
+ \skipto Item
+ \printuntil component Button
+ \skipto TapHandler
+ \printuntil }
+ \skipuntil Text {
+ \skipuntil }
+ \printuntil Button
+ \printuntil Button
+ \printuntil }
+
+ \row
+ \li \c TapHandler.WithinBounds
+ \image pointerHandlers/tapHandlerButtonWithinBounds.webp
+ Grab on press: \e exclusive
+ \li If the \l eventPoint leaves the bounds of the \c parent Item, the tap
+ gesture is canceled. The TapHandler will take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on
+ press, but will release the grab as soon as the boundary constraint
+ is no longer satisfied.
+ \snippet pointerHandlers/tapHandlerButtonWithinBounds.qml 1
+
+ \row
+ \li \c TapHandler.ReleaseWithinBounds
+ \image pointerHandlers/tapHandlerButtonReleaseWithinBounds.webp
+ Grab on press: \e exclusive
+ \li At the time of release (the mouse button is released or the finger
+ is lifted), if the \l eventPoint is outside the bounds of the
+ \c parent Item, a tap gesture is not recognized. This corresponds to
+ typical behavior for button widgets: you can cancel a click by
+ dragging outside the button, and you can also change your mind by
+ dragging back inside the button before release. Note that it's
+ necessary for TapHandler to take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press
+ and retain it until release in order to detect this gesture.
+ \snippet pointerHandlers/tapHandlerButtonReleaseWithinBounds.qml 1
+
+ \row
+ \li \c TapHandler.DragWithinBounds
+ \image pointerHandlers/dragReleaseMenu.webp
+ Grab on press: \e exclusive
+ \li On press, TapHandler takes the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab}; after that,
+ the \l eventPoint can be dragged within the bounds of the \c parent
+ item, while the \l timeHeld property keeps counting, and the
+ \l longPressed() signal will be emitted regardless of drag distance.
+ However, like \c WithinBounds, if the point leaves the bounds,
+ the tap gesture is \l {PointerHandler::}{canceled()}, \l active()
+ becomes \c false, and \l timeHeld stops counting. This is suitable
+ for implementing press-drag-release components, such as menus, in
+ which a single TapHandler detects press, \c timeHeld drives an
+ "opening" animation, and then the user can drag to a menu item and
+ release, while never leaving the bounds of the parent scene containing
+ the menu. This value was added in Qt 6.3.
+ \snippet pointerHandlers/dragReleaseMenu.qml 1
+ \endtable
+
+ The \l {Qt Quick Examples - Pointer Handlers} demonstrates some use cases for these.
+
+ \note If you find that TapHandler is reacting in cases that conflict with
+ some other behavior, the first thing you should try is to think about which
+ \c gesturePolicy is appropriate. If you cannot fix it by changing \c gesturePolicy,
+ some cases are better served by adjusting \l {PointerHandler::}{grabPermissions},
+ either in this handler, or in another handler that should \e prevent TapHandler
+ from reacting.
*/
void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gesturePolicy)
{
@@ -250,12 +319,44 @@ void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gestureP
}
/*!
+ \qmlproperty enumeration QtQuick::TapHandler::exclusiveSignals
+ \since 6.5
+
+ Determines the exclusivity of the singleTapped() and doubleTapped() signals.
+
+ \value NotExclusive (the default) singleTapped() and doubleTapped() are
+ emitted immediately when the user taps once or twice, respectively.
+
+ \value SingleTap singleTapped() is emitted immediately when the user taps
+ once, and doubleTapped() is never emitted.
+
+ \value DoubleTap doubleTapped() is emitted immediately when the user taps
+ twice, and singleTapped() is never emitted.
+
+ \value (SingleTap | DoubleTap) Both signals are delayed until
+ QStyleHints::mouseDoubleClickInterval(), such that either singleTapped()
+ or doubleTapped() can be emitted, but not both. But if 3 or more taps
+ occur within \c mouseDoubleClickInterval, neither signal is emitted.
+
+ \note The remaining signals such as tapped() and tapCountChanged() are
+ always emitted immediately, regardless of this property.
+*/
+void QQuickTapHandler::setExclusiveSignals(QQuickTapHandler::ExclusiveSignals exc)
+{
+ if (m_exclusiveSignals == exc)
+ return;
+
+ m_exclusiveSignals = exc;
+ emit exclusiveSignalsChanged();
+}
+
+/*!
\qmlproperty bool QtQuick::TapHandler::pressed
\readonly
Holds true whenever the mouse or touch point is pressed,
and any movement since the press is compliant with the current
- \l gesturePolicy. When the event point is released or the policy is
+ \l gesturePolicy. When the \l eventPoint is released or the policy is
violated, \e pressed will change to false.
*/
void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, QEventPoint &point)
@@ -267,7 +368,8 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event,
connectPreRenderSignal(press);
updateTimeHeld();
if (press) {
- m_longPressTimer.start(longPressThresholdMilliseconds(), this);
+ if (m_longPressThreshold > 0)
+ m_longPressTimer.start(m_longPressThreshold, this);
m_holdTimer.start();
} else {
m_longPressTimer.stop();
@@ -281,29 +383,57 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event,
setExclusiveGrab(event, point, press);
}
if (!cancel && !press && parentContains(point)) {
- if (point.timeHeld() < longPressThreshold()) {
+ if (m_longPressed) {
+ qCDebug(lcTapHandler) << objectName() << "long press threshold" << longPressThreshold() << "exceeded:" << point.timeHeld();
+ } else {
// Assuming here that pointerEvent()->timestamp() is in ms.
- qreal ts = event->timestamp() / 1000.0;
- if (ts - m_lastTapTimestamp < m_multiTapInterval &&
- QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared() <
+ const quint64 ts = event->timestamp();
+ const quint64 interval = ts - m_lastTapTimestamp;
+ const auto distanceSquared = QVector2D(point.scenePosition() - m_lastTapPos).lengthSquared();
+ const auto singleTapReleasedButton = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
+ if ((interval < m_multiTapInterval && distanceSquared <
(event->device()->type() == QInputDevice::DeviceType::Mouse ?
m_mouseMultiClickDistanceSquared : m_touchMultiTapDistanceSquared))
+ && m_singleTapReleasedButton == singleTapReleasedButton) {
++m_tapCount;
- else
+ } else {
+ m_singleTapReleasedButton = singleTapReleasedButton;
+ m_singleTapReleasedPoint = point;
m_tapCount = 1;
- qCDebug(lcTapHandler) << objectName() << "tapped" << m_tapCount << "times";
- emit tapped(point);
+ }
+ qCDebug(lcTapHandler) << objectName() << "tapped" << m_tapCount << "times; interval since last:" << interval
+ << "sec; distance since last:" << qSqrt(distanceSquared);
+ auto button = event->isSinglePointEvent() ? static_cast<QSinglePointEvent *>(event)->button() : Qt::NoButton;
+ emit tapped(point, button);
emit tapCountChanged();
- if (m_tapCount == 1)
- emit singleTapped(point);
- else if (m_tapCount == 2)
- emit doubleTapped(point);
+ switch (m_exclusiveSignals) {
+ case NotExclusive:
+ if (m_tapCount == 1)
+ emit singleTapped(point, button);
+ else if (m_tapCount == 2)
+ emit doubleTapped(point, button);
+ break;
+ case SingleTap:
+ if (m_tapCount == 1)
+ emit singleTapped(point, button);
+ break;
+ case DoubleTap:
+ if (m_tapCount == 2)
+ emit doubleTapped(point, button);
+ break;
+ case (SingleTap | DoubleTap):
+ if (m_tapCount == 1) {
+ qCDebug(lcTapHandler) << objectName() << "waiting to emit singleTapped:" << m_multiTapInterval << "ms";
+ m_doubleTapTimer.start(m_multiTapInterval, this);
+ }
+ }
+ qCDebug(lcTapHandler) << objectName() << "tap" << m_tapCount << "after" << event->timestamp() - m_lastTapTimestamp << "ms";
+
m_lastTapTimestamp = ts;
m_lastTapPos = point.scenePosition();
- } else {
- qCDebug(lcTapHandler) << objectName() << "tap threshold" << longPressThreshold() << "exceeded:" << point.timeHeld();
}
}
+ m_longPressed = false;
emit pressedChanged();
if (!press && m_gesturePolicy != DragThreshold) {
// on release, ungrab after emitting changed signals
@@ -331,10 +461,25 @@ void QQuickTapHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDev
void QQuickTapHandler::connectPreRenderSignal(bool conn)
{
- if (conn)
- connect(parentItem()->window(), &QQuickWindow::beforeSynchronizing, this, &QQuickTapHandler::updateTimeHeld);
- else
- disconnect(parentItem()->window(), &QQuickWindow::beforeSynchronizing, this, &QQuickTapHandler::updateTimeHeld);
+ // disconnect pre-existing connection, if any
+ disconnect(m_preRenderSignalConnection);
+
+ auto par = parentItem();
+ if (!par || !par->window())
+ return;
+
+ /*
+ Note: beforeSynchronizing is emitted from the SG thread, and the
+ timeHeldChanged signal can be used to do arbitrary things in user QML.
+
+ But the docs say the GUI thread is blockd, and "Therefore, it is safe
+ to access GUI thread thread data in a slot or lambda that is connected
+ with Qt::DirectConnection." We use the default AutoConnection just in case.
+ */
+ if (conn) {
+ m_preRenderSignalConnection = connect(par->window(), &QQuickWindow::beforeSynchronizing,
+ this, &QQuickTapHandler::updateTimeHeld);
+ }
}
void QQuickTapHandler::updateTimeHeld()
@@ -347,8 +492,8 @@ void QQuickTapHandler::updateTimeHeld()
\readonly
The number of taps which have occurred within the time and space
- constraints to be considered a single gesture. For example, to detect
- a triple-tap, you can write:
+ constraints to be considered a single gesture. The counter is reset to 1
+ if the button changed. For example, to detect a triple-tap, you can write:
\qml
Rectangle {
@@ -375,10 +520,15 @@ void QQuickTapHandler::updateTimeHeld()
A value of less than zero means no point is being held within this
handler's \l [QML] Item.
+
+ \note If \l gesturePolicy is set to \c TapHandler.DragWithinBounds,
+ \c timeHeld does not stop counting even when the pressed point is moved
+ beyond the drag threshold, but only when the point leaves the \l {Item::}
+ {parent} item's \l {QtQuick::Item::contains()}{bounds}.
*/
/*!
- \qmlsignal QtQuick::TapHandler::tapped(EventPoint eventPoint)
+ \qmlsignal QtQuick::TapHandler::tapped(eventPoint eventPoint, Qt::MouseButton button)
This signal is emitted each time the \c parent Item is tapped.
@@ -386,24 +536,28 @@ void QQuickTapHandler::updateTimeHeld()
period less than \l longPressThreshold, while any movement does not exceed
the drag threshold, then the \c tapped signal will be emitted at the time
of release. The \a eventPoint signal parameter contains information
- from the release event about the point that was tapped:
+ from the release event about the point that was tapped, and \a button
+ is the \l {Qt::MouseButton}{mouse button} that was clicked, or \c NoButton
+ on a touchscreen.
\snippet pointerHandlers/tapHandlerOnTapped.qml 0
*/
/*!
- \qmlsignal QtQuick::TapHandler::singleTapped(EventPoint eventPoint)
+ \qmlsignal QtQuick::TapHandler::singleTapped(eventPoint eventPoint, Qt::MouseButton button)
\since 5.11
This signal is emitted when the \c parent Item is tapped once.
After an amount of time greater than QStyleHints::mouseDoubleClickInterval,
it can be tapped again; but if the time until the next tap is less,
\l tapCount will increase. The \a eventPoint signal parameter contains
- information from the release event about the point that was tapped.
+ information from the release event about the point that was tapped, and
+ \a button is the \l {Qt::MouseButton}{mouse button} that was clicked, or
+ \c NoButton on a touchscreen.
*/
/*!
- \qmlsignal QtQuick::TapHandler::doubleTapped(EventPoint eventPoint)
+ \qmlsignal QtQuick::TapHandler::doubleTapped(eventPoint eventPoint, Qt::MouseButton button)
\since 5.11
This signal is emitted when the \c parent Item is tapped twice within a
@@ -412,7 +566,9 @@ void QQuickTapHandler::updateTimeHeld()
QStyleHints::touchDoubleTapDistance()). This signal always occurs after
\l singleTapped, \l tapped, and \l tapCountChanged. The \a eventPoint
signal parameter contains information from the release event about the
- point that was tapped.
+ point that was tapped, and \a button is the
+ \l {Qt::MouseButton}{mouse button} that was clicked, or \c NoButton
+ on a touchscreen.
*/
/*!
@@ -433,3 +589,5 @@ void QQuickTapHandler::updateTimeHeld()
from the previous \c tapCount.
*/
QT_END_NAMESPACE
+
+#include "moc_qquicktaphandler_p.cpp"