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);
133 Simplest case. TouchGate is the only candidate for the touch point, thus it
134 will instantly gain ownership causing the event to pass through it directly to
137void tst_TouchGate::onlyCandidate_passThrough()
139 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
142 TestItem *testItem = new TestItem;
143 testItem->setWidth(touchGate->width());
144 testItem->setHeight(touchGate->height());
145 testItem->setParentItem(view->rootObject());
148 touchGate->setZ(1.0);
149 touchGate->setTargetItem(testItem);
151 QTest::touchEvent(view, device)
152 .press(0, QPoint(100,100));
154 QCOMPARE(testItem->touchEventsReceived.count(), 1);
155 QVERIFY(touchGate->m_storedEvents.isEmpty());
158void tst_TouchGate::holdsEventsUntilGainsOwnership()
160 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
162 QFETCH(bool, ownershipAfterTouchEnd);
164 TestItem *testItem = new TestItem;
165 testItem->setWidth(touchGate->width());
166 testItem->setHeight(touchGate->height());
167 testItem->setParentItem(view->rootObject());
170 touchGate->setZ(1.0);
171 touchGate->setTargetItem(testItem);
173 // Put it in front of touchGate
174 CandidateItem *candidateItem = new CandidateItem;
175 candidateItem->setWidth(touchGate->width());
176 candidateItem->setHeight(touchGate->height());
177 candidateItem->setParentItem(view->rootObject());
178 candidateItem->setZ(2.0);
180 candidateItem->touchEventHandler = [&](QTouchEvent* event) {
181 touchRegistry->addCandidateOwnerForTouch(0, candidateItem);
185 QTest::touchEvent(view, device)
186 .press(0, QPoint(100,100));
188 QCOMPARE(testItem->touchEventsReceived.count(), 0);
190 QTest::touchEvent(view, device)
191 .move(0, QPoint(101,101));
193 QCOMPARE(testItem->touchEventsReceived.count(), 0);
195 if (!ownershipAfterTouchEnd) {
196 touchRegistry->removeCandidateOwnerForTouch(0, candidateItem);
197#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
198 QQuickWindowPrivate *wp = QQuickWindowPrivate::get(testItem->window());
199 wp->flushDelayedTouchEvent();
201 // TouchGate should now open its flood gates and let testItem get all
202 // events from touch 0 produced so far
203 QCOMPARE(testItem->touchEventsReceived.count(), 2);
206 QTest::touchEvent(view, device)
207 .release(0, QPoint(101,101));
209 if (ownershipAfterTouchEnd) {
210 QCOMPARE(testItem->touchEventsReceived.count(), 0);
211 touchRegistry->removeCandidateOwnerForTouch(0, candidateItem);
212 // TouchGate should now open its flood gates and let testItem get all
213 // events from touch 0 produced so far
216 QCOMPARE(testItem->touchEventsReceived.count(), 3);
218 QVERIFY(touchGate->m_storedEvents.isEmpty());
219 QVERIFY(touchGate->m_touchInfoMap.isEmpty());
222void tst_TouchGate::holdsEventsUntilGainsOwnership_data()
224 QTest::addColumn<bool>("ownershipAfterTouchEnd");
226 QTest::newRow("touch end after touch ownership") << false;
227 QTest::newRow("touch ownership after touch end") << true;
231 A touch point of id 0 starts and ends. Then the next touch point is also given
232 id 0. Check that TouchGate behaves correcly recognizing them as two distinct touch
235 Note that this won't be a problem with Mir as it assigns unique ids for the touch
238void tst_TouchGate::holdsEventsUntilGainsOwnership_repeatingTouchId()
240 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
243 TestItem *testItem = new TestItem;
244 testItem->setWidth(touchGate->width());
245 testItem->setHeight(touchGate->height());
246 testItem->setParentItem(view->rootObject());
249 touchGate->setZ(1.0);
250 touchGate->setTargetItem(testItem);
252 QTest::touchEvent(view, device)
253 .press(0, QPoint(100,100));
254 QTest::touchEvent(view, device)
255 .move(0, QPoint(101,101));
256 QTest::touchEvent(view, device)
257 .release(0, QPoint(101,101));
259 QCOMPARE(testItem->touchEventsReceived.count(), 3);
260 testItem->touchEventsReceived.clear();
262 // Put it in front of touchGate
263 CandidateItem *candidateItem = new CandidateItem;
264 candidateItem->setWidth(touchGate->width());
265 candidateItem->setHeight(touchGate->height());
266 candidateItem->setParentItem(view->rootObject());
267 candidateItem->setZ(2.0);
269 candidateItem->touchEventHandler = [&](QTouchEvent* event) {
270 touchRegistry->addCandidateOwnerForTouch(0, candidateItem);
274 // A brand new touch, but with the same id as the previous one
275 QTest::touchEvent(view, device)
276 .press(0, QPoint(200,200));
277 QTest::touchEvent(view, device)
278 .move(0, QPoint(201,201));
279 QTest::touchEvent(view, device)
280 .release(0, QPoint(201,201));
282 QCOMPARE(testItem->touchEventsReceived.count(), 0);
284 touchRegistry->requestTouchOwnership(0, candidateItem);
286 QCOMPARE(testItem->touchEventsReceived.count(), 0);
288 QVERIFY(touchGate->m_storedEvents.isEmpty());
291void tst_TouchGate::dontDispacthToDisabledOrInvisibleTarget()
293 TouchGate *touchGate = view->rootObject()->findChild<TouchGate*>("touchGate");
296 TestItem *testItem = new TestItem;
297 testItem->setWidth(touchGate->width());
298 testItem->setHeight(touchGate->height());
299 testItem->setParentItem(view->rootObject());
302 QFETCH(bool, isEnabled);
303 testItem->setEnabled(isEnabled);
305 QFETCH(bool, isVisible);
306 testItem->setVisible(isVisible);
308 touchGate->setZ(1.0);
309 touchGate->setTargetItem(testItem);
311 QTest::touchEvent(view, device)
312 .press(0, QPoint(100,100));
314 QCOMPARE(testItem->touchEventsReceived.count(), 0);
315 QVERIFY(touchGate->m_storedEvents.isEmpty());
318void tst_TouchGate::dontDispacthToDisabledOrInvisibleTarget_data()
320 QTest::addColumn<bool>("isEnabled");
321 QTest::addColumn<bool>("isVisible");
323 QTest::newRow("disabled visible") << false << true;
324 QTest::newRow("enabled invisible") << true << false;
325 QTest::newRow("disabled invisible") << false << false;
328///////////// TestItem /////////////////////////////////////////////////////////////
330void TestItem::touchEvent(QTouchEvent *event)
332 QTouchEvent *clonedEvent = new QTouchEvent(event->type(),
335 event->touchPointStates(),
336 event->touchPoints());
338 touchEventsReceived.append(QSharedPointer<QTouchEvent>(clonedEvent));
341///////////// CandidateItem /////////////////////////////////////////////////////////////
343void CandidateItem::touchEvent(QTouchEvent *event)
345 touchEventHandler(event);
349QTEST_MAIN(tst_TouchGate)
351#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