on xenial help sign in
WindowInputMonitor - also map Qt::Key_HomePage to our home key
e7bb4ceDaniel d'Andrada
plugins/Utils/WindowInputMonitor.cpp+8−8
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -30,7 +30,6 @@ WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
30 QQuickItem *parent)
30 QQuickItem *parent)
31 : QQuickItem(parent)
31 : QQuickItem(parent)
32 , m_windowBeingTouched(false)
32 , m_windowBeingTouched(false)
33− , m_homeKeyPressed(false)
34 , m_windowLastTouchedTimer(elapsedTimer)
33 , m_windowLastTouchedTimer(elapsedTimer)
35 , m_activationTimer(timer)
34 , m_activationTimer(timer)
36{
35{
@@ -42,6 +41,7 @@ WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
42 connect(m_activationTimer, &UnityUtil::AbstractTimer::timeout,
41 connect(m_activationTimer, &UnityUtil::AbstractTimer::timeout,
43 this, &WindowInputMonitor::emitActivatedIfNoTouchesAround);
42 this, &WindowInputMonitor::emitActivatedIfNoTouchesAround);
44 m_activationTimer->setInterval(msecsWithoutTouches);
43 m_activationTimer->setInterval(msecsWithoutTouches);
44+ m_activationTimer->setSingleShot(true);
45}
45}
46
46
47WindowInputMonitor::~WindowInputMonitor()
47WindowInputMonitor::~WindowInputMonitor()
@@ -67,19 +67,19 @@ void WindowInputMonitor::update(QEvent *event)
67 if (event->type() == QEvent::KeyPress) {
67 if (event->type() == QEvent::KeyPress) {
68 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
68 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
69
69
70− m_homeKeyPressed = true;
70+ if (m_pressedHomeKey == 0 && m_homeKeys.contains(keyEvent->key()) && !keyEvent->isAutoRepeat()
71−
71+ && !m_activationTimer->isRunning()
72− if (keyEvent->key() == Qt::Key_Super_L && !keyEvent->isAutoRepeat()
73 && !m_windowBeingTouched
72 && !m_windowBeingTouched
74 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
73 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
74+ m_pressedHomeKey = keyEvent->key();
75 m_activationTimer->start();
75 m_activationTimer->start();
76 }
76 }
77
77
78 } else if (event->type() == QEvent::KeyRelease) {
78 } else if (event->type() == QEvent::KeyRelease) {
79 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
79 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
80
80
81− if (keyEvent->key() == Qt::Key_Super_L) {
81+ if (keyEvent->key() == m_pressedHomeKey) {
82− m_homeKeyPressed = false;
82+ m_pressedHomeKey = 0;
83 }
83 }
84
84
85 } else if (event->type() == QEvent::TouchBegin) {
85 } else if (event->type() == QEvent::TouchBegin) {
@@ -116,7 +116,7 @@ void WindowInputMonitor::setupFilterOnWindow(QQuickWindow *window)
116
116
117void WindowInputMonitor::emitActivatedIfNoTouchesAround()
117void WindowInputMonitor::emitActivatedIfNoTouchesAround()
118{
118{
119− if (!m_homeKeyPressed && !m_windowBeingTouched &&
119+ if (m_pressedHomeKey == 0 && !m_windowBeingTouched &&
120 (m_windowLastTouchedTimer->elapsed() > msecsWithoutTouches)) {
120 (m_windowLastTouchedTimer->elapsed() > msecsWithoutTouches)) {
121 Q_EMIT homeKeyActivated();
121 Q_EMIT homeKeyActivated();
122 }
122 }
plugins/Utils/WindowInputMonitor.h+8−2
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
18#define UNITY_WINDOWINPUTMONITOR_H
18#define UNITY_WINDOWINPUTMONITOR_H
19
19
20#include <QQuickItem>
20#include <QQuickItem>
21+#include <QList>
21#include <QPointer>
22#include <QPointer>
22
23
23#include "Timer.h"
24#include "Timer.h"
@@ -83,9 +84,14 @@ private Q_SLOTS:
83private:
84private:
84 QPointer<QQuickWindow> m_filteredWindow;
85 QPointer<QQuickWindow> m_filteredWindow;
85 bool m_windowBeingTouched;
86 bool m_windowBeingTouched;
86− bool m_homeKeyPressed;
87 UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
87 UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
88 UnityUtil::AbstractTimer *m_activationTimer;
88 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};
89};
95};
90
96
91#endif // UNITY_WINDOWINPUTMONITOR_H
97#endif // UNITY_WINDOWINPUTMONITOR_H
tests/plugins/Utils/WindowInputMonitorTest.cpp+50−11
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2015 Canonical, Ltd.
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -81,6 +81,7 @@ private Q_SLOTS:
81 void touchTapTouch();
81 void touchTapTouch();
82
82
83 void tapWhileTouching();
83 void tapWhileTouching();
84+ void multipleHomeKeys();
84
85
85private:
86private:
86 void passTime(qint64 timeSpanMs);
87 void passTime(qint64 timeSpanMs);
@@ -112,13 +113,15 @@ void WindowInputMonitorTest::touchTapTouch_data()
112 QTest::addColumn<int>("tapDuration");
113 QTest::addColumn<int>("tapDuration");
113 QTest::addColumn<int>("silenceAfterTap");
114 QTest::addColumn<int>("silenceAfterTap");
114 QTest::addColumn<int>("expectedActivatedCount");
115 QTest::addColumn<int>("expectedActivatedCount");
115−
116+ QTest::addColumn<Qt::Key>("key");
117+
116− QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0;
118+ QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0 << Qt::Key_Super_L;
117− QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0;
119+ QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0 << Qt::Key_Super_L;
118− QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0;
120+ QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0 << Qt::Key_Super_L;
119− QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0;
121+ QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0 << Qt::Key_Super_L;
120− QTest::newRow("isolated tap") << 1000 << 50 << 1000 << 1;
122+ QTest::newRow("isolated tap, Super_L") << 1000 << 50 << 1000 << 1 << Qt::Key_Super_L;
123+ QTest::newRow("isolated tap, HomePage") << 1000 << 50 << 1000 << 1 << Qt::Key_HomePage;
121− QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0;
124+ QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0 << Qt::Key_Super_L;
122}
125}
123
126
124void WindowInputMonitorTest::touchTapTouch()
127void WindowInputMonitorTest::touchTapTouch()
@@ -127,6 +130,7 @@ void WindowInputMonitorTest::touchTapTouch()
127 QFETCH(int, tapDuration);
130 QFETCH(int, tapDuration);
128 QFETCH(int, silenceAfterTap);
131 QFETCH(int, silenceAfterTap);
129 QFETCH(int, expectedActivatedCount);
132 QFETCH(int, expectedActivatedCount);
133+ QFETCH(Qt::Key, key);
130 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
134 WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
131 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
135 QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
132 QVERIFY(activatedSpy.isValid());
136 QVERIFY(activatedSpy.isValid());
@@ -149,7 +153,7 @@ void WindowInputMonitorTest::touchTapTouch()
149 passTime(silenceBeforeTap);
153 passTime(silenceBeforeTap);
150
154
151 {
155 {
152− QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
156+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
153 homeKeyWatcher.update(&keyEvent);
157 homeKeyWatcher.update(&keyEvent);
154 }
158 }
155 int tapTime = 0;
159 int tapTime = 0;
@@ -157,10 +161,10 @@ void WindowInputMonitorTest::touchTapTouch()
157 passTime(10);
161 passTime(10);
158 tapTime += 10;
162 tapTime += 10;
159 if (tapTime + 10 >= tapDuration) {
163 if (tapTime + 10 >= tapDuration) {
160− QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
164+ QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
161 homeKeyWatcher.update(&keyEvent);
165 homeKeyWatcher.update(&keyEvent);
162 } else {
166 } else {
163− QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier, QString(), true /*autorepeat*/);
167+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier, QString(), true /*autorepeat*/);
164 homeKeyWatcher.update(&keyEvent);
168 homeKeyWatcher.update(&keyEvent);
165 }
169 }
166 }
170 }
@@ -217,6 +221,41 @@ void WindowInputMonitorTest::tapWhileTouching()
217 QCOMPARE(activatedSpy.count(), 0);
221 QCOMPARE(activatedSpy.count(), 0);
218}
222}
219
223
224+/*
225+ Press multiple of the mapped home keys roughly at the same time.
226+ The first pressed will be recognized and the other ignored
227+ */
228+void WindowInputMonitorTest::multipleHomeKeys()
229+{
230+ WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
231+ QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
232+ QVERIFY(activatedSpy.isValid());
233+
234+ passTime(1000);
235+ {
236+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_HomePage, Qt::NoModifier);
237+ homeKeyWatcher.update(&keyEvent);
238+ }
239+ passTime(50);
240+ {
241+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
242+ homeKeyWatcher.update(&keyEvent);
243+ }
244+ passTime(50);
245+ {
246+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_HomePage, Qt::NoModifier);
247+ homeKeyWatcher.update(&keyEvent);
248+ }
249+ passTime(10);
250+ {
251+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
252+ homeKeyWatcher.update(&keyEvent);
253+ }
254+ passTime(1000);
255+
256+ QCOMPARE(activatedSpy.count(), 1);
257+}
258+
220/////////////////////////////////// FakeTimer //////////////////////////////////
259/////////////////////////////////// FakeTimer //////////////////////////////////
221
260
222FakeTimer::FakeTimer(QObject *parent)
261FakeTimer::FakeTimer(QObject *parent)