Merge lp:~3v1n0/unity/hud-lock-out-monitors-tests into lp:unity

Proposed by Marco Trevisan (Treviño) on 2012-03-21
Status: Superseded
Proposed branch: lp:~3v1n0/unity/hud-lock-out-monitors-tests
Merge into: lp:unity
Diff against target: 799 lines (+295/-92)
13 files modified
manual-tests/Hud.txt (+1/-4)
plugins/unityshell/src/BamfLauncherIcon.cpp (+2/-1)
plugins/unityshell/src/HudController.cpp (+40/-35)
plugins/unityshell/src/HudController.h (+6/-9)
plugins/unityshell/src/HudView.cpp (+10/-8)
plugins/unityshell/src/HudView.h (+2/-8)
plugins/unityshell/src/LauncherIcon.cpp (+14/-12)
plugins/unityshell/src/unityshell.cpp (+3/-2)
tests/autopilot/autopilot/emulators/X11.py (+12/-1)
tests/autopilot/autopilot/emulators/unity/hud.py (+23/-0)
tests/autopilot/autopilot/emulators/unity/icons.py (+8/-0)
tests/autopilot/autopilot/emulators/unity/launcher.py (+18/-4)
tests/autopilot/autopilot/tests/test_hud.py (+156/-8)
To merge this branch: bzr merge lp:~3v1n0/unity/hud-lock-out-monitors-tests
Reviewer Review Type Date Requested Status
Thomi Richards (community) Needs Fixing on 2012-03-21
Gord Allott (community) 2012-03-21 Approve on 2012-03-21
Review via email: mp+98634@code.launchpad.net

This proposal has been superseded by a proposal from 2012-03-25.

Description of the change

Added tests for multimonitor in HUD and to check the lock-out

To post a comment you must log in.
Gord Allott (gordallott) wrote :

+1, seems good here

review: Approve

Hi,

44 + def is_rect_on_monitor(self, monitor_number, x, y, w, h):
45 + (m_x, m_y, m_w, m_h) = self.get_monitor_geometry(monitor_number)
46 + return (x >= m_x and x + w <= m_x + m_w and y >= m_y and y + h <= m_y + m_h)
47 +

Instead of passing x,y,w & h as separate parameters, just pass 'rect', and make sure it's a tuple in the function:
def is_rect_on_monitor(self, monitor_number, rect):
    """Returns True if `rect` is _entirely_ on the specified monitor, with no overlap"""
    if type(rect) is not tuple:
        raise TypeError("rect must be a tuple.")

...if you want you can also check that monitor_number is a valid integer, and that the tuple values are all ints.

This:

59 + def get_geometry(self):
60 + return (self.x, self.y, self.width, self.height)
61 +

should be a property, like this:

58 + @property
59 + def geometry(self):
60 + return (self.x, self.y, self.width, self.height)
61 +

this:

84 + screen_geometry = ScreenGeometry()
85 + num_monitors = screen_geometry.get_num_monitors()
86 +
87 + if num_monitors == 1:
88 + scenarios = [
89 + ('Single Monitor, Launcher never hide', {'hud_monitor': 0, 'launcher_hide_mode': 0}),
90 + ('Single Monitor, Launcher autohide', {'hud_monitor': 0, 'launcher_hide_mode': 1}),
91 + ]
92 + else:
93 + scenarios = []
94 + for i in range(num_monitors):
95 + scenarios.append(('Monitor %d, Launcher never hide' % (i), {'hud_monitor': i, 'launcher_hide_mode': 0}))
96 + scenarios.append(('Monitor %d, Launcher autohide' % (i), {'hud_monitor': i, 'launcher_hide_mode': 1}))

is kind of ugly. A better way to do it is how we do it in the launcher tests - use a function to generate the scenarios.

The first two changes I mentioned mean that you can rewrite this:

112 + (x, y, w, h) = self.hud.get_geometry()
113 + self.assertTrue(self.screen_geometry.is_rect_on_monitor(self.hud_monitor, x, y, w, h))

like this:

self.assertTrue(self.screen_geometry.is_rect_on_monitor(self.hud_monitor, self.hud.geometry)

The new test:

131 + def test_hud_dont_change_launcher_status(self):

...needs a docstring.

Finally, please use matchers for everything except simple true/false tests, so this:

139 + self.assertEqual(launcher_shows_pre, launcher_shows_post)

becomes:

self.assertThat(launcher_shows_pre, Equals(launcher_shows_post))

Cheers,

review: Needs Fixing
2111. By Marco Trevisan (Treviño) on 2012-03-23

autopilot, tests: updated against Thomi's suggestions

2112. By Marco Trevisan (Treviño) on 2012-03-23

Merging with trunk

2113. By Marco Trevisan (Treviño) on 2012-03-24

HudController: add support for the multiple launchers feature

The HUD should show at the left edge of the screen when multiple
launchers are disabled and the mouse pointer is on a non-primary screen.

2114. By Marco Trevisan (Treviño) on 2012-03-24

autopilot, test_hud: added checks for geometry for both locked and unlocked status

2115. By Marco Trevisan (Treviño) on 2012-03-25

HudController: some code cleanup, use functions to reduce code duplication

2116. By Marco Trevisan (Treviño) on 2012-03-25

HudView: simplify the embedded icon showing API, add some introspection

2117. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, hud: added new HudController / HudView properties

They allow to check if the HUD is locked to the launcher, in which
monitor is shown and if the embedded icon is shown on the view.

Added an extra assert to check if hud_monitor equals hud.monitor

2118. By Marco Trevisan (Treviño) on 2012-03-25

HudController: oops... g_strcmp != 0 => str1 != str2 ;)

