QtBase  v6.3.1
tst_qgesturerecognizer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 
30 #include <QtTest/QTest>
31 #include <QtWidgets/QApplication>
32 #include <QtWidgets/QWidget>
33 #include <QtWidgets/QGestureEvent>
34 #include <QtGui/QScreen>
35 #include <QtGui/QPointingDevice>
36 #include <QtCore/QList>
37 #include <QtCore/QString>
38 #include <QtCore/QHash>
39 #include <QtCore/QDebug>
40 
42 {
43  Q_OBJECT
44 public:
46 
47 private Q_SLOTS:
48  void initTestCase();
49 #ifndef QT_NO_GESTURES
50  void panGesture_data();
51  void panGesture();
52  void pinchGesture_data();
53  void pinchGesture();
54  void swipeGesture_data();
55  void swipeGesture();
56  void touchReplay();
57 #endif // !QT_NO_GESTURES
58 
59 private:
60  const int m_fingerDistance;
61  QPointingDevice *m_touchDevice;
62 };
63 
65  : m_fingerDistance(qRound(QGuiApplication::primaryScreen()->physicalDotsPerInch() / 2.0))
66  , m_touchDevice(QTest::createTouchDevice())
67 {
68  qputenv("QT_PAN_TOUCHPOINTS", "2"); // Prevent device detection of pan touch point count.
69 }
70 
71 void tst_QGestureRecognizer::initTestCase()
72 {
73 }
74 
75 #ifndef QT_NO_GESTURES
76 
78 
79 class TestWidget : public QWidget
80 {
81 public:
82  explicit TestWidget(const GestureTypeVector &gestureTypes);
83 
84  bool gestureReceived(Qt::GestureType gestureType) const
85  { return m_receivedGestures.value(gestureType); }
86 
87 protected:
88  bool event(QEvent * event) override;
89 
90 private:
91  typedef QHash<Qt::GestureType, bool> GestureTypeHash;
92  GestureTypeHash m_receivedGestures;
93 };
94 
96 {
98 
99  foreach (Qt::GestureType gestureType, gestureTypes) {
100  grabGesture(gestureType);
101  m_receivedGestures.insert(gestureType, false);
102  }
103 
105  const QSize size = geometry.size() / 2;
106  resize(size);
107  move(geometry.center() - QPoint(size.width() / 2, size.height() / 2));
108 }
109 
111 {
112  switch (event->type()) {
113  case QEvent::Gesture: {
114  const QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event);
115  const GestureTypeHash::iterator hend = m_receivedGestures.end();
116  for (GestureTypeHash::iterator it = m_receivedGestures.begin(); it != hend; ++it) {
117  if (const QGesture *gesture = gestureEvent->gesture(it.key())) {
118  if (gesture->state() == Qt::GestureFinished)
119  it.value() = true;
120  }
121  }
122  }
123  break;
124  default:
125  break;
126  }
127  return QWidget::event(event);
128 }
129 
130 static void pressSequence(QTest::QTouchEventWidgetSequence &sequence, QList<QPoint> &points,
131  QWidget *widget)
132 {
133  const int pointCount = points.size();
134  for (int p = 0; p < pointCount; ++p)
135  sequence.press(p, points.at(p), widget);
136  sequence.commit();
137 }
138 
139 static void linearSequence(int n, const QPoint &delta, QTest::QTouchEventWidgetSequence &sequence,
141 {
142  const int pointCount = points.size();
143  for (int s = 0; s < n; ++s) {
144  for (int p = 0; p < pointCount; ++p) {
145  points[p] += delta;
146  sequence.move(p, points[p], widget);
147  }
148  sequence.commit();
149  }
150 }
151 
152 static void releaseSequence(QTest::QTouchEventWidgetSequence &sequence, QList<QPoint> &points,
153  QWidget *widget)
154 {
155  const int pointCount = points.size();
156  for (int p = 0; p < pointCount; ++p)
157  sequence.release(p, points[p], widget);
158  sequence.commit();
159 }
160 
161 // --- Pan
162 
165 };
166 
167 void tst_QGestureRecognizer::panGesture_data()
168 {
169  QTest::addColumn<int>("panSubTest");
170  QTest::addColumn<bool>("gestureExpected");
171  QTest::newRow("Two finger") << int(TwoFingerPanSubTest) << true;
172 }
173 
174 void tst_QGestureRecognizer::panGesture()
175 {
176  QFETCH(int, panSubTest);
177  QFETCH(bool, gestureExpected);
178 
179  Q_UNUSED(panSubTest); // Single finger pan will be added later.
180 
181  const int panPoints = 2;
182  const Qt::GestureType gestureType = Qt::PanGesture;
183  TestWidget widget(GestureTypeVector(1, gestureType));
185  widget.show();
187 
189  for (int i = 0; i < panPoints; ++i)
190  points.append(QPoint(10 + i *20, 10 + i *20));
191 
192  QTest::QTouchEventWidgetSequence panSequence = QTest::touchEvent(&widget, m_touchDevice);
193  pressSequence(panSequence, points, &widget);
194  linearSequence(5, QPoint(20, 20), panSequence, points, &widget);
195  releaseSequence(panSequence, points, &widget);
196 
197  if (gestureExpected) {
198  QTRY_VERIFY(widget.gestureReceived(gestureType));
199  } else {
201  QVERIFY(!widget.gestureReceived(gestureType));
202  }
203 }
204 
205 // --- Pinch
206 
209 };
210 
211 void tst_QGestureRecognizer::pinchGesture_data()
212 {
213  QTest::addColumn<int>("pinchSubTest");
214  QTest::addColumn<bool>("gestureExpected");
215  QTest::newRow("Standard") << int(StandardPinchSubTest) << true;
216 }
217 
218 void tst_QGestureRecognizer::pinchGesture()
219 {
220  QFETCH(int, pinchSubTest);
221  QFETCH(bool, gestureExpected);
222 
223  Q_UNUSED(pinchSubTest);
224 
225  const Qt::GestureType gestureType = Qt::PinchGesture;
226  TestWidget widget(GestureTypeVector(1, gestureType));
228  widget.show();
230 
232  points.append(widget.rect().center());
233  points.append(points.front() + QPoint(0, 20));
234 
235  QTest::QTouchEventWidgetSequence pinchSequence = QTest::touchEvent(&widget, m_touchDevice);
236  pressSequence(pinchSequence, points, &widget);
237 
238  for (int s = 0; s < 5; ++s) {
239  points[0] += QPoint(5, 30);
240  pinchSequence.move(0, points[0], &widget);
241  points[1] += QPoint(5, -30);
242  pinchSequence.move(1, points[1], &widget);
243  pinchSequence.commit();
244  }
245 
246  releaseSequence(pinchSequence, points, &widget);
247 
248  if (gestureExpected) {
249  QTRY_VERIFY(widget.gestureReceived(gestureType));
250  } else {
252  QVERIFY(!widget.gestureReceived(gestureType));
253  }
254 }
255 
256 // --- Swipe
257 
262 };
263 
264 void tst_QGestureRecognizer::swipeGesture_data()
265 {
266  QTest::addColumn<int>("swipeSubTest");
267  QTest::addColumn<bool>("gestureExpected");
268  QTest::newRow("Line") << int(SwipeLineSubTest) << true;
269  QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << false;
270  QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << true;
271 }
272 
273 void tst_QGestureRecognizer::swipeGesture()
274 {
275  enum { swipePoints = 3 };
276 
277  QFETCH(int, swipeSubTest);
278  QFETCH(bool, gestureExpected);
279 
280  const Qt::GestureType gestureType = Qt::SwipeGesture;
281  TestWidget widget(GestureTypeVector(1, gestureType));
283  widget.show();
285 
286  // Start a swipe sequence with 2 points (QTBUG-15768)
287  const QPoint fingerDistance(m_fingerDistance, m_fingerDistance);
289  for (int i = 0; i < swipePoints - 1; ++i)
290  points.append(fingerDistance + i * fingerDistance);
291 
292  QTest::QTouchEventWidgetSequence swipeSequence = QTest::touchEvent(&widget, m_touchDevice);
293  pressSequence(swipeSequence, points, &widget);
294 
295  // Press point #3
296  points.append(points.last() + fingerDistance);
297  swipeSequence.stationary(0).stationary(1).press(points.size() - 1, points.last(), &widget);
298  swipeSequence.commit();
299  Q_ASSERT(points.size() == swipePoints);
300 
301  // Move.
302  const QPoint moveDelta(60, 20);
303  switch (swipeSubTest) {
304  case SwipeLineSubTest:
305  linearSequence(5, moveDelta, swipeSequence, points, &widget);
306  break;
308  linearSequence(5, moveDelta, swipeSequence, points, &widget);
309  linearSequence(3, QPoint(-moveDelta.x(), moveDelta.y()), swipeSequence, points, &widget);
310  break;
311  case SwipeSmallDirectionChangeSubTest: { // QTBUG-46195, small changes in direction should not cause the gesture to be canceled.
312  const QPoint smallChangeMoveDelta(50, 1);
313  linearSequence(5, smallChangeMoveDelta, swipeSequence, points, &widget);
314  linearSequence(1, QPoint(smallChangeMoveDelta.x(), -3), swipeSequence, points, &widget);
315  linearSequence(5, smallChangeMoveDelta, swipeSequence, points, &widget);
316  }
317  break;
318  }
319 
320  releaseSequence(swipeSequence, points, &widget);
321 
322  if (gestureExpected) {
323  QTRY_VERIFY(widget.gestureReceived(gestureType));
324  } else {
326  QVERIFY(!widget.gestureReceived(gestureType));
327  }
328 }
329 
330 void tst_QGestureRecognizer::touchReplay()
331 {
332  const Qt::GestureType gestureType = Qt::TapGesture;
333  QWidget parent;
334  TestWidget widget(GestureTypeVector(1, gestureType));
336  widget.setGeometry(0, 0, 100, 100);
337  parent.adjustSize();
338  parent.show();
340 
341  QWindow* windowHandle = parent.window()->windowHandle();
342  const QPoint globalPos = QPoint(42, 16);
343  QTest::touchEvent(windowHandle, m_touchDevice).press(1, globalPos);
344  QTest::touchEvent(windowHandle, m_touchDevice).release(1, globalPos);
345 
346  QVERIFY(widget.gestureReceived(gestureType));
347 }
348 
349 #endif // !QT_NO_GESTURES
350 
352 
353 #include "tst_qgesturerecognizer.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ Gesture
Definition: qcoreevent.h:266
The QGestureEvent class provides the description of triggered gestures.
Definition: qgesture.h:276
QGesture * gesture(Qt::GestureType type) const
Definition: qgesture.cpp:905
The QGesture class represents a gesture, containing properties that describe the corresponding user i...
Definition: qgesture.h:62
QRectF geometry
the geometry of the widget
void resize(const QSizeF &size)
void setAttribute(Qt::WidgetAttribute attribute, bool on=true)
The QGuiApplication class manages the GUI application's control flow and main settings.
QScreen * primaryScreen
the primary (or default) screen of the application.
iterator begin()
Definition: qhash.h:1155
T value(const Key &key) const noexcept
Definition: qhash.h:997
iterator end() noexcept
Definition: qhash.h:1159
iterator insert(const Key &key, const T &value)
Definition: qhash.h:1228
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
QObject * parent() const
Definition: qobject.h:409
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
constexpr QPointF center() const noexcept
Definition: qrect.h:708
constexpr QSizeF size() const noexcept
Definition: qrect.h:744
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
constexpr QPoint center() const noexcept
Definition: qrect.h:260
QRect availableGeometry
the screen's available geometry in pixels
Definition: qscreen.h:82
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
QTouchEventSequence & press(int touchId, const QPoint &pt, QWindow *window=nullptr)
QTouchEventSequence & release(int touchId, const QPoint &pt, QWindow *window=nullptr)
void commit(bool processEvents=true) override
QTouchEventWidgetSequence & press(int touchId, const QPoint &pt, QWidget *widget=nullptr)
QTouchEventWidgetSequence & stationary(int touchId) override
QTouchEventWidgetSequence & move(int touchId, const QPoint &pt, QWidget *widget=nullptr)
QTouchEventWidgetSequence & release(int touchId, const QPoint &pt, QWidget *widget=nullptr)
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
void setGeometry(int x, int y, int w, int h)
Definition: qwidget.h:919
void setParent(QWidget *parent)
Definition: qwidget.cpp:10512
void move(int x, int y)
Definition: qwidget.h:913
QRect rect
the internal geometry of the widget excluding any window frame
Definition: qwidget.h:150
void show()
Definition: qwidget.cpp:7825
void grabGesture(Qt::GestureType type, Qt::GestureFlags flags=Qt::GestureFlags())
Definition: qwidget.cpp:12249
void setWindowTitle(const QString &)
Definition: qwidget.cpp:6119
bool event(QEvent *event) override
Definition: qwidget.cpp:8772
The QWindow class represents a window in the underlying windowing system.
Definition: qwindow.h:99
bool gestureReceived(Qt::GestureType gestureType) const
bool event(QEvent *event) override
QOpenGLWidget * widget
[1]
[15]
Definition: tst_encoder.cpp:33
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT const char * currentTestFunction()
Definition: qtestcase.cpp:2749
Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType=QInputDevice::DeviceType::TouchScreen, QInputDevice::Capabilities caps=QInputDevice::Capability::Position)
Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout=5000)
Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout=5000)
QTouchEventSequence touchEvent(QWindow *window, QPointingDevice *device, bool autoCommit=true)
Definition: qtesttouch.h:78
@ WA_AcceptTouchEvents
Definition: qnamespace.h:429
@ GestureFinished
Definition: qnamespace.h:1636
GestureType
Definition: qnamespace.h:1641
@ SwipeGesture
Definition: qnamespace.h:1646
@ PinchGesture
Definition: qnamespace.h:1645
@ PanGesture
Definition: qnamespace.h:1644
@ TapGesture
Definition: qnamespace.h:1642
int qRound(qfloat16 d) noexcept
Definition: qfloat16.h:227
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat n
struct _cl_event * event
Definition: qopenglext.h:2998
GLfixed GLfixed GLint GLint GLfixed points
Definition: qopenglext.h:5206
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define QTRY_VERIFY(expr)
Definition: qtestcase.h:196
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define Q_SLOTS
Definition: qtmetamacros.h:80
Q_UNUSED(salary)
[21]
QStringList::Iterator it
@ StandardPinchSubTest
@ SwipeSmallDirectionChangeSubTest
@ SwipeDirectionChangeSubTest
@ TwoFingerPanSubTest
QList< Qt::GestureType > GestureTypeVector