Qt 4.8
qstandardgestures.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qstandardgestures_p.h"
43 #include "qgesture.h"
44 #include "qgesture_p.h"
45 #include "qevent.h"
46 #include "qwidget.h"
47 #include "qabstractscrollarea.h"
48 #include <qgraphicssceneevent.h>
49 #include "qdebug.h"
50 
51 #ifndef QT_NO_GESTURES
52 
54 
56 {
57 }
58 
60 {
61  if (target && target->isWidgetType()) {
62 #if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
63  // for scroll areas on Windows we want to use native gestures instead
64  if (!qobject_cast<QAbstractScrollArea *>(target->parent()))
65  static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
66 #else
67  static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
68 #endif
69  }
70  return new QPanGesture;
71 }
72 
73 QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
74  QObject *,
75  QEvent *event)
76 {
77  QPanGesture *q = static_cast<QPanGesture *>(state);
78  QPanGesturePrivate *d = q->d_func();
79 
80  const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
81 
82  QGestureRecognizer::Result result;
83  switch (event->type()) {
84  case QEvent::TouchBegin: {
87  d->lastOffset = d->offset = QPointF();
88  break;
89  }
90  case QEvent::TouchEnd: {
91  if (q->state() != Qt::NoGesture) {
92  if (ev->touchPoints().size() == 2) {
95  d->lastOffset = d->offset;
96  d->offset =
97  QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
98  p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
99  }
101  } else {
103  }
104  break;
105  }
106  case QEvent::TouchUpdate: {
107  if (ev->touchPoints().size() >= 2) {
108  QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
109  QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
110  d->lastOffset = d->offset;
111  d->offset =
112  QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
113  p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
114  if (d->offset.x() > 10 || d->offset.y() > 10 ||
115  d->offset.x() < -10 || d->offset.y() < -10) {
116  q->setHotSpot(p1.startScreenPos());
118  } else {
120  }
121  }
122  break;
123  }
125  case QEvent::MouseMove:
128  break;
129  default:
131  break;
132  }
133  return result;
134 }
135 
137 {
138  QPanGesture *pan = static_cast<QPanGesture*>(state);
139  QPanGesturePrivate *d = pan->d_func();
140 
141  d->lastOffset = d->offset = QPointF();
142  d->acceleration = 0;
143 
145 }
146 
147 
148 //
149 // QPinchGestureRecognizer
150 //
151 
153 {
154 }
155 
157 {
158  if (target && target->isWidgetType()) {
159  static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
160  }
161  return new QPinchGesture;
162 }
163 
164 QGestureRecognizer::Result QPinchGestureRecognizer::recognize(QGesture *state,
165  QObject *,
166  QEvent *event)
167 {
168  QPinchGesture *q = static_cast<QPinchGesture *>(state);
169  QPinchGesturePrivate *d = q->d_func();
170 
171  const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
172 
173  QGestureRecognizer::Result result;
174 
175  switch (event->type()) {
176  case QEvent::TouchBegin: {
178  break;
179  }
180  case QEvent::TouchEnd: {
181  if (q->state() != Qt::NoGesture) {
183  } else {
185  }
186  break;
187  }
188  case QEvent::TouchUpdate: {
189  d->changeFlags = 0;
190  if (ev->touchPoints().size() == 2) {
191  QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
192  QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
193 
194  d->hotSpot = p1.screenPos();
195  d->isHotSpotSet = true;
196 
197  QPointF centerPoint = (p1.screenPos() + p2.screenPos()) / 2.0;
198  if (d->isNewSequence) {
199  d->startPosition[0] = p1.screenPos();
200  d->startPosition[1] = p2.screenPos();
201  d->lastCenterPoint = centerPoint;
202  } else {
204  }
205  d->centerPoint = centerPoint;
206 
208 
209  if (d->isNewSequence) {
210  d->scaleFactor = 1.0;
211  d->lastScaleFactor = 1.0;
212  } else {
214  QLineF line(p1.screenPos(), p2.screenPos());
215  QLineF lastLine(p1.lastScreenPos(), p2.lastScreenPos());
216  d->scaleFactor = line.length() / lastLine.length();
217  }
220 
221  qreal angle = QLineF(p1.screenPos(), p2.screenPos()).angle();
222  if (angle > 180)
223  angle -= 360;
224  qreal startAngle = QLineF(p1.startScreenPos(), p2.startScreenPos()).angle();
225  if (startAngle > 180)
226  startAngle -= 360;
227  const qreal rotationAngle = startAngle - angle;
228  if (d->isNewSequence)
229  d->lastRotationAngle = 0.0;
230  else
232  d->rotationAngle = rotationAngle;
235 
236  d->totalChangeFlags |= d->changeFlags;
237  d->isNewSequence = false;
239  } else {
240  d->isNewSequence = true;
241  if (q->state() == Qt::NoGesture)
243  else
245  }
246  break;
247  }
249  case QEvent::MouseMove:
252  break;
253  default:
255  break;
256  }
257  return result;
258 }
259 
261 {
262  QPinchGesture *pinch = static_cast<QPinchGesture *>(state);
263  QPinchGesturePrivate *d = pinch->d_func();
264 
265  d->totalChangeFlags = d->changeFlags = 0;
266 
270 
271  d->isNewSequence = true;
272  d->startPosition[0] = d->startPosition[1] = QPointF();
273 
275 }
276 
277 //
278 // QSwipeGestureRecognizer
279 //
280 
282 {
283 }
284 
286 {
287  if (target && target->isWidgetType()) {
288  static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
289  }
290  return new QSwipeGesture;
291 }
292 
293 QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
294  QObject *,
295  QEvent *event)
296 {
297  QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
298  QSwipeGesturePrivate *d = q->d_func();
299 
300  const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
301 
302  QGestureRecognizer::Result result;
303 
304  switch (event->type()) {
305  case QEvent::TouchBegin: {
306  d->velocityValue = 1;
307  d->time.start();
308  d->started = true;
310  break;
311  }
312  case QEvent::TouchEnd: {
313  if (q->state() != Qt::NoGesture) {
315  } else {
317  }
318  break;
319  }
320  case QEvent::TouchUpdate: {
321  if (!d->started)
323  else if (ev->touchPoints().size() == 3) {
324  QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
325  QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
326  QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2);
327 
328  if (d->lastPositions[0].isNull()) {
329  d->lastPositions[0] = p1.startScreenPos().toPoint();
330  d->lastPositions[1] = p2.startScreenPos().toPoint();
331  d->lastPositions[2] = p3.startScreenPos().toPoint();
332  }
333  d->hotSpot = p1.screenPos();
334  d->isHotSpotSet = true;
335 
336  int xDistance = (p1.screenPos().x() - d->lastPositions[0].x() +
337  p2.screenPos().x() - d->lastPositions[1].x() +
338  p3.screenPos().x() - d->lastPositions[2].x()) / 3;
339  int yDistance = (p1.screenPos().y() - d->lastPositions[0].y() +
340  p2.screenPos().y() - d->lastPositions[1].y() +
341  p3.screenPos().y() - d->lastPositions[2].y()) / 3;
342 
343  const int distance = xDistance >= yDistance ? xDistance : yDistance;
344  int elapsedTime = d->time.restart();
345  if (!elapsedTime)
346  elapsedTime = 1;
347  d->velocityValue = 0.9 * d->velocityValue + distance / elapsedTime;
348  d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
349 
350  static const int MoveThreshold = 50;
351  if (xDistance > MoveThreshold || yDistance > MoveThreshold) {
352  // measure the distance to check if the direction changed
353  d->lastPositions[0] = p1.screenPos().toPoint();
354  d->lastPositions[1] = p2.screenPos().toPoint();
355  d->lastPositions[2] = p3.screenPos().toPoint();
356  QSwipeGesture::SwipeDirection horizontal =
357  xDistance > 0 ? QSwipeGesture::Right : QSwipeGesture::Left;
359  yDistance > 0 ? QSwipeGesture::Down : QSwipeGesture::Up;
361  d->verticalDirection = vertical;
363  d->horizontalDirection = horizontal;
364  if (d->verticalDirection != vertical || d->horizontalDirection != horizontal) {
365  // the user has changed the direction!
367  }
369  } else {
370  if (q->state() != Qt::NoGesture)
372  else
374  }
375  } else if (ev->touchPoints().size() > 3) {
377  } else { // less than 3 touch points
378  if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed))
380  else if (d->started)
382  else
384  }
385  break;
386  }
388  case QEvent::MouseMove:
391  break;
392  default:
394  break;
395  }
396  return result;
397 }
398 
400 {
401  QSwipeGesture *q = static_cast<QSwipeGesture *>(state);
402  QSwipeGesturePrivate *d = q->d_func();
403 
405  d->swipeAngle = 0;
406 
407  d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint();
408  d->started = false;
409  d->velocityValue = 0;
410  d->time.invalidate();
411 
413 }
414 
415 //
416 // QTapGestureRecognizer
417 //
418 
420 {
421 }
422 
424 {
425  if (target && target->isWidgetType()) {
426  static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
427  }
428  return new QTapGesture;
429 }
430 
431 QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state,
432  QObject *,
433  QEvent *event)
434 {
435  QTapGesture *q = static_cast<QTapGesture *>(state);
436  QTapGesturePrivate *d = q->d_func();
437 
438  const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
439 
440  QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture;
441 
442  switch (event->type()) {
443  case QEvent::TouchBegin: {
444  d->position = ev->touchPoints().at(0).pos();
445  q->setHotSpot(ev->touchPoints().at(0).screenPos());
447  break;
448  }
449  case QEvent::TouchUpdate:
450  case QEvent::TouchEnd: {
451  if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) {
453  QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
454  enum { TapRadius = 40 };
455  if (delta.manhattanLength() <= TapRadius) {
456  if (event->type() == QEvent::TouchEnd)
458  else
460  }
461  }
462  break;
463  }
465  case QEvent::MouseMove:
468  break;
469  default:
471  break;
472  }
473  return result;
474 }
475 
477 {
478  QTapGesture *q = static_cast<QTapGesture *>(state);
479  QTapGesturePrivate *d = q->d_func();
480 
481  d->position = QPointF();
482 
484 }
485 
486 //
487 // QTapAndHoldGestureRecognizer
488 //
489 
491 {
492 }
493 
495 {
496  if (target && target->isWidgetType()) {
497  static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
498  }
499  return new QTapAndHoldGesture;
500 }
501 
502 QGestureRecognizer::Result
504  QEvent *event)
505 {
506  QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state);
507  QTapAndHoldGesturePrivate *d = q->d_func();
508 
509  if (object == state && event->type() == QEvent::Timer) {
510  q->killTimer(d->timerId);
511  d->timerId = 0;
513  }
514 
515  const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
516  const QMouseEvent *me = static_cast<const QMouseEvent *>(event);
517 #ifndef QT_NO_GRAPHICSVIEW
518  const QGraphicsSceneMouseEvent *gsme = static_cast<const QGraphicsSceneMouseEvent *>(event);
519 #endif
520 
521  enum { TapRadius = 40 };
522 
523  switch (event->type()) {
524 #ifndef QT_NO_GRAPHICSVIEW
526  d->position = gsme->screenPos();
527  q->setHotSpot(d->position);
528  if (d->timerId)
529  q->killTimer(d->timerId);
531  return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
532 #endif
534  d->position = me->globalPos();
535  q->setHotSpot(d->position);
536  if (d->timerId)
537  q->killTimer(d->timerId);
539  return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
540  case QEvent::TouchBegin:
541  d->position = ev->touchPoints().at(0).startScreenPos();
542  q->setHotSpot(d->position);
543  if (d->timerId)
544  q->killTimer(d->timerId);
546  return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout
547 #ifndef QT_NO_GRAPHICSVIEW
549 #endif
551  case QEvent::TouchEnd:
552  return QGestureRecognizer::CancelGesture; // get out of the MayBeGesture state
553  case QEvent::TouchUpdate:
554  if (d->timerId && ev->touchPoints().size() == 1) {
556  QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
557  if (delta.manhattanLength() <= TapRadius)
559  }
561  case QEvent::MouseMove: {
562  QPoint delta = me->globalPos() - d->position.toPoint();
563  if (d->timerId && delta.manhattanLength() <= TapRadius)
566  }
567 #ifndef QT_NO_GRAPHICSVIEW
569  QPoint delta = gsme->screenPos() - d->position.toPoint();
570  if (d->timerId && delta.manhattanLength() <= TapRadius)
573  }
574 #endif
575  default:
577  }
578 }
579 
581 {
582  QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state);
583  QTapAndHoldGesturePrivate *d = q->d_func();
584 
585  d->position = QPointF();
586  if (d->timerId)
587  q->killTimer(d->timerId);
588  d->timerId = 0;
589 
591 }
592 
594 
595 #endif // QT_NO_GESTURES
int startTimer(int interval)
Starts a timer and returns a timer identifier, or returns zero if it could not start a timer...
Definition: qobject.cpp:1623
double d
Definition: qnumeric_p.h:62
The QPanGesture class describes a panning gesture made by the user.
Definition: qgesture.h:107
QPoint screenPos() const
Returns the mouse cursor position in screen coordinates.
void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
double qreal
Definition: qglobal.h:1193
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPinchGesture::ChangeFlags changeFlags
Definition: qgesture_p.h:122
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event)
Handles the given event for the watched object, updating the state of the gesture object as required...
EventRef event
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
The QGraphicsSceneMouseEvent class provides mouse events in the graphics view framework.
The QTapAndHoldGesture class describes a tap-and-hold (aka LongTap) gesture made by the user...
Definition: qgesture.h:249
QPointF lastScreenPos() const
Returns the screen position of this touch point from the previous touch event.
Definition: qevent.cpp:4598
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QPointF hotSpot
Definition: qgesture_p.h:79
void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
QPointF startPosition[2]
Definition: qgesture_p.h:137
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
virtual void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
qint64 restart()
Restarts the timer and returns the time elapsed since the previous start.
QGesture * create(QObject *target)
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
QGesture * create(QObject *target)
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
QGesture * create(QObject *target)
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
Qt::GestureState state() const
int manhattanLength() const
Returns the sum of the absolute values of x() and y(), traditionally known as the "Manhattan length" ...
Definition: qpoint.cpp:489
The QPinchGesture class describes a pinch gesture made by the user.
Definition: qgesture.h:136
bool isNull() const
Returns true if both the x and y coordinates are set to 0, otherwise returns false.
Definition: qpoint.h:125
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event)
Handles the given event for the watched object, updating the state of the gesture object as required...
static int distance(QWidget *source, QWidget *target, QAccessible::RelationFlag relation)
Qt::TouchPointStates touchPointStates() const
Returns a bitwise OR of all the touch point states for this event.
Definition: qevent.h:819
void invalidate()
Marks this QElapsedTimer object as invalid.
QPointF screenPos() const
Returns the screen position of this touch point.
Definition: qevent.cpp:4498
QPointF startScreenPos() const
Returns the starting screen position of this touch point.
Definition: qevent.cpp:4547
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event)
Handles the given event for the watched object, updating the state of the gesture object as required...
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:85
QPointF startCenterPoint
Definition: qgesture_p.h:124
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event)
Handles the given event for the watched object, updating the state of the gesture object as required...
bool isWidgetType() const
Returns true if the object is a widget; otherwise returns false.
Definition: qobject.h:146
qreal angle(const QPointF &p1, const QPointF &p2)
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event)
Handles the given event for the watched object, updating the state of the gesture object as required...
QGesture * create(QObject *target)
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
QSwipeGesture::SwipeDirection horizontalDirection
Definition: qgesture_p.h:156
void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
The QGesture class represents a gesture, containing properties that describe the corresponding user i...
Definition: qgesture.h:64
QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition: qpoint.h:376
void setHotSpot(const QPointF &value)
Definition: qgesture.cpp:180
QPointF pos() const
Returns the position of this touch point, relative to the widget or QGraphicsItem that received the e...
Definition: qevent.cpp:4473
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
const QList< QTouchEvent::TouchPoint > & touchPoints() const
Returns the list of touch points contained in the touch event.
Definition: qevent.h:820
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QPinchGesture::ChangeFlags totalChangeFlags
Definition: qgesture_p.h:121
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
The TouchPoint class provides information about a touch point in a QTouchEvent.
Definition: qevent.h:744
void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
The QTouchEvent class contains parameters that describe a touch event.
Definition: qevent.h:741
The QTapGesture class describes a tap gesture made by the user.
Definition: qgesture.h:232
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
QPoint lastPositions[3]
Definition: qgesture_p.h:160
QGesture * create(QObject *target)
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
The QSwipeGesture class describes a swipe gesture made by the user.
Definition: qgesture.h:207
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
const QPoint & globalPos() const
Returns the global position of the mouse cursor at the time of the event.
Definition: qevent.h:96
SwipeDirection
This enum describes the possible directions for the gesture&#39;s motion along the horizontal and vertica...
Definition: qgesture.h:219
void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
void start()
Starts this timer.
QElapsedTimer time
Definition: qgesture_p.h:163
QPointF startPos() const
Returns the starting position of this touch point, relative to the widget or QGraphicsItem that recei...
Definition: qevent.cpp:4522
QSwipeGesture::SwipeDirection verticalDirection
Definition: qgesture_p.h:157
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition: qobject.cpp:1650