Merge lp:~mzanetti/unity8/launcher-improve-flicking-behavior into lp:unity8
- launcher-improve-flicking-behavior
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | MichaĆ Sawicz |
Approved revision: | 77 |
Merged at revision: | 80 |
Proposed branch: | lp:~mzanetti/unity8/launcher-improve-flicking-behavior |
Merge into: | lp:unity8 |
Diff against target: |
319 lines (+143/-52) 3 files modified
Launcher/LauncherDelegate.qml (+0/-1) Launcher/LauncherPanel.qml (+26/-14) tests/qmltests/Launcher/tst_Launcher.qml (+117/-37) |
To merge this branch: | bzr merge lp:~mzanetti/unity8/launcher-improve-flicking-behavior |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Albert Astals Cid (community) | Approve | ||
Review via email: mp+172648@code.launchpad.net |
Commit message
improve launcher flicking bahavior
- fix initial snapping
- improve foldingAreas behavior
- increase clickFlick speed to flick 4 items
Description of the change
Michael Zanetti (mzanetti) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:70
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:70
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:70
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:71
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:72
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:74
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Albert Astals Cid (aacid) wrote : | # |
As discussed on IRC it'd be great if the comment of why a Timer is needed is improved and also to have a test that fails when the Timer is not there
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:76
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Albert Astals Cid (aacid) wrote : | # |
Looks good to me (that have the fix for 32251 :D)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:77
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'Launcher/LauncherDelegate.qml' |
2 | --- Launcher/LauncherDelegate.qml 2013-06-26 14:21:39 +0000 |
3 | +++ Launcher/LauncherDelegate.qml 2013-07-05 09:05:30 +0000 |
4 | @@ -65,7 +65,6 @@ |
5 | onClicked: root.clicked() |
6 | onCanceled: root.released() |
7 | preventStealing: false |
8 | - enabled: root.angle < 5 |
9 | |
10 | onPressAndHold: { |
11 | root.state = "moving" |
12 | |
13 | === modified file 'Launcher/LauncherPanel.qml' |
14 | --- Launcher/LauncherPanel.qml 2013-06-25 13:25:45 +0000 |
15 | +++ Launcher/LauncherPanel.qml 2013-07-05 09:05:30 +0000 |
16 | @@ -100,6 +100,7 @@ |
17 | height: parent.height - dashItem.height - parent.spacing*2 |
18 | ListView { |
19 | id: launcherListView |
20 | + objectName: "launcherListView" |
21 | anchors.fill: parent |
22 | anchors.topMargin: -itemSize |
23 | anchors.bottomMargin: -itemSize |
24 | @@ -116,15 +117,7 @@ |
25 | // The height of the area where icons start getting folded |
26 | property int foldingAreaHeight: itemSize * 0.75 |
27 | property int itemSize: width |
28 | - |
29 | - Component.onCompleted: { |
30 | - // This is needed because snapping would partially fold |
31 | - // the first item on initialisation. This can only be |
32 | - // overridden by mouse interactions - which is what flick() |
33 | - // simulates. Setting contentY to 0 would not work because |
34 | - // of this. |
35 | - flick(0, units.gu(20)) |
36 | - } |
37 | + property int clickFlickSpeed: units.gu(60) |
38 | |
39 | delegate: LauncherDelegate { |
40 | id: launcherDelegate |
41 | @@ -139,7 +132,26 @@ |
42 | maxAngle: 60 |
43 | |
44 | onClicked: { |
45 | - root.applicationSelected(launcherModel.get(index).desktopFile); |
46 | + // First/last item do the scrolling at more than 12 degrees |
47 | + if (index == 0 || index == launcherListView.count -1) { |
48 | + if (angle > 12) { |
49 | + launcherListView.flick(0, -launcherListView.clickFlickSpeed); |
50 | + } else if (angle < -12) { |
51 | + launcherListView.flick(0, launcherListView.clickFlickSpeed); |
52 | + } else { |
53 | + root.applicationSelected(launcherModel.get(index).desktopFile); |
54 | + } |
55 | + return; |
56 | + } |
57 | + |
58 | + // the rest launches apps up to an angle of 30 degrees |
59 | + if (angle > 30) { |
60 | + launcherListView.flick(0, -launcherListView.clickFlickSpeed); |
61 | + } else if (angle < -30) { |
62 | + launcherListView.flick(0, launcherListView.clickFlickSpeed); |
63 | + } else { |
64 | + root.applicationSelected(launcherModel.get(index).desktopFile); |
65 | + } |
66 | } |
67 | } |
68 | |
69 | @@ -151,9 +163,9 @@ |
70 | top: parent.top |
71 | topMargin: launcherListView.topMargin |
72 | } |
73 | - height: launcherListView.itemSize |
74 | + height: launcherListView.itemSize / 2 |
75 | enabled: launcherListView.contentY > -launcherListView.topMargin |
76 | - onClicked: launcherListView.flick(0, units.gu(40)) |
77 | + onClicked: launcherListView.flick(0, launcherListView.clickFlickSpeed) |
78 | } |
79 | |
80 | MouseArea { |
81 | @@ -164,9 +176,9 @@ |
82 | bottom: parent.bottom |
83 | bottomMargin: launcherListView.bottomMargin |
84 | } |
85 | - height: launcherListView.itemSize |
86 | + height: launcherListView.itemSize / 2 |
87 | enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin |
88 | - onClicked: launcherListView.flick(0, -units.gu(40)) |
89 | + onClicked: launcherListView.flick(0, -launcherListView.clickFlickSpeed) |
90 | } |
91 | } |
92 | } |
93 | |
94 | === modified file 'tests/qmltests/Launcher/tst_Launcher.qml' |
95 | --- tests/qmltests/Launcher/tst_Launcher.qml 2013-06-28 16:35:24 +0000 |
96 | +++ tests/qmltests/Launcher/tst_Launcher.qml 2013-07-05 09:05:30 +0000 |
97 | @@ -23,20 +23,21 @@ |
98 | /* Nothing is shown at first. If you drag from left edge you will bring up the |
99 | launcher. */ |
100 | Item { |
101 | + id: root |
102 | width: units.gu(50) |
103 | - height: units.gu(81) |
104 | + height: units.gu(55) |
105 | |
106 | Launcher { |
107 | id: launcher |
108 | x: 0 |
109 | y: 0 |
110 | width: units.gu(40) |
111 | - height: units.gu(81) |
112 | + height: parent.height |
113 | |
114 | - property string latestApplicationSelected |
115 | + property string lastSelectedApplication |
116 | |
117 | onLauncherApplicationSelected: { |
118 | - latestApplicationSelected = desktopFile |
119 | + lastSelectedApplication = desktopFile |
120 | } |
121 | |
122 | property int dashItemSelected_count: 0 |
123 | @@ -58,9 +59,33 @@ |
124 | } |
125 | |
126 | UT.UnityTestCase { |
127 | + id: revealer |
128 | + |
129 | + function dragLauncherIntoView() { |
130 | + var startX = launcher.dragAreaWidth/2; |
131 | + var startY = launcher.height/2; |
132 | + touchFlick(launcher, |
133 | + startX, startY, |
134 | + startX+units.gu(8), startY); |
135 | + |
136 | + var panel = findChild(launcher, "launcherPanel"); |
137 | + verify(panel != undefined); |
138 | + |
139 | + // wait until it gets fully extended |
140 | + tryCompare(panel, "x", 0); |
141 | + tryCompare(launcher, "state", "visible"); |
142 | + } |
143 | + |
144 | + function waitUntilLauncherDisappears() { |
145 | + var panel = findChild(launcher, "launcherPanel"); |
146 | + tryCompare(panel, "x", -panel.width, 1000); |
147 | + } |
148 | + } |
149 | + |
150 | + UT.UnityTestCase { |
151 | id: testCase |
152 | name: "Launcher" |
153 | - when: windowShown |
154 | + when: windowShown && initTestCase.completed |
155 | |
156 | // Drag from the left edge of the screen rightwards and check that the launcher |
157 | // appears (as if being dragged by the finger/pointer) |
158 | @@ -71,7 +96,7 @@ |
159 | // it starts out hidden just left of the left launcher edge |
160 | compare(panel.x, -panel.width) |
161 | |
162 | - dragLauncherIntoView() |
163 | + revealer.dragLauncherIntoView() |
164 | |
165 | // tapping on the center of the screen should dismiss the launcher |
166 | mouseClick(launcher, launcher.width/2, launcher.height/2) |
167 | @@ -85,20 +110,25 @@ |
168 | corresponding desktop file. E.g. clicking on phone icon should yield |
169 | launcherApplicationSelected("[...]phone-app.desktop") */ |
170 | function test_clickingOnAppIconCausesSignalEmission() { |
171 | - launcher.latestApplicationSelected = "" |
172 | - |
173 | - dragLauncherIntoView() |
174 | + launcher.lastSelectedApplication = "" |
175 | + |
176 | + revealer.dragLauncherIntoView() |
177 | + |
178 | + var listView = findChild(launcher, "launcherListView"); |
179 | + listView.flick(0, units.gu(500)); |
180 | + tryCompare(listView, "flicking", false); |
181 | |
182 | var appIcon = findChild(launcher, "launcherDelegate0") |
183 | + |
184 | verify(appIcon != undefined) |
185 | |
186 | mouseClick(appIcon, appIcon.width/2, appIcon.height/2) |
187 | |
188 | - tryCompare(launcher, "latestApplicationSelected", |
189 | + tryCompare(launcher, "lastSelectedApplication", |
190 | "/usr/share/applications/phone-app.desktop") |
191 | |
192 | // Tapping on an application icon also dismisses the launcher |
193 | - waitUntilLauncherDisappears() |
194 | + revealer.waitUntilLauncherDisappears() |
195 | } |
196 | |
197 | /* If I click on the dash icon on the launcher |
198 | @@ -106,7 +136,7 @@ |
199 | function test_clickingOnDashIconCausesSignalEmission() { |
200 | launcher.dashItemSelected_count = 0 |
201 | |
202 | - dragLauncherIntoView() |
203 | + revealer.dragLauncherIntoView() |
204 | |
205 | var dashIcon = findChild(launcher, "dashItem") |
206 | verify(dashIcon != undefined) |
207 | @@ -116,29 +146,8 @@ |
208 | tryCompare(launcher, "dashItemSelected_count", 1) |
209 | |
210 | // Tapping on the dash icon also dismisses the launcher |
211 | - waitUntilLauncherDisappears() |
212 | - } |
213 | - |
214 | - function dragLauncherIntoView() { |
215 | - var startX = launcher.dragAreaWidth/2 |
216 | - var startY = launcher.height/2 |
217 | - touchFlick(launcher, |
218 | - startX, startY, |
219 | - startX+units.gu(8), startY) |
220 | - |
221 | - var panel = findChild(launcher, "launcherPanel") |
222 | - verify(panel != undefined) |
223 | - |
224 | - // wait until it gets fully extended |
225 | - tryCompare(panel, "x", 0) |
226 | - tryCompare(launcher, "state", "visible") |
227 | - } |
228 | - |
229 | - function waitUntilLauncherDisappears() { |
230 | - var panel = findChild(launcher, "launcherPanel") |
231 | - tryCompare(panel, "x", -panel.width, 1000) |
232 | - } |
233 | - |
234 | + revealer.waitUntilLauncherDisappears() |
235 | + } |
236 | |
237 | function test_teaseLauncher_data() { |
238 | return [ |
239 | @@ -164,7 +173,78 @@ |
240 | wait(100) |
241 | compare(launcher.maxPanelX, -launcher.panelWidth, "Launcher moved even if it shouldn't") |
242 | } |
243 | - waitUntilLauncherDisappears(); |
244 | - } |
245 | + revealer.waitUntilLauncherDisappears(); |
246 | + launcher.available = true; |
247 | + } |
248 | + } |
249 | + |
250 | + UT.UnityTestCase { |
251 | + id: clickFlickTestCase |
252 | + when: windowShown && testCase.completed |
253 | + |
254 | + function test_clickFlick_data() { |
255 | + var listView = findChild(launcher, "launcherListView"); |
256 | + return [ |
257 | + {tag: "unfolded top", flickSpeed: units.gu(200), clickY: listView.topMargin + units.gu(2), expectFlick: false}, |
258 | + {tag: "folded top", flickSpeed: -units.gu(200), clickY: listView.topMargin + units.gu(2), expectFlick: true}, |
259 | + {tag: "unfolded bottom", flickSpeed: -units.gu(200), clickY: listView.height - listView.topMargin - units.gu(1), expectFlick: false}, |
260 | + {tag: "folded bottom", flickSpeed: units.gu(200), clickY: listView.height - listView.topMargin - units.gu(1), expectFlick: true}, |
261 | + ]; |
262 | + } |
263 | + |
264 | + function test_clickFlick(data) { |
265 | + launcher.lastSelectedApplication = ""; |
266 | + revealer.dragLauncherIntoView(); |
267 | + var listView = findChild(launcher, "launcherListView"); |
268 | + |
269 | + listView.flick(0, data.flickSpeed); |
270 | + tryCompare(listView, "flicking", false); |
271 | + |
272 | + var oldY = listView.contentY; |
273 | + |
274 | + mouseClick(listView, listView.width / 2, data.clickY); |
275 | + tryCompare(listView, "flicking", false); |
276 | + |
277 | + if (data.expectFlick) { |
278 | + verify(listView.contentY != oldY); |
279 | + compare(launcher.lastSelectedApplication, "", "Launcher app clicked signal emitted even though it should only flick"); |
280 | + } else { |
281 | + verify(launcher.lastSelectedApplication != ""); |
282 | + compare(listView.contentY, oldY, "Launcher was flicked even though it should only launch an app"); |
283 | + } |
284 | + |
285 | + // Restore position on top |
286 | + listView.flick(0, units.gu(200)); |
287 | + tryCompare(listView, "flicking", false) |
288 | + // Click somewhere in the empty space to make it hide in case it isn't |
289 | + mouseClick(launcher, launcher.width - units.gu(1), units.gu(1)); |
290 | + revealer.waitUntilLauncherDisappears(); |
291 | + } |
292 | + } |
293 | + |
294 | + UT.UnityTestCase { |
295 | + id: initTestCase |
296 | + name: "LauncherInit" |
297 | + when: windowShown |
298 | + |
299 | + /* |
300 | + * FIXME: There is a bug in ListView which makes it snap to an item |
301 | + * instead of the edge at startup. Enable this test once our patch for |
302 | + * ListView has landed upstream. |
303 | + * https://bugreports.qt-project.org/browse/QTBUG-32251 |
304 | + |
305 | + function test_initFirstUnfolded() { |
306 | + |
307 | + // Make sure noone changed the height of the window. The issue this test case |
308 | + // is verifying only happens on certain heights of the Launcher |
309 | + compare(root.height, units.gu(55)); |
310 | + |
311 | + var listView = findChild(launcher, "launcherListView"); |
312 | + compare(listView.contentY, -listView.topMargin, "Launcher did not start up with first item unfolded"); |
313 | + |
314 | + // Now do check that snapping is in fact enabled |
315 | + compare(listView.snapMode, ListView.SnapToItem, "Snapping is not enabled"); |
316 | + } |
317 | + */ |
318 | } |
319 | } |
improving/changing flick behavior to reflect feedback from design.