Merge lp:~dandrader/unity8/runningAppsEndClose into lp:unity8

Proposed by Daniel d'Andrada
Status: Superseded
Proposed branch: lp:~dandrader/unity8/runningAppsEndClose
Merge into: lp:unity8
Diff against target: 1251 lines (+607/-131)
15 files modified
Dash/Apps/RunningApplicationsGrid.qml (+18/-11)
Dash/DashApps.qml (+0/-1)
Dash/GenericScopeView.qml (+0/-1)
plugins/Ubuntu/Gestures/CMakeLists.txt (+1/-0)
plugins/Ubuntu/Gestures/PressedOutsideNotifier.cpp (+118/-0)
plugins/Ubuntu/Gestures/PressedOutsideNotifier.h (+62/-0)
plugins/Ubuntu/Gestures/plugin.cpp (+2/-0)
tests/plugins/Ubuntu/Gestures/CMakeLists.txt (+21/-18)
tests/plugins/Ubuntu/Gestures/GestureTest.cpp (+44/-0)
tests/plugins/Ubuntu/Gestures/GestureTest.h (+44/-0)
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp (+67/-99)
tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.cpp (+146/-0)
tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.qml (+61/-0)
tests/qmltests/CMakeLists.txt (+3/-1)
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml (+20/-0)
To merge this branch: bzr merge lp:~dandrader/unity8/runningAppsEndClose
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michał Sawicz Needs Information
Review via email: mp+196006@code.launchpad.net

This proposal has been superseded by a proposal from 2013-11-22.

Commit message

Dash: disable app termination mode on click outside thumbnails

To leave the termination mode you can now just mouse/touch press anywhere
outside the running applications' thumbnails

The other way, which still works, is long-pressing a thumbnail once more.

Description of the change

Fixes bug 1193414.

InverseMouseArea is not fit for this job (e.g. doesn't work with touches when in topMostMode), thus I created a simple, light-weight, PressedOutsideNotifier that suites perfectly our needs.

Most of the diff is about tests and some test refactoring.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
542. By Albert Astals Cid

Do not include the QtQml megaheader

Include only qqml.h which is what we need in these files.

Approved by PS Jenkins bot, Michał Sawicz.

Revision history for this message
Michał Sawicz (saviq) wrote :

tst_PressedOutsideNotifier.qml: bad whitespace in line 37

BUT... Isn't InverseMouseArea supposed to do the same thing?

review: Needs Information
543. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> tst_PressedOutsideNotifier.qml: bad whitespace in line 37

Fixed.

> BUT... Isn't InverseMouseArea supposed to do the same thing?

Kind-of, but it's hindered by all the promises its API makes (it's a bit of a mess IMHO) and doesn't really work for that case. Have you read the description?

e.g.: It would have, for instance, to monitor touch events and translate them to mouse events himself because it's a Inverse*Mouse*Area. When its topMost property is on it listens for input events at a level before QQuickWindow is able to synthesize touch events out of mouse events.

Thus instead of trying to have it working for our case it's easier to come up with something concise and simple designed to fit perfectly with our needs. Since we're not a library, we're free to do this kind of things, which is good.

I don't see the point in striving to use InverseMouseArea just for the sake of using it because it already exists. If it's about improving InverseMouseArea itself, I'm not too hopeful.

Revision history for this message
Albert Astals Cid (aacid) wrote :

> e.g.: It would have, for instance, to monitor touch events and translate them
> to mouse events himself because it's a Inverse*Mouse*Area. When its topMost
> property is on it listens for input events at a level before QQuickWindow is
> able to synthesize touch events out of mouse events.

But didn't you have a patch for Qt to fix that?

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> > e.g.: It would have, for instance, to monitor touch events and translate
> them
> > to mouse events himself because it's a Inverse*Mouse*Area. When its topMost
> > property is on it listens for input events at a level before QQuickWindow is
> > able to synthesize touch events out of mouse events.
>
> But didn't you have a patch for Qt to fix that?

No. That's a different topic. But maybe InverseMouseArea does it to workaround that bug.

Revision history for this message
Albert Astals Cid (aacid) wrote :

> > > e.g.: It would have, for instance, to monitor touch events and translate
> > them
> > > to mouse events himself because it's a Inverse*Mouse*Area. When its
> topMost
> > > property is on it listens for input events at a level before QQuickWindow
> is
> > > able to synthesize touch events out of mouse events.
> >
> > But didn't you have a patch for Qt to fix that?
>
> No. That's a different topic. But maybe InverseMouseArea does it to workaround
> that bug.

Oh, it was my understanding that you where making the synthezised events go properly through the event stack again and thus they'd be caught by the InverseMouseArea and everything would just work.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> > > > e.g.: It would have, for instance, to monitor touch events and translate
> > > them
> > > > to mouse events himself because it's a Inverse*Mouse*Area. When its
> > topMost
> > > > property is on it listens for input events at a level before
> QQuickWindow
> > is
> > > > able to synthesize touch events out of mouse events.
> > >
> > > But didn't you have a patch for Qt to fix that?
> >
> > No. That's a different topic. But maybe InverseMouseArea does it to
> workaround
> > that bug.
>
> Oh, it was my understanding that you where making the synthezised events go
> properly through the event stack again and thus they'd be caught by the
> InverseMouseArea and everything would just work.

A topMost InverseMouseArea listens for events at QGuiApplication level (a bad idea, IMHO). synthesized mouse events from QQuickWindow will never to that high up, and they shouldn't.

544. By Omer Akram

make the non working code in the screen unlocker helper work.

Approved by PS Jenkins bot, Christopher Lee, Michael Zanetti.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> > > > > e.g.: It would have, for instance, to monitor touch events and
> translate
> > > > them
> > > > > to mouse events himself because it's a Inverse*Mouse*Area. When its
> > > topMost
> > > > > property is on it listens for input events at a level before
> > QQuickWindow
> > > is
> > > > > able to synthesize touch events out of mouse events.
> > > >
> > > > But didn't you have a patch for Qt to fix that?
> > >
> > > No. That's a different topic. But maybe InverseMouseArea does it to
> > workaround
> > > that bug.
> >
> > Oh, it was my understanding that you where making the synthezised events go
> > properly through the event stack again and thus they'd be caught by the
> > InverseMouseArea and everything would just work.
>
> A topMost InverseMouseArea listens for events at QGuiApplication level (a bad
> idea, IMHO). synthesized mouse events from QQuickWindow will never to that
> high up, and they shouldn't.

And even if it listened at the right level (rootItem), it still wouldn't work if there a touch-aware item in the scene that accepts the touches. In that situation QQuickWindow wound't synthesize mouse events out of the touch events because there's no need to.

Revision history for this message
Albert Astals Cid (aacid) wrote :

ok, in my opinion we should still fix InverseMouseArea to do what we want, i mean, what about all the other people out there that want to do exactly this? InverseMouseArea is supposed to do it, so why not fix it and then use it?

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> And even if it listened at the right level (rootItem), it still wouldn't work
> if there a touch-aware item in the scene that accepts the touches. In that
> situation QQuickWindow wound't synthesize mouse events out of the touch events
> because there's no need to.

