2 * Copyright (C) 2014 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17#include <qpa/qwindowsysteminterface.h>
21#include <QSharedPointer>
22#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
23 #include <private/qquickwindow_p.h>
30#include <TouchRegistry.h>
32class TestItem : public QQuickItem
37 QList<QSharedPointer<QTouchEvent>> touchEventsReceived;
40 void touchEvent(QTouchEvent *event) override;
43class CandidateItem : public QQuickItem
48 std::function<void(QTouchEvent*)> touchEventHandler;
51 void touchEvent(QTouchEvent *event) override;
54class tst_TouchGate : public QObject
58 tst_TouchGate(QObject *parent = nullptr);
60 void initTestCase(); // will be called before the first test function is executed
61 void cleanupTestCase(); // will be called after the last test function was executed.
63 void init(); // called right before each and every test function is executed
64 void cleanup(); // called right after each and every test function is executed
66 void onlyCandidate_passThrough();
67 void holdsEventsUntilGainsOwnership();
68 void holdsEventsUntilGainsOwnership_data();
69 void holdsEventsUntilGainsOwnership_repeatingTouchId();
70 void dontDispacthToDisabledOrInvisibleTarget();
71 void dontDispacthToDisabledOrInvisibleTarget_data();
74 QQuickView *createView();
75 TouchRegistry *touchRegistry;
80tst_TouchGate::tst_TouchGate(QObject *parent)
82 , touchRegistry(nullptr)
88void tst_TouchGate::initTestCase()
91 device = new QTouchDevice;
92 device->setType(QTouchDevice::TouchScreen);
93 QWindowSystemInterface::registerTouchDevice(device);
97void tst_TouchGate::cleanupTestCase()
101void tst_TouchGate::init()
103 touchRegistry = new TouchRegistry;
106 view->installEventFilter(touchRegistry);
107 view->setSource(QUrl::fromLocalFile("touchGateExample.qml"));
109 QVERIFY(QTest::qWaitForWindowExposed(view));
110 QVERIFY(view->rootObject() != 0);
111 qApp->processEvents();
114void tst_TouchGate::cleanup()
119 delete touchRegistry;
120 touchRegistry = nullptr;
123QQuickView *tst_TouchGate::createView()
125 QQuickView *window = new QQuickView(0);
126 window->setResizeMode(QQuickView::SizeRootObjectToView);
127 window->resize(720, 720);
128 window->engine()->addImportPath(QLatin1String(UBUNTU_GESTURES_PLUGIN_DIR));
134 Simplest case. TouchGate is the only candidate for the touch point, thus it
135 will instantly gain ownership causing the event to pass through it directly to
138void tst_TouchGate::onlyCandidate_passThrough()
140 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
143 TestItem *testItem = new TestItem;
144 testItem->setWidth(touchGate->width());
145 testItem->setHeight(touchGate->height());
146 testItem->setParentItem(view->rootObject());
149 touchGate->setZ(1.0);
150 touchGate->setTargetItem(testItem);
152 QTest::touchEvent(view, device)
153 .press(0, QPoint(100,100));
155 QCOMPARE(testItem->touchEventsReceived.count(), 1);
156 QVERIFY(touchGate->m_storedEvents.isEmpty());
159void tst_TouchGate::holdsEventsUntilGainsOwnership()
161 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
163 QFETCH(bool, ownershipAfterTouchEnd);
165 TestItem *testItem = new TestItem;
166 testItem->setWidth(touchGate->width());
167 testItem->setHeight(touchGate->height());
168 testItem->setParentItem(view->rootObject());
171 touchGate->setZ(1.0);
172 touchGate->setTargetItem(testItem);
174 // Put it in front of touchGate
175 CandidateItem *candidateItem = new CandidateItem;
176 candidateItem->setWidth(touchGate->width());
177 candidateItem->setHeight(touchGate->height());
178 candidateItem->setParentItem(view->rootObject());
179 candidateItem->setZ(2.0);
181 candidateItem->touchEventHandler = [&](QTouchEvent* event) {
182 touchRegistry->addCandidateOwnerForTouch(0, candidateItem);
186 QTest::touchEvent(view, device)
187 .press(0, QPoint(100,100));
189 QCOMPARE(testItem->touchEventsReceived.count(), 0);
191 QTest::touchEvent(view, device)
192 .move(0, QPoint(101,101));
194 QCOMPARE(testItem->touchEventsReceived.count(), 0);
196 if (!ownershipAfterTouchEnd) {
197 touchRegistry->removeCandidateOwnerForTouch(0, candidateItem);
198#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
199 QQuickWindowPrivate *wp = QQuickWindowPrivate::get(testItem->window());
200 wp->flushDelayedTouchEvent();
202 // TouchGate should now open its flood gates and let testItem get all
203 // events from touch 0 produced so far
204 QCOMPARE(testItem->touchEventsReceived.count(), 2);
207 QTest::touchEvent(view, device)
208 .release(0, QPoint(101,101));
210 if (ownershipAfterTouchEnd) {
211 QCOMPARE(testItem->touchEventsReceived.count(), 0);
212 touchRegistry->removeCandidateOwnerForTouch(0, candidateItem);
213 // TouchGate should now open its flood gates and let testItem get all
214 // events from touch 0 produced so far
217 QCOMPARE(testItem->touchEventsReceived.count(), 3);
219 QVERIFY(touchGate->m_storedEvents.isEmpty());
220 QVERIFY(touchGate->m_touchInfoMap.isEmpty());
223void tst_TouchGate::holdsEventsUntilGainsOwnership_data()
225 QTest::addColumn<bool>("ownershipAfterTouchEnd");
227 QTest::newRow("touch end after touch ownership") << false;
228 QTest::newRow("touch ownership after touch end") << true;
232 A touch point of id 0 starts and ends. Then the next touch point is also given
233 id 0. Check that TouchGate behaves correcly recognizing them as two distinct touch
236 Note that this won't be a problem with Mir as it assigns unique ids for the touch
239void tst_TouchGate::holdsEventsUntilGainsOwnership_repeatingTouchId()
241 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
244 TestItem *testItem = new TestItem;
245 testItem->setWidth(touchGate->width());
246 testItem->setHeight(touchGate->height());
247 testItem->setParentItem(view->rootObject());
250 touchGate->setZ(1.0);
251 touchGate->setTargetItem(testItem);
253 QTest::touchEvent(view, device)
254 .press(0, QPoint(100,100));
255 QTest::touchEvent(view, device)
256 .move(0, QPoint(101,101));
257 QTest::touchEvent(view, device)
258 .release(0, QPoint(101,101));
260 QCOMPARE(testItem->touchEventsReceived.count(), 3);
261 testItem->touchEventsReceived.clear();
263 // Put it in front of touchGate
264 CandidateItem *candidateItem = new CandidateItem;
265 candidateItem->setWidth(touchGate->width());
266 candidateItem->setHeight(touchGate->height());
267 candidateItem->setParentItem(view->rootObject());
268 candidateItem->setZ(2.0);
270 candidateItem->touchEventHandler = [&](QTouchEvent* event) {
271 touchRegistry->addCandidateOwnerForTouch(0, candidateItem);
275 // A brand new touch, but with the same id as the previous one
276 QTest::touchEvent(view, device)
277 .press(0, QPoint(200,200));
278 QTest::touchEvent(view, device)
279 .move(0, QPoint(201,201));
280 QTest::touchEvent(view, device)
281 .release(0, QPoint(201,201));
283 QCOMPARE(testItem->touchEventsReceived.count(), 0);
285 touchRegistry->requestTouchOwnership(0, candidateItem);
287 QCOMPARE(testItem->touchEventsReceived.count(), 0);
289 QVERIFY(touchGate->m_storedEvents.isEmpty());
292void tst_TouchGate::dontDispacthToDisabledOrInvisibleTarget()
294 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
297 TestItem *testItem = new TestItem;
298 testItem->setWidth(touchGate->width());
299 testItem->setHeight(touchGate->height());
300 testItem->setParentItem(view->rootObject());
303 QFETCH(bool, isEnabled);
304 testItem->setEnabled(isEnabled);
306 QFETCH(bool, isVisible);
307 testItem->setVisible(isVisible);
309 touchGate->setZ(1.0);
310 touchGate->setTargetItem(testItem);
312 QTest::touchEvent(view, device)
313 .press(0, QPoint(100,100));
315 QCOMPARE(testItem->touchEventsReceived.count(), 0);
316 QVERIFY(touchGate->m_storedEvents.isEmpty());
319void tst_TouchGate::dontDispacthToDisabledOrInvisibleTarget_data()
321 QTest::addColumn<bool>("isEnabled");
322 QTest::addColumn<bool>("isVisible");
324 QTest::newRow("disabled visible") << false << true;
325 QTest::newRow("enabled invisible") << true << false;
326 QTest::newRow("disabled invisible") << false << false;
329///////////// TestItem /////////////////////////////////////////////////////////////
331void TestItem::touchEvent(QTouchEvent *event)
333 QTouchEvent *clonedEvent = new QTouchEvent(event->type(),
336 event->touchPointStates(),
337 event->touchPoints());
339 touchEventsReceived.append(QSharedPointer<QTouchEvent>(clonedEvent));
342///////////// CandidateItem /////////////////////////////////////////////////////////////
344void CandidateItem::touchEvent(QTouchEvent *event)
346 touchEventHandler(event);
350QTEST_MAIN(tst_TouchGate)
352#include "tst_TouchGate.moc"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list