on xenial help sign in
WindowInputMonitor - also map Qt::Key_HomePage to our home key

+ Improve key press logic a bit: avoid restarting the timer if it's already running (eg: in a very quick double-tap). Such delay in activation hardly being noticeable from user's point of view. Approved by: Albert Astals Cid

commita1583958b50b433be251b3e9566f1ad747cf6c2b authorDaniel d'Andrada <daniel.dandrada@canonical.com> dateFri 27 May 2016, 13:51 (10 years ago) parent6e3c4b2f95e5dd
3 files changed+68−21
plugins/Utils/WindowInputMonitor.cpp+8−8 plugins/Utils/WindowInputMonitor.h+8−2 tests/plugins/Utils/WindowInputMonitorTest.cpp+52−11
plugins/Utils/WindowInputMonitor.cpp+8−8
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -30,7 +30,6 @@ WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
3030 QQuickItem *parent)
3131 : QQuickItem(parent)
3232 , m_windowBeingTouched(false)
33− , m_homeKeyPressed(false)
3433 , m_windowLastTouchedTimer(elapsedTimer)
3534 , m_activationTimer(timer)
3635{
@@ -42,6 +41,7 @@ WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
4241 connect(m_activationTimer, &UnityUtil::AbstractTimer::timeout,
4342 this, &WindowInputMonitor::emitActivatedIfNoTouchesAround);
4443 m_activationTimer->setInterval(msecsWithoutTouches);
44+ m_activationTimer->setSingleShot(true);
4545}
4646
4747WindowInputMonitor::~WindowInputMonitor()
@@ -67,19 +67,19 @@ void WindowInputMonitor::update(QEvent *event)
6767 if (event->type() == QEvent::KeyPress) {
6868 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
6969
70− m_homeKeyPressed = true;
71−
72− if (keyEvent->key() == Qt::Key_Super_L && !keyEvent->isAutoRepeat()
70+ if (m_pressedHomeKey == 0 && m_homeKeys.contains(keyEvent->key()) && !keyEvent->isAutoRepeat()
71+ && !m_activationTimer->isRunning()
7372 && !m_windowBeingTouched
7473 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
74+ m_pressedHomeKey = keyEvent->key();
7575 m_activationTimer->start();
7676 }
7777
7878 } else if (event->type() == QEvent::KeyRelease) {
7979 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
8080
81− if (keyEvent->key() == Qt::Key_Super_L) {
82− m_homeKeyPressed = false;
81+ if (keyEvent->key() == m_pressedHomeKey) {
82+ m_pressedHomeKey = 0;
8383 }
8484
8585 } else if (event->type() == QEvent::TouchBegin) {
@@ -116,7 +116,7 @@ void WindowInputMonitor::setupFilterOnWindow(QQuickWindow *window)
116116
117117void WindowInputMonitor::emitActivatedIfNoTouchesAround()
118118{
119− if (!m_homeKeyPressed && !m_windowBeingTouched &&
119+ if (m_pressedHomeKey == 0 && !m_windowBeingTouched &&
120120 (m_windowLastTouchedTimer->elapsed() > msecsWithoutTouches)) {
121121 Q_EMIT homeKeyActivated();
122122 }
plugins/Utils/WindowInputMonitor.h+8−2
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
1818#define UNITY_WINDOWINPUTMONITOR_H
1919
2020#include <QQuickItem>
21+#include <QList>
2122#include <QPointer>
2223
2324#include "Timer.h"
@@ -83,9 +84,14 @@ private Q_SLOTS:
8384private:
8485 QPointer<QQuickWindow> m_filteredWindow;
8586 bool m_windowBeingTouched;
86− bool m_homeKeyPressed;
8787 UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
8888 UnityUtil::AbstractTimer *m_activationTimer;
89+
90+ // Qt::Keys that are mapped to our "home" key.
91+ QList<int> m_homeKeys{Qt::Key_Super_L, Qt::Key_HomePage};
92+ // Which Qt::Key from m_homeKeys is currently pressed.
93+ // 0 if none
94+ int m_pressedHomeKey{0};
8995};
9096
9197#endif // UNITY_WINDOWINPUTMONITOR_H
tests/plugins/Utils/WindowInputMonitorTest.cpp+52−11
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -71,6 +71,8 @@ public:
7171
7272using namespace UnityUtil;
7373
74+Q_DECLARE_METATYPE(Qt::Key) // because of QTest::addColumn<Qt::Key>
75+
7476class WindowInputMonitorTest : public QObject {
7577 Q_OBJECT
7678private Q_SLOTS:
@@ -81,6 +83,7 @@ private Q_SLOTS:
8183 void touchTapTouch();
8284
8385 void tapWhileTouching();
86+ void multipleHomeKeys();
8487
8588private:
8689 void passTime(qint64 timeSpanMs);
@@ -112,13 +115,15 @@ void WindowInputMonitorTest::touchTapTouch_data()
112115 QTest::addColumn<int>("tapDuration");
113116 QTest::addColumn<int>("silenceAfterTap");
114117 QTest::addColumn<int>("expectedActivatedCount");
115−
116− QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0;
117− QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0;
118− QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0;
119− QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0;
120− QTest::newRow("isolated tap") << 1000 << 50 << 1000 << 1;
121− QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0;
118+ QTest::addColumn<Qt::Key>("key");
119+
120+ QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0 << Qt::Key_Super_L;
121+ QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0 << Qt::Key_Super_L;
122+ QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0 << Qt::Key_Super_L;
123+ QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0 << Qt::Key_Super_L;
124+ QTest::newRow("isolated tap, Super_L") << 1000 << 50 << 1000 << 1 << Qt::Key_Super_L;
125+ QTest::newRow("isolated tap, HomePage") << 1000 << 50 << 1000 << 1 << Qt::Key_HomePage;
126+ QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0 << Qt::Key_Super_L;
122127}
123128
124129void WindowInputMonitorTest::touchTapTouch()
@@ -127,6 +132,7 @@ void WindowInputMonitorTest::touchTapTouch()
127132 QFETCH(int, tapDuration);
128133 QFETCH(int, silenceAfterTap);
129134 QFETCH(int, expectedActivatedCount);
135+ QFETCH(Qt::Key, key);
130136 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
131137 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
132138 QVERIFY(activatedSpy.isValid());
@@ -149,7 +155,7 @@ void WindowInputMonitorTest::touchTapTouch()
149155 passTime(silenceBeforeTap);
150156
151157 {
152− QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
158+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
153159 homeKeyWatcher.update(&keyEvent);
154160 }
155161 int tapTime = 0;
@@ -157,10 +163,10 @@ void WindowInputMonitorTest::touchTapTouch()
157163 passTime(10);
158164 tapTime += 10;
159165 if (tapTime + 10 >= tapDuration) {
160− QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
166+ QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
161167 homeKeyWatcher.update(&keyEvent);
162168 } else {
163− QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier, QString(), true /*autorepeat*/);
169+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier, QString(), true /*autorepeat*/);
164170 homeKeyWatcher.update(&keyEvent);
165171 }
166172 }
@@ -217,6 +223,41 @@ void WindowInputMonitorTest::tapWhileTouching()
217223 QCOMPARE(activatedSpy.count(), 0);
218224}
219225
226+/*
227+ Press multiple of the mapped home keys roughly at the same time.
228+ The first pressed will be recognized and the other ignored
229+ */
230+void WindowInputMonitorTest::multipleHomeKeys()
231+{
232+ WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
233+ QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
234+ QVERIFY(activatedSpy.isValid());
235+
236+ passTime(1000);
237+ {
238+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_HomePage, Qt::NoModifier);
239+ homeKeyWatcher.update(&keyEvent);
240+ }
241+ passTime(50);
242+ {
243+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
244+ homeKeyWatcher.update(&keyEvent);
245+ }
246+ passTime(50);
247+ {
248+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_HomePage, Qt::NoModifier);
249+ homeKeyWatcher.update(&keyEvent);
250+ }
251+ passTime(10);
252+ {
253+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
254+ homeKeyWatcher.update(&keyEvent);
255+ }
256+ passTime(1000);
257+
258+ QCOMPARE(activatedSpy.count(), 1);
259+}
260+
220261/////////////////////////////////// FakeTimer //////////////////////////////////
221262
222263FakeTimer::FakeTimer(QObject *parent)