Ah, and for listening at the "right level", that's when you would need my fix.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> ok, in my opinion we should still fix InverseMouseArea to do what we want, i
> mean, what about all the other people out there that want to do exactly this?
> InverseMouseArea is supposed to do it, so why not fix it and then use it?

Can't we do both?

1 - fix our UI *now*, which is what matters to the final user and people trying to sell our phone demoing it.
2 - Fix InverseMouseArea, so that application developer have better building blocks to build their ubuntu apps.

The thing is that item 2 requires much work because InverseMouseArea is meant to cover much more cases and has a more complex API. And we might have to sit around until my QQuickItem event dispatch fix is available in ubuntu repos, translating into even more time.

Item 1 is what the bug that this patch fixes is all about.
Item 2 is a bonus.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
545. By Nicolas d'Offay

Search history is now persistent across all scopes and remains in QML. Fixes: https://bugs.launchpad.net/bugs/1226221.

Approved by PS Jenkins bot, Albert Astals Cid.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:539
http://jenkins.qa.ubuntu.com/job/unity8-ci/1695/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/965
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/949
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/357
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/218
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/219
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/219/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/218
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/866
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/965
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/965/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/949
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/949/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3542
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1641

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1695/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:539
http://jenkins.qa.ubuntu.com/job/unity8-ci/1697/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/972
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/956
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/360
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/220
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/221
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/221/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/220
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/872
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/972
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/972/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/956
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/956/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3547
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1646

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1697/rebuild

review: Needs Fixing (continuous-integration)
546. By Albert Astals Cid

Don't do stuff if our parent context is gone

We'll be gone soon too (and crash probably) so don't do anything.
This looks a bit like a workaround, wait for 5.2 better painting/dispatching
loop to see if this is not needed anymore, we find a better way to do it,
or we decide this is fine.

Approved by PS Jenkins bot, Nick Dedekind.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:539
http://jenkins.qa.ubuntu.com/job/unity8-ci/1700/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/978
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/962
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/365
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/223
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/224
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/224/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/223
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/877
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/978
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/978/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/962
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/962/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3553
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1653

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1700/rebuild

review: Approve (continuous-integration)
547. By Michael Zanetti

drop all references to LighDM from the Lockscreen

This should make it generic enough to allow reusing it for SIM PIN entry
.

Approved by PS Jenkins bot, Mirco Müller.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:539
http://jenkins.qa.ubuntu.com/job/unity8-ci/1702/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/981
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/965
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/368
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/225
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/226
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/226/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/225
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/880
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/981
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/981/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/965
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/965/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/3558
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/1659

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1702/rebuild

review: Approve (continuous-integration)
548. By Lars Karlitski

Allow setting different indicator positions for different profiles.

Approved by PS Jenkins bot, Nick Dedekind.

Revision history for this message
Michał Sawicz (saviq) wrote :

Please split out the unrelated refactoring changes into a separate MP.

549. By Mirco Müller

Fixes bug #1200569. Fixes: https://bugs.launchpad.net/bugs/1200569.

Approved by PS Jenkins bot, Michael Zanetti.

550. By Daniel d'Andrada

Refactor Ubuntu.Gesture tests to share common logic

Take the common part out of tst_DirectionalDragArea and put
it into a separate base class, GestureTest, so that it can
be shared with other, future, tests.

In CMakeLists.txt, create a macro out of DirectionalDragArea build script
to be used by future tests with similar requirements and structure.

Also add the "m_" prefix to member variables.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> Please split out the unrelated refactoring changes into a separate MP.

And there it is:
https://code.launchpad.net/~dandrader/unity8/gestureTestsBaseClass/+merge/196256

551. By Daniel d'Andrada

More GestureTest and tst_DirectionalDragArea refactoring

- Move more stuff to GestureTest base class
- add tryFoo make command
- Let the qml file dictate the scene/window size, not the c++ code

552. By Daniel d'Andrada

Some string-related improvements

- Use QString instead of raw char array
- s/QLatin1String/QStringLiteral to optimize code

553. By Daniel d'Andrada

Dash: disable app termination mode on click outside thumbnails

To leave the termination mode you can now just mouse/touch press anywhere
outside the running applications' thumbnails

The other way, which still works, is long-pressing a thumbnail once more.

554. By Daniel d'Andrada

Put canEnableTerminationMode stuff back

To cover a minor "visual glitch" in a specific corner case

555. By Daniel d'Andrada

Add a Q_ASSERT to state that we really don't expect it to be null