2119. By Marco Trevisan (Treviño) on 2012-03-25

LauncherIcon: added autopilot introspection friendly properties

2120. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, test HUD: added checks for the HUDLauncherIcon

2121. By Marco Trevisan (Treviño) on 2012-03-25

autopilot: update icon properties against new quirkless names

2122. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, launcher emulator: update against icon introspection changes

Allow to get an icon by its desktop id

2123. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, test_hud: get icon by desktop id, not by tooltip_text

It fixes internationalization issues.

2124. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, test_hud: Check if the launcher icons (except the HUD one) are desaturated

2125. By Marco Trevisan (Treviño) on 2012-03-25

unityshell: make sure we initialize the HudController multiple_launchers property

2126. By Marco Trevisan (Treviño) on 2012-03-25

HudController: removed typo

2127. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, hud emulator: removing deprecated get_geometry method

2128. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, test_hud: simplify the desaturated test

2129. By Marco Trevisan (Treviño) on 2012-03-25

BamfLauncherIcon: use the GetWindows function when we can

2130. By Marco Trevisan (Treviño) on 2012-03-25

SimpleLauncherIcon: add the icon_name to the introspection properties

2131. By Marco Trevisan (Treviño) on 2012-03-25

IconTexture: move to std::string

2132. By Marco Trevisan (Treviño) on 2012-03-25

HudIcon: make it Introspectable, and use the new IconTexture API

2133. By Marco Trevisan (Treviño) on 2012-03-25

HudView: set the icon as introspectable child.

And add and remove it when needed.

2134. By Marco Trevisan (Treviño) on 2012-03-25

autopilot, test_hud: updated the tests against the new embedded icon introspection

2135. By Marco Trevisan (Treviño) on 2012-03-26

autopilot, hud: add test to check if the hud icon shows the proper emblem

2136. By Marco Trevisan (Treviño) on 2012-03-26

HudView: no need to remove the introspection child on destruction

2137. By Marco Trevisan (Treviño) on 2012-03-26

HudController: make the HUD relayout if the monitor has changed

2138. By Marco Trevisan (Treviño) on 2012-03-26

autopilot, X11: fix typo... actually use rect when checking for monitor geo!

2139. By Marco Trevisan (Treviño) on 2012-03-26

autopilot, launcher: allow to get the bfb launcher icon from LauncherModel

2140. By Marco Trevisan (Treviño) on 2012-03-26

autopilot: test_hud some cleanups

2141. By Marco Trevisan (Treviño) on 2012-03-26

autopilot, hud: Removed unneeded print

2142. By Marco Trevisan (Treviño) on 2012-03-27

autopilot: default tests, use C locale to launch applications.

2143. By Marco Trevisan (Treviño) on 2012-03-27

autopilot, test_hud: test splitted in multiple parts, use multiply_scenarios

2144. By Marco Trevisan (Treviño) on 2012-03-27

Merging with trunk

2145. By Marco Trevisan (Treviño) on 2012-03-27

BamfLauncherIcon: g_variant_new_array can compute the array size automatically

2146. By Marco Trevisan (Treviño) on 2012-03-27

BamfLauncherIcon: use GVariantBuilder to build the xids array

2147. By Marco Trevisan (Treviño) on 2012-03-27

autopilot: allow to launch applications with C locale

And use it for gedit HUD test

2148. By Marco Trevisan (Treviño) on 2012-03-27

autopilot, switcher: update against new introspection values

2149. By Marco Trevisan (Treviño) on 2012-03-27

autopilot, test_switcher: use BAMF application names, to work with different locales

2150. By Marco Trevisan (Treviño) on 2012-03-27

autopilot, test_showdesktop: be more locale friendly

2151. By Marco Trevisan (Treviño) on 2012-03-27

autopilot, use start_app with one more locale parameter, more than start_app_c_locale

2152. By Marco Trevisan (Treviño) on 2012-03-27

autopliot, test_hud: check that the HUD icon is not desaturated

2153. By Marco Trevisan (Treviño) on 2012-03-27

BamfLauncherIcon: add GetDesktopID function to perform the common operations

2154. By Marco Trevisan (Treviño) on 2012-03-27

