1/****************************************************************************
2**
3** Copyright (C) 2018 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qquickhandlerpoint_p.h"
41#include "private/qquickevents_p_p.h"
42
43QT_BEGIN_NAMESPACE
44Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH_TARGET)
45
46/*!
47 \qmltype HandlerPoint
48 \instantiates QQuickHandlerPoint
49 \inqmlmodule QtQuick
50 \brief An event point.
51
52 A QML representation of a QQuickEventPoint.
53
54 It's possible to make bindings to properties of a handler's current
55 \l {SinglePointHandler::point}{point} or
56 \l {MultiPointHandler::centroid}{centroid}. For example:
57
58 \snippet pointerHandlers/dragHandlerNullTarget.qml 0
59
60 The point is kept up-to-date when the DragHandler is actively responding to
61 an EventPoint; but after the point is released, or when the current point is
62 being handled by a different handler, \c position.x and \c position.y are 0.
63
64 \note This is practically identical to QtQuick::EventPoint; however an
65 EventPoint is a long-lived QObject which is invalidated between gestures
66 and reused for subsequent event deliveries. Continuous bindings to its
67 properties are not possible, and an individual handler cannot rely on it
68 outside the period when that point is part of an active gesture which that
69 handler is handling. HandlerPoint is a Q_GADGET that the handler owns.
70 This allows you to make lifetime bindings to its properties.
71
72 \sa SinglePointHandler::point, MultiPointHandler::centroid
73*/
74
75QQuickHandlerPoint::QQuickHandlerPoint()
76{}
77
78void QQuickHandlerPoint::localize(QQuickItem *item)
79{
80 m_pressPosition = item->mapFromScene(point: m_scenePressPosition);
81}
82
83void QQuickHandlerPoint::reset()
84{
85 m_id = 0;
86 m_uniqueId = QPointingDeviceUniqueId();
87 m_position = QPointF();
88 m_scenePosition = QPointF();
89 m_pressPosition = QPointF();
90 m_scenePressPosition = QPointF();
91 m_sceneGrabPosition = QPointF();
92 m_velocity = QVector2D();
93 m_rotation = 0;
94 m_pressure = 0;
95 m_ellipseDiameters = QSizeF();
96 m_pressedButtons = Qt::NoButton;
97 m_pressedModifiers = Qt::NoModifier;
98}
99
100void QQuickHandlerPoint::reset(const QQuickEventPoint *point)
101{
102 m_id = point->pointId();
103 const QQuickPointerEvent *event = point->pointerEvent();
104 switch (point->state()) {
105 case QQuickEventPoint::Pressed:
106 m_pressPosition = point->position();
107 m_scenePressPosition = point->scenePosition();
108 m_pressedButtons = event->buttons();
109 break;
110 default:
111 break;
112 }
113 m_scenePressPosition = point->scenePressPosition();
114 m_pressedButtons = event->buttons();
115 m_pressedModifiers = event->modifiers();
116 if (event->asPointerTouchEvent()) {
117 const QQuickEventTouchPoint *tp = static_cast<const QQuickEventTouchPoint *>(point);
118 m_uniqueId = tp->uniqueId();
119 m_rotation = tp->rotation();
120 m_pressure = tp->pressure();
121 m_ellipseDiameters = tp->ellipseDiameters();
122#if QT_CONFIG(tabletevent)
123 } else if (event->asPointerTabletEvent()) {
124 m_uniqueId = event->device()->uniqueId();
125 m_rotation = static_cast<const QQuickEventTabletPoint *>(point)->rotation();
126 m_pressure = static_cast<const QQuickEventTabletPoint *>(point)->pressure();
127 m_ellipseDiameters = QSizeF();
128#endif
129 } else {
130 m_uniqueId = event->device()->uniqueId();
131 m_rotation = 0;
132 m_pressure = event->buttons() ? 1 : 0;
133 m_ellipseDiameters = QSizeF();
134 }
135 m_position = point->position();
136 m_scenePosition = point->scenePosition();
137 if (point->state() == QQuickEventPoint::Updated)
138 m_velocity = point->velocity();
139}
140
141void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
142{
143 if (points.isEmpty()) {
144 qWarning(msg: "reset: no points");
145 return;
146 }
147 if (points.count() == 1) {
148 *this = points.first(); // copy all values
149 return;
150 }
151 // all points are required to be from the same event
152 QPointF posSum;
153 QPointF scenePosSum;
154 QPointF pressPosSum;
155 QPointF scenePressPosSum;
156 QVector2D velocitySum;
157 qreal pressureSum = 0;
158 QSizeF ellipseDiameterSum;
159 for (const QQuickHandlerPoint &point : points) {
160 posSum += point.position();
161 scenePosSum += point.scenePosition();
162 pressPosSum += point.pressPosition();
163 scenePressPosSum += point.scenePressPosition();
164 velocitySum += point.velocity();
165 pressureSum += point.pressure();
166 ellipseDiameterSum += point.ellipseDiameters();
167 }
168 m_id = 0;
169 m_uniqueId = QPointingDeviceUniqueId();
170 // all points are required to be from the same event, so pressed buttons and modifiers should be the same
171 m_pressedButtons = points.first().pressedButtons();
172 m_pressedModifiers = points.first().modifiers();
173 m_position = posSum / points.size();
174 m_scenePosition = scenePosSum / points.size();
175 m_pressPosition = pressPosSum / points.size();
176 m_scenePressPosition = scenePressPosSum / points.size();
177 m_velocity = velocitySum / points.size();
178 m_rotation = 0; // averaging the rotations of all the points isn't very sensible
179 m_pressure = pressureSum / points.size();
180 m_ellipseDiameters = ellipseDiameterSum / points.size();
181}
182
183/*!
184 \readonly
185 \qmlproperty int QtQuick::HandlerPoint::id
186 \brief The ID number of the point
187
188 During a touch gesture, from the time that the first finger is pressed
189 until the last finger is released, each touchpoint will have a unique ID
190 number. Likewise, if input from multiple devices occurs (for example
191 simultaneous mouse and touch presses), all the current event points from
192 all the devices will have unique IDs.
193
194 \note Do not assume that id numbers start at zero or that they are
195 sequential. Such an assumption is often false due to the way the underlying
196 drivers work.
197
198 \sa QTouchEvent::TouchPoint::id
199*/
200
201/*!
202 \readonly
203 \qmlproperty PointingDeviceUniqueId QtQuick::HandlerPoint::uniqueId
204 \brief The unique ID of the point, if any
205
206 This is normally empty, because touchscreens cannot uniquely identify fingers.
207
208 On some types of touchscreens, especially those using TUIO drivers,
209 it's possible to use recognizable physical tokens (fiducial objects)
210 in addition to fingers. So if this point is a touch point, and
211 uniqueId is set, it is the identifier for such an object.
212
213 On a graphics tablet, each type of stylus or other tool often has a unique
214 ID or serial number, which can be useful to respond in different ways to
215 different tools.
216
217 Interpreting the contents of this ID requires knowledge of the hardware and
218 drivers in use.
219
220 \sa QTabletEvent::uniqueId, QtQuick::TouchPoint::uniqueId, QtQuick::EventTouchPoint::uniqueId
221*/
222
223/*!
224 \readonly
225 \qmlproperty QPointF QtQuick::HandlerPoint::position
226 \brief The position within the \c parent Item
227
228 This is the position of the event point relative to the bounds of
229 the \l {PointerHandler::parent} {parent}.
230*/
231
232/*!
233 \readonly
234 \qmlproperty QPointF QtQuick::HandlerPoint::scenePosition
235 \brief The position within the scene
236
237 This is the position of the event point relative to the bounds of the Qt
238 Quick scene (typically the whole window).
239*/
240
241/*!
242 \readonly
243 \qmlproperty QPointF QtQuick::HandlerPoint::pressPosition
244 \brief The pressed position within the \c parent Item
245
246 This is the position at which this point was pressed, relative to the
247 bounds of the \l {PointerHandler::parent} {parent}.
248*/
249
250/*!
251 \readonly
252 \qmlproperty QPointF QtQuick::HandlerPoint::scenePressPosition
253 \brief The pressed position within the scene
254
255 This is the position at which this point was pressed, in the coordinate
256 system of the \l {Qt Quick Scene Graph}{scene graph}.
257*/
258
259/*!
260 \readonly
261 \qmlproperty QPointF QtQuick::HandlerPoint::sceneGrabPosition
262 \brief The grabbed position within the scene
263
264 If this point has been grabbed by a Pointer Handler or an Item, it means
265 that object has taken sole responsibility for handling the movement and the
266 release if this point. In that case, this is the position at which the grab
267 occurred, in the coordinate system of the \l {Qt Quick Scene Graph}{scene graph}.
268*/
269
270/*!
271 \readonly
272 \qmlproperty enumeration QtQuick::HandlerPoint::pressedButtons
273 \brief Which mouse or stylus buttons are currently pressed
274
275 \sa MouseArea::pressedButtons
276*/
277
278/*!
279 \readonly
280 \qmlproperty enumeration QtQuick::HandlerPoint::modifiers
281 \brief Which modifier keys are currently pressed
282
283 This property holds the keyboard modifiers that were pressed at the time
284 the event occurred.
285*/
286
287/*!
288 \readonly
289 \qmlproperty QVector2D QtQuick::HandlerPoint::velocity
290 \brief A vector representing the average speed and direction of movement
291
292 This is a velocity vector pointing in the direction of movement, in logical
293 pixels per second. It has x and y components, at least one of which will be
294 nonzero when this point is in motion. It holds the average recent velocity:
295 how fast and in which direction the event point has been moving recently.
296
297 \sa QtQuick::EventPoint::velocity, QtQuick::TouchPoint::velocity, QTouchEvent::TouchPoint::velocity
298*/
299
300/*!
301 \readonly
302 \qmlproperty qreal QtQuick::HandlerPoint::rotation
303
304 This property holds the rotation angle of the stylus on a graphics tablet
305 or the contact patch of a touchpoint on a touchscreen.
306
307 It is valid only with certain tablet stylus devices and touchscreens that
308 can measure the rotation angle. Otherwise, it will be zero.
309*/
310
311/*!
312 \readonly
313 \qmlproperty qreal QtQuick::HandlerPoint::pressure
314
315 This property tells how hard the user is pressing the stylus on a graphics
316 tablet or the finger against a touchscreen, in the range from \c 0 (no
317 measurable pressure) to \c 1.0 (maximum pressure which the device can
318 measure).
319
320 It is valid only with certain tablets and touchscreens that can measure
321 pressure. Otherwise, it will be zero.
322*/
323
324/*!
325 \readonly
326 \qmlproperty size QtQuick::HandlerPoint::ellipseDiameters
327
328 This property holds the diameters of the contact patch, if the event
329 comes from a touchpoint and the device provides this information.
330
331 A touchpoint is modeled as an elliptical area where the finger is pressed
332 against the touchscreen. (In fact, it could also be modeled as a bitmap;
333 but in that case we expect an elliptical bounding estimate to be fitted to
334 the contact patch before the event is sent.) The harder the user presses,
335 the larger the contact patch; so, these diameters provide an alternate way
336 of detecting pressure, in case the device does not include a separate
337 pressure sensor. The ellipse is centered on \l scenePosition (\l position
338 in the PointerHandler's Item's local coordinates). The \l rotation property
339 provides the rotation of the ellipse, if known. It is expected that if the
340 \l rotation is zero, the \l {QSize::height}{height} is the larger dimension
341 (the major axis), because of the usual hand position, reaching upward or
342 outward across the surface.
343
344 If the contact patch is unknown, or the device is not a touchscreen,
345 these values will be zero.
346
347 \sa QtQuick::EventTouchPoint::ellipseDiameters, QtQuick::TouchPoint::ellipseDiameters, QTouchEvent::TouchPoint::ellipseDiameters
348*/
349
350QT_END_NAMESPACE
351

source code of qtdeclarative/src/quick/handlers/qquickhandlerpoint.cpp