Merge lp:~townsend/unity/fix_lp765732 into lp:unity

Proposed by Christopher Townsend
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 3213
Proposed branch: lp:~townsend/unity/fix_lp765732
Merge into: lp:unity
Diff against target: 216 lines (+127/-20)
4 files modified
launcher/Launcher.cpp (+14/-18)
launcher/Launcher.h (+0/-2)
tests/autopilot/unity/emulators/launcher.py (+21/-0)
tests/autopilot/unity/tests/launcher/test_scroll.py (+92/-0)
To merge this branch: bzr merge lp:~townsend/unity/fix_lp765732
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Brandon Schaefer (community) Approve
Thomi Richards (community) Needs Fixing
Review via email: mp+151995@code.launchpad.net

Commit message

Add the ability to progressively autoscroll the Launcher when there are stacked icons.

Description of the change

This adds to ability to progressively autoscroll when there are enough icons to be stacked and the mouse cursor is within the 24 pixel high autoscroll zone at the bottom and top of the Launcher.

Also added new autoscrolling AP tests for testing autoscrolling at the top and bottom of the Launcher.

To post a comment you must log in.
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

Hi,

146 + def open_apps_in_launcher(self):
147 + """Opens some apps in order to get icon stacking in the Launcher"""
148 + apps = [
149 + ("Calculator"),
150 + ("Mahjongg"),
151 + ("Text Editor"),
152 + ("Character Map"),
153 + ("Terminal"),
154 + ("Remmina")
155 + ]
156 + for app in apps:
157 + self.start_app_window(app)

I think this is better expressed as:

apps = ("Calculator", "Mahjongg", "Text Editor", "Character Map", "Terminal", "Remina")
for app in apps:
    self.start_app_window(app)

i.e.- don't need the parenthesis around each app name, and using a tuple is better than a list, since we don't need to modify the contents.

I'm also a bit worried that the unity code might break existing autopilot tests. We've kicked off an autopilot run here:

http://10.97.0.6:8080/view/autopilot/job/autopilot-run-custom-branch/35/

So please don't merge this until those tests pass (or at least, don't show serious regressions compared to trunk).

Cheers,

review: Needs Fixing
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Awesome, this works waaaay better then trunk atm. Just a few things:

Wait for AP tests to check out
Fix thomis comment above
Add an int const for the FPS (the 30)
Check the launcher standalone for any bugs

Once those are done we are ready for a merge :).

review: Needs Fixing
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Ignore these results, a new one will be starting soon....the login screen got stuck on!
http://10.97.0.6:8080/view/autopilot/job/autopilot-run-custom-branch/35/

Im guessing it'll be branch 36, but we'll see :)

Revision history for this message
Christopher Townsend (townsend) wrote :

Thanks Thomi and Brandon!

I made the suggested changes to the code.

Looks like the AP tests finally completed, so we are good there.

And the weirdness seen in standalone is not due to my change, but due to the fact that the Launcher is taller than the standalone window it's drawn in, so scrolling from the bottom doesn't work since it's off the window:( The same thing happened with unity-standalone built from trunk.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

For reference, here is the AP tests running:
http://10.97.0.6:8080/view/autopilot/job/autopilot-run-custom-branch/41/