autopilot, updated changes following thomi's review

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'manual-tests/Hud.txt'
2--- manual-tests/Hud.txt 2012-03-21 14:44:41 +0000
3+++ manual-tests/Hud.txt 2012-03-25 18:15:22 +0000
4@@ -64,10 +64,7 @@
5 #. Tap Alt
6
7 Outcome
8- The Launcher should stick be locked out.
9- The Launcher icons should be desaturated.
10- The top most Launcher icon should be an icon related the the focused window
11- The BFB should not be present
12+ The top most Launcher icon should be an icon related to the focused window
13
14
15 Hud Sending Undo
16
17=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
18--- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-03-22 15:14:49 +0000
19+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-03-25 18:15:22 +0000
20@@ -473,7 +473,8 @@
21 g_list_free(children);
22
23 variant::BuilderWrapper(builder)
24- .add("desktop-file", DesktopFile())
25+ .add("desktop_file", DesktopFile())
26+ .add("desktop_id", glib::String(g_path_get_basename(DesktopFile().c_str())).Str())
27 .add("xids", g_variant_new_array(G_VARIANT_TYPE_UINT32, xids, i))
28 .add("sticky", IsSticky());
29 }
30
31=== modified file 'plugins/unityshell/src/HudController.cpp'
32--- plugins/unityshell/src/HudController.cpp 2012-03-21 15:30:49 +0000
33+++ plugins/unityshell/src/HudController.cpp 2012-03-25 18:15:22 +0000
34@@ -40,6 +40,8 @@
35
36 Controller::Controller()
37 : launcher_width(65)
38+ , launcher_locked_out(false)
39+ , multiple_launchers(true)
40 , hud_service_("com.canonical.hud", "/com/canonical/hud")
41 , window_(nullptr)
42 , visible_(false)
43@@ -47,12 +49,11 @@
44 , timeline_id_(0)
45 , last_opacity_(0.0f)
46 , start_time_(0)
47- , launcher_is_locked_out_(false)
48 , view_(nullptr)
49 , monitor_index_(0)
50 {
51 LOG_DEBUG(logger) << "hud startup";
52- SetupRelayoutCallbacks();
53+ UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(); });
54
55 ubus.RegisterInterest(UBUS_HUD_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));
56
57@@ -65,13 +66,13 @@
58 gint32 overlay_monitor = 0;
59 g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING, &overlay_identity, &can_maximise, &overlay_monitor);
60
61- if (g_strcmp0(overlay_identity, "hud"))
62+ if (overlay_identity.Str() != "hud")
63 {
64 HideHud(true);
65 }
66 });
67
68- launcher_width.changed.connect([this] (int new_width) { Relayout(); });
69+ launcher_width.changed.connect([&] (int new_width) { Relayout(); });
70
71 PluginAdapter::Default()->compiz_screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
72
73@@ -120,14 +121,24 @@
74 AddChild(view_);
75 }
76
77-void Controller::SetupRelayoutCallbacks()
78-{
79- GdkScreen* screen = gdk_screen_get_default();
80-
81- sig_manager_.Add(new glib::Signal<void, GdkScreen*>(screen,
82- "monitors-changed", sigc::mem_fun(this, &Controller::Relayout)));
83- sig_manager_.Add(new glib::Signal<void, GdkScreen*>(screen,
84- "size-changed", sigc::mem_fun(this, &Controller::Relayout)));
85+int Controller::GetTargetMonitor()
86+{
87+ return UScreen::GetDefault()->GetMonitorWithMouse();
88+}
89+
90+bool Controller::IsLockedToLauncher(int monitor)
91+{
92+ if (launcher_locked_out)
93+ {
94+ int primary_monitor = UScreen::GetDefault()->GetPrimaryMonitor();
95+
96+ if (multiple_launchers || (!multiple_launchers && primary_monitor == monitor))
97+ {
98+ return true;
99+ }
100+ }
101+
102+ return false;
103 }
104
105 void Controller::EnsureHud()
106@@ -158,26 +169,27 @@
107
108 nux::Geometry Controller::GetIdealWindowGeometry()
109 {
110- UScreen *uscreen = UScreen::GetDefault();
111- int primary_monitor = uscreen->GetMonitorWithMouse();
112- auto monitor_geo = uscreen->GetMonitorGeometry(primary_monitor);
113+ int target_monitor = GetTargetMonitor();
114+ auto monitor_geo = UScreen::GetDefault()->GetMonitorGeometry(target_monitor);
115
116- // We want to cover as much of the screen as possible to grab any mouse events outside
117+ // We want to cover as much of the screen as possible to grab any mouse events outside447
118 // of our window
119 panel::Style &panel_style = panel::Style::Instance();
120 nux::Geometry geo(monitor_geo.x,
121- monitor_geo.y + panel_style.panel_height,
122- monitor_geo.width,
123- monitor_geo.height - panel_style.panel_height);
124- if (launcher_is_locked_out_)
125+ monitor_geo.y + panel_style.panel_height,
126+ monitor_geo.width,
127+ monitor_geo.height - panel_style.panel_height);
128+
129+ if (IsLockedToLauncher(target_monitor))
130 {
131 geo.x += launcher_width;
132 geo.width -= launcher_width;
133 }
134+
135 return geo;
136 }
137
138-void Controller::Relayout(GdkScreen*screen)
139+void Controller::Relayout()
140 {
141 EnsureHud();
142 nux::Geometry content_geo = view_->GetGeometry();
143@@ -190,7 +202,7 @@
144 }
145
146 void Controller::OnMouseDownOutsideWindow(int x, int y,
147- unsigned long bflags, unsigned long kflags)
148+ unsigned long bflags, unsigned long kflags)
149 {
150 LOG_DEBUG(logger) << "OnMouseDownOutsideWindow called";
151 HideHud();
152@@ -234,16 +246,6 @@
153 return visible_;
154 }
155
156-void Controller::SetLauncherIsLockedOut(bool launcher_is_locked_out)
157-{
158- launcher_is_locked_out_ = launcher_is_locked_out;
159- if (launcher_is_locked_out_)
160- view_->SetHideIcon(IconHideState::HIDE);
161- else
162- view_->SetHideIcon(IconHideState::SHOW);
163- Relayout();
164-}
165-
166 void Controller::ShowHud()
167 {
168 PluginAdapter* adaptor = PluginAdapter::Default();
169@@ -259,6 +261,8 @@
170 return;
171 }
172
173+ monitor_index_ = GetTargetMonitor();
174+ view_->ShowEmbeddedIcon(!IsLockedToLauncher(monitor_index_));
175 view_->AboutToShow();
176
177 // we first want to grab the currently active window, luckly we can just ask the jason interface(bamf)
178@@ -289,7 +293,6 @@
179 // hide the launcher
180 GVariant* message_data = g_variant_new("(b)", TRUE);
181 ubus.SendMessage(UBUS_LAUNCHER_LOCK_HIDE, message_data);
182- monitor_index_ = UScreen::GetDefault()->GetMonitorWithMouse();
183 GVariant* info = g_variant_new(UBUS_OVERLAY_FORMAT_STRING, "hud", FALSE, monitor_index_);
184 ubus.SendMessage(UBUS_OVERLAY_SHOWN, info);
185
186@@ -410,7 +413,6 @@
187 ubus.SendMessage(UBUS_HUD_ICON_CHANGED, g_variant_new_string(query->icon_name.c_str()));
188 }
189
190-
191 void Controller::OnQueriesFinished(Hud::Queries queries)
192 {
193 view_->SetQueries(queries);
194@@ -438,7 +440,10 @@
195 void Controller::AddProperties(GVariantBuilder* builder)
196 {
197 variant::BuilderWrapper(builder)
198- .add("visible", visible_);
199+ .add(window_ ? window_->GetGeometry() : nux::Geometry())
200+ .add("visible", visible_)
201+ .add("hud_monitor", monitor_index_)
202+ .add("locked_to_launcher", IsLockedToLauncher(monitor_index_));
203 }
204
205
206
207=== modified file 'plugins/unityshell/src/HudController.h'
208--- plugins/unityshell/src/HudController.h 2012-03-21 15:30:49 +0000
209+++ plugins/unityshell/src/HudController.h 2012-03-25 18:15:22 +0000
210@@ -22,7 +22,6 @@
211 #include <memory>
212
213 #include <gdk/gdk.h>
214-#include <UnityCore/GLibSignal.h>
215 #include <UnityCore/Hud.h>
216
217 #include <NuxCore/Property.h>
218@@ -49,12 +48,13 @@
219 nux::BaseWindow* window() const;
220
221 nux::Property<int> launcher_width;
222+ nux::Property<bool> launcher_locked_out;
223+ nux::Property<bool> multiple_launchers;
224
225 void ShowHideHud();
226 void ShowHud();
227 void HideHud(bool restore_focus = true);
228 bool IsVisible();
229- void SetLauncherIsLockedOut(bool launcher_is_locked_out);
230
231 protected:
232 std::string GetName() const;
233@@ -64,11 +64,13 @@
234 void EnsureHud();
235 void SetupWindow();
236 void SetupHudView();
237- void SetupRelayoutCallbacks();
238 void RegisterUBusInterests();
239
240+ int GetTargetMonitor();
241+ bool IsLockedToLauncher(int monitor);
242+
243 nux::Geometry GetIdealWindowGeometry();
244- void Relayout(GdkScreen*screen=NULL);
245+ void Relayout();
246
247 void OnMouseDownOutsideWindow(int x, int y, unsigned long bflags, unsigned long kflags);
248 void OnScreenUngrabbed();
249@@ -81,8 +83,6 @@
250 void OnQueryActivated(Query::Ptr query);
251 void OnQuerySelected(Query::Ptr query);
252
253-
254-private:
255 void StartShowHideTimeline();
256 static gboolean OnViewShowHideFrame(Controller* self);
257
258@@ -93,7 +93,6 @@
259 private:
260 UBusManager ubus;
261 Hud hud_service_;
262- glib::SignalManager sig_manager_;
263 nux::BaseWindow* window_;
264 bool visible_;
265 bool need_show_;
266@@ -101,8 +100,6 @@
267 guint timeline_id_;
268 float last_opacity_;
269 gint64 start_time_;
270-
271- bool launcher_is_locked_out_;
272
273 View* view_;
274 guint ensure_id_;
275
276=== modified file 'plugins/unityshell/src/HudView.cpp'
277--- plugins/unityshell/src/HudView.cpp 2012-03-21 15:07:29 +0000
278+++ plugins/unityshell/src/HudView.cpp 2012-03-25 18:15:22 +0000
279@@ -64,7 +64,7 @@
280 , current_height_(0)
281 , timeline_need_more_draw_(false)
282 , selected_button_(0)
283- , icon_state_(IconHideState::SHOW)
284+ , show_embedded_icon_(true)
285 , activated_signal_sent_(false)
286 {
287 renderer_.SetOwner(this);
288@@ -276,16 +276,16 @@
289 QueueDraw();
290 }
291
292-void View::SetHideIcon(IconHideState hide_icon)
293+void View::ShowEmbeddedIcon(bool show)
294 {
295 LOG_DEBUG(logger) << "Hide icon called";
296- if (hide_icon == icon_state_)
297+ if (show == show_embedded_icon_)
298 return;
299
300- icon_state_ = hide_icon;
301+ show_embedded_icon_ = show;
302
303- if (icon_state_ == IconHideState::HIDE)
304- layout_->RemoveChildObject(dynamic_cast<nux::Area*>(icon_layout_.GetPointer()));
305+ if (!show)
306+ layout_->RemoveChildObject(static_cast<nux::Area*>(icon_layout_.GetPointer()));
307 else
308 layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP, nux::MINOR_SIZE_MATCHCONTENT, 100.0f, nux::LayoutPosition::NUX_LAYOUT_BEGIN);
309
310@@ -303,7 +303,7 @@
311 width = 1024;
312 height = 276;
313
314- if (icon_state_ == IconHideState::HIDE)
315+ if (!show_embedded_icon_)
316 {
317 width -= icon_layout_->GetGeometry().width;
318 }
319@@ -491,8 +491,10 @@
320 {
321 unsigned num_buttons = buttons_.size();
322 variant::BuilderWrapper(builder)
323+ .add(GetGeometry())
324 .add("selected_button", selected_button_)
325- .add("num_buttons", num_buttons);
326+ .add("num_buttons", num_buttons)
327+ .add("show_embedded_icon", show_embedded_icon_);
328 }
329
330 bool View::InspectKeyEvent(unsigned int eventType,
331
332=== modified file 'plugins/unityshell/src/HudView.h'
333--- plugins/unityshell/src/HudView.h 2012-03-21 14:44:41 +0000
334+++ plugins/unityshell/src/HudView.h 2012-03-25 18:15:22 +0000
335@@ -44,12 +44,6 @@
336 namespace hud
337 {
338
339-enum IconHideState
340-{
341- HIDE,
342- SHOW
343-};
344-
345 class View : public nux::View, public unity::debug::Introspectable
346 {
347 NUX_DECLARE_OBJECT_TYPE(HudView, nux::View);
348@@ -65,7 +59,7 @@
349
350 void SetQueries(Hud::Queries queries);
351 void SetIcon(std::string icon_name);
352- void SetHideIcon(IconHideState hide_icon);
353+ void ShowEmbeddedIcon(bool show);
354
355 void AboutToShow();
356 void AboutToHide();
357@@ -126,7 +120,7 @@
358 int current_height_;
359 bool timeline_need_more_draw_;
360 int selected_button_;
361- IconHideState icon_state_;
362+ bool show_embedded_icon_;
363 bool activated_signal_sent_;
364 };
365
366
367=== modified file 'plugins/unityshell/src/LauncherIcon.cpp'
368--- plugins/unityshell/src/LauncherIcon.cpp 2012-03-21 12:31:11 +0000
369+++ plugins/unityshell/src/LauncherIcon.cpp 2012-03-25 18:15:22 +0000
370@@ -185,18 +185,20 @@
371 LauncherIcon::AddProperties(GVariantBuilder* builder)
372 {
373 unity::variant::BuilderWrapper(builder)
374- .add("x", _center[0].x)
375- .add("y", _center[0].y)
376- .add("z", _center[0].z)
377- .add("related-windows", (int)Windows().size())
378- .add("icon-type", _icon_type)
379- .add("tooltip-text", tooltip_text())
380- .add("sort-priority", _sort_priority)
381- .add("quirk-active", GetQuirk(QUIRK_ACTIVE))
382- .add("quirk-visible", GetQuirk(QUIRK_VISIBLE))
383- .add("quirk-urgent", GetQuirk(QUIRK_URGENT))
384- .add("quirk-running", GetQuirk(QUIRK_RUNNING))
385- .add("quirk-presented", GetQuirk(QUIRK_PRESENTED));
386+ .add("center_x", _center[0].x)
387+ .add("center_y", _center[0].y)
388+ .add("center_z", _center[0].z)
389+ .add("related_windows", static_cast<unsigned int>(Windows().size()))
390+ .add("icon_type", _icon_type)
391+ .add("tooltip_text", tooltip_text())
392+ .add("sort_priority", _sort_priority)
393+ .add("active", GetQuirk(QUIRK_ACTIVE))
394+ .add("visible", GetQuirk(QUIRK_VISIBLE))
395+ .add("urgent", GetQuirk(QUIRK_URGENT))
396+ .add("running", GetQuirk(QUIRK_RUNNING))
397+ .add("starting", GetQuirk(QUIRK_STARTING))
398+ .add("desaturated", GetQuirk(QUIRK_DESAT))
399+ .add("presented", GetQuirk(QUIRK_PRESENTED));
400 }
401
402 void
403
404=== modified file 'plugins/unityshell/src/unityshell.cpp'
405--- plugins/unityshell/src/unityshell.cpp 2012-03-22 19:33:10 +0000
406+++ plugins/unityshell/src/unityshell.cpp 2012-03-25 18:15:22 +0000
407@@ -2520,6 +2520,7 @@
408 case UnityshellOptions::NumLaunchers:
409 launcher_controller_->multiple_launchers = optionGetNumLaunchers() == 0;
410 dash_controller_->use_primary = !launcher_controller_->multiple_launchers();
411+ hud_controller_->multiple_launchers = launcher_controller_->multiple_launchers();
412 break;
413 case UnityshellOptions::LauncherCaptureMouse:
414 launcher_options->edge_resist = optionGetLauncherCaptureMouse();
415@@ -2540,7 +2541,7 @@
416 case UnityshellOptions::LauncherHideMode:
417 {
418 launcher_options->hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
419- hud_controller_->SetLauncherIsLockedOut(launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
420+ hud_controller_->launcher_locked_out = (launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
421 break;
422 }
423 case UnityshellOptions::BacklightMode:
424@@ -2775,7 +2776,7 @@
425 /* Setup Hud */
426 hud_controller_.reset(new hud::Controller());
427 auto hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
428- hud_controller_->SetLauncherIsLockedOut(hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
429+ hud_controller_->launcher_locked_out = (hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
430 AddChild(hud_controller_.get());
431 LOG_INFO(logger) << "initLauncher-hud " << timer.ElapsedSeconds() << "s";
432
433
434=== modified file 'tests/autopilot/autopilot/emulators/X11.py'
435--- tests/autopilot/autopilot/emulators/X11.py 2012-03-21 12:31:11 +0000
436+++ tests/autopilot/autopilot/emulators/X11.py 2012-03-25 18:15:22 +0000
437@@ -339,10 +339,21 @@
438 Returns a tuple containing (x,y,width,height).
439
440 """
441- if monitor_number >= self.get_num_monitors():
442+ if monitor_number < 0 or monitor_number >= self.get_num_monitors():
443 raise ValueError('Specified monitor number is out of range.')
444 return tuple(self._default_screen.get_monitor_geometry(monitor_number))
445
446+ def is_rect_on_monitor(self, monitor_number, rect):
447+ """Returns True if `rect` is _entirely_ on the specified monitor, with no overlap"""
448+
449+ if type(rect) is not tuple or len(rect) != 4:
450+ raise TypeError("rect must be a tuple of 4 int elements.")
451+
452+ (x, y, w, h) = self.get_monitor_geometry(monitor_number)
453+
454+ (m_x, m_y, m_w, m_h) = self.get_monitor_geometry(monitor_number)
455+ return (x >= m_x and x + w <= m_x + m_w and y >= m_y and y + h <= m_y + m_h)
456+
457 def move_mouse_to_monitor(self, monitor_number):
458 """Move the mouse to the center of the specified monitor."""
459 geo = self.get_monitor_geometry(monitor_number)
460
461=== modified file 'tests/autopilot/autopilot/emulators/unity/hud.py'
462--- tests/autopilot/autopilot/emulators/unity/hud.py 2012-03-04 23:12:19 +0000
463+++ tests/autopilot/autopilot/emulators/unity/hud.py 2012-03-25 18:15:22 +0000
464@@ -35,11 +35,18 @@
465 """Tap the 'Alt' key to toggle the hud visibility."""
466 self.keybinding("hud/reveal", tap_delay)
467
468+ def get_geometry(self):
469+ return (self.x, self.y, self.width, self.height)
470+
471 def _get_view(self):
472 views = self.get_children_by_type(HudView)
473 return views[0] if views else None
474
475 @property
476+ def geometry(self):
477+ return (self.x, self.y, self.width, self.height)
478+
479+ @property
480 def selected_button(self):
481 view = self._get_view()
482 if view:
483@@ -54,3 +61,19 @@
484 return view.num_buttons
485 else:
486 return 0
487+
488+ @property
489+ def is_locked_to_launcher(self):
490+ return bool(self.locked_to_launcher)
491+
492+ @property
493+ def monitor(self):
494+ return int(self.hud_monitor)
495+
496+ @property
497+ def show_embedded_icon(self):
498+ view = self._get_view()
499+ if view:
500+ return bool(view.show_embedded_icon)
501+ else:
502+ return False
503
504=== modified file 'tests/autopilot/autopilot/emulators/unity/icons.py'
505--- tests/autopilot/autopilot/emulators/unity/icons.py 2012-03-04 23:12:19 +0000
506+++ tests/autopilot/autopilot/emulators/unity/icons.py 2012-03-25 18:15:22 +0000
507@@ -19,6 +19,10 @@
508
509 """
510
511+ @property
512+ def center_geometry(self):
513+ return (self.center_x, self.center_y, self.center_z)
514+
515 def get_quicklist(self):
516 """Get the quicklist for this launcher icon.
517
518@@ -34,6 +38,10 @@
519 """Represents the BFB button in the launcher."""
520
521
522+class HudLauncherIcon(SimpleLauncherIcon):
523+ """Represents the HUD button in the launcher."""
524+
525+
526 class BamfLauncherIcon(SimpleLauncherIcon):
527 """Represents a launcher icon with BAMF integration."""
528
529
530=== modified file 'tests/autopilot/autopilot/emulators/unity/launcher.py'
531--- tests/autopilot/autopilot/emulators/unity/launcher.py 2012-03-15 20:03:08 +0000
532+++ tests/autopilot/autopilot/emulators/unity/launcher.py 2012-03-25 18:15:22 +0000
533@@ -196,8 +196,8 @@
534 logger.debug("Clicking launcher icon %r on monitor %d with mouse button %d",
535 icon, self.monitor, button)
536 self.mouse_reveal_launcher()
537- target_x = icon.x + self.x
538- target_y = icon.y + (self.icon_size / 2)
539+ target_x = icon.center_x + self.x
540+ target_y = icon.center_y
541 self._mouse.move(target_x, target_y )
542 self._mouse.click(button)
543 self.move_mouse_to_right_of_launcher()
544@@ -257,7 +257,7 @@
545 def get_launcher_icons(self, visible_only=True):
546 """Get a list of launcher icons in this launcher."""
547 if visible_only:
548- return self.get_children_by_type(SimpleLauncherIcon, quirk_visible=True)
549+ return self.get_children_by_type(SimpleLauncherIcon, visible=True)
550 else:
551 return self.get_children_by_type(SimpleLauncherIcon)
552
553@@ -277,7 +277,21 @@
554 Returns None if there is no such launcher icon.
555 """
556 icons = self.get_children_by_type(SimpleLauncherIcon, desktop_file=desktop_file)
557- return icons or None
558+ if len(icons):
559+ return icons[0]
560+
561+ return None
562+
563+ def get_icon_by_desktop_id(self, desktop_id):
564+ """Gets a launcher icon with the specified desktop id.
565+
566+ Returns None if there is no such launcher icon.
567+ """
568+ icons = self.get_children_by_type(SimpleLauncherIcon, desktop_id=desktop_id)
569+ if len(icons):
570+ return icons[0]
571+
572+ return None
573
574 def num_launcher_icons(self):
575 """Get the number of icons in the launcher model."""
576
577=== modified file 'tests/autopilot/autopilot/tests/test_hud.py'
578--- tests/autopilot/autopilot/tests/test_hud.py 2012-03-21 14:44:41 +0000
579+++ tests/autopilot/autopilot/tests/test_hud.py 2012-03-25 18:15:22 +0000
580@@ -6,23 +6,55 @@
581 # under the terms of the GNU General Public License version 3, as published
582 # by the Free Software Foundation.
583
584-from testtools.matchers import Equals, LessThan
585+from testtools.matchers import Equals, LessThan, GreaterThan
586 from time import sleep
587
588+from autopilot.emulators.X11 import ScreenGeometry
589 from autopilot.emulators.unity.hud import HudController
590+from autopilot.emulators.unity.icons import BFBLauncherIcon, HudLauncherIcon
591 from autopilot.tests import AutopilotTestCase
592 from os import remove
593
594+def _make_scenarios():
595+ screen_geometry = ScreenGeometry()
596+ num_monitors = screen_geometry.get_num_monitors()
597+
598+ scenarios = []
599+
600+ if num_monitors == 1:
601+ scenarios = [
602+ ('Single Monitor, Launcher never hide', {'hud_monitor': 0, 'launcher_hide_mode': 0, 'launcher_primary_only': False}),
603+ ('Single Monitor, Launcher autohide', {'hud_monitor': 0, 'launcher_hide_mode': 1, 'launcher_primary_only': False}),
604+ ]
605+ else:
606+ for i in range(num_monitors):
607+ scenario_setting = {'hud_monitor': i, 'launcher_hide_mode': 0, 'launcher_primary_only': False}
608+ scenarios.append(('Monitor %d, Launcher never hide, on all monitors' % (i), scenario_setting))
609+
610+ scenario_setting = {'hud_monitor': i, 'launcher_hide_mode': 0, 'launcher_primary_only': True}
611+ scenarios.append(('Monitor %d, Launcher never hide, only on primary monitor' % (i), scenario_setting))
612+
613+ scenario_setting = {'hud_monitor': i, 'launcher_hide_mode': 1, 'launcher_primary_only': True}
614+ scenarios.append(('Monitor %d, Launcher autohide, on all monitors' % (i), scenario_setting))
615+
616+ scenario_setting = {'hud_monitor': i, 'launcher_hide_mode': 1, 'launcher_primary_only': True}
617+ scenarios.append(('Monitor %d, Launcher autohide, only on primary monitor' % (i), scenario_setting))
618+
619+ return scenarios
620+
621 class HudTests(AutopilotTestCase):
622
623- scenarios = [
624- ('Launcher never hide', {'launcher_hide_mode': 0}),
625- ('Launcher autohide', {'launcher_hide_mode': 1}),
626- ]
627+ screen_geo = ScreenGeometry()
628+ scenarios = _make_scenarios()
629
630 def setUp(self):
631 super(HudTests, self).setUp()
632 self.set_unity_option('launcher_hide_mode', self.launcher_hide_mode)
633+ self.set_unity_option('num_launchers', int(self.launcher_primary_only))
634+ self.hud_monitor_is_primary = (self.screen_geo.get_primary_monitor() == self.hud_monitor)
635+ self.hud_locked = (self.launcher_hide_mode == 0 and (not self.launcher_primary_only or self.hud_monitor_is_primary))
636+ self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
637+
638 sleep(0.5)
639 self.hud = self.get_hud_controller()
640
641@@ -35,10 +67,15 @@
642 self.assertEqual(1, len(controllers))
643 return controllers[0]
644
645+ def get_hud_launcher_icon(self):
646+ icons = HudLauncherIcon.get_all_instances()
647+ self.assertEqual(1, len(icons))
648+ return icons[0]
649+
650 def get_num_active_launcher_icons(self):
651 num_active = 0
652 for icon in self.launcher.model.get_launcher_icons():
653- if icon.quirk_active and icon.quirk_visible:
654+ if icon.active and icon.visible:
655 num_active += 1
656 return num_active
657
658@@ -51,8 +88,32 @@
659 sleep(1)
660 if self.hud.visible:
661 break
662+
663 self.assertTrue(self.hud.visible, "HUD did not appear.")
664
665+ def test_hud_is_on_right_monitor(self):
666+ """Tests if the hud is shown and fits the monitor where it should be"""
667+ self.reveal_hud()
668+ self.assertThat(self.hud_monitor, Equals(self.hud.monitor))
669+ self.assertTrue(self.screen_geo.is_rect_on_monitor(self.hud.monitor, self.hud.geometry))
670+
671+ def test_hud_geometries(self):
672+ """Tests the HUD geometries for the given monitor and status"""
673+ self.reveal_hud()
674+ monitor_geo = self.screen_geo.get_monitor_geometry(self.hud_monitor)
675+ monitor_x = monitor_geo[0]
676+ monitor_w = monitor_geo[2]
677+ hud_x = self.hud.geometry[0]
678+ hud_w = self.hud.geometry[2]
679+
680+ if self.hud_locked:
681+ self.assertThat(hud_x, GreaterThan(monitor_x))
682+ self.assertThat(hud_x, LessThan(monitor_x + monitor_w))
683+ self.assertThat(hud_w, Equals(monitor_x + monitor_w - hud_x))
684+ else:
685+ self.assertThat(hud_x, Equals(monitor_x))
686+ self.assertThat(hud_w, Equals(monitor_w))
687+
688 def test_no_initial_values(self):
689 self.reveal_hud()
690 self.assertThat(self.hud.num_buttons, Equals(0))
691@@ -126,6 +187,11 @@
692 apps as active.
693
694 """
695+ launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
696+
697+ if not launcher:
698+ self.skipTest("The monitor %d has not a launcher" % self.hud_monitor)
699+
700 # We need an app to switch to:
701 self.start_app('Character Map')
702 # We need an application to play with - I'll use the calculator.
703@@ -144,8 +210,8 @@
704 sleep(0.5)
705
706 # click application icons for running apps in the launcher:
707- icon = self.launcher.model.get_icon_by_tooltip_text("Character Map")
708- self.launcher.get_launcher_for_monitor(0).click_launcher_icon(icon)
709+ icon = self.launcher.model.get_icon_by_desktop_id("gucharmap.desktop")
710+ launcher.click_launcher_icon(icon)
711
712 # see how many apps are marked as being active:
713 num_active = self.get_num_active_launcher_icons()
714@@ -211,3 +277,85 @@
715 contents = open("/tmp/autopilot_gedit_undo_test_temp_file.txt").read().strip('\n')
716 self.assertEqual("0 ", contents)
717
718+ def test_hud_does_not_change_launcher_status(self):
719+ """Tests if the HUD reveal keeps the launcher in the status it was"""
720+
721+ launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
722+
723+ if not launcher:
724+ self.skipTest("The monitor %d has not a launcher" % self.hud_monitor)
725+
726+ launcher_shows_pre = launcher.is_showing()
727+ sleep(.25)
728+
729+ self.reveal_hud()
730+ sleep(1)
731+
732+ launcher_shows_post = launcher.is_showing()
733+ self.assertThat(launcher_shows_pre, Equals(launcher_shows_post))
734+
735+ def test_hud_is_locked_to_launcher(self):
736+ """Tests if the HUD is locked to launcher as we expect or not"""
737+ self.reveal_hud()
738+ sleep(.25)
739+
740+ self.assertThat(self.hud.is_locked_to_launcher, Equals(self.hud_locked))
741+
742+ def test_hud_icon_is_shown(self):
743+ """Tests that the correct HUD icon is shown"""
744+ self.reveal_hud()
745+ sleep(.5)
746+
747+ hud_icon = self.get_hud_launcher_icon()
748+
749+ # FIXME this should check self.hud.is_locked_to_launcher
750+ # but the HUD icon is currently shared between launchers.
751+ if self.launcher_hide_mode == 0:
752+ self.assertTrue(hud_icon.visible)
753+ self.assertFalse(hud_icon.desaturated)
754+
755+ # FIXME remove this once the issue above has been resolved
756+ if self.hud.is_locked_to_launcher:
757+ self.assertFalse(self.hud.show_embedded_icon)
758+ else:
759+ self.assertTrue(self.hud.show_embedded_icon)
760+ self.assertFalse(hud_icon.visible)
761+
762+ def test_hud_launcher_icon_hides_bfb(self):
763+ """Tests that the BFB icon is hidden when the HUD launcher icon is shown"""
764+ if not self.hud.is_locked_to_launcher:
765+ self.skipTest("This test needs a locked launcher")
766+
767+ hud_icon = self.get_hud_launcher_icon()
768+
769+ icons = BFBLauncherIcon.get_all_instances()
770+ self.assertEqual(1, len(icons))
771+ bfb_icon = icons[0]
772+
773+ self.assertTrue(bfb_icon.visible)
774+ self.assertFalse(hud_icon.visible)
775+ sleep(.25)
776+
777+ self.reveal_hud()
778+ sleep(.5)
779+
780+ self.assertTrue(hud_icon.visible)
781+ self.assertFalse(bfb_icon.visible)
782+
783+ def test_hud_desaturates_launcher_icons(self):
784+ """Tests that the launcher icons are desaturates when HUD is open"""
785+ if not self.hud.is_locked_to_launcher:
786+ self.skipTest("This test needs a locked launcher")
787+
788+ self.reveal_hud()
789+ sleep(.5)
790+
791+ hud_icon = self.get_hud_launcher_icon()
792+ desaturated = True
793+
794+ for icon in self.launcher.model.get_launcher_icons():
795+ if (not isinstance(icon, HudLauncherIcon) and not icon.desaturated):
796+ desaturated = False
797+ break
798+
799+ self.assertTrue(desaturated)