Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquicksinglepointhandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7#include <private/qquickdeliveryagent_p_p.h>
8
9#include <private/qquickdeliveryagent_p.h>
10
12
13/*!
14 \qmltype SinglePointHandler
15 \qmlabstract
16 \preliminary
17 \nativetype QQuickSinglePointHandler
18 \inherits PointerDeviceHandler
19 \inqmlmodule QtQuick
20 \brief Abstract handler for single-point Pointer Events.
21
22 An intermediate class (not registered as a QML type)
23 for the most common handlers: those which expect only a single point.
24 wantsPointerEvent() will choose the first point which is inside the
25 \l target item, and return true as long as the event contains that point.
26 Override handleEventPoint() to implement a single-point handler.
27*/
28
29QQuickSinglePointHandler::QQuickSinglePointHandler(QQuickItem *parent)
30 : QQuickPointerDeviceHandler(*(new QQuickSinglePointHandlerPrivate), parent)
31{
32}
33
34QQuickSinglePointHandler::QQuickSinglePointHandler(QQuickSinglePointHandlerPrivate &dd, QQuickItem *parent)
35 : QQuickPointerDeviceHandler(dd, parent)
36{
37}
38
39bool QQuickSinglePointHandler::wantsPointerEvent(QPointerEvent *event)
40{
41 Q_D(QQuickSinglePointHandler);
42 if (!QQuickPointerDeviceHandler::wantsPointerEvent(event))
43 return false;
44
45 if (d->pointInfo.id() != -1) {
46 // We already know which one we want, so check whether it's there.
47 // It's expected to be an update or a release.
48 // If we no longer want it, cancel the grab.
49 int candidatePointCount = 0;
50 bool missing = true;
51 QEventPoint *point = nullptr;
52 for (int i = 0; i < event->pointCount(); ++i) {
53 auto &p = event->point(i);
54 const bool found = (p.id() == d->pointInfo.id());
55 if (found)
56 missing = false;
57 if (wantsEventPoint(event, p)) {
58 ++candidatePointCount;
59 if (found)
60 point = &p;
61 }
62 }
63 if (missing) {
64 // Received a stray touch begin event => reset and start over.
65 if (event->type() == QEvent::TouchBegin && event->points().count() == 1) {
66 const QEventPoint &point = event->point(0);
67 qCDebug(lcTouchTarget) << this << "pointId" << Qt::hex << point.id()
68 << "was received as a stray TouchBegin event. Canceling existing gesture"
69 " and starting over.";
70 d->pointInfo.reset(event, point);
71 return true;
72 } else {
73 qCWarning(lcTouchTarget) << this << "pointId" << Qt::hex << d->pointInfo.id()
74 << "is missing from current event, but was neither canceled nor released."
75 " Ignoring:" << event->type();
76 }
77 }
78 if (point) {
79 if (candidatePointCount == 1 || (candidatePointCount > 1 && d->ignoreAdditionalPoints)) {
80 point->setAccepted();
81 return true;
82 } else {
83 cancelAllGrabs(event, *point);
84 }
85 } else {
86 return false;
87 }
88 } else {
89 // We have not yet chosen a point; choose the first one for which wantsEventPoint() returns true.
90 int candidatePointCount = 0;
91 QEventPoint *chosen = nullptr;
92 for (int i = 0; i < event->pointCount(); ++i) {
93 auto &p = event->point(i);
94 if (!event->exclusiveGrabber(p) && wantsEventPoint(event, p)) {
95 ++candidatePointCount;
96 if (!chosen) {
97 chosen = &p;
98 break;
99 }
100 }
101 }
102 if (chosen && candidatePointCount == 1) {
103 setPointId(chosen->id());
104 chosen->setAccepted();
105 }
106 }
107 return d->pointInfo.id() != -1;
108}
109
110void QQuickSinglePointHandler::handlePointerEventImpl(QPointerEvent *event)
111{
112 Q_D(QQuickSinglePointHandler);
113 QQuickPointerDeviceHandler::handlePointerEventImpl(event);
114 QEventPoint *currentPoint = const_cast<QEventPoint *>(event->pointById(d->pointInfo.id()));
115 Q_ASSERT(currentPoint);
116 if (!QQuickDeliveryAgentPrivate::isSynthMouse(event))
117 d->pointInfo.reset(event, *currentPoint);
118 handleEventPoint(event, *currentPoint);
119 emit pointChanged();
120}
121
122void QQuickSinglePointHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point)
123{
124 if (point.state() == QEventPoint::Released) {
125 // If it's a mouse or tablet event, with buttons,
126 // do not deactivate unless all acceptable buttons are released.
127 if (event->isSinglePointEvent()) {
128 const Qt::MouseButtons releasedButtons = static_cast<QSinglePointEvent *>(event)->buttons();
129 if ((releasedButtons & acceptedButtons()) != Qt::NoButton)
130 return;
131 }
132
133 // Deactivate this handler on release
134 setExclusiveGrab(event, point, false);
135 d_func()->reset();
136 }
137}
138
139void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
140{
141 Q_D(QQuickSinglePointHandler);
142 if (grabber != this)
143 return;
144 switch (transition) {
145 case QPointingDevice::GrabExclusive:
146 d->pointInfo.m_sceneGrabPosition = point.sceneGrabPosition();
147 setActive(true);
148 QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
149 break;
150 case QPointingDevice::GrabPassive:
151 d->pointInfo.m_sceneGrabPosition = point.sceneGrabPosition();
152 QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
153 break;
154 case QPointingDevice::OverrideGrabPassive:
155 return; // don't emit
156 case QPointingDevice::UngrabPassive:
157 case QPointingDevice::UngrabExclusive:
158 case QPointingDevice::CancelGrabPassive:
159 case QPointingDevice::CancelGrabExclusive:
160 // the grab is lost or relinquished, so the point is no longer relevant
161 QQuickPointerHandler::onGrabChanged(grabber, transition, event, point);
162 d->reset();
163 break;
164 }
165}
166
167void QQuickSinglePointHandler::setIgnoreAdditionalPoints(bool v)
168{
169 Q_D(QQuickSinglePointHandler);
170 d->ignoreAdditionalPoints = v;
171}
172
173void QQuickSinglePointHandler::moveTarget(QPointF pos, QEventPoint &point)
174{
175 Q_D(QQuickSinglePointHandler);
176 target()->setPosition(pos);
177 d->pointInfo.m_scenePosition = point.scenePosition();
178 d->pointInfo.m_position = target()->mapFromScene(d->pointInfo.m_scenePosition);
179}
180
181void QQuickSinglePointHandler::setPointId(int id)
182{
183 Q_D(QQuickSinglePointHandler);
184 d->pointInfo.m_id = id;
185}
186
187QQuickHandlerPoint QQuickSinglePointHandler::point() const
188{
189 Q_D(const QQuickSinglePointHandler);
190 return d->pointInfo;
191}
192
193/*!
194 \readonly
195 \qmlproperty handlerPoint QtQuick::SinglePointHandler::point
196
197 The \l eventPoint currently being handled. When no point is currently being
198 handled, this object is reset to default values (all coordinates are 0).
199*/
200
201QQuickSinglePointHandlerPrivate::QQuickSinglePointHandlerPrivate()
202 : QQuickPointerDeviceHandlerPrivate()
203{
204}
205
206void QQuickSinglePointHandlerPrivate::reset()
207{
208 Q_Q(QQuickSinglePointHandler);
209 q->setActive(false);
210 pointInfo.reset();
211}
212
213QT_END_NAMESPACE
214
215#include "moc_qquicksinglepointhandler_p.cpp"