Nothing that this branch is causing, so Im happy with the changes (and works waay better then trunk :)

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'launcher/Launcher.cpp'
2--- launcher/Launcher.cpp 2013-03-06 16:38:17 +0000
3+++ launcher/Launcher.cpp 2013-03-13 18:53:21 +0000
4@@ -91,6 +91,9 @@
5 const int MOUSE_DEADZONE = 15;
6 const float DRAG_OUT_PIXELS = 300.0f;
7
8+const int SCROLL_AREA_HEIGHT = 24;
9+const int SCROLL_FPS = 30;
10+
11 const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";
12 const std::string SCROLL_TIMEOUT = "scroll-timeout";
13 const std::string ANIMATION_IDLE = "animation-idle";
14@@ -1503,27 +1506,18 @@
15
16 bool Launcher::MouseOverTopScrollArea()
17 {
18- return _mouse_position.y < panel::Style::Instance().panel_height;
19-}
20-
21-bool Launcher::MouseOverTopScrollExtrema()
22-{
23- return _mouse_position.y == 0;
24+ return _mouse_position.y < SCROLL_AREA_HEIGHT;
25 }
26
27 bool Launcher::MouseOverBottomScrollArea()
28 {
29- return _mouse_position.y > GetGeometry().height - panel::Style::Instance().panel_height;
30-}
31-
32-bool Launcher::MouseOverBottomScrollExtrema()
33-{
34- return _mouse_position.y == GetGeometry().height - 1;
35+ return _mouse_position.y >= GetGeometry().height - SCROLL_AREA_HEIGHT;
36 }
37
38 bool Launcher::OnScrollTimeout()
39 {
40 bool continue_animation = true;
41+ int speed = 0;
42
43 if (IsInKeyNavMode() || !_hovered ||
44 GetActionState() == ACTION_DRAG_LAUNCHER)
45@@ -1534,19 +1528,21 @@
46 {
47 if (_launcher_drag_delta >= _launcher_drag_delta_max)
48 continue_animation = false;
49- else if (MouseOverTopScrollExtrema())
50- _launcher_drag_delta += 6;
51 else
52- _launcher_drag_delta += 3;
53+ {
54+ speed = (SCROLL_AREA_HEIGHT - _mouse_position.y) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
55+ _launcher_drag_delta += speed;
56+ }
57 }
58 else if (MouseOverBottomScrollArea())
59 {
60 if (_launcher_drag_delta <= _launcher_drag_delta_min)
61 continue_animation = false;
62- else if (MouseOverBottomScrollExtrema())
63- _launcher_drag_delta -= 6;
64 else
65- _launcher_drag_delta -= 3;
66+ {
67+ speed = ((_mouse_position.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT)) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
68+ _launcher_drag_delta -= speed;
69+ }
70 }
71 else
72 {
73
74=== modified file 'launcher/Launcher.h'
75--- launcher/Launcher.h 2013-03-05 19:11:25 +0000
76+++ launcher/Launcher.h 2013-03-13 18:53:21 +0000
77@@ -243,10 +243,8 @@
78 void EnsureScrollTimer();
79
80 bool MouseOverTopScrollArea();
81- bool MouseOverTopScrollExtrema();
82
83 bool MouseOverBottomScrollArea();
84- bool MouseOverBottomScrollExtrema();
85
86 float DnDStartProgress(struct timespec const& current) const;
87 float DnDExitProgress(struct timespec const& current) const;
88
89=== modified file 'tests/autopilot/unity/emulators/launcher.py'
90--- tests/autopilot/unity/emulators/launcher.py 2013-02-28 17:38:29 +0000
91+++ tests/autopilot/unity/emulators/launcher.py 2013-03-13 18:53:21 +0000
92@@ -419,6 +419,27 @@
93 pin_item = quicklist.get_quicklist_item_by_text('Unlock from Launcher')
94 quicklist.click_item(pin_item)
95
96+ def autoscroll_to_icon(self, icon, autoscroll_offset=0):
97+ """Moves the mouse to the autoscroll zone to scroll the Launcher to the icon
98+ in question.
99+
100+ autoscroll_offet is the offset, in number of pixels, from the end of the
101+ autoscroll zone where is the autoscroll zone is currently 24 pixels high.
102+ """
103+ (x, y, w, h) = self.geometry
104+
105+ while 1:
106+ mouse_x = target_x = icon.center_x + self.x
107+ mouse_y = target_y = icon.center_y
108+ if target_y > h:
109+ mouse_y = h + y - autoscroll_offset
110+ elif target_y < 0:
111+ mouse_y = y + autoscroll_offset
112+ if self._mouse.x == target_x and self._mouse.y == target_y:
113+ break
114+ self._mouse.move(mouse_x, mouse_y)
115+ sleep(0.5)
116+
117 @property
118 def geometry(self):
119 """Returns a tuple of (x,y,w,h) for the current launcher."""
120
121=== added file 'tests/autopilot/unity/tests/launcher/test_scroll.py'
122--- tests/autopilot/unity/tests/launcher/test_scroll.py 1970-01-01 00:00:00 +0000
123+++ tests/autopilot/unity/tests/launcher/test_scroll.py 2013-03-13 18:53:21 +0000
124@@ -0,0 +1,92 @@
125+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
126+# Copyright 2013 Canonical
127+# Authors: Chris Townsend
128+#
129+# This program is free software: you can redistribute it and/or modify it
130+# under the terms of the GNU General Public License version 3, as published
131+# by the Free Software Foundation.
132+
133+from __future__ import absolute_import
134+
135+from autopilot.matchers import Eventually
136+import logging
137+from testtools.matchers import Equals, GreaterThan, LessThan
138+from time import sleep
139+
140+from unity.tests.launcher import LauncherTestCase
141+
142+logger = logging.getLogger(__name__)
143+
144+class LauncherScrollTests(LauncherTestCase):
145+ """Tests for scrolling behavior of the Launcher"""
146+
147+ def open_apps_in_launcher(self):
148+ """Opens some apps in order to get icon stacking in the Launcher"""
149+ apps = ("Calculator", "Mahjongg", "Text Editor", "Character Map", "Terminal", "Remmina")
150+
151+ for app in apps:
152+ self.start_app_window(app)
153+
154+ def test_autoscrolling_from_bottom(self):
155+ """Tests the autoscrolling from the bottom of the Launcher"""
156+ self.open_apps_in_launcher()
157+
158+ # Set the autoscroll_offset to 10 (this is arbitrary for this test).
159+ autoscroll_offset = 10
160+
161+ launcher_instance = self.get_launcher()
162+ (x, y, w, h) = launcher_instance.geometry
163+
164+ icons = self.unity.launcher.model.get_launcher_icons()
165+ num_icons = self.unity.launcher.model.num_launcher_icons()
166+
167+ last_icon = icons[num_icons - 1]
168+
169+ # Move mouse to the middle of the Launcher in order to expand all
170+ # of the icons for scrolling
171+ launcher_instance.move_mouse_over_launcher()
172+
173+ # Make sure the last icon is off the screen or else there is no
174+ # scrolling.
175+ self.assertThat(last_icon.center_y, Eventually(GreaterThan(h)))
176+
177+ # Autoscroll to the last icon
178+ launcher_instance.autoscroll_to_icon(last_icon, autoscroll_offset)
179+
180+ (x_fin, y_fin) = self.mouse.position()
181+
182+ # Make sure we ended up in the center of the last icon
183+ self.assertThat(x_fin, Equals(last_icon.center_x))
184+ self.assertThat(y_fin, Equals(last_icon.center_y))
185+
186+ def test_autoscrolling_from_top(self):
187+ """Test the autoscrolling from the top of the Launcher"""
188+ self.open_apps_in_launcher()
189+
190+ # Set the autoscroll_offset to 10 (this is arbitrary for this test).
191+ autoscroll_offset = 10
192+
193+ launcher_instance = self.get_launcher()
194+ (x, y, w, h) = launcher_instance.geometry
195+
196+ icons = self.unity.launcher.model.get_launcher_icons()
197+ num_icons = self.unity.launcher.model.num_launcher_icons()
198+
199+ first_icon = icons[0]
200+ last_icon = icons[num_icons - 1]
201+
202+ # Move to the last icon in order to expand the top of the Launcher
203+ launcher_instance.move_mouse_to_icon(last_icon)
204+
205+ # Make sure the first icon is off the screen or else there is no
206+ # scrolling.
207+ self.assertThat(first_icon.center_y, Eventually(LessThan(y)))
208+
209+ # Autoscroll to the first icon
210+ launcher_instance.autoscroll_to_icon(first_icon, autoscroll_offset)
211+
212+ (x_fin, y_fin) = self.mouse.position()
213+
214+ # Make sure we ended up in the center of the first icon
215+ self.assertThat(x_fin, Equals(first_icon.center_x))
216+ self.assertThat(y_fin, Equals(first_icon.center_y))