as opposed to "we forget to handle the null case"

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Dash/Apps/RunningApplicationsGrid.qml'
2--- Dash/Apps/RunningApplicationsGrid.qml 2013-10-02 11:01:49 +0000
3+++ Dash/Apps/RunningApplicationsGrid.qml 2013-11-22 10:45:28 +0000
4@@ -17,6 +17,8 @@
5 import QtQuick 2.0
6 import "../../Components"
7
8+import Ubuntu.Gestures 0.1
9+
10 ResponsiveFlowView {
11 id: root
12 clip: true
13@@ -50,13 +52,6 @@
14 }
15 }
16
17- property bool canEnableTerminationMode: true
18-
19- onCanEnableTerminationModeChanged: {
20- if (!canEnableTerminationMode)
21- terminationModeEnabled = false
22- }
23-
24 // when false, it means it's on activation mode
25 property bool terminationModeEnabled: false
26
27@@ -78,10 +73,7 @@
28 }
29 application: model
30 onRequestedActivationMode: { root.terminationModeEnabled = false }
31- onRequestedTerminationMode: {
32- if (canEnableTerminationMode)
33- root.terminationModeEnabled = true
34- }
35+ onRequestedTerminationMode: { root.terminationModeEnabled = true }
36 onRequestedApplicationTermination: {
37 shell.applicationManager.stopApplication(model.appId)
38 }
39@@ -100,4 +92,19 @@
40 move: Transition {
41 NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutCubic }
42 }
43+
44+ MouseArea {
45+ anchors.fill: parent
46+ z: -1 // behind all RunningApplicationTiles
47+ enabled: root.terminationModeEnabled
48+ onPressed: { root.terminationModeEnabled = false; }
49+ }
50+
51+ PressedOutsideNotifier {
52+ anchors.fill: parent
53+ enabled: root.terminationModeEnabled
54+ onPressedOutside: {
55+ root.terminationModeEnabled = false;
56+ }
57+ }
58 }
59
60=== modified file 'Dash/DashApps.qml'
61--- Dash/DashApps.qml 2013-11-11 10:24:51 +0000
62+++ Dash/DashApps.qml 2013-11-22 10:45:28 +0000
63@@ -44,7 +44,6 @@
64
65 property var firstModel: mainStageApplicationsModel
66 property var secondModel: sideStageApplicationModel
67- property bool canEnableTerminationMode: scopeView.isCurrent
68
69 model: dummyVisibilityModifier
70 filterRole: 0
71
72=== modified file 'Dash/GenericScopeView.qml'
73--- Dash/GenericScopeView.qml 2013-11-19 14:33:40 +0000
74+++ Dash/GenericScopeView.qml 2013-11-22 10:45:28 +0000
75@@ -151,7 +151,6 @@
76 // TODO: the running apps grid doesn't support standard scope results model yet
77 item.firstModel = Qt.binding(function() { return results.firstModel })
78 item.secondModel = Qt.binding(function() { return results.secondModel })
79- item.canEnableTerminationMode = Qt.binding(function() { return scopeView.isCurrent })
80 } else {
81 item.model = Qt.binding(function() { return results })
82 }
83
84=== modified file 'plugins/Ubuntu/Gestures/CMakeLists.txt'
85--- plugins/Ubuntu/Gestures/CMakeLists.txt 2013-10-22 15:56:37 +0000
86+++ plugins/Ubuntu/Gestures/CMakeLists.txt 2013-11-22 10:45:28 +0000
87@@ -6,6 +6,7 @@
88 AxisVelocityCalculator.cpp
89 Direction.cpp
90 DirectionalDragArea.cpp
91+ PressedOutsideNotifier.cpp
92 TimeSource.cpp
93 )
94
95
96=== added file 'plugins/Ubuntu/Gestures/PressedOutsideNotifier.cpp'
97--- plugins/Ubuntu/Gestures/PressedOutsideNotifier.cpp 1970-01-01 00:00:00 +0000
98+++ plugins/Ubuntu/Gestures/PressedOutsideNotifier.cpp 2013-11-22 10:45:28 +0000
99@@ -0,0 +1,118 @@
100+/*
101+ * Copyright (C) 2013 Canonical, Ltd.
102+ *
103+ * This program is free software; you can redistribute it and/or modify
104+ * it under the terms of the GNU General Public License as published by
105+ * the Free Software Foundation; version 3.
106+ *
107+ * This program is distributed in the hope that it will be useful,
108+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
109+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
110+ * GNU General Public License for more details.
111+ *
112+ * You should have received a copy of the GNU General Public License
113+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
114+ */
115+
116+#include "PressedOutsideNotifier.h"
117+
118+#include <QMouseEvent>
119+
120+PressedOutsideNotifier::PressedOutsideNotifier(QQuickItem *parent)
121+ : QQuickItem(parent)
122+{
123+ connect(this, &QQuickItem::enabledChanged,
124+ this, &PressedOutsideNotifier::setupOrTearDownEventFiltering);
125+
126+ m_signalEmissionTimer.setSingleShot(true);
127+ m_signalEmissionTimer.setInterval(0); // times out on the next iteration of the event loop
128+ connect(&m_signalEmissionTimer, &QTimer::timeout,
129+ this, &PressedOutsideNotifier::pressedOutside);
130+}
131+
132+bool PressedOutsideNotifier::eventFilter(QObject *watched, QEvent *event)
133+{
134+ Q_UNUSED(watched);
135+ Q_ASSERT(watched == m_filteredWindow);
136+
137+ // We are already going to emit pressedOutside() anyway, thus no need
138+ // for new checks.
139+ // This case takes place when a QTouchEvent comes in and isn't handled by any item,
140+ // causing QQuickWindow to synthesize a QMouseEvent out of it, which would
141+ // be filtered by us as well and count as a second press, which is wrong.
142+ if (m_signalEmissionTimer.isActive()) {
143+ return false;
144+ }
145+
146+ switch (event->type()) {
147+ case QEvent::MouseButtonPress: {
148+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
149+ QPointF p = mapFromScene(mouseEvent->windowPos());
150+ if (!contains(p)) {
151+ m_signalEmissionTimer.start();
152+ }
153+ break;
154+ }
155+ case QEvent::TouchBegin:
156+ processFilteredTouchBegin(static_cast<QTouchEvent*>(event));
157+ default:
158+ break;
159+ }
160+
161+ // let the event be handled further
162+ return false;
163+}
164+
165+void PressedOutsideNotifier::itemChange(ItemChange change, const ItemChangeData &value)
166+{
167+ if (change == QQuickItem::ItemSceneChange) {
168+ setupOrTearDownEventFiltering();
169+ }
170+
171+ QQuickItem::itemChange(change, value);
172+}
173+
174+void PressedOutsideNotifier::setupOrTearDownEventFiltering()
175+{
176+ if (isEnabled() && window()) {
177+ setupEventFiltering();
178+ } else if (m_filteredWindow) {
179+ tearDownEventFiltering();
180+ }
181+}
182+
183+void PressedOutsideNotifier::setupEventFiltering()
184+{
185+ QQuickWindow *currentWindow = window();
186+
187+ if (currentWindow == m_filteredWindow)
188+ return;
189+
190+ if (m_filteredWindow) {
191+ m_filteredWindow->removeEventFilter(this);
192+ }
193+
194+ currentWindow->installEventFilter(this);
195+ m_filteredWindow = currentWindow;
196+}
197+
198+void PressedOutsideNotifier::tearDownEventFiltering()
199+{
200+ m_filteredWindow->removeEventFilter(this);
201+ m_filteredWindow.clear();
202+}
203+
204+void PressedOutsideNotifier::processFilteredTouchBegin(QTouchEvent *event)
205+{
206+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
207+ for (int i = 0; i < touchPoints.count(); ++i) {
208+ const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
209+ if (touchPoint.state() == Qt::TouchPointPressed) {
210+ QPointF p = mapFromScene(touchPoint.pos());
211+ if (!contains(p)) {
212+ m_signalEmissionTimer.start();
213+ return;
214+ }
215+ }
216+ }
217+}
218
219=== added file 'plugins/Ubuntu/Gestures/PressedOutsideNotifier.h'
220--- plugins/Ubuntu/Gestures/PressedOutsideNotifier.h 1970-01-01 00:00:00 +0000
221+++ plugins/Ubuntu/Gestures/PressedOutsideNotifier.h 2013-11-22 10:45:28 +0000
222@@ -0,0 +1,62 @@
223+/*
224+ * Copyright (C) 2013 Canonical, Ltd.
225+ *
226+ * This program is free software; you can redistribute it and/or modify
227+ * it under the terms of the GNU General Public License as published by
228+ * the Free Software Foundation; version 3.
229+ *
230+ * This program is distributed in the hope that it will be useful,
231+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
232+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
233+ * GNU General Public License for more details.
234+ *
235+ * You should have received a copy of the GNU General Public License
236+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
237+ */
238+
239+#ifndef PRESSED_OUTSIDE_NOTIFIER_H
240+#define PRESSED_OUTSIDE_NOTIFIER_H
241+
242+#include <QQuickItem>
243+
244+#include <QQuickWindow>
245+#include <QPointer>
246+#include <QTimer>
247+
248+#include "UbuntuGesturesGlobal.h"
249+
250+/*
251+ Notifies when a point, mouse or touch, is pressed outside its area.
252+
253+ Only enable it while needed.
254+ */
255+class UBUNTUGESTURES_EXPORT PressedOutsideNotifier : public QQuickItem {
256+ Q_OBJECT
257+
258+public:
259+ PressedOutsideNotifier(QQuickItem * parent = nullptr);
260+
261+ // From QObject
262+ bool eventFilter(QObject *watched, QEvent *event) override;
263+
264+Q_SIGNALS:
265+ void pressedOutside();
266+
267+protected:
268+ void itemChange(ItemChange change, const ItemChangeData &value) override;
269+
270+private Q_SLOTS:
271+ void setupOrTearDownEventFiltering();
272+
273+private:
274+ void setupEventFiltering();
275+ void tearDownEventFiltering();
276+ void processFilteredTouchBegin(QTouchEvent *event);
277+
278+ QPointer<QQuickWindow> m_filteredWindow;
279+
280+ // Emits pressedOutside() signal on timeout
281+ QTimer m_signalEmissionTimer;
282+};
283+
284+#endif // PRESSED_OUTSIDE_NOTIFIER_H
285
286=== modified file 'plugins/Ubuntu/Gestures/plugin.cpp'
287--- plugins/Ubuntu/Gestures/plugin.cpp 2013-06-17 13:45:28 +0000
288+++ plugins/Ubuntu/Gestures/plugin.cpp 2013-11-22 10:45:28 +0000
289@@ -18,6 +18,7 @@
290 #include "AxisVelocityCalculator.h"
291 #include "Direction.h"
292 #include "DirectionalDragArea.h"
293+#include "PressedOutsideNotifier.h"
294
295 #include <qqml.h>
296
297@@ -32,4 +33,5 @@
298 qmlRegisterSingletonType<Direction>(uri, 0, 1, "Direction", directionSingleton);
299 qmlRegisterType<DirectionalDragArea>(uri, 0, 1, "DirectionalDragArea");
300 qmlRegisterType<AxisVelocityCalculator>(uri, 0, 1, "AxisVelocityCalculator");
301+ qmlRegisterType<PressedOutsideNotifier>(uri, 0, 1, "PressedOutsideNotifier");
302 }
303
304=== modified file 'tests/plugins/Ubuntu/Gestures/CMakeLists.txt'
305--- tests/plugins/Ubuntu/Gestures/CMakeLists.txt 2013-06-11 18:22:43 +0000
306+++ tests/plugins/Ubuntu/Gestures/CMakeLists.txt 2013-11-22 10:45:28 +0000
307@@ -1,33 +1,33 @@
308-########## tst_DirectionalDragArea
309+include(QmlTest)
310
311 include_directories(
312 ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
313 ${CMAKE_CURRENT_BINARY_DIR}
314 )
315
316-set(testCommand
317- LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
318- ${CMAKE_CURRENT_BINARY_DIR}/DirectionalDragAreaTestExec
319- -o ${CMAKE_BINARY_DIR}/DirectionalDragAreaTest.xml,xunitxml
320- -o -,txt)
321-
322-add_custom_target(testDirectionalDragArea ${testCommand})
323-add_dependencies(qmluitests testDirectionalDragArea)
324-add_dependencies(testDirectionalDragArea DirectionalDragAreaTestExec UbutunGesturesTestQmlFiles)
325-
326-add_executable(DirectionalDragAreaTestExec tst_DirectionalDragArea.cpp)
327-qt5_use_modules(DirectionalDragAreaTestExec Test Core Qml Gui Quick)
328-target_link_libraries(DirectionalDragAreaTestExec UbuntuGestureQml)
329-
330-add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
331-
332 file(GLOB qmlFiles *.qml)
333 add_custom_target(UbuntuGesturesTestQmlFiles ALL
334 COMMAND cp ${qmlFiles} ${CMAKE_CURRENT_BINARY_DIR}
335 DEPENDS ${qmlFiles}
336 )
337
338-########## other tests
339+add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
340+
341+macro(add_gesture_ui_test CLASSNAME)
342+ set(testCommand
343+ LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
344+ ${CMAKE_CURRENT_BINARY_DIR}/${CLASSNAME}TestExec
345+ -o ${CMAKE_BINARY_DIR}/${CLASSNAME}Test.xml,xunitxml
346+ -o -,txt)
347+
348+ add_custom_target(test${CLASSNAME} ${testCommand})
349+ add_dependencies(qmluitests test${CLASSNAME})
350+ add_dependencies(test${CLASSNAME} ${CLASSNAME}TestExec UbuntuGesturesTestQmlFiles)
351+
352+ add_executable(${CLASSNAME}TestExec tst_${CLASSNAME}.cpp GestureTest.cpp)
353+ qt5_use_modules(${CLASSNAME}TestExec Test Core Qml Gui Quick)
354+ target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
355+endmacro(add_gesture_ui_test)
356
357 macro(add_gesture_test CLASSNAME)
358 set(testCommand
359@@ -43,5 +43,8 @@
360 target_link_libraries(${CLASSNAME}TestExec UbuntuGestureQml)
361 endmacro(add_gesture_test)
362
363+add_gesture_ui_test(DirectionalDragArea)
364+add_gesture_ui_test(PressedOutsideNotifier)
365+add_manual_qml_test(. PressedOutsideNotifier IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
366 add_gesture_test(Damper)
367 add_gesture_test(AxisVelocityCalculator)
368
369=== added file 'tests/plugins/Ubuntu/Gestures/GestureTest.cpp'
370--- tests/plugins/Ubuntu/Gestures/GestureTest.cpp 1970-01-01 00:00:00 +0000
371+++ tests/plugins/Ubuntu/Gestures/GestureTest.cpp 2013-11-22 10:45:28 +0000
372@@ -0,0 +1,44 @@
373+/*
374+ * Copyright (C) 2013 Canonical, Ltd.
375+ *
376+ * This program is free software; you can redistribute it and/or modify
377+ * it under the terms of the GNU General Public License as published by
378+ * the Free Software Foundation; version 3.
379+ *
380+ * This program is distributed in the hope that it will be useful,
381+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
382+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
383+ * GNU General Public License for more details.
384+ *
385+ * You should have received a copy of the GNU General Public License
386+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
387+ */
388+
389+#include "GestureTest.h"
390+
391+#include <qpa/qwindowsysteminterface.h>
392+#include <QQmlEngine>
393+#include <QQuickView>
394+
395+void GestureTest::initTestCase()
396+{
397+ if (!m_device) {
398+ m_device = new QTouchDevice;
399+ m_device->setType(QTouchDevice::TouchScreen);
400+ QWindowSystemInterface::registerTouchDevice(m_device);
401+ }
402+}
403+
404+void GestureTest::init()
405+{
406+ m_view = new QQuickView(0);
407+ m_view->setResizeMode(QQuickView::SizeRootObjectToView);
408+ m_view->resize(600, 600);
409+ m_view->engine()->addImportPath(QLatin1String(UBUNTU_GESTURES_PLUGIN_DIR));
410+}
411+
412+void GestureTest::cleanup()
413+{
414+ delete m_view;
415+ m_view = nullptr;
416+}
417
418=== added file 'tests/plugins/Ubuntu/Gestures/GestureTest.h'
419--- tests/plugins/Ubuntu/Gestures/GestureTest.h 1970-01-01 00:00:00 +0000
420+++ tests/plugins/Ubuntu/Gestures/GestureTest.h 2013-11-22 10:45:28 +0000
421@@ -0,0 +1,44 @@
422+/*
423+ * Copyright (C) 2013 Canonical, Ltd.
424+ *
425+ * This program is free software; you can redistribute it and/or modify
426+ * it under the terms of the GNU General Public License as published by
427+ * the Free Software Foundation; version 3.
428+ *
429+ * This program is distributed in the hope that it will be useful,
430+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
431+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432+ * GNU General Public License for more details.
433+ *
434+ * You should have received a copy of the GNU General Public License
435+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
436+ */
437+
438+#ifndef GESTURETEST_H
439+#endif // GESTURETEST_H
440+
441+#include <QObject>
442+
443+class QQuickView;
444+class QTouchDevice;
445+
446+/*
447+ The common stuff among tests come here
448+ */
449+class GestureTest : public QObject
450+{
451+ Q_OBJECT
452+public:
453+ GestureTest() : QObject(), m_device(nullptr), m_view(nullptr) {}
454+
455+protected Q_SLOTS:
456+ void initTestCase(); // will be called before the first test function is executed
457+ virtual void init(); // called right before each and every test function is executed
458+ virtual void cleanup(); // called right after each and every test function is executed
459+
460+protected:
461+ QTouchDevice *m_device;
462+ QQuickView *m_view;
463+};
464+
465+#define GESTURETEST_H
466
467=== modified file 'tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp'
468--- tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp 2013-10-23 12:25:40 +0000
469+++ tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp 2013-11-22 10:45:28 +0000
470@@ -16,13 +16,14 @@
471
472 #include <QtTest/QtTest>
473 #include <QtCore/QObject>
474-#include <qpa/qwindowsysteminterface.h>
475 #include <QtQuick/QQuickView>
476 #include <QtQml/QQmlEngine>
477 #include <QPointer>
478
479 #include <DirectionalDragArea.h>
480
481+#include "GestureTest.h"
482+
483 using namespace UbuntuGestures;
484
485 class FakeTimer : public AbstractTimer
486@@ -61,15 +62,11 @@
487 qint64 m_msecsSinceReference;
488 };
489
490-class tst_DirectionalDragArea: public QObject
491+class tst_DirectionalDragArea: public GestureTest
492 {
493 Q_OBJECT
494 public:
495- tst_DirectionalDragArea() : device(0) { }
496 private Q_SLOTS:
497- void initTestCase(); // will be called before the first test function is executed
498- void cleanupTestCase(); // will be called after the last test function was executed.
499-
500 void init(); // called right before each and every test function is executed
501 void cleanup(); // called right after each and every test function is executed
502
503@@ -87,36 +84,18 @@
504 void ignoreOldFinger();
505
506 private:
507- QQuickView *createView();
508 void passTime(qint64 timeSpan);
509- QQuickView *view;
510- QTouchDevice *device;
511 FakeTimer *fakeTimer;
512 QSharedPointer<FakeTimeSource> fakeTimeSource;
513 };
514
515-void tst_DirectionalDragArea::initTestCase()
516-{
517- if (!device) {
518- device = new QTouchDevice;
519- device->setType(QTouchDevice::TouchScreen);
520- QWindowSystemInterface::registerTouchDevice(device);
521- }
522-
523- view = 0;
524-}
525-
526-void tst_DirectionalDragArea::cleanupTestCase()
527-{
528-}
529-
530 void tst_DirectionalDragArea::init()
531 {
532- view = createView();
533- view->setSource(QUrl::fromLocalFile("edgeDragExample.qml"));
534- view->show();
535- QVERIFY(QTest::qWaitForWindowExposed(view));
536- QVERIFY(view->rootObject() != 0);
537+ GestureTest::init();
538+ m_view->setSource(QUrl::fromLocalFile("edgeDragExample.qml"));
539+ m_view->show();
540+ QVERIFY(QTest::qWaitForWindowExposed(m_view));
541+ QVERIFY(m_view->rootObject() != 0);
542 qApp->processEvents();
543
544 fakeTimeSource.reset(new FakeTimeSource);
545@@ -125,23 +104,12 @@
546
547 void tst_DirectionalDragArea::cleanup()
548 {
549- delete view;
550- view = 0;
551-
552 delete fakeTimer;
553 fakeTimer = 0;
554
555 fakeTimeSource.reset();
556-}
557-
558-QQuickView *tst_DirectionalDragArea::createView()
559-{
560- QQuickView *window = new QQuickView(0);
561- window->setResizeMode(QQuickView::SizeRootObjectToView);
562- window->resize(600, 600);
563- window->engine()->addImportPath(QLatin1String(UBUNTU_GESTURES_PLUGIN_DIR));
564-
565- return window;
566+
567+ GestureTest::cleanup();
568 }
569
570 void tst_DirectionalDragArea::passTime(qint64 timeSpan)
571@@ -217,14 +185,14 @@
572 QFETCH(bool, expectGestureRecognition);
573
574 DirectionalDragArea *edgeDragArea =
575- view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
576+ m_view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
577 QVERIFY(edgeDragArea != 0);
578 edgeDragArea->setRecognitionTimer(fakeTimer);
579 edgeDragArea->setTimeSource(fakeTimeSource);
580
581 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
582
583- QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
584+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
585 QPointF touchPoint = initialTouchPos;
586
587 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
588@@ -235,7 +203,7 @@
589 int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
590 int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
591
592- QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
593+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
594
595 QCOMPARE(draggingSpy.count(), 1);
596 QCOMPARE(edgeDragArea->dragging(), true);
597@@ -245,13 +213,13 @@
598 // in order to make it easier to leave it by dragging at an angle
599 // slightly bigger than the widening angle
600 touchPoint += createTouchDeviation(edgeDragArea);
601- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
602+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
603 }
604
605 for (int i = 0; i < totalMovementSteps; ++i) {
606 touchPoint += touchMovement;
607 passTime(movementTimeStepMs);
608- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
609+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
610 }
611
612 if (expectGestureRecognition)
613@@ -262,7 +230,7 @@
614 QCOMPARE(draggingSpy.count(), 2);
615 }
616
617- QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
618+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
619
620 QCOMPARE(draggingSpy.count(), 2);
621 QCOMPARE(edgeDragArea->dragging(), false);
622@@ -326,12 +294,12 @@
623 void tst_DirectionalDragArea::dragWithShortDirectionChange()
624 {
625 DirectionalDragArea *edgeDragArea =
626- view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
627+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
628 QVERIFY(edgeDragArea != 0);
629 edgeDragArea->setRecognitionTimer(fakeTimer);
630 edgeDragArea->setTimeSource(fakeTimeSource);
631
632- QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
633+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
634 QPointF touchPoint = initialTouchPos;
635
636 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
637@@ -341,32 +309,32 @@
638 int touchStepTimeMs = (touchStepDistance / (edgeDragArea->minSpeed() * 5.0f)) * 1000.0f;
639 QPointF touchMovement = dragDirectionVector * touchStepDistance;
640
641- QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
642+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
643
644 // Move a bit in the proper direction
645 for (int i=0; i < 3; ++i) {
646 touchPoint += touchMovement;
647 passTime(touchStepTimeMs);
648- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
649+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
650 }
651
652 // Then a sudden and small movement to the opposite direction
653 touchPoint -= touchMovement*0.2;
654 passTime(touchStepTimeMs*0.2);
655- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
656+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
657
658 // And then resume movment in the correct direction until it crosses the distance and time
659 // thresholds.
660 do {
661 touchPoint += touchMovement;
662 passTime(touchStepTimeMs);
663- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
664+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
665 } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance
666 || fakeTimeSource->m_msecsSinceReference < (edgeDragArea->compositionTime() * 1.5f));
667
668 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
669
670- QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
671+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
672 }
673
674 /*
675@@ -380,7 +348,7 @@
676 QFETCH(int, expectedStatusAfterSpeedCheck);
677
678 DirectionalDragArea *edgeDragArea =
679- view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
680+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
681 QVERIFY(edgeDragArea != 0);
682 edgeDragArea->setRecognitionTimer(fakeTimer);
683 edgeDragArea->setTimeSource(fakeTimeSource);
684@@ -391,7 +359,7 @@
685
686 edgeDragArea->setMinSpeed(minSpeed);
687
688- QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
689+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
690 QPointF touchPoint = initialTouchPos;
691
692 QPointF dragDirectionVector(1.0, 0.0);
693@@ -399,13 +367,13 @@
694 qreal distanceStep = (speed / 1000.0f) * timeStepMsecs;
695 QPointF touchMovement = dragDirectionVector * distanceStep;
696
697- QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
698+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
699
700 // Move for a while to ensure our speed check is performed a couple of times
701 for (int i=0; i < 20; ++i) {
702 touchPoint += touchMovement;
703 passTime(timeStepMsecs);
704- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
705+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
706 }
707
708 QCOMPARE((int)edgeDragArea->status(), expectedStatusAfterSpeedCheck);
709@@ -429,7 +397,7 @@
710 void tst_DirectionalDragArea::recognitionTimerUsage()
711 {
712 DirectionalDragArea *edgeDragArea =
713- view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
714+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
715 QVERIFY(edgeDragArea != 0);
716 edgeDragArea->setRecognitionTimer(fakeTimer);
717 edgeDragArea->setTimeSource(fakeTimeSource);
718@@ -439,7 +407,7 @@
719
720 int timeStepMs = 5; // some arbitrary small value.
721
722- QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
723+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
724 QPointF touchPoint = initialTouchPos;
725
726 QPointF dragDirectionVector(1.0, 0.0);
727@@ -448,7 +416,7 @@
728 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
729 QVERIFY(!fakeTimer->isRunning());
730
731- QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
732+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
733
734 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
735 QVERIFY(fakeTimer->isRunning());
736@@ -461,7 +429,7 @@
737
738 touchPoint += touchMovement;
739 passTime(timeStepMs);
740- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
741+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
742 }
743
744 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
745@@ -475,7 +443,7 @@
746 void tst_DirectionalDragArea::maxSilenceTime()
747 {
748 DirectionalDragArea *edgeDragArea =
749- view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
750+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
751 QVERIFY(edgeDragArea != 0);
752 edgeDragArea->setRecognitionTimer(fakeTimer);
753 edgeDragArea->setTimeSource(fakeTimeSource);
754@@ -483,10 +451,10 @@
755 // Make sure this property is not disabled
756 edgeDragArea->setMaxSilenceTime(100);
757
758- QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
759+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
760 QPointF touchPoint = initialTouchPos;
761
762- QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
763+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
764
765 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
766 QVERIFY(fakeTimer->isRunning());
767@@ -506,20 +474,20 @@
768 void tst_DirectionalDragArea::sceneXAndX()
769 {
770 DirectionalDragArea *edgeDragArea =
771- view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
772+ m_view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
773 QVERIFY(edgeDragArea != 0);
774 edgeDragArea->setRecognitionTimer(fakeTimer);
775 edgeDragArea->setTimeSource(fakeTimeSource);
776
777- QPointF touchScenePos(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
778+ QPointF touchScenePos(m_view->width() - (edgeDragArea->width()/2.0f), m_view->height()/2.0f);
779
780- QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
781+ QTest::touchEvent(m_view, m_device).press(0, touchScenePos.toPoint());
782
783 QSignalSpy touchXSpy(edgeDragArea, SIGNAL(touchXChanged(qreal)));
784 QSignalSpy touchSceneXSpy(edgeDragArea, SIGNAL(touchSceneXChanged(qreal)));
785
786- touchScenePos.rx() = view->width() / 2;
787- QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
788+ touchScenePos.rx() = m_view->width() / 2;
789+ QTest::touchEvent(m_view, m_device).move(0, touchScenePos.toPoint());
790
791 QCOMPARE(touchXSpy.count(), 1);
792 QCOMPARE(touchSceneXSpy.count(), 1);
793@@ -534,20 +502,20 @@
794 void tst_DirectionalDragArea::sceneYAndY()
795 {
796 DirectionalDragArea *edgeDragArea =
797- view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
798+ m_view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
799 QVERIFY(edgeDragArea != 0);
800 edgeDragArea->setRecognitionTimer(fakeTimer);
801 edgeDragArea->setTimeSource(fakeTimeSource);
802
803- QPointF touchScenePos(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
804+ QPointF touchScenePos(m_view->width()/2.0f, m_view->height() - (edgeDragArea->height()/2.0f));
805
806- QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
807+ QTest::touchEvent(m_view, m_device).press(0, touchScenePos.toPoint());
808
809 QSignalSpy touchYSpy(edgeDragArea, SIGNAL(touchYChanged(qreal)));
810 QSignalSpy touchSceneYSpy(edgeDragArea, SIGNAL(touchSceneYChanged(qreal)));
811
812- touchScenePos.ry() = view->height() / 2;
813- QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
814+ touchScenePos.ry() = m_view->height() / 2;
815+ QTest::touchEvent(m_view, m_device).move(0, touchScenePos.toPoint());
816
817 QCOMPARE(touchYSpy.count(), 1);
818 QCOMPARE(touchSceneYSpy.count(), 1);
819@@ -564,27 +532,27 @@
820 void tst_DirectionalDragArea::twoFingerTap()
821 {
822 DirectionalDragArea *edgeDragArea =
823- view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
824+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
825 QVERIFY(edgeDragArea != 0);
826 edgeDragArea->setRecognitionTimer(fakeTimer);
827 edgeDragArea->setTimeSource(fakeTimeSource);
828
829 // Make touches evenly spaced along the edgeDragArea
830- QPoint touchAPos(edgeDragArea->width()/2.0f, view->height()*0.33f);
831- QPoint touchBPos(edgeDragArea->width()/2.0f, view->height()*0.66f);
832+ QPoint touchAPos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
833+ QPoint touchBPos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
834
835 qint64 timeStepMsecs = 5; // some arbitrary, small value
836
837 // Perform the first two-finger tap
838 // NB: using move() instead of stationary() becasue in the latter you cannot provide
839 // the touch position and therefore it's left with some garbage numbers.
840- QTest::touchEvent(view, device)
841+ QTest::touchEvent(m_view, m_device)
842 .press(0, touchAPos);
843
844 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
845
846 passTime(timeStepMsecs);
847- QTest::touchEvent(view, device)
848+ QTest::touchEvent(m_view, m_device)
849 .move(0, touchAPos)
850 .press(1, touchBPos);
851
852@@ -593,14 +561,14 @@
853 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
854
855 passTime(timeStepMsecs);
856- QTest::touchEvent(view, device)
857+ QTest::touchEvent(m_view, m_device)
858 .release(0, touchAPos)
859 .move(1, touchBPos);
860
861 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
862
863 passTime(timeStepMsecs);
864- QTest::touchEvent(view, device)
865+ QTest::touchEvent(m_view, m_device)
866 .release(1, touchBPos);
867
868 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
869@@ -608,27 +576,27 @@
870 // Perform the second two-finger tap
871
872 passTime(timeStepMsecs);
873- QTest::touchEvent(view, device)
874+ QTest::touchEvent(m_view, m_device)
875 .press(0, touchAPos);
876
877 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
878
879 passTime(timeStepMsecs);
880- QTest::touchEvent(view, device)
881+ QTest::touchEvent(m_view, m_device)
882 .move(0, touchAPos)
883 .press(1, touchBPos);
884
885 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
886
887 passTime(timeStepMsecs);
888- QTest::touchEvent(view, device)
889+ QTest::touchEvent(m_view, m_device)
890 .release(0, touchAPos)
891 .move(1, touchBPos);
892
893 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
894
895 passTime(timeStepMsecs);
896- QTest::touchEvent(view, device)
897+ QTest::touchEvent(m_view, m_device)
898 .release(1, touchBPos);
899
900 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
901@@ -642,7 +610,7 @@
902 */
903 void tst_DirectionalDragArea::movingDDA()
904 {
905- QQuickItem *rightwardsLauncher = view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
906+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
907 Q_ASSERT(rightwardsLauncher != 0);
908
909 DirectionalDragArea *edgeDragArea =
910@@ -651,7 +619,7 @@
911 edgeDragArea->setRecognitionTimer(fakeTimer);
912 edgeDragArea->setTimeSource(fakeTimeSource);
913
914- QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
915+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, m_view);
916 QPointF touchPoint = initialTouchPos;
917
918 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
919@@ -662,7 +630,7 @@
920 int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
921 int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
922
923- QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
924+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
925
926 // Move it far ahead along the direction of the gesture
927 // rightwardsLauncher is a parent of our DirectionalDragArea. So moving it will move our DDA
928@@ -671,12 +639,12 @@
929 for (int i = 0; i < totalMovementSteps; ++i) {
930 touchPoint += touchMovement;
931 passTime(movementTimeStepMs);
932- QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
933+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
934 }
935
936 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
937
938- QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
939+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
940 }
941
942 /*
943@@ -686,16 +654,16 @@
944 void tst_DirectionalDragArea::ignoreOldFinger()
945 {
946 DirectionalDragArea *edgeDragArea =
947- view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
948+ m_view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
949 Q_ASSERT(edgeDragArea != 0);
950 edgeDragArea->setRecognitionTimer(fakeTimer);
951 edgeDragArea->setTimeSource(fakeTimeSource);
952
953 // Make touches evenly spaced along the edgeDragArea
954- QPoint touch0Pos(edgeDragArea->width()/2.0f, view->height()*0.33f);
955- QPoint touch1Pos(edgeDragArea->width()/2.0f, view->height()*0.66f);
956+ QPoint touch0Pos(edgeDragArea->width()/2.0f, m_view->height()*0.33f);
957+ QPoint touch1Pos(edgeDragArea->width()/2.0f, m_view->height()*0.66f);
958
959- QTest::touchEvent(view, device).press(0, touch0Pos);
960+ QTest::touchEvent(m_view, m_device).press(0, touch0Pos);
961
962 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
963
964@@ -712,7 +680,7 @@
965 int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
966 int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
967
968- QTest::touchEvent(view, device)
969+ QTest::touchEvent(m_view, m_device)
970 .move(0, touch0Pos)
971 .press(1, touch1Pos);
972
973@@ -721,14 +689,14 @@
974 for (int i = 0; i < totalMovementSteps; ++i) {
975 touch1Pos += touchMovement.toPoint();
976 passTime(movementTimeStepMs);
977- QTest::touchEvent(view, device)
978+ QTest::touchEvent(m_view, m_device)
979 .move(0, touch0Pos)
980 .move(1, touch1Pos);
981 }
982
983 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
984
985- QTest::touchEvent(view, device)
986+ QTest::touchEvent(m_view, m_device)
987 .move(0, touch0Pos)
988 .release(1, touch1Pos);
989
990
991=== added file 'tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.cpp'
992--- tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.cpp 1970-01-01 00:00:00 +0000
993+++ tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.cpp 2013-11-22 10:45:28 +0000
994@@ -0,0 +1,146 @@
995+/*
996+ * Copyright (C) 2013 Canonical, Ltd.
997+ *
998+ * This program is free software; you can redistribute it and/or modify
999+ * it under the terms of the GNU General Public License as published by
1000+ * the Free Software Foundation; version 3.
1001+ *
1002+ * This program is distributed in the hope that it will be useful,
1003+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1004+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1005+ * GNU General Public License for more details.
1006+ *
1007+ * You should have received a copy of the GNU General Public License
1008+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1009+ */
1010+
1011+#include "GestureTest.h"
1012+
1013+#include <PressedOutsideNotifier.h>
1014+
1015+#include <QQuickItem>
1016+#include <QQuickView>
1017+#include <QtTest>
1018+
1019+class tst_PressedOutsideNotifier: public GestureTest
1020+{
1021+ Q_OBJECT
1022+private Q_SLOTS:
1023+ void init(); // called right before each and every test function is executed
1024+
1025+ void touchOutsideAreaTriggersSignal();
1026+ void touchInsideAreaHasNoEffect();
1027+ void mousePressOutsideAreaTriggersSignal();
1028+ void mousePresssInsideAreaHasNoEffect();
1029+ void nothingHappensWhileDisabled();
1030+
1031+private:
1032+ QQuickItem *m_blueRect;
1033+ PressedOutsideNotifier *m_notifier;
1034+};
1035+
1036+void tst_PressedOutsideNotifier::init()
1037+{
1038+ GestureTest::init();
1039+ m_view->setSource(QUrl::fromLocalFile("tst_PressedOutsideNotifier.qml"));
1040+ m_view->show();
1041+ QVERIFY(QTest::qWaitForWindowExposed(m_view));
1042+ QVERIFY(m_view->rootObject() != 0);
1043+ qApp->processEvents();
1044+
1045+ m_blueRect = m_view->rootObject()->findChild<QQuickItem*>("blueRect");
1046+ Q_ASSERT(m_blueRect != nullptr);
1047+
1048+ m_notifier =
1049+ m_view->rootObject()->findChild<PressedOutsideNotifier*>("pressedOutsideNotifier");
1050+ Q_ASSERT(m_notifier != nullptr);
1051+}
1052+
1053+void tst_PressedOutsideNotifier::touchOutsideAreaTriggersSignal()
1054+{
1055+ QPoint touch0 = QPoint(m_blueRect->x() - 50, m_blueRect->y() - 50);
1056+
1057+ QSignalSpy pressedOutsideSpy(m_notifier, SIGNAL(pressedOutside()));
1058+
1059+ QTest::touchEvent(m_view, m_device)
1060+ .press(0, touch0);
1061+
1062+ qApp->processEvents();
1063+
1064+ QCOMPARE(pressedOutsideSpy.count(), 1);
1065+
1066+ QTest::touchEvent(m_view, m_device)
1067+ .release(0, touch0);
1068+}
1069+
1070+void tst_PressedOutsideNotifier::touchInsideAreaHasNoEffect()
1071+{
1072+ QPoint touch0 = QPoint(m_blueRect->x() + m_blueRect->width()*0.5,
1073+ m_blueRect->y() + m_blueRect->height()*0.5);
1074+
1075+ QSignalSpy pressedOutsideSpy(m_notifier, SIGNAL(pressedOutside()));
1076+
1077+ QTest::touchEvent(m_view, m_device)
1078+ .press(0, touch0);
1079+
1080+ qApp->processEvents();
1081+
1082+ QCOMPARE(pressedOutsideSpy.count(), 0);
1083+
1084+ QTest::touchEvent(m_view, m_device)
1085+ .release(0, touch0);
1086+}
1087+
1088+void tst_PressedOutsideNotifier::mousePressOutsideAreaTriggersSignal()
1089+{
1090+ QPoint mousePos = QPoint(m_blueRect->x() - 50, m_blueRect->y() - 50);
1091+
1092+ QSignalSpy pressedOutsideSpy(m_notifier, SIGNAL(pressedOutside()));
1093+
1094+ QTest::mousePress(m_view, Qt::LeftButton, 0 /*modifiers*/, mousePos);
1095+
1096+ qApp->processEvents();
1097+
1098+ QCOMPARE(pressedOutsideSpy.count(), 1);
1099+
1100+ QTest::mouseRelease(m_view, Qt::LeftButton, 0 /*modifiers*/, mousePos);
1101+}
1102+
1103+void tst_PressedOutsideNotifier::mousePresssInsideAreaHasNoEffect()
1104+{
1105+ QPoint mousePos = QPoint(m_blueRect->x() + m_blueRect->width()*0.5,
1106+ m_blueRect->y() + m_blueRect->height()*0.5);
1107+
1108+ QSignalSpy pressedOutsideSpy(m_notifier, SIGNAL(pressedOutside()));
1109+
1110+ QTest::mousePress(m_view, Qt::LeftButton, 0 /*modifiers*/, mousePos);
1111+
1112+ qApp->processEvents();
1113+
1114+ QCOMPARE(pressedOutsideSpy.count(), 0);
1115+
1116+ QTest::mouseRelease(m_view, Qt::LeftButton, 0 /*modifiers*/, mousePos);
1117+}
1118+
1119+void tst_PressedOutsideNotifier::nothingHappensWhileDisabled()
1120+{
1121+ QPoint touch0 = QPoint(m_blueRect->x() - 50, m_blueRect->y() - 50);
1122+
1123+ QSignalSpy pressedOutsideSpy(m_notifier, SIGNAL(pressedOutside()));
1124+
1125+ m_notifier->setEnabled(false);
1126+
1127+ QTest::touchEvent(m_view, m_device)
1128+ .press(0, touch0);
1129+
1130+ qApp->processEvents();
1131+
1132+ QCOMPARE(pressedOutsideSpy.count(), 0);
1133+
1134+ QTest::touchEvent(m_view, m_device)
1135+ .release(0, touch0);
1136+}
1137+
1138+QTEST_MAIN(tst_PressedOutsideNotifier)
1139+
1140+#include "tst_PressedOutsideNotifier.moc"
1141
1142=== added file 'tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.qml'
1143--- tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.qml 1970-01-01 00:00:00 +0000
1144+++ tests/plugins/Ubuntu/Gestures/tst_PressedOutsideNotifier.qml 2013-11-22 10:45:28 +0000
1145@@ -0,0 +1,61 @@
1146+/*
1147+ * Copyright (C) 2013 Canonical, Ltd.
1148+ *
1149+ * This program is free software; you can redistribute it and/or modify
1150+ * it under the terms of the GNU General Public License as published by
1151+ * the Free Software Foundation; version 3.
1152+ *
1153+ * This program is distributed in the hope that it will be useful,
1154+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1155+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1156+ * GNU General Public License for more details.
1157+ *
1158+ * You should have received a copy of the GNU General Public License
1159+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1160+ */
1161+
1162+import QtQuick 2.0
1163+import Ubuntu.Gestures 0.1
1164+
1165+/*
1166+ NB: If you change positions or sizes here make sure
1167+ tst_PressedOutsideNotifier.cpp is updated accordingly
1168+ */
1169+
1170+Rectangle {
1171+ width: 600
1172+ height: 600
1173+ color: "white"
1174+
1175+ Rectangle {
1176+ id: blueRect
1177+ objectName: "blueRect"
1178+ color: "blue"
1179+ x: 100
1180+ y: 100
1181+ width: 200
1182+ height: 200
1183+
1184+ Timer {
1185+ id: resetColorTimer
1186+ interval: 300
1187+ repeat: false
1188+ onTriggered: {
1189+ blueRect.color = "blue";
1190+ }
1191+ }
1192+
1193+ function blinkRed() {
1194+ blueRect.color = "red";
1195+ resetColorTimer.start();
1196+ }
1197+
1198+ PressedOutsideNotifier {
1199+ objectName: "pressedOutsideNotifier"
1200+ anchors.fill: parent
1201+ onPressedOutside: {
1202+ blueRect.blinkRed();
1203+ }
1204+ }
1205+ }
1206+}
1207
1208=== modified file 'tests/qmltests/CMakeLists.txt'
1209--- tests/qmltests/CMakeLists.txt 2013-11-19 09:43:35 +0000
1210+++ tests/qmltests/CMakeLists.txt 2013-11-22 10:45:28 +0000
1211@@ -46,7 +46,9 @@
1212 add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
1213 add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
1214 ${CMAKE_BINARY_DIR}/tests/mocks)
1215-add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
1216+add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
1217+ ${CMAKE_BINARY_DIR}/tests/mocks
1218+ ${CMAKE_BINARY_DIR}/plugins)
1219 add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
1220 add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
1221 add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
1222
1223=== modified file 'tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml'
1224--- tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml 2013-10-25 07:59:15 +0000
1225+++ tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml 2013-11-22 10:45:28 +0000
1226@@ -239,5 +239,25 @@
1227 return findChild(runningApplicationsGrid, "runningAppTile Calendar")
1228 != undefined
1229 }
1230+
1231+ // While in termination mode, if you click outside any of the tiles, the
1232+ // termination mode is disabled (i.e. we switch back to activation mode).
1233+ function test_clickOutsideTilesDisablesTerminationMode() {
1234+ runningApplicationsGrid.terminationModeEnabled = true
1235+
1236+ var calendarTile = findChild(runningApplicationsGrid, "runningAppTile Calendar")
1237+ verify(calendarTile != undefined)
1238+
1239+ verify(runningApplicationsGrid.terminationModeEnabled);
1240+
1241+ // Click on the bottom right corner of the grid, where there's no
1242+ // RunningApplicationTile lying around
1243+ mouseClick(runningApplicationsGrid,
1244+ runningApplicationsGrid.width - 1, runningApplicationsGrid.height - 1);
1245+
1246+ wait(0) // spin event loop to ensure that any pending signal emission went through
1247+
1248+ verify(!runningApplicationsGrid.terminationModeEnabled);
1249+ }
1250 }
1251 }

Subscribers

People subscribed via source and target branches