2 * Copyright (C) 2015-2016 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 "WindowInputMonitor.h"
24class FakeElapsedTimer : public AbstractElapsedTimer {
26 static qint64 msecsSinceEpoch;
28 FakeElapsedTimer() { start(); }
30 void start() override { m_msecsSinceReference = msecsSinceEpoch; }
31 qint64 msecsSinceReference() const override { return m_msecsSinceReference; }
32 qint64 elapsed() const override { return msecsSinceEpoch - m_msecsSinceReference; }
35 qint64 m_msecsSinceReference;
37qint64 FakeElapsedTimer::msecsSinceEpoch = 0;
39class FakeTimer : public AbstractTimer
43 FakeTimer(QObject *parent = nullptr);
46 qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
48 int interval() const override;
49 void setInterval(int msecs) override;
50 void start() override;
52 bool isRunning() const override;
53 bool isSingleShot() const override;
54 void setSingleShot(bool value) override;
59 qint64 m_nextTimeoutTime;
62class FakeTimerFactory : public AbstractTimerFactory
66 virtual ~FakeTimerFactory();
68 void updateTime(qint64 targetTime);
70 AbstractTimer *create(QObject *parent = nullptr) override;
71 QList<QPointer<FakeTimer>> timers;
73} // namespace UnityUtil
75using namespace UnityUtil;
77Q_DECLARE_METATYPE(Qt::Key) // because of QTest::addColumn<Qt::Key>
79class WindowInputMonitorTest : public QObject {
82 void init(); // called right before each and every test function is executed
83 void cleanup(); // called right after each and every test function is executed
85 void touchTapTouch_data();
88 void tapWhileTouching();
89 void multipleHomeKeys();
91 void repeatedSuperPress();
94 void passTime(qint64 timeSpanMs);
96 FakeTimerFactory *m_fakeTimerFactory;
99void WindowInputMonitorTest::init()
101 m_fakeTimerFactory = new FakeTimerFactory;
104void WindowInputMonitorTest::cleanup()
106 delete m_fakeTimerFactory;
107 m_fakeTimerFactory = nullptr;
111void WindowInputMonitorTest::passTime(qint64 timeSpanMs)
113 qint64 finalTime = FakeElapsedTimer::msecsSinceEpoch + timeSpanMs;
114 m_fakeTimerFactory->updateTime(finalTime);
117void WindowInputMonitorTest::touchTapTouch_data()
119 QTest::addColumn<int>("silenceBeforeTap");
120 QTest::addColumn<int>("tapDuration");
121 QTest::addColumn<int>("silenceAfterTap");
122 QTest::addColumn<int>("expectedActivatedCount");
123 QTest::addColumn<Qt::Key>("key");
125 QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0 << Qt::Key_Super_L;
126 QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0 << Qt::Key_Super_L;
127 QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0 << Qt::Key_Super_L;
128 QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0 << Qt::Key_Super_L;
129 QTest::newRow("isolated tap, Super_L") << 1000 << 50 << 1000 << 1 << Qt::Key_Super_L;
130 QTest::newRow("isolated tap, HomePage") << 1000 << 50 << 1000 << 1 << Qt::Key_HomePage;
131 QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0 << Qt::Key_Super_L;
134void WindowInputMonitorTest::touchTapTouch()
136 QFETCH(int, silenceBeforeTap);
137 QFETCH(int, tapDuration);
138 QFETCH(int, silenceAfterTap);
139 QFETCH(int, expectedActivatedCount);
140 QFETCH(Qt::Key, key);
141 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
142 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
143 QVERIFY(activatedSpy.isValid());
146 QTouchEvent touchEvent(QEvent::TouchBegin);
147 homeKeyWatcher.update(&touchEvent);
151 QTouchEvent touchEvent(QEvent::TouchUpdate);
152 homeKeyWatcher.update(&touchEvent);
156 QTouchEvent touchEvent(QEvent::TouchEnd);
157 homeKeyWatcher.update(&touchEvent);
160 passTime(silenceBeforeTap);
163 QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
164 homeKeyWatcher.update(&keyEvent);
167 while (tapTime < tapDuration) {
170 if (tapTime + 10 >= tapDuration) {
171 QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
172 homeKeyWatcher.update(&keyEvent);
174 QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier, QString(), true /*autorepeat*/);
175 homeKeyWatcher.update(&keyEvent);
179 passTime(silenceAfterTap);
182 QTouchEvent touchEvent(QEvent::TouchBegin);
183 homeKeyWatcher.update(&touchEvent);
187 QTouchEvent touchEvent(QEvent::TouchUpdate);
188 homeKeyWatcher.update(&touchEvent);
192 QTouchEvent touchEvent(QEvent::TouchEnd);
193 homeKeyWatcher.update(&touchEvent);
197 QCOMPARE(activatedSpy.count(), expectedActivatedCount);
200void WindowInputMonitorTest::tapWhileTouching()
202 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
203 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
204 QVERIFY(activatedSpy.isValid());
207 QTouchEvent touchEvent(QEvent::TouchBegin);
208 homeKeyWatcher.update(&touchEvent);
212 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
213 homeKeyWatcher.update(&keyEvent);
217 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
218 homeKeyWatcher.update(&keyEvent);
222 QTouchEvent touchEvent(QEvent::TouchEnd);
223 homeKeyWatcher.update(&touchEvent);
228 QCOMPARE(activatedSpy.count(), 0);
232 Press multiple of the mapped home keys roughly at the same time.
233 The first pressed will be recognized and the other ignored
235void WindowInputMonitorTest::multipleHomeKeys()
237 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
238 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
239 QVERIFY(activatedSpy.isValid());
243 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_HomePage, Qt::NoModifier);
244 homeKeyWatcher.update(&keyEvent);
248 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
249 homeKeyWatcher.update(&keyEvent);
253 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_HomePage, Qt::NoModifier);
254 homeKeyWatcher.update(&keyEvent);
258 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
259 homeKeyWatcher.update(&keyEvent);
263 QCOMPARE(activatedSpy.count(), 1);
266// regression test for lp:1607427
267void WindowInputMonitorTest::repeatedSuperPress()
269 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
270 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
271 QVERIFY(activatedSpy.isValid());
276 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
277 homeKeyWatcher.update(&keyEvent);
281 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
282 homeKeyWatcher.update(&keyEvent);
285 QCOMPARE(activatedSpy.count(), 1);
288 activatedSpy.clear();
290 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
291 homeKeyWatcher.update(&keyEvent);
295 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
296 homeKeyWatcher.update(&keyEvent);
299 QCOMPARE(activatedSpy.count(), 1);
302/////////////////////////////////// FakeTimer //////////////////////////////////
304FakeTimer::FakeTimer(QObject *parent)
305 : UnityUtil::AbstractTimer(parent)
312void FakeTimer::update()
318 if (m_nextTimeoutTime <= FakeElapsedTimer::msecsSinceEpoch) {
319 if (isSingleShot()) {
322 m_nextTimeoutTime += interval();
328void FakeTimer::start()
331 m_nextTimeoutTime = FakeElapsedTimer::msecsSinceEpoch + (qint64)interval();
334void FakeTimer::stop()
339bool FakeTimer::isRunning() const
344int FakeTimer::interval() const
349void FakeTimer::setInterval(int msecs)
354bool FakeTimer::isSingleShot() const
359void FakeTimer::setSingleShot(bool value)
361 m_singleShot = value;
364/////////////////////////////////// FakeTimerFactory //////////////////////////////////
366FakeTimerFactory::FakeTimerFactory()
370FakeTimerFactory::~FakeTimerFactory()
372 for (int i = 0; i < timers.count(); ++i) {
373 FakeTimer *timer = timers[i].data();
380void FakeTimerFactory::updateTime(qint64 targetTime)
382 qint64 minTimeoutTime = targetTime;
384 for (int i = 0; i < timers.count(); ++i) {
385 FakeTimer *timer = timers[i].data();
386 if (timer && timer->isRunning() && timer->nextTimeoutTime() < minTimeoutTime) {
387 minTimeoutTime = timer->nextTimeoutTime();
391 FakeElapsedTimer::msecsSinceEpoch = minTimeoutTime;
393 for (int i = 0; i < timers.count(); ++i) {
394 FakeTimer *timer = timers[i].data();
400 if (FakeElapsedTimer::msecsSinceEpoch < targetTime) {
401 updateTime(targetTime);
405AbstractTimer *FakeTimerFactory::create(QObject *parent)
407 FakeTimer *fakeTimer = new FakeTimer(parent);
409 timers.append(fakeTimer);
414QTEST_GUILESS_MAIN(WindowInputMonitorTest)
416#include "WindowInputMonitorTest.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