1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt for Python.
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 #ifndef PYSIDEQTESTTOUCH_H
41 #define PYSIDEQTESTTOUCH_H
42 
43 #include <QtTest/qttestglobal.h>
44 #include <QtTest/qtestassert.h>
45 #include <QtTest/qtestsystem.h>
46 #include <QtTest/qtestspontaneevent.h>
47 #include <QtTest/qtesttouch.h>
48 
49 #include <QtCore/qmap.h>
50 #include <QtGui/qevent.h>
51 #include <QtGui/qwindow.h>
52 #ifdef QT_WIDGETS_LIB
53 #include <QtWidgets/qwidget.h>
54 #endif
55 
56 QT_BEGIN_NAMESPACE
57 
58 namespace QTest
59 {
60 
61     class PySideQTouchEventSequence
62     {
63     public:
~PySideQTouchEventSequence()64         ~PySideQTouchEventSequence()
65         {
66             if (commitWhenDestroyed)
67                 commit();
68         }
69         PySideQTouchEventSequence *press(int touchId, const QPoint &pt, QWindow *window = nullptr)
70         {
71             QTouchEvent::TouchPoint &p = point(touchId);
72             p.setScreenPos(mapToScreen(window, pt));
73             p.setState(Qt::TouchPointPressed);
74             return this;
75         }
76         PySideQTouchEventSequence *move(int touchId, const QPoint &pt, QWindow *window = nullptr)
77         {
78             QTouchEvent::TouchPoint &p = point(touchId);
79             p.setScreenPos(mapToScreen(window, pt));
80             p.setState(Qt::TouchPointMoved);
81             return this;
82         }
83         PySideQTouchEventSequence *release(int touchId, const QPoint &pt, QWindow *window = nullptr)
84         {
85             QTouchEvent::TouchPoint &p = point(touchId);
86             p.setScreenPos(mapToScreen(window, pt));
87             p.setState(Qt::TouchPointReleased);
88             return this;
89         }
stationary(int touchId)90         PySideQTouchEventSequence *stationary(int touchId)
91         {
92             QTouchEvent::TouchPoint &p = pointOrPreviousPoint(touchId);
93             p.setState(Qt::TouchPointStationary);
94             return this;
95         }
96 
97 #ifdef QT_WIDGETS_LIB
98         PySideQTouchEventSequence *press(int touchId, const QPoint &pt, QWidget *widget = nullptr)
99         {
100             QTouchEvent::TouchPoint &p = point(touchId);
101             p.setScreenPos(mapToScreen(widget, pt));
102             p.setState(Qt::TouchPointPressed);
103             return this;
104         }
105 
106         PySideQTouchEventSequence *move(int touchId, const QPoint &pt, QWidget *widget = nullptr)
107         {
108             QTouchEvent::TouchPoint &p = point(touchId);
109             p.setScreenPos(mapToScreen(widget, pt));
110             p.setState(Qt::TouchPointMoved);
111             return this;
112         }
113 
114         PySideQTouchEventSequence *release(int touchId, const QPoint &pt, QWidget *widget = nullptr)
115         {
116             QTouchEvent::TouchPoint &p = point(touchId);
117             p.setScreenPos(mapToScreen(widget, pt));
118             p.setState(Qt::TouchPointReleased);
119             return this;
120         }
121 #endif
122 
123         void commit(bool processEvents = true)
124         {
125             if (!points.isEmpty()) {
126                 if (targetWindow)
127                 {
128                     qt_handleTouchEvent(targetWindow, device, points.values());
129                 }
130 #ifdef QT_WIDGETS_LIB
131                 else if (targetWidget)
132                 {
133                     qt_handleTouchEvent(targetWidget->windowHandle(), device, points.values());
134                 }
135 #endif
136             }
137             if (processEvents)
138                 QCoreApplication::processEvents();
139             previousPoints = points;
140             points.clear();
141         }
142 
143 private:
144 #ifdef QT_WIDGETS_LIB
PySideQTouchEventSequence(QWidget * widget,QTouchDevice * aDevice,bool autoCommit)145         PySideQTouchEventSequence(QWidget *widget, QTouchDevice *aDevice, bool autoCommit)
146             : targetWidget(widget), targetWindow(0), device(aDevice), commitWhenDestroyed(autoCommit)
147         {
148         }
149 #endif
PySideQTouchEventSequence(QWindow * window,QTouchDevice * aDevice,bool autoCommit)150         PySideQTouchEventSequence(QWindow *window, QTouchDevice *aDevice, bool autoCommit)
151             :
152 #ifdef QT_WIDGETS_LIB
153               targetWidget(0),
154 #endif
155               targetWindow(window), device(aDevice), commitWhenDestroyed(autoCommit)
156         {
157         }
158 
point(int touchId)159         QTouchEvent::TouchPoint &point(int touchId)
160         {
161             if (!points.contains(touchId))
162                 points[touchId] = QTouchEvent::TouchPoint(touchId);
163             return points[touchId];
164         }
165 
pointOrPreviousPoint(int touchId)166         QTouchEvent::TouchPoint &pointOrPreviousPoint(int touchId)
167         {
168             if (!points.contains(touchId)) {
169                 if (previousPoints.contains(touchId))
170                     points[touchId] = previousPoints.value(touchId);
171                 else
172                     points[touchId] = QTouchEvent::TouchPoint(touchId);
173             }
174             return points[touchId];
175         }
176 
177 #ifdef QT_WIDGETS_LIB
mapToScreen(QWidget * widget,const QPoint & pt)178         QPoint mapToScreen(QWidget *widget, const QPoint &pt)
179         {
180             if (widget)
181                 return widget->mapToGlobal(pt);
182             return targetWidget ? targetWidget->mapToGlobal(pt) : pt;
183         }
184 #endif
mapToScreen(QWindow * window,const QPoint & pt)185         QPoint mapToScreen(QWindow *window, const QPoint &pt)
186         {
187             if(window)
188                 return window->mapToGlobal(pt);
189             return targetWindow ? targetWindow->mapToGlobal(pt) : pt;
190         }
191 
192         QMap<int, QTouchEvent::TouchPoint> previousPoints;
193         QMap<int, QTouchEvent::TouchPoint> points;
194 #ifdef QT_WIDGETS_LIB
195         QWidget *targetWidget;
196 #endif
197         QWindow *targetWindow;
198         QTouchDevice *device;
199         bool commitWhenDestroyed;
200 #ifdef QT_WIDGETS_LIB
201         friend PySideQTouchEventSequence *generateTouchEvent(QWidget *, QTouchDevice *, bool);
202 #endif
203         friend PySideQTouchEventSequence *generateTouchEvent(QWindow *, QTouchDevice *, bool);
204     };
205 
206 #ifdef QT_WIDGETS_LIB
207     inline
208     PySideQTouchEventSequence *generateTouchEvent(QWidget *widget,
209                                                   QTouchDevice *device,
210                                                   bool autoCommit = true)
211     {
212         return new PySideQTouchEventSequence(widget, device, autoCommit);
213     }
214 #endif
215     inline
216     PySideQTouchEventSequence *generateTouchEvent(QWindow *window,
217                                                   QTouchDevice *device,
218                                                   bool autoCommit = true)
219     {
220         return new PySideQTouchEventSequence(window, device, autoCommit);
221     }
222 
223 }
224 
225 QT_END_NAMESPACE
226 
227 #endif // PYSIDEQTESTTOUCH_H
228