on xenial help sign in
Hide/reveal the mouse pointer on touch/mouse events
commit0b10661e9c50985629db860b976b9bb67f87e6b6 authorLukáš Tinkl <lukas.tinkl@canonical.com> dateFri 29 Jan 2016, 11:52 (11 years ago) parent03541714f01f5d
13 files changed+149−109
plugins/Cursor/MousePointer.cpp+4 plugins/Cursor/MousePointer.h+1 plugins/Utils/CMakeLists.txt+1−1 plugins/Utils/HomeKeyWatcher.h−74 plugins/Utils/HomeKeyWatcher.cpp → plugins/Utils/WindowInputMonitor.cpp+19−12 plugins/Utils/WindowInputMonitor.h+91 plugins/Utils/plugin.cpp+2−2 qml/Shell.qml+11−3 tests/mocks/Cursor/Cursor.qml+1 tests/mocks/Utils/HomeKeyWatcher.qml → tests/mocks/Utils/WindowInputMonitor.qml+3−1 tests/mocks/Utils/qmldir+1−1 tests/plugins/Utils/CMakeLists.txt+1−1 tests/plugins/Utils/HomeKeyWatcherTest.cpp → tests/plugins/Utils/WindowInputMonitorTest.cpp+14−14
plugins/Cursor/MousePointer.cpp+4
@@ -42,6 +42,10 @@ void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::Mouse
4242 return;
4343 }
4444
45+ if (!movement.isNull()) {
46+ Q_EMIT mouseMoved();
47+ }
48+
4549 qreal newX = x() + movement.x();
4650 if (newX < 0) {
4751 Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
plugins/Cursor/MousePointer.h+1
@@ -48,6 +48,7 @@ public Q_SLOTS:
4848Q_SIGNALS:
4949 void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);
5050 void pushedRightBoundary(qreal amount, Qt::MouseButtons buttons);
51+ void mouseMoved();
5152
5253protected:
5354 void itemChange(ItemChange change, const ItemChangeData &value) override;
plugins/Utils/CMakeLists.txt+1−1
@@ -13,7 +13,7 @@ set(QMLPLUGIN_SRC
1313 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
1414 applicationsfiltermodel.cpp
1515 constants.cpp
16− HomeKeyWatcher.cpp
16+ WindowInputMonitor.cpp
1717 inputwatcher.cpp
1818 qlimitproxymodelqml.cpp
1919 unitysortfilterproxymodelqml.cpp
plugins/Utils/HomeKeyWatcher.hdeleted−74
@@ -1,74 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
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.
7− *
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.
12− *
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/>.
15− */
16−
17−#ifndef UNITY_HOMEKEYWATCHER_H
18−#define UNITY_HOMEKEYWATCHER_H
19−
20−#include <QQuickItem>
21−#include <QPointer>
22−
23−#include "Timer.h"
24−#include "ElapsedTimer.h"
25−
26−/*
27− Signals when the home key seems to be have been intentionally tapped.
28−
29− It only says the home key has been activated if it has been tapped in isolation,
30− that is, without being accompanied by touches on the screen. Home key taps that
31− happen along with (or immediately after, or immediately before) touches on the
32− screen are considered to have happened unintentionally and are thus ignored.
33−
34− Rationale being that it's easy to accidentally hit the home key while performing
35− a swipe from a screen edge, for instance. That's particularly the case when the
36− home key is a capacitive key.
37− */
38−class HomeKeyWatcher : public QQuickItem
39−{
40− Q_OBJECT
41−public:
42−
43− HomeKeyWatcher(QQuickItem *parent = 0);
44−
45− // for testing
46− HomeKeyWatcher(UnityUtil::AbstractTimer *timer,
47− UnityUtil::AbstractElapsedTimer *elapsedTimer,
48− QQuickItem *parent = 0);
49−
50− virtual ~HomeKeyWatcher();
51−
52− bool eventFilter(QObject *watched, QEvent *event) override;
53−
54− void update(QEvent *event);
55−
56− const qint64 msecsWithoutTouches = 150;
57−
58−Q_SIGNALS:
59− // Emitted when the home key has been intentionally tapped
60− void activated();
61−
62−private Q_SLOTS:
63− void setupFilterOnWindow(QQuickWindow *window);
64− void emitActivatedIfNoTouchesAround();
65−
66−private:
67− QPointer<QQuickWindow> m_filteredWindow;
68− bool m_windowBeingTouched;
69− bool m_homeKeyPressed;
70− UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
71− UnityUtil::AbstractTimer *m_activationTimer;
72−};
73−
74−#endif // UNITY_HOMEKEYWATCHER_H
plugins/Utils/HomeKeyWatcher.cpp → plugins/Utils/WindowInputMonitor.cpprenamed+19−12
@@ -14,18 +14,18 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#include "HomeKeyWatcher.h"
17+#include "WindowInputMonitor.h"
1818
1919#include <QQuickWindow>
2020
2121using namespace UnityUtil;
2222
23−HomeKeyWatcher::HomeKeyWatcher(QQuickItem *parent)
24− : HomeKeyWatcher(new Timer, new ElapsedTimer, parent)
23+WindowInputMonitor::WindowInputMonitor(QQuickItem *parent)
24+ : WindowInputMonitor(new Timer, new ElapsedTimer, parent)
2525{
2626}
2727
28−HomeKeyWatcher::HomeKeyWatcher(UnityUtil::AbstractTimer *timer,
28+WindowInputMonitor::WindowInputMonitor(UnityUtil::AbstractTimer *timer,
2929 UnityUtil::AbstractElapsedTimer *elapsedTimer,
3030 QQuickItem *parent)
3131 : QQuickItem(parent)
@@ -37,20 +37,20 @@ HomeKeyWatcher::HomeKeyWatcher(UnityUtil::AbstractTimer *timer,
3737 m_windowLastTouchedTimer->start();
3838
3939 connect(this, &QQuickItem::windowChanged,
40− this, &HomeKeyWatcher::setupFilterOnWindow);
40+ this, &WindowInputMonitor::setupFilterOnWindow);
4141
4242 connect(m_activationTimer, &UnityUtil::AbstractTimer::timeout,
43− this, &HomeKeyWatcher::emitActivatedIfNoTouchesAround);
43+ this, &WindowInputMonitor::emitActivatedIfNoTouchesAround);
4444 m_activationTimer->setInterval(msecsWithoutTouches);
4545}
4646
47−HomeKeyWatcher::~HomeKeyWatcher()
47+WindowInputMonitor::~WindowInputMonitor()
4848{
4949 delete m_windowLastTouchedTimer;
5050 delete m_activationTimer;
5151}
5252
53−bool HomeKeyWatcher::eventFilter(QObject *watched, QEvent *event)
53+bool WindowInputMonitor::eventFilter(QObject *watched, QEvent *event)
5454{
5555 Q_ASSERT(!m_filteredWindow.isNull());
5656 Q_ASSERT(watched == static_cast<QObject*>(m_filteredWindow.data()));
@@ -62,7 +62,7 @@ bool HomeKeyWatcher::eventFilter(QObject *watched, QEvent *event)
6262 return false;
6363}
6464
65−void HomeKeyWatcher::update(QEvent *event)
65+void WindowInputMonitor::update(QEvent *event)
6666{
6767 if (event->type() == QEvent::KeyPress) {
6868 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
@@ -86,15 +86,22 @@ void HomeKeyWatcher::update(QEvent *event)
8686
8787 m_activationTimer->stop();
8888 m_windowBeingTouched = true;
89+ Q_EMIT touchBegun();
8990
9091 } else if (event->type() == QEvent::TouchEnd) {
9192
9293 m_windowBeingTouched = false;
9394 m_windowLastTouchedTimer->start();
95+
96+ QTouchEvent * touchEv = static_cast<QTouchEvent *>(event);
97+ if (touchEv && !touchEv->touchPoints().isEmpty()) {
98+ const QPointF pos = touchEv->touchPoints().last().screenPos();
99+ Q_EMIT touchEnded(pos);
100+ }
94101 }
95102}
96103
97−void HomeKeyWatcher::setupFilterOnWindow(QQuickWindow *window)
104+void WindowInputMonitor::setupFilterOnWindow(QQuickWindow *window)
98105{
99106 if (!m_filteredWindow.isNull()) {
100107 m_filteredWindow->removeEventFilter(this);
@@ -107,10 +114,10 @@ void HomeKeyWatcher::setupFilterOnWindow(QQuickWindow *window)
107114 }
108115}
109116
110−void HomeKeyWatcher::emitActivatedIfNoTouchesAround()
117+void WindowInputMonitor::emitActivatedIfNoTouchesAround()
111118{
112119 if (!m_homeKeyPressed && !m_windowBeingTouched &&
113120 (m_windowLastTouchedTimer->elapsed() > msecsWithoutTouches)) {
114− Q_EMIT activated();
121+ Q_EMIT homeKeyActivated();
115122 }
116123}
plugins/Utils/WindowInputMonitor.hnew file+91
@@ -0,0 +1,91 @@
1+/*
2+ * Copyright (C) 2015 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+#ifndef UNITY_WINDOWINPUTMONITOR_H
18+#define UNITY_WINDOWINPUTMONITOR_H
19+
20+#include <QQuickItem>
21+#include <QPointer>
22+
23+#include "Timer.h"
24+#include "ElapsedTimer.h"
25+
26+/**
27+ * Monitors input events received by the window holding this item and the Home (Win aka Super_L)
28+ * key presses.
29+ *
30+ * Additionally, this class monitors for generic touch events on the screen, to
31+ * help with hiding/revealing the mouse pointer.
32+ */
33+class WindowInputMonitor : public QQuickItem
34+{
35+ Q_OBJECT
36+public:
37+
38+ WindowInputMonitor(QQuickItem *parent = 0);
39+
40+ // for testing
41+ WindowInputMonitor(UnityUtil::AbstractTimer *timer,
42+ UnityUtil::AbstractElapsedTimer *elapsedTimer,
43+ QQuickItem *parent = 0);
44+
45+ virtual ~WindowInputMonitor();
46+
47+ bool eventFilter(QObject *watched, QEvent *event) override;
48+
49+ void update(QEvent *event);
50+
51+ const qint64 msecsWithoutTouches = 150;
52+
53+Q_SIGNALS:
54+ /**
55+ * Emitted when the home key has been intentionally tapped
56+ *
57+ * It only says the home key has been activated if it has been tapped in isolation,
58+ * that is, without being accompanied by touches on the screen. Home key taps that
59+ * happen along with (or immediately after, or immediately before) touches on the
60+ * screen are considered to have happened unintentionally and are thus ignored.
61+ *
62+ * Rationale being that it's easy to accidentally hit the home key while performing
63+ * a swipe from a screen edge, for instance. That's particularly the case when the
64+ * home key is a capacitive key.
65+ */
66+ void homeKeyActivated();
67+
68+ /**
69+ * Emitted when a touch begin event is detected
70+ */
71+ void touchBegun();
72+
73+ /**
74+ * Emitted when a touch end event is detected
75+ * @param pos the position in screen coordinates
76+ */
77+ void touchEnded(const QPointF &pos);
78+
79+private Q_SLOTS:
80+ void setupFilterOnWindow(QQuickWindow *window);
81+ void emitActivatedIfNoTouchesAround();
82+
83+private:
84+ QPointer<QQuickWindow> m_filteredWindow;
85+ bool m_windowBeingTouched;
86+ bool m_homeKeyPressed;
87+ UnityUtil::AbstractElapsedTimer *m_windowLastTouchedTimer;
88+ UnityUtil::AbstractTimer *m_activationTimer;
89+};
90+
91+#endif // UNITY_WINDOWINPUTMONITOR_H
plugins/Utils/plugin.cpp+2−2
@@ -25,7 +25,7 @@
2525// local
2626#include "activefocuslogger.h"
2727#include "easingcurve.h"
28−#include "HomeKeyWatcher.h"
28+#include "WindowInputMonitor.h"
2929#include "inputwatcher.h"
3030#include "qlimitproxymodelqml.h"
3131#include "unitysortfilterproxymodelqml.h"
@@ -54,7 +54,7 @@ static QObject *createConstants(QQmlEngine *engine, QJSEngine *scriptEngine)
5454void UtilsPlugin::registerTypes(const char *uri)
5555{
5656 Q_ASSERT(uri == QLatin1String("Utils"));
57− qmlRegisterType<HomeKeyWatcher>(uri, 0, 1, "HomeKeyWatcher");
57+ qmlRegisterType<WindowInputMonitor>(uri, 0, 1, "WindowInputMonitor");
5858 qmlRegisterType<QAbstractItemModel>();
5959 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
6060 qmlRegisterType<UnitySortFilterProxyModelQML>(uri, 0, 1, "UnitySortFilterProxyModel");
qml/Shell.qml+11−3
@@ -56,7 +56,6 @@ Item {
5656 property bool beingResized
5757 property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop"
5858 property string mode: "full-greeter"
59− property bool cursorVisible: false
6059 property alias oskEnabled: inputMethod.enabled
6160 function updateFocusedAppOrientation() {
6261 applicationsDisplayLoader.item.updateFocusedAppOrientation();
@@ -177,8 +176,15 @@ Item {
177176 Keys.onReleased: physicalKeysMapper.onKeyReleased(event, currentEventTimestamp);
178177 }
179178
180− HomeKeyWatcher {
181− onActivated: { launcher.fadeOut(); shell.showHome(); }
179+ WindowInputMonitor {
180+ onHomeKeyActivated: { launcher.fadeOut(); shell.showHome(); }
181+ onTouchBegun: { cursor.opacity = 0; }
182+ onTouchEnded: {
183+ // move the (hidden) cursor to the last known touch position
184+ var mappedCoords = mapFromItem(null, pos.x, pos.y);
185+ cursor.x = mappedCoords.x;
186+ cursor.y = mappedCoords.y;
187+ }
182188 }
183189
184190 Item {
@@ -677,6 +683,8 @@ Item {
677683 applicationsDisplayLoader.item.pushRightEdge(amount);
678684 }
679685 }
686+
687+ onMouseMoved: { cursor.opacity = 1; }
680688 }
681689
682690 Rectangle {
tests/mocks/Cursor/Cursor.qml+1
@@ -19,4 +19,5 @@ import QtQuick 2.4
1919Item {
2020 signal pushedLeftBoundary(real amount, int buttons)
2121 signal pushedRightBoundary(real amount, int buttons)
22+ signal mouseMoved()
2223}
tests/mocks/Utils/HomeKeyWatcher.qml → tests/mocks/Utils/WindowInputMonitor.qmlrenamed+3−1
@@ -17,5 +17,7 @@
1717import QtQuick 2.4
1818
1919QtObject {
20− signal activated()
20+ signal homeKeyActivated()
21+ signal touchBegun()
22+ signal touchEnded(point pos)
2123}
tests/mocks/Utils/qmldir+1−1
@@ -2,5 +2,5 @@ module Utils
22plugin FakeUtils-qml
33typeinfo Utils.qmltypes
44Style 0.1 Style.js
5−HomeKeyWatcher 0.1 HomeKeyWatcher.qml
5+WindowInputMonitor 0.1 WindowInputMonitor.qml
66singleton EdgeBarrierSettings 0.1 EdgeBarrierSettings.qml
tests/plugins/Utils/CMakeLists.txt+1−1
@@ -7,7 +7,7 @@ include_directories(
77foreach(util_test
88 QLimitProxyModel
99 UnitySortFilterProxyModel
10− HomeKeyWatcher
10+ WindowInputMonitor
1111)
1212 add_executable(${util_test}TestExec ${util_test}Test.cpp ModelTest.cpp)
1313 qt5_use_modules(${util_test}TestExec Test Core Qml)
tests/plugins/Utils/HomeKeyWatcherTest.cpp → tests/plugins/Utils/WindowInputMonitorTest.cpprenamed+14−14
@@ -14,7 +14,7 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#include "HomeKeyWatcher.h"
17+#include "WindowInputMonitor.h"
1818
1919#include <QTest>
2020#include <QSignalSpy>
@@ -71,7 +71,7 @@ public:
7171
7272using namespace UnityUtil;
7373
74−class HomeKeyWatcherTest : public QObject {
74+class WindowInputMonitorTest : public QObject {
7575 Q_OBJECT
7676private Q_SLOTS:
7777 void init(); // called right before each and every test function is executed
@@ -88,25 +88,25 @@ private:
8888 FakeTimerFactory *m_fakeTimerFactory;
8989};
9090
91−void HomeKeyWatcherTest::init()
91+void WindowInputMonitorTest::init()
9292{
9393 m_fakeTimerFactory = new FakeTimerFactory;
9494}
9595
96−void HomeKeyWatcherTest::cleanup()
96+void WindowInputMonitorTest::cleanup()
9797{
9898 delete m_fakeTimerFactory;
9999 m_fakeTimerFactory = nullptr;
100100}
101101
102102
103−void HomeKeyWatcherTest::passTime(qint64 timeSpanMs)
103+void WindowInputMonitorTest::passTime(qint64 timeSpanMs)
104104{
105105 qint64 finalTime = FakeElapsedTimer::msecsSinceEpoch + timeSpanMs;
106106 m_fakeTimerFactory->updateTime(finalTime);
107107}
108108
109−void HomeKeyWatcherTest::touchTapTouch_data()
109+void WindowInputMonitorTest::touchTapTouch_data()
110110{
111111 QTest::addColumn<int>("silenceBeforeTap");
112112 QTest::addColumn<int>("tapDuration");
@@ -121,14 +121,14 @@ void HomeKeyWatcherTest::touchTapTouch_data()
121121 QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0;
122122}
123123
124−void HomeKeyWatcherTest::touchTapTouch()
124+void WindowInputMonitorTest::touchTapTouch()
125125{
126126 QFETCH(int, silenceBeforeTap);
127127 QFETCH(int, tapDuration);
128128 QFETCH(int, silenceAfterTap);
129129 QFETCH(int, expectedActivatedCount);
130− HomeKeyWatcher homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
131− QSignalSpy activatedSpy(&homeKeyWatcher, &HomeKeyWatcher::activated);
130+ WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
131+ QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
132132 QVERIFY(activatedSpy.isValid());
133133
134134 {
@@ -186,10 +186,10 @@ void HomeKeyWatcherTest::touchTapTouch()
186186 QCOMPARE(activatedSpy.count(), expectedActivatedCount);
187187}
188188
189−void HomeKeyWatcherTest::tapWhileTouching()
189+void WindowInputMonitorTest::tapWhileTouching()
190190{
191− HomeKeyWatcher homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
192− QSignalSpy activatedSpy(&homeKeyWatcher, &HomeKeyWatcher::activated);
191+ WindowInputMonitor homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
192+ QSignalSpy activatedSpy(&homeKeyWatcher, &WindowInputMonitor::homeKeyActivated);
193193 QVERIFY(activatedSpy.isValid());
194194
195195 {
@@ -318,6 +318,6 @@ AbstractTimer *FakeTimerFactory::create(QObject *parent)
318318 return fakeTimer;
319319}
320320
321−QTEST_GUILESS_MAIN(HomeKeyWatcherTest)
321+QTEST_GUILESS_MAIN(WindowInputMonitorTest)
322322
323−#include "HomeKeyWatcherTest.moc"
323+#include "WindowInputMonitorTest.moc"