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

Proposed by Marco Trevisan (Treviño) on 2012-03-25
Status: Merged
Approved by: Gord Allott on 2012-03-29
Approved revision: 2154
Merged at revision: 2188
Proposed branch: lp:~3v1n0/unity/hud-lock-out-monitors-tests
Merge into: lp:unity
Diff against target: 1544 lines (+530/-245)
27 files modified
manual-tests/Hud.txt (+0/-16)
plugins/unityshell/src/BamfLauncherIcon.cpp (+36/-43)
plugins/unityshell/src/BamfLauncherIcon.h (+2/-1)
plugins/unityshell/src/HudController.cpp (+50/-38)
plugins/unityshell/src/HudController.h (+6/-9)
plugins/unityshell/src/HudIcon.cpp (+4/-4)
plugins/unityshell/src/HudIcon.h (+2/-1)
plugins/unityshell/src/HudView.cpp (+20/-11)
plugins/unityshell/src/HudView.h (+2/-8)
plugins/unityshell/src/IconTexture.cpp (+21/-18)
plugins/unityshell/src/IconTexture.h (+1/-0)
plugins/unityshell/src/LauncherIcon.cpp (+14/-12)
plugins/unityshell/src/SimpleLauncherIcon.cpp (+7/-0)
plugins/unityshell/src/SimpleLauncherIcon.h (+2/-0)
plugins/unityshell/src/unityshell.cpp (+4/-2)
tests/autopilot/autopilot/emulators/X11.py (+11/-1)
tests/autopilot/autopilot/emulators/bamf.py (+5/-0)
tests/autopilot/autopilot/emulators/unity/hud.py (+35/-0)
tests/autopilot/autopilot/emulators/unity/icons.py (+9/-0)
tests/autopilot/autopilot/emulators/unity/launcher.py (+24/-5)
tests/autopilot/autopilot/emulators/unity/switcher.py (+2/-2)
tests/autopilot/autopilot/tests/__init__.py (+12/-4)
tests/autopilot/autopilot/tests/test_hud.py (+240/-50)
tests/autopilot/autopilot/tests/test_launcher.py (+1/-2)
tests/autopilot/autopilot/tests/test_shortcut_hint.py (+3/-5)
tests/autopilot/autopilot/tests/test_showdesktop.py (+5/-4)
tests/autopilot/autopilot/tests/test_switcher.py (+12/-9)
To merge this branch: bzr merge lp:~3v1n0/unity/hud-lock-out-monitors-tests
Reviewer Review Type Date Requested Status
Thomi Richards (community) 2012-03-25 Approve on 2012-03-27
Gord Allott 2012-03-25 Pending
Review via email: mp+99215@code.launchpad.net

This proposal supersedes a proposal from 2012-03-21.

Commit message

HudController: Fixed geometries for single-launcher mode.

And added tests for multimonitor in HUD, with lock-out support.

Description of the change

Added tests for multimonitor in HUD, with lock-out support.

Also fixed the bug #963577 with some HudController and HudView code cleanup and improvements.
The tests now also support the HudLauncherIcon, and I've included some more utility functions to avoid them to fail.

To post a comment you must log in.
Gord Allott (gordallott) wrote : Posted in a previous version of this proposal

+1, seems good here

review: Approve
Thomi Richards (thomir) wrote : Posted in a previous version of this proposal

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
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

Thomi Richards (thomir) wrote :
Download full text (5.7 KiB)

Hi,

There are a few things that need to be fixed:

712 - .add("x", _center[0].x)
713 - .add("y", _center[0].y)
714 - .add("z", _center[0].z)
715 - .add("related-windows", (int)Windows().size())
716 - .add("icon-type", _icon_type)
717 - .add("tooltip-text", tooltip_text())
718 - .add("sort-priority", _sort_priority)
719 - .add("quirk-active", GetQuirk(QUIRK_ACTIVE))
720 - .add("quirk-visible", GetQuirk(QUIRK_VISIBLE))
721 - .add("quirk-urgent", GetQuirk(QUIRK_URGENT))
722 - .add("quirk-running", GetQuirk(QUIRK_RUNNING))
723 - .add("quirk-presented", GetQuirk(QUIRK_PRESENTED));
724 + .add("center_x", _center[0].x)
725 + .add("center_y", _center[0].y)
726 + .add("center_z", _center[0].z)
727 + .add("related_windows", static_cast<unsigned int>(Windows().size()))
728 + .add("icon_type", _icon_type)
729 + .add("tooltip_text", tooltip_text())
730 + .add("sort_priority", _sort_priority)
731 + .add("active", GetQuirk(QUIRK_ACTIVE))
732 + .add("visible", GetQuirk(QUIRK_VISIBLE))
733 + .add("urgent", GetQuirk(QUIRK_URGENT))
734 + .add("running", GetQuirk(QUIRK_RUNNING))
735 + .add("starting", GetQuirk(QUIRK_STARTING))
736 + .add("desaturated", GetQuirk(QUIRK_DESAT))
737 + .add("presented", GetQuirk(QUIRK_PRESENTED));

Hyphens ('-') get translated to underscores ('_') in python automatically. You don't need to do this in the C++ code. It doesn't hurt, but you don't need to do it. More importantly, I don't think renaming 'x', 'y', 'z' to center_x, center_y, and center_z is a good idea. It seems natural to me that the x,y & z properties represent the center of the icon. If you are going to change this, please make sure that all the autopilot tests are updated accordingly.

There's something very wrong with this code:

823 + def is_rect_on_monitor(self, monitor_number, rect):
824 + """Returns True if `rect` is _entirely_ on the specified monitor, with no overlap"""
825 +
826 + if type(rect) is not tuple or len(rect) != 4:
827 + raise TypeError("rect must be a tuple of 4 int elements.")
828 +
829 + (x, y, w, h) = self.get_monitor_geometry(monitor_number)
830 +
831 + (m_x, m_y, m_w, m_h) = self.get_monitor_geometry(monitor_number)
832 + return (x >= m_x and x + w <= m_x + m_w and y >= m_y and y + h <= m_y + m_h)
833 +

...Can you spot it? What exactly is 'rect' used for?

THis property:

910 + @property
911 + def show_embedded_icon(self):

Should be renamed. Either 'showing_embedded_icon' or 'has_embedded_icon', or maybe even 'displaying_embedded_icon'. 'show' is a verb, and shouldn't be used in property names.

I notice that you've changed this code:

970 icons = self.get_children_by_type(SimpleLauncherIcon, desktop_file=desktop_file)
971 - return icons or None
972 + if len(icons):
973 + return icons[0]
974 +
975 + return None
976 +

It used to return a list or none, now it returns an instance or none. Have you updated everywhere that called this method to cope with the change? Further, are you *absolutely* sure that it's impossible for there to be more than one launcher icon with the same desktop file? I'm pretty sure Jason said that this could happen, whcih is why I was returning a list.

This:

1016 +def _make_scenarios():
1017 + screen_geometry = Screen...

Read more...

review: Needs Fixing
Marco Trevisan (Treviño) (3v1n0) wrote :
Download full text (4.8 KiB)

Ooops... Myabe I was too tired yesterday night, I figured there was still some debugging code around, sorry.

> Hi,
>
> There are a few things that need to be fixed:
>
> 728 + .add("icon_type", _icon_type)

> Hyphens ('-') get translated to underscores ('_') in python automatically. You
> don't need to do this in the C++ code. It doesn't hurt, but you don't need to
> do it.

Yes, I know, but it also was to keep the same way of naming the introspection parameters.
Plus, there was no need to include the "quirk-" prefix.

> More importantly, I don't think renaming 'x', 'y', 'z' to center_x,
> center_y, and center_z is a good idea. It seems natural to me that the x,y & z
> properties represent the center of the icon.

Yes, maybe you are, but I'm not sure we're all since there was this code:
  target_y = icon.y + (self.icon_size / 2)
  self._mouse.move(target_x, target_y )
  self._mouse.click(button)

Also, considering that everywhere we consider the X / Y points as the coordinates of the top left edge, we should just apply this to icons too.

> If you are going to change this, please make sure that all the autopilot tests
> are updated accordingly.

Yes, I've done that.

> There's something very wrong with this code:
>
> 823 + def is_rect_on_monitor(self, monitor_number, rect):

> ...Can you spot it? What exactly is 'rect' used for?

Yes, sorry it should have been used here:

> 829 + (x, y, w, h) = self.get_monitor_geometry(monitor_number)

Maybe a copy&paste typo.

> THis property:
>
> 910 + @property
> 911 + def show_embedded_icon(self):
>
> Should be renamed. Either 'showing_embedded_icon' or 'has_embedded_icon', or
> maybe even 'displaying_embedded_icon'. 'show' is a verb, and shouldn't be used
> in property names.

Yes, actually I should have removed that, since I don't use it anymore (I used on previous revisions).
I've updated it against new API and new name, btw.

> I notice that you've changed this code:
>
> 970 icons = self.get_children_by_type(SimpleLauncherIcon,
> desktop_file=desktop_file)
> 971 - return icons or None
> 972 + if len(icons):
> 973 + return icons[0]
> 974 +
> 975 + return None
> 976 +
>
> It used to return a list or none, now it returns an instance or none. Have you
> updated everywhere that called this method to cope with the change?

Yes, it was called only once in an HUD test, that I've updated moving to desktop_id

> Further, are you *absolutely* sure that it's impossible for there to be more than one
> launcher icon with the same desktop file? I'm pretty sure Jason said that this
> could happen, whcih is why I was returning a list.

No, it's currently impossible (at least, it shouldn't happen unless we have bamf crashes, but this something to be fixed elsewhere) that two icons have the same desktop file, considering by "desktop file" the .desktop full path.
If it happens, btw it's safe to just take the first icon.
Otherwise we should just rename it into get_icons_by_desktop_file (plural form, I mean) since the current name could lead to some misunderstanding.
Anyway I'm for the only-one-icon way: it simplifies the usage and just works.

> This:
>
> 1016 +...

Read more...

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

Marco Trevisan (Treviño) (3v1n0) wrote :

Thomi, the tests now should be done.

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

Thomi Richards (thomir) wrote :
Download full text (3.7 KiB)

Hi,

Almost there :)

Please change this:

81 + .add("desktop_id", glib::String(g_path_get_basename(DesktopFile().c_str())).Str())

to use the methods on the std::string. Something like this (untested, but should work):

std::string desktop_file = DesktopFile();
std::string desktop_id = desktop_file.substr(desktop_file.rfind('/'));

The current code involves way too much casting, uses c functions when we have c++ alternatives, and looks awful.

This docstringsd needs a period at the end:

762 + """Returns True if `rect` is _entirely_ on the specified monitor, with no overlap"""

Please add a blank line between the class docstring at the property:

797 """Proxy object for the hud view child of the controller."""
798 + @property
799 + def geometry(self):

Please add a docstring here:

814 + def get_embedded_icon(self):

...detailing what the possible return values are.

Please rename this:

858 + @property
859 + def center_geometry(self):

since you're not returning the geometry, just a point. Maybe call it "position", "center_position", or "center_point" or something. Also, please add a docstring, since you're returning x, y AND z properties, which might confuse people (who only expect X & Y).

Please revert this change:

966 - scenario_name = ','.join(names)
967 + scenario_name = ', '.join(names)

multiply_scenarios is from testscenarios. I won't want two functions that behave differently.

This should go in AutopilotTestCase:

1034 + screen_geo = ScreenGeometry()

Please add a blank line betweeb the class definition and the setUp method:

1081 +class HudBehaviorTests(HudTestsBase):
1082 + def setUp(self):

This test:

1245 + def test_hud_desaturates_launcher_icons(self):
1246 + """Tests that the launcher icons are desaturates when HUD is open"""
1247 +
1248 + self.reveal_hud()
1249 + sleep(.5)
1250 +
1251 + for icon in self.launcher.model.get_launcher_icons():
1252 + if not isinstance(icon, HudLauncherIcon):
1253 + self.assertTrue(icon.desaturated)

Is good, but we probably want another one that asserts that the hud icon is NOT desaturated.

As discussed on IRC, please change this:

975 + def start_app_c_locale(self, app_name, files=[]):
976 + """Start one of the known apps using the C locale, and kill it on tear down.
977 +
978 + if files is specified, start the application with the specified files.
979 + """
980 + os.putenv("LC_ALL", "C")
981 + self.start_app(app_name, files)
982 + self.addCleanup(os.unsetenv, "LC_ALL")

to something like this (changing the current start_app):

def start_app(self, app_name, files=[], locale=None):
        """Start one of the known apps, and kill it on tear down.

        If files is specified, start the application with the specified files.
        If locale is specified, the locale will be set when the application is launched.
        """
        if locale:
            os.putenv("LC_ALL", "C")
            self.addCleanup(os.unsetenv, "LC_ALL")
            logger.info("Starting application '%s' with files %r in locale %s", app_name, files, locale)
        else:
            logger.info("Starting application '%s' with files %r", app_name, files)
        app = self.KNOWN_APPS[app_name]
        self.bamf....

Read more...

review: Needs Fixing
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

Thomi Richards (thomir) wrote :

+1

review: Approve

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-26 21:04:10 +0000
3+++ manual-tests/Hud.txt 2012-03-27 22:51:18 +0000
4@@ -49,22 +49,6 @@
5 After pressing escape in step three, the text "test" should be removed from the hud search
6 After step four, the hud should dismiss itself and not be present.
7
8-Hud Reveal Behaviour
9----------
10-This test ensures that the hud behaves correctly with a locked out launcher
11-
12-Setup:
13-#. Ensure the launchers hide mode is set to "Never"
14-
15-Action:
16-#. Tap Alt
17-
18-Outcome:
19- The Launcher should stick be locked out.
20- The Launcher icons should be desaturated.
21- The top most Launcher icon should be an icon related the the focused window
22- The BFB should not be present
23-
24 Alt+Arrow keys not passed to application
25 ----------------------------------------
26 Tests that Alt+ArrowKey events are correctly passed to the active window
27
28=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
29--- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-03-22 15:14:49 +0000
30+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-03-27 22:51:18 +0000
31@@ -335,7 +335,7 @@
32
33 std::vector<Window> BamfLauncherIcon::WindowsOnViewport()
34 {
35- WindowFilterMask filter;
36+ WindowFilterMask filter = 0;
37 filter |= WindowFilter::MAPPED;
38 filter |= WindowFilter::USER_VISIBLE;
39 filter |= WindowFilter::ON_CURRENT_DESKTOP;
40@@ -346,7 +346,7 @@
41
42 std::vector<Window> BamfLauncherIcon::WindowsForMonitor(int monitor)
43 {
44- WindowFilterMask filter;
45+ WindowFilterMask filter = 0;
46 filter |= WindowFilter::MAPPED;
47 filter |= WindowFilter::USER_VISIBLE;
48 filter |= WindowFilter::ON_CURRENT_DESKTOP;
49@@ -455,26 +455,18 @@
50
51 void BamfLauncherIcon::AddProperties(GVariantBuilder* builder)
52 {
53- LauncherIcon::AddProperties(builder);
54-
55- GList* children, *l;
56- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
57- GVariant* xids[(int) g_list_length(children)];
58-
59- int i = 0;
60- for (l = children; l; l = l->next)
61- {
62- if (!BAMF_IS_WINDOW(l->data))
63- continue;
64-
65- Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
66- xids[i++] = g_variant_new_uint32(xid);
67- }
68- g_list_free(children);
69+ SimpleLauncherIcon::AddProperties(builder);
70+
71+ GVariantBuilder xids_builder;
72+ g_variant_builder_init(&xids_builder, G_VARIANT_TYPE ("au"));
73+
74+ for (auto xid : GetWindows())
75+ g_variant_builder_add(&xids_builder, "u", xid);
76
77 variant::BuilderWrapper(builder)
78- .add("desktop-file", DesktopFile())
79- .add("xids", g_variant_new_array(G_VARIANT_TYPE_UINT32, xids, i))
80+ .add("desktop_file", DesktopFile())
81+ .add("desktop_id", GetDesktopID())
82+ .add("xids", g_variant_builder_end(&xids_builder))
83 .add("sticky", IsSticky());
84 }
85
86@@ -627,26 +619,8 @@
87
88 bool BamfLauncherIcon::Spread(bool current_desktop, int state, bool force)
89 {
90- GList* children, *l;
91- children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
92- WindowManager* wm = WindowManager::Default();
93-
94- std::vector<Window> windowList;
95- for (l = children; l; l = l->next)
96- {
97- if (!BAMF_IS_WINDOW(l->data))
98- continue;
99-
100- Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
101-
102- if (!current_desktop || (current_desktop && wm->IsWindowOnCurrentDesktop(xid)))
103- {
104- windowList.push_back(xid);
105- }
106- }
107-
108- g_list_free(children);
109- return WindowManager::Default()->ScaleWindowGroup(windowList, state, force);
110+ auto windows = GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0);
111+ return WindowManager::Default()->ScaleWindowGroup(windows, state, force);
112 }
113
114 void BamfLauncherIcon::EnsureWindowState()
115@@ -1049,16 +1023,35 @@
116 UpdateIconGeometries(center);
117 }
118
119+std::string BamfLauncherIcon::GetDesktopID()
120+{
121+ std::string const& desktop_file = DesktopFile();
122+
123+ if (!desktop_file.empty())
124+ {
125+ size_t id_pos = desktop_file.rfind('/');
126+
127+ if (id_pos != std::string::npos)
128+ {
129+ size_t id_start = id_pos + 1;
130+
131+ return (id_start < desktop_file.length()) ? desktop_file.substr(id_start) : "";
132+ }
133+ }
134+
135+ return desktop_file;
136+}
137+
138 const gchar* BamfLauncherIcon::GetRemoteUri()
139 {
140 if (_remote_uri.empty())
141 {
142 const std::string prefix = "application://";
143- glib::String basename(g_path_get_basename(DesktopFile().c_str()));
144+ std::string const& desktop_id = GetDesktopID();
145
146- if (!basename.Str().empty())
147+ if (!desktop_id.empty())
148 {
149- _remote_uri = prefix + basename.Str();
150+ _remote_uri = prefix + desktop_id;
151 }
152 }
153
154
155=== modified file 'plugins/unityshell/src/BamfLauncherIcon.h'
156--- plugins/unityshell/src/BamfLauncherIcon.h 2012-03-22 15:14:49 +0000
157+++ plugins/unityshell/src/BamfLauncherIcon.h 2012-03-27 22:51:18 +0000
158@@ -113,8 +113,9 @@
159
160 bool OwnsWindow(Window w) const;
161
162- std::vector<Window> GetWindows(WindowFilterMask filter, int monitor = -1);
163+ std::vector<Window> GetWindows(WindowFilterMask filter = 0, int monitor = -1);
164 const std::set<std::string>& GetSupportedTypes();
165+ std::string GetDesktopID();
166
167
168 glib::Object<BamfApplication> _bamf_app;
169
170=== modified file 'plugins/unityshell/src/HudController.cpp'
171--- plugins/unityshell/src/HudController.cpp 2012-03-21 15:30:49 +0000
172+++ plugins/unityshell/src/HudController.cpp 2012-03-27 22:51:18 +0000
173@@ -40,6 +40,8 @@
174
175 Controller::Controller()
176 : launcher_width(65)
177+ , launcher_locked_out(false)
178+ , multiple_launchers(true)
179 , hud_service_("com.canonical.hud", "/com/canonical/hud")
180 , window_(nullptr)
181 , visible_(false)
182@@ -47,12 +49,11 @@
183 , timeline_id_(0)
184 , last_opacity_(0.0f)
185 , start_time_(0)
186- , launcher_is_locked_out_(false)
187 , view_(nullptr)
188 , monitor_index_(0)
189 {
190 LOG_DEBUG(logger) << "hud startup";
191- SetupRelayoutCallbacks();
192+ UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(); });
193
194 ubus.RegisterInterest(UBUS_HUD_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));
195
196@@ -65,13 +66,13 @@
197 gint32 overlay_monitor = 0;
198 g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING, &overlay_identity, &can_maximise, &overlay_monitor);
199
200- if (g_strcmp0(overlay_identity, "hud"))
201+ if (overlay_identity.Str() != "hud")
202 {
203 HideHud(true);
204 }
205 });
206
207- launcher_width.changed.connect([this] (int new_width) { Relayout(); });
208+ launcher_width.changed.connect([&] (int new_width) { Relayout(); });
209
210 PluginAdapter::Default()->compiz_screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
211
212@@ -120,14 +121,24 @@
213 AddChild(view_);
214 }
215
216-void Controller::SetupRelayoutCallbacks()
217-{
218- GdkScreen* screen = gdk_screen_get_default();
219-
220- sig_manager_.Add(new glib::Signal<void, GdkScreen*>(screen,
221- "monitors-changed", sigc::mem_fun(this, &Controller::Relayout)));
222- sig_manager_.Add(new glib::Signal<void, GdkScreen*>(screen,
223- "size-changed", sigc::mem_fun(this, &Controller::Relayout)));
224+int Controller::GetTargetMonitor()
225+{
226+ return UScreen::GetDefault()->GetMonitorWithMouse();
227+}
228+
229+bool Controller::IsLockedToLauncher(int monitor)
230+{
231+ if (launcher_locked_out)
232+ {
233+ int primary_monitor = UScreen::GetDefault()->GetPrimaryMonitor();
234+
235+ if (multiple_launchers || (!multiple_launchers && primary_monitor == monitor))
236+ {
237+ return true;
238+ }
239+ }
240+
241+ return false;
242 }
243
244 void Controller::EnsureHud()
245@@ -158,30 +169,31 @@
246
247 nux::Geometry Controller::GetIdealWindowGeometry()
248 {
249- UScreen *uscreen = UScreen::GetDefault();
250- int primary_monitor = uscreen->GetMonitorWithMouse();
251- auto monitor_geo = uscreen->GetMonitorGeometry(primary_monitor);
252+ int target_monitor = GetTargetMonitor();
253+ auto monitor_geo = UScreen::GetDefault()->GetMonitorGeometry(target_monitor);
254
255- // We want to cover as much of the screen as possible to grab any mouse events outside
256- // of our window
257+ // We want to cover as much of the screen as possible to grab any mouse events
258+ // outside of our window
259 panel::Style &panel_style = panel::Style::Instance();
260 nux::Geometry geo(monitor_geo.x,
261- monitor_geo.y + panel_style.panel_height,
262- monitor_geo.width,
263- monitor_geo.height - panel_style.panel_height);
264- if (launcher_is_locked_out_)
265+ monitor_geo.y + panel_style.panel_height,
266+ monitor_geo.width,
267+ monitor_geo.height - panel_style.panel_height);
268+
269+ if (IsLockedToLauncher(target_monitor))
270 {
271 geo.x += launcher_width;
272 geo.width -= launcher_width;
273 }
274+
275 return geo;
276 }
277
278-void Controller::Relayout(GdkScreen*screen)
279+void Controller::Relayout()
280 {
281 EnsureHud();
282- nux::Geometry content_geo = view_->GetGeometry();
283- nux::Geometry geo = GetIdealWindowGeometry();
284+ nux::Geometry const& content_geo = view_->GetGeometry();
285+ nux::Geometry const& geo = GetIdealWindowGeometry();
286
287 window_->SetGeometry(geo);
288 layout_->SetMinMaxSize(content_geo.width, content_geo.height);
289@@ -190,7 +202,7 @@
290 }
291
292 void Controller::OnMouseDownOutsideWindow(int x, int y,
293- unsigned long bflags, unsigned long kflags)
294+ unsigned long bflags, unsigned long kflags)
295 {
296 LOG_DEBUG(logger) << "OnMouseDownOutsideWindow called";
297 HideHud();
298@@ -234,16 +246,6 @@
299 return visible_;
300 }
301
302-void Controller::SetLauncherIsLockedOut(bool launcher_is_locked_out)
303-{
304- launcher_is_locked_out_ = launcher_is_locked_out;
305- if (launcher_is_locked_out_)
306- view_->SetHideIcon(IconHideState::HIDE);
307- else
308- view_->SetHideIcon(IconHideState::SHOW);
309- Relayout();
310-}
311-
312 void Controller::ShowHud()
313 {
314 PluginAdapter* adaptor = PluginAdapter::Default();
315@@ -259,6 +261,15 @@
316 return;
317 }
318
319+ unsigned int target_monitor = GetTargetMonitor();
320+
321+ if (target_monitor != monitor_index_)
322+ {
323+ Relayout();
324+ monitor_index_ = target_monitor;
325+ }
326+
327+ view_->ShowEmbeddedIcon(!IsLockedToLauncher(monitor_index_));
328 view_->AboutToShow();
329
330 // we first want to grab the currently active window, luckly we can just ask the jason interface(bamf)
331@@ -289,7 +300,6 @@
332 // hide the launcher
333 GVariant* message_data = g_variant_new("(b)", TRUE);
334 ubus.SendMessage(UBUS_LAUNCHER_LOCK_HIDE, message_data);
335- monitor_index_ = UScreen::GetDefault()->GetMonitorWithMouse();
336 GVariant* info = g_variant_new(UBUS_OVERLAY_FORMAT_STRING, "hud", FALSE, monitor_index_);
337 ubus.SendMessage(UBUS_OVERLAY_SHOWN, info);
338
339@@ -410,7 +420,6 @@
340 ubus.SendMessage(UBUS_HUD_ICON_CHANGED, g_variant_new_string(query->icon_name.c_str()));
341 }
342
343-
344 void Controller::OnQueriesFinished(Hud::Queries queries)
345 {
346 view_->SetQueries(queries);
347@@ -438,7 +447,10 @@
348 void Controller::AddProperties(GVariantBuilder* builder)
349 {
350 variant::BuilderWrapper(builder)
351- .add("visible", visible_);
352+ .add(window_ ? window_->GetGeometry() : nux::Geometry())
353+ .add("visible", visible_)
354+ .add("hud_monitor", monitor_index_)
355+ .add("locked_to_launcher", IsLockedToLauncher(monitor_index_));
356 }
357
358
359
360=== modified file 'plugins/unityshell/src/HudController.h'
361--- plugins/unityshell/src/HudController.h 2012-03-21 15:30:49 +0000
362+++ plugins/unityshell/src/HudController.h 2012-03-27 22:51:18 +0000
363@@ -22,7 +22,6 @@
364 #include <memory>
365
366 #include <gdk/gdk.h>
367-#include <UnityCore/GLibSignal.h>
368 #include <UnityCore/Hud.h>
369
370 #include <NuxCore/Property.h>
371@@ -49,12 +48,13 @@
372 nux::BaseWindow* window() const;
373
374 nux::Property<int> launcher_width;
375+ nux::Property<bool> launcher_locked_out;
376+ nux::Property<bool> multiple_launchers;
377
378 void ShowHideHud();
379 void ShowHud();
380 void HideHud(bool restore_focus = true);
381 bool IsVisible();
382- void SetLauncherIsLockedOut(bool launcher_is_locked_out);
383
384 protected:
385 std::string GetName() const;
386@@ -64,11 +64,13 @@
387 void EnsureHud();
388 void SetupWindow();
389 void SetupHudView();
390- void SetupRelayoutCallbacks();
391 void RegisterUBusInterests();
392
393+ int GetTargetMonitor();
394+ bool IsLockedToLauncher(int monitor);
395+
396 nux::Geometry GetIdealWindowGeometry();
397- void Relayout(GdkScreen*screen=NULL);
398+ void Relayout();
399
400 void OnMouseDownOutsideWindow(int x, int y, unsigned long bflags, unsigned long kflags);
401 void OnScreenUngrabbed();
402@@ -81,8 +83,6 @@
403 void OnQueryActivated(Query::Ptr query);
404 void OnQuerySelected(Query::Ptr query);
405
406-
407-private:
408 void StartShowHideTimeline();
409 static gboolean OnViewShowHideFrame(Controller* self);
410
411@@ -93,7 +93,6 @@
412 private:
413 UBusManager ubus;
414 Hud hud_service_;
415- glib::SignalManager sig_manager_;
416 nux::BaseWindow* window_;
417 bool visible_;
418 bool need_show_;
419@@ -101,8 +100,6 @@
420 guint timeline_id_;
421 float last_opacity_;
422 gint64 start_time_;
423-
424- bool launcher_is_locked_out_;
425
426 View* view_;
427 guint ensure_id_;
428
429=== modified file 'plugins/unityshell/src/HudIcon.cpp'
430--- plugins/unityshell/src/HudIcon.cpp 2012-03-26 22:43:48 +0000
431+++ plugins/unityshell/src/HudIcon.cpp 2012-03-27 22:51:18 +0000
432@@ -42,10 +42,6 @@
433 Init();
434 }
435
436-Icon::~Icon()
437-{
438-}
439-
440 void Icon::Init()
441 {
442 SetMinimumWidth(66);
443@@ -89,6 +85,10 @@
444 icon_renderer_.RenderIcon(GfxContext, arg, toplevel->GetGeometry(), toplevel->GetGeometry());
445 }
446
447+std::string Icon::GetName() const
448+{
449+ return "EmbeddedIcon";
450+}
451
452 }
453 }
454
455=== modified file 'plugins/unityshell/src/HudIcon.h'
456--- plugins/unityshell/src/HudIcon.h 2012-03-26 22:43:48 +0000
457+++ plugins/unityshell/src/HudIcon.h 2012-03-27 22:51:18 +0000
458@@ -53,12 +53,13 @@
459 typedef nux::ObjectPtr<IconTexture> Ptr;
460 Icon(nux::BaseTexture* texture, guint width, guint height);
461 Icon(std::string const& icon_name, unsigned int size, bool defer_icon_loading = false);
462- ~Icon();
463
464 protected:
465 void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
466 void Init();
467
468+ std::string GetName() const;
469+
470 nux::ObjectPtr<nux::BaseTexture> background_;
471 nux::ObjectPtr<nux::BaseTexture> gloss_;
472 nux::ObjectPtr<nux::BaseTexture> edge_;
473
474=== modified file 'plugins/unityshell/src/HudView.cpp'
475--- plugins/unityshell/src/HudView.cpp 2012-03-21 15:07:29 +0000
476+++ plugins/unityshell/src/HudView.cpp 2012-03-27 22:51:18 +0000
477@@ -64,7 +64,7 @@
478 , current_height_(0)
479 , timeline_need_more_draw_(false)
480 , selected_button_(0)
481- , icon_state_(IconHideState::SHOW)
482+ , show_embedded_icon_(true)
483 , activated_signal_sent_(false)
484 {
485 renderer_.SetOwner(this);
486@@ -127,7 +127,6 @@
487
488 View::~View()
489 {
490- RemoveChild(search_bar_.GetPointer());
491 for (auto button = buttons_.begin(); button != buttons_.end(); button++)
492 {
493 RemoveChild((*button).GetPointer());
494@@ -272,22 +271,30 @@
495 void View::SetIcon(std::string icon_name)
496 {
497 LOG_DEBUG(logger) << "Setting icon to " << icon_name;
498- icon_->SetByIconName(icon_name.c_str(), icon_size);
499+ icon_->SetByIconName(icon_name, icon_size);
500 QueueDraw();
501 }
502
503-void View::SetHideIcon(IconHideState hide_icon)
504+void View::ShowEmbeddedIcon(bool show)
505 {
506 LOG_DEBUG(logger) << "Hide icon called";
507- if (hide_icon == icon_state_)
508+ if (show == show_embedded_icon_)
509 return;
510
511- icon_state_ = hide_icon;
512-
513- if (icon_state_ == IconHideState::HIDE)
514- layout_->RemoveChildObject(dynamic_cast<nux::Area*>(icon_layout_.GetPointer()));
515+ show_embedded_icon_ = show;
516+
517+ if (show_embedded_icon_)
518+ {
519+ layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP,
520+ nux::MINOR_SIZE_MATCHCONTENT, 100.0f, nux::LayoutPosition::NUX_LAYOUT_BEGIN);
521+
522+ AddChild(icon_.GetPointer());
523+ }
524 else
525- layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP, nux::MINOR_SIZE_MATCHCONTENT, 100.0f, nux::LayoutPosition::NUX_LAYOUT_BEGIN);
526+ {
527+ layout_->RemoveChildObject(static_cast<nux::Area*>(icon_layout_.GetPointer()));
528+ RemoveChild(icon_.GetPointer());
529+ }
530
531 Relayout();
532 }
533@@ -303,7 +310,7 @@
534 width = 1024;
535 height = 276;
536
537- if (icon_state_ == IconHideState::HIDE)
538+ if (!show_embedded_icon_)
539 {
540 width -= icon_layout_->GetGeometry().width;
541 }
542@@ -351,6 +358,7 @@
543 icon_ = new Icon("", icon_size, true);
544 icon_layout_ = new nux::VLayout();
545 {
546+ AddChild(icon_.GetPointer());
547 icon_layout_->SetVerticalExternalMargin(icon_vertical_margin);
548 icon_layout_->AddView(icon_.GetPointer(), 0, nux::MINOR_POSITION_LEFT, nux::MINOR_SIZE_FULL);
549 layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP, nux::MINOR_SIZE_MATCHCONTENT);
550@@ -491,6 +499,7 @@
551 {
552 unsigned num_buttons = buttons_.size();
553 variant::BuilderWrapper(builder)
554+ .add(GetGeometry())
555 .add("selected_button", selected_button_)
556 .add("num_buttons", num_buttons);
557 }
558
559=== modified file 'plugins/unityshell/src/HudView.h'
560--- plugins/unityshell/src/HudView.h 2012-03-21 14:44:41 +0000
561+++ plugins/unityshell/src/HudView.h 2012-03-27 22:51:18 +0000
562@@ -44,12 +44,6 @@
563 namespace hud
564 {
565
566-enum IconHideState
567-{
568- HIDE,
569- SHOW
570-};
571-
572 class View : public nux::View, public unity::debug::Introspectable
573 {
574 NUX_DECLARE_OBJECT_TYPE(HudView, nux::View);
575@@ -65,7 +59,7 @@
576
577 void SetQueries(Hud::Queries queries);
578 void SetIcon(std::string icon_name);
579- void SetHideIcon(IconHideState hide_icon);
580+ void ShowEmbeddedIcon(bool show);
581
582 void AboutToShow();
583 void AboutToHide();
584@@ -126,7 +120,7 @@
585 int current_height_;
586 bool timeline_need_more_draw_;
587 int selected_button_;
588- IconHideState icon_state_;
589+ bool show_embedded_icon_;
590 bool activated_signal_sent_;
591 };
592
593
594=== modified file 'plugins/unityshell/src/IconTexture.cpp'
595--- plugins/unityshell/src/IconTexture.cpp 2012-03-27 01:38:08 +0000
596+++ plugins/unityshell/src/IconTexture.cpp 2012-03-27 22:51:18 +0000
597@@ -57,44 +57,47 @@
598 }
599
600 IconTexture::IconTexture(std::string const& icon_name, unsigned int size, bool defer_icon_loading)
601- : TextureArea(NUX_TRACKER_LOCATION)
602- , _accept_key_nav_focus(false)
603- , _icon_name(icon_name.empty() ? DEFAULT_ICON : icon_name)
604- , _size(size)
605- , _texture_width(0)
606- , _texture_height(0)
607- , _loading(false)
608- , _opacity(1.0f)
609+ : TextureArea(NUX_TRACKER_LOCATION),
610+ _accept_key_nav_focus(false),
611+ _icon_name(!icon_name.empty() ? icon_name : DEFAULT_ICON),
612+ _size(size),
613+ _texture_width(0),
614+ _texture_height(0),
615+ _loading(false),
616+ _opacity(1.0f)
617 {
618-
619- if (_icon_name != "" && !defer_icon_loading)
620+ if (!defer_icon_loading)
621 LoadIcon();
622 }
623
624+IconTexture::~IconTexture()
625+{}
626+
627 void IconTexture::SetByIconName(std::string const& icon_name, unsigned int size)
628 {
629+ if (_icon_name == icon_name && _size == size)
630+ return;
631+
632 _icon_name = icon_name;
633 _size = size;
634+
635 LoadIcon();
636 }
637
638+
639 void IconTexture::SetByFilePath(std::string const& file_path, unsigned int size)
640 {
641- _icon_name = file_path;
642- _size = size;
643-
644- LoadIcon();
645+ SetByIconName(file_path, size);
646 }
647
648 void IconTexture::LoadIcon()
649 {
650 LOG_DEBUG(logger) << "LoadIcon called (" << _icon_name << ") - loading: " << _loading;
651-static const char* const DEFAULT_GICON = ". GThemedIcon text-x-preview";
652- if (_icon_name.empty())
653- return;
654+ static const char* const DEFAULT_GICON = ". GThemedIcon text-x-preview";
655
656 if (_loading)
657 return;
658+
659 _loading = true;
660
661 glib::Object<GIcon> icon(::g_icon_new_for_string(_icon_name.empty() ? DEFAULT_GICON : _icon_name.c_str(), NULL));
662@@ -231,7 +234,7 @@
663 {
664 unity::variant::BuilderWrapper(builder)
665 .add(GetGeometry())
666- .add("iconname", _icon_name);
667+ .add("icon_name", _icon_name);
668 }
669
670 //
671
672=== modified file 'plugins/unityshell/src/IconTexture.h'
673--- plugins/unityshell/src/IconTexture.h 2012-03-26 22:43:48 +0000
674+++ plugins/unityshell/src/IconTexture.h 2012-03-27 22:51:18 +0000
675@@ -38,6 +38,7 @@
676 public:
677 IconTexture(nux::BaseTexture* texture, guint width, guint height);
678 IconTexture(std::string const& icon_name, unsigned int size, bool defer_icon_loading = false);
679+ virtual ~IconTexture();
680
681 void SetByIconName(std::string const& icon_name, unsigned int size);
682 void SetByFilePath(std::string const& file_path, unsigned int size);
683
684=== modified file 'plugins/unityshell/src/LauncherIcon.cpp'
685--- plugins/unityshell/src/LauncherIcon.cpp 2012-03-26 23:23:42 +0000
686+++ plugins/unityshell/src/LauncherIcon.cpp 2012-03-27 22:51:18 +0000
687@@ -185,18 +185,20 @@
688 LauncherIcon::AddProperties(GVariantBuilder* builder)
689 {
690 unity::variant::BuilderWrapper(builder)
691- .add("x", _center[0].x)
692- .add("y", _center[0].y)
693- .add("z", _center[0].z)
694- .add("related-windows", (int)Windows().size())
695- .add("icon-type", _icon_type)
696- .add("tooltip-text", tooltip_text())
697- .add("sort-priority", _sort_priority)
698- .add("quirk-active", GetQuirk(QUIRK_ACTIVE))
699- .add("quirk-visible", GetQuirk(QUIRK_VISIBLE))
700- .add("quirk-urgent", GetQuirk(QUIRK_URGENT))
701- .add("quirk-running", GetQuirk(QUIRK_RUNNING))
702- .add("quirk-presented", GetQuirk(QUIRK_PRESENTED));
703+ .add("center_x", _center[0].x)
704+ .add("center_y", _center[0].y)
705+ .add("center_z", _center[0].z)
706+ .add("related_windows", static_cast<unsigned int>(Windows().size()))
707+ .add("icon_type", _icon_type)
708+ .add("tooltip_text", tooltip_text())
709+ .add("sort_priority", _sort_priority)
710+ .add("active", GetQuirk(QUIRK_ACTIVE))
711+ .add("visible", GetQuirk(QUIRK_VISIBLE))
712+ .add("urgent", GetQuirk(QUIRK_URGENT))
713+ .add("running", GetQuirk(QUIRK_RUNNING))
714+ .add("starting", GetQuirk(QUIRK_STARTING))
715+ .add("desaturated", GetQuirk(QUIRK_DESAT))
716+ .add("presented", GetQuirk(QUIRK_PRESENTED));
717 }
718
719 void
720
721=== modified file 'plugins/unityshell/src/SimpleLauncherIcon.cpp'
722--- plugins/unityshell/src/SimpleLauncherIcon.cpp 2012-03-14 06:24:18 +0000
723+++ plugins/unityshell/src/SimpleLauncherIcon.cpp 2012-03-27 22:51:18 +0000
724@@ -23,6 +23,7 @@
725 #include <NuxCore/Logger.h>
726 #include <Nux/Nux.h>
727 #include <Nux/BaseWindow.h>
728+#include <UnityCore/Variant.h>
729
730 #include "SimpleLauncherIcon.h"
731 #include "PluginAdapter.h"
732@@ -148,6 +149,12 @@
733 return "SimpleLauncherIcon";
734 }
735
736+void SimpleLauncherIcon::AddProperties(GVariantBuilder* builder)
737+{
738+ LauncherIcon::AddProperties(builder);
739+ variant::BuilderWrapper(builder).add("icon_name", icon_name);
740+}
741+
742 } // namespace launcher
743 } // namespace unity
744
745
746=== modified file 'plugins/unityshell/src/SimpleLauncherIcon.h'
747--- plugins/unityshell/src/SimpleLauncherIcon.h 2012-03-14 06:24:18 +0000
748+++ plugins/unityshell/src/SimpleLauncherIcon.h 2012-03-27 22:51:18 +0000
749@@ -47,6 +47,8 @@
750
751 protected:
752 std::string GetName() const;
753+ void AddProperties(GVariantBuilder* builder);
754+
755 virtual void OnMouseDown(int button, int monitor);
756 virtual void OnMouseUp(int button, int monitor);
757 virtual void OnMouseClick(int button, int monitor);
758
759=== modified file 'plugins/unityshell/src/unityshell.cpp'
760--- plugins/unityshell/src/unityshell.cpp 2012-03-26 21:52:33 +0000
761+++ plugins/unityshell/src/unityshell.cpp 2012-03-27 22:51:18 +0000
762@@ -2520,6 +2520,7 @@
763 case UnityshellOptions::NumLaunchers:
764 launcher_controller_->multiple_launchers = optionGetNumLaunchers() == 0;
765 dash_controller_->use_primary = !launcher_controller_->multiple_launchers();
766+ hud_controller_->multiple_launchers = launcher_controller_->multiple_launchers();
767 break;
768 case UnityshellOptions::LauncherCaptureMouse:
769 launcher_options->edge_resist = optionGetLauncherCaptureMouse();
770@@ -2540,7 +2541,7 @@
771 case UnityshellOptions::LauncherHideMode:
772 {
773 launcher_options->hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
774- hud_controller_->SetLauncherIsLockedOut(launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
775+ hud_controller_->launcher_locked_out = (launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
776 break;
777 }
778 case UnityshellOptions::BacklightMode:
779@@ -2775,7 +2776,8 @@
780 /* Setup Hud */
781 hud_controller_.reset(new hud::Controller());
782 auto hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
783- hud_controller_->SetLauncherIsLockedOut(hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
784+ hud_controller_->launcher_locked_out = (hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
785+ hud_controller_->multiple_launchers = (optionGetNumLaunchers() == 0);
786 AddChild(hud_controller_.get());
787 LOG_INFO(logger) << "initLauncher-hud " << timer.ElapsedSeconds() << "s";
788
789
790=== modified file 'tests/autopilot/autopilot/emulators/X11.py'
791--- tests/autopilot/autopilot/emulators/X11.py 2012-03-25 20:50:33 +0000
792+++ tests/autopilot/autopilot/emulators/X11.py 2012-03-27 22:51:18 +0000
793@@ -360,10 +360,20 @@
794 Returns a tuple containing (x,y,width,height).
795
796 """
797- if monitor_number >= self.get_num_monitors():
798+ if monitor_number < 0 or monitor_number >= self.get_num_monitors():
799 raise ValueError('Specified monitor number is out of range.')
800 return tuple(self._default_screen.get_monitor_geometry(monitor_number))
801
802+ def is_rect_on_monitor(self, monitor_number, rect):
803+ """Returns True if `rect` is _entirely_ on the specified monitor, with no overlap."""
804+
805+ if type(rect) is not tuple or len(rect) != 4:
806+ raise TypeError("rect must be a tuple of 4 int elements.")
807+
808+ (x, y, w, h) = rect
809+ (m_x, m_y, m_w, m_h) = self.get_monitor_geometry(monitor_number)
810+ return (x >= m_x and x + w <= m_x + m_w and y >= m_y and y + h <= m_y + m_h)
811+
812 def move_mouse_to_monitor(self, monitor_number):
813 """Move the mouse to the center of the specified monitor."""
814 geo = self.get_monitor_geometry(monitor_number)
815
816=== modified file 'tests/autopilot/autopilot/emulators/bamf.py'
817--- tests/autopilot/autopilot/emulators/bamf.py 2012-03-20 00:21:52 +0000
818+++ tests/autopilot/autopilot/emulators/bamf.py 2012-03-27 22:51:18 +0000
819@@ -184,6 +184,11 @@
820 return self._view_iface.Name()
821
822 @property
823+ def icon(self):
824+ """Get the application icon."""
825+ return self._view_iface.Icon()
826+
827+ @property
828 def is_active(self):
829 """Is the application active (i.e.- has keyboard focus)?"""
830 return self._view_iface.IsActive()
831
832=== modified file 'tests/autopilot/autopilot/emulators/unity/hud.py'
833--- tests/autopilot/autopilot/emulators/unity/hud.py 2012-03-04 23:12:19 +0000
834+++ tests/autopilot/autopilot/emulators/unity/hud.py 2012-03-27 22:51:18 +0000
835@@ -14,6 +14,16 @@
836 class HudView(UnityIntrospectionObject):
837 """Proxy object for the hud view child of the controller."""
838
839+ @property
840+ def geometry(self):
841+ return (self.x, self.y, self.width, self.height)
842+
843+class EmbeddedIcon(UnityIntrospectionObject):
844+ """Proxy object for the hud embedded icon child of the view."""
845+
846+ @property
847+ def geometry(self):
848+ return (self.x, self.y, self.width, self.height)
849
850 class HudController(UnityIntrospectionObject, KeybindingsHelper):
851 """Proxy object for the Unity Hud Controller."""
852@@ -35,11 +45,24 @@
853 """Tap the 'Alt' key to toggle the hud visibility."""
854 self.keybinding("hud/reveal", tap_delay)
855
856+ def get_embedded_icon(self):
857+ """Returns the HUD view embedded icon or None if is not shown."""
858+ view = self._get_view()
859+ if (not view):
860+ return None
861+
862+ icons = view.get_children_by_type(EmbeddedIcon)
863+ return icons[0] if icons else None
864+
865 def _get_view(self):
866 views = self.get_children_by_type(HudView)
867 return views[0] if views else None
868
869 @property
870+ def geometry(self):
871+ return (self.x, self.y, self.width, self.height)
872+
873+ @property
874 def selected_button(self):
875 view = self._get_view()
876 if view:
877@@ -54,3 +77,15 @@
878 return view.num_buttons
879 else:
880 return 0
881+
882+ @property
883+ def is_locked_to_launcher(self):
884+ return bool(self.locked_to_launcher)
885+
886+ @property
887+ def monitor(self):
888+ return int(self.hud_monitor)
889+
890+ @property
891+ def has_embedded_icon(self):
892+ return (self.get_embedded_icon() != None)
893
894=== modified file 'tests/autopilot/autopilot/emulators/unity/icons.py'
895--- tests/autopilot/autopilot/emulators/unity/icons.py 2012-03-04 23:12:19 +0000
896+++ tests/autopilot/autopilot/emulators/unity/icons.py 2012-03-27 22:51:18 +0000
897@@ -19,6 +19,11 @@
898
899 """
900
901+ @property
902+ def center_position(self):
903+ """Get the center point of an icon, returns a tuple with (x, y, z)"""
904+ return (self.center_x, self.center_y, self.center_z)
905+
906 def get_quicklist(self):
907 """Get the quicklist for this launcher icon.
908
909@@ -34,6 +39,10 @@
910 """Represents the BFB button in the launcher."""
911
912
913+class HudLauncherIcon(SimpleLauncherIcon):
914+ """Represents the HUD button in the launcher."""
915+
916+
917 class BamfLauncherIcon(SimpleLauncherIcon):
918 """Represents a launcher icon with BAMF integration."""
919
920
921=== modified file 'tests/autopilot/autopilot/emulators/unity/launcher.py'
922--- tests/autopilot/autopilot/emulators/unity/launcher.py 2012-03-25 21:25:54 +0000
923+++ tests/autopilot/autopilot/emulators/unity/launcher.py 2012-03-27 22:51:18 +0000
924@@ -12,7 +12,7 @@
925
926 from autopilot.keybindings import KeybindingsHelper
927 from autopilot.emulators.unity import UnityIntrospectionObject
928-from autopilot.emulators.unity.icons import BamfLauncherIcon, SimpleLauncherIcon
929+from autopilot.emulators.unity.icons import BFBLauncherIcon, BamfLauncherIcon, SimpleLauncherIcon
930 from autopilot.emulators.X11 import Mouse, ScreenGeometry
931
932
933@@ -200,8 +200,8 @@
934 logger.debug("Clicking launcher icon %r on monitor %d with mouse button %d",
935 icon, self.monitor, button)
936 self.mouse_reveal_launcher()
937- target_x = icon.x + self.x
938- target_y = icon.y + (self.icon_size / 2)
939+ target_x = icon.center_x + self.x
940+ target_y = icon.center_y
941 self._mouse.move(target_x, target_y )
942 self._mouse.click(button)
943 self.move_mouse_to_right_of_launcher()
944@@ -258,10 +258,15 @@
945 class LauncherModel(UnityIntrospectionObject):
946 """THe launcher model. Contains all launcher icons as children."""
947
948+ def get_bfb_icon(self):
949+ icons = BFBLauncherIcon.get_all_instances()
950+ assert(len(icons) == 1)
951+ return icons[0]
952+
953 def get_launcher_icons(self, visible_only=True):
954 """Get a list of launcher icons in this launcher."""
955 if visible_only:
956- return self.get_children_by_type(SimpleLauncherIcon, quirk_visible=True)
957+ return self.get_children_by_type(SimpleLauncherIcon, visible=True)
958 else:
959 return self.get_children_by_type(SimpleLauncherIcon)
960
961@@ -281,7 +286,21 @@
962 Returns None if there is no such launcher icon.
963 """
964 icons = self.get_children_by_type(SimpleLauncherIcon, desktop_file=desktop_file)
965- return icons or None
966+ if len(icons):
967+ return icons[0]
968+
969+ return None
970+
971+ def get_icon_by_desktop_id(self, desktop_id):
972+ """Gets a launcher icon with the specified desktop id.
973+
974+ Returns None if there is no such launcher icon.
975+ """
976+ icons = self.get_children_by_type(SimpleLauncherIcon, desktop_id=desktop_id)
977+ if len(icons):
978+ return icons[0]
979+
980+ return None
981
982 def num_launcher_icons(self):
983 """Get the number of icons in the launcher model."""
984
985=== modified file 'tests/autopilot/autopilot/emulators/unity/switcher.py'
986--- tests/autopilot/autopilot/emulators/unity/switcher.py 2012-03-07 17:24:15 +0000
987+++ tests/autopilot/autopilot/emulators/unity/switcher.py 2012-03-27 22:51:18 +0000
988@@ -136,11 +136,11 @@
989 return None
990
991 def get_icon_name(self, index):
992- return self.__get_icon(index)['tooltip-text']
993+ return self.__get_icon(index)['tooltip_text']
994
995 def get_icon_desktop_file(self, index):
996 try:
997- return self.__get_icon(index)['desktop-file']
998+ return self.__get_icon(index)['desktop_file']
999 except:
1000 return None
1001
1002
1003=== modified file 'tests/autopilot/autopilot/tests/__init__.py'
1004--- tests/autopilot/autopilot/tests/__init__.py 2012-03-27 20:48:14 +0000
1005+++ tests/autopilot/autopilot/tests/__init__.py 2012-03-27 22:51:18 +0000
1006@@ -25,7 +25,7 @@
1007 from autopilot.emulators.unity.launcher import LauncherController
1008 from autopilot.emulators.unity.switcher import Switcher
1009 from autopilot.emulators.unity.workspace import WorkspaceManager
1010-from autopilot.emulators.X11 import Keyboard, Mouse
1011+from autopilot.emulators.X11 import ScreenGeometry, Keyboard, Mouse
1012 from autopilot.glibrunner import GlibRunner
1013 from autopilot.globals import (global_context,
1014 video_recording_enabled,
1015@@ -229,17 +229,25 @@
1016 self.dash = Dash()
1017 self.switcher = Switcher()
1018 self.workspace = WorkspaceManager()
1019+ self.screen_geo = ScreenGeometry()
1020 self.launcher = self._get_launcher_controller()
1021 self.addCleanup(self.workspace.switch_to, self.workspace.current_workspace)
1022 self.addCleanup(Keyboard.cleanup)
1023 self.addCleanup(Mouse.cleanup)
1024
1025- def start_app(self, app_name, files=[]):
1026+ def start_app(self, app_name, files=[], locale=None):
1027 """Start one of the known apps, and kill it on tear down.
1028
1029- if files is specified, start the application with the specified files.
1030+ If files is specified, start the application with the specified files.
1031+ If locale is specified, the locale will be set when the application is launched.
1032 """
1033- logger.info("Starting application '%s'", app_name)
1034+ if locale:
1035+ os.putenv("LC_ALL", locale)
1036+ self.addCleanup(os.unsetenv, "LC_ALL")
1037+ logger.info("Starting application '%s' with files %r in locale %s", app_name, files, locale)
1038+ else:
1039+ logger.info("Starting application '%s' with files %r", app_name, files)
1040+
1041 app = self.KNOWN_APPS[app_name]
1042 self.bamf.launch_application(app['desktop-file'], files)
1043 self.addCleanup(call, ["killall", app['process-name']])
1044
1045=== modified file 'tests/autopilot/autopilot/tests/test_hud.py'
1046--- tests/autopilot/autopilot/tests/test_hud.py 2012-03-21 14:44:41 +0000
1047+++ tests/autopilot/autopilot/tests/test_hud.py 2012-03-27 22:51:18 +0000
1048@@ -1,58 +1,81 @@
1049 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1050-# Copyright 2010 Canonical
1051-# Author: Alex Launi
1052+# Copyright 2012 Canonical
1053+# Author: Alex Launi,
1054+# Marco Trevisan
1055 #
1056 # This program is free software: you can redistribute it and/or modify it
1057 # under the terms of the GNU General Public License version 3, as published
1058 # by the Free Software Foundation.
1059
1060-from testtools.matchers import Equals, LessThan
1061+from testtools.matchers import Equals, NotEquals, LessThan, GreaterThan
1062 from time import sleep
1063
1064+from autopilot.emulators.X11 import ScreenGeometry
1065 from autopilot.emulators.unity.hud import HudController
1066-from autopilot.tests import AutopilotTestCase
1067+from autopilot.emulators.unity.icons import HudLauncherIcon
1068+from autopilot.tests import AutopilotTestCase, multiply_scenarios
1069 from os import remove
1070
1071-class HudTests(AutopilotTestCase):
1072-
1073- scenarios = [
1074- ('Launcher never hide', {'launcher_hide_mode': 0}),
1075- ('Launcher autohide', {'launcher_hide_mode': 1}),
1076- ]
1077+def _make_monitor_scenarios():
1078+ num_monitors = ScreenGeometry().get_num_monitors()
1079+ scenarios = []
1080+
1081+ if num_monitors == 1:
1082+ scenarios = [('Single Monitor', {'hud_monitor': 0})]
1083+
1084+ else:
1085+ for i in range(num_monitors):
1086+ scenarios += [('Monitor %d' % (i), {'hud_monitor': i})]
1087+
1088+ return scenarios
1089+
1090+class HudTestsBase(AutopilotTestCase):
1091
1092 def setUp(self):
1093- super(HudTests, self).setUp()
1094- self.set_unity_option('launcher_hide_mode', self.launcher_hide_mode)
1095- sleep(0.5)
1096+ super(HudTestsBase, self).setUp()
1097+
1098+ sleep(0.25)
1099 self.hud = self.get_hud_controller()
1100
1101 def tearDown(self):
1102 self.hud.ensure_hidden()
1103- super(HudTests, self).tearDown()
1104+ super(HudTestsBase, self).tearDown()
1105
1106 def get_hud_controller(self):
1107 controllers = HudController.get_all_instances()
1108 self.assertEqual(1, len(controllers))
1109 return controllers[0]
1110
1111+ def get_hud_launcher_icon(self):
1112+ icons = HudLauncherIcon.get_all_instances()
1113+ self.assertEqual(1, len(icons))
1114+ return icons[0]
1115+
1116 def get_num_active_launcher_icons(self):
1117 num_active = 0
1118 for icon in self.launcher.model.get_launcher_icons():
1119- if icon.quirk_active and icon.quirk_visible:
1120+ if icon.active and icon.visible:
1121 num_active += 1
1122 return num_active
1123
1124- def test_initially_hidden(self):
1125- self.assertFalse(self.hud.visible)
1126-
1127 def reveal_hud(self):
1128 self.hud.toggle_reveal()
1129 for counter in range(10):
1130 sleep(1)
1131 if self.hud.visible:
1132 break
1133+
1134 self.assertTrue(self.hud.visible, "HUD did not appear.")
1135
1136+
1137+class HudBehaviorTests(HudTestsBase):
1138+
1139+ def setUp(self):
1140+ super(HudBehaviorTests, self).setUp()
1141+
1142+ self.hud_monitor = self.screen_geo.get_primary_monitor()
1143+ self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
1144+
1145 def test_no_initial_values(self):
1146 self.reveal_hud()
1147 self.assertThat(self.hud.num_buttons, Equals(0))
1148@@ -121,36 +144,6 @@
1149 sleep(1)
1150 self.assertFalse(self.hud.visible)
1151
1152- def test_multiple_hud_reveal_does_not_break_launcher(self):
1153- """Multiple Hud reveals must not cause the launcher to set multiple
1154- apps as active.
1155-
1156- """
1157- # We need an app to switch to:
1158- self.start_app('Character Map')
1159- # We need an application to play with - I'll use the calculator.
1160- self.start_app('Calculator')
1161- sleep(1)
1162-
1163- # before we start, make sure there's zero or one active icon:
1164- num_active = self.get_num_active_launcher_icons()
1165- self.assertThat(num_active, LessThan(2), "Invalid number of launcher icons active before test has run!")
1166-
1167- # reveal and hide hud several times over:
1168- for i in range(3):
1169- self.hud.ensure_visible()
1170- sleep(0.5)
1171- self.hud.ensure_hidden()
1172- sleep(0.5)
1173-
1174- # click application icons for running apps in the launcher:
1175- icon = self.launcher.model.get_icon_by_tooltip_text("Character Map")
1176- self.launcher.get_launcher_for_monitor(0).click_launcher_icon(icon)
1177-
1178- # see how many apps are marked as being active:
1179- num_active = self.get_num_active_launcher_icons()
1180- self.assertLessEqual(num_active, 1, "More than one launcher icon active after test has run!")
1181-
1182 def test_restore_focus(self):
1183 """Ensures that once the hud is dismissed, the same application
1184 that was focused before hud invocation is refocused
1185@@ -191,7 +184,7 @@
1186 """Read the saved file. The content should be "0 "."""
1187
1188 self.addCleanup(remove, '/tmp/autopilot_gedit_undo_test_temp_file.txt')
1189- self.start_app('Text Editor', files=['/tmp/autopilot_gedit_undo_test_temp_file.txt'])
1190+ self.start_app('Text Editor', files=['/tmp/autopilot_gedit_undo_test_temp_file.txt'], locale='C')
1191
1192 sleep(1)
1193 self.keyboard.type("0")
1194@@ -202,8 +195,9 @@
1195 sleep(1)
1196
1197 self.keyboard.type("undo")
1198+ sleep(1)
1199 self.keyboard.press_and_release('Return')
1200- sleep(1)
1201+ sleep(.5)
1202
1203 self.keyboard.press_and_release("Ctrl+s")
1204 sleep(1)
1205@@ -211,3 +205,199 @@
1206 contents = open("/tmp/autopilot_gedit_undo_test_temp_file.txt").read().strip('\n')
1207 self.assertEqual("0 ", contents)
1208
1209+
1210+class HudLauncherInteractionsTests(HudTestsBase):
1211+
1212+ launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
1213+ ('Launcher never hide', {'launcher_autohide': True})]
1214+
1215+ scenarios = multiply_scenarios(_make_monitor_scenarios(), launcher_modes)
1216+
1217+ def setUp(self):
1218+ super(HudLauncherInteractionsTests, self).setUp()
1219+ # Launchers on all monitors
1220+ self.set_unity_option('num_launchers', 0)
1221+ self.set_unity_option('launcher_hide_mode', int(self.launcher_autohide))
1222+
1223+ self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
1224+ sleep(0.5)
1225+
1226+ def test_multiple_hud_reveal_does_not_break_launcher(self):
1227+ """Multiple Hud reveals must not cause the launcher to set multiple
1228+ apps as active.
1229+
1230+ """
1231+ launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
1232+
1233+ # We need an app to switch to:
1234+ self.start_app('Character Map')
1235+ # We need an application to play with - I'll use the calculator.
1236+ self.start_app('Calculator')
1237+ sleep(1)
1238+
1239+ # before we start, make sure there's zero or one active icon:
1240+ num_active = self.get_num_active_launcher_icons()
1241+ self.assertThat(num_active, LessThan(2), "Invalid number of launcher icons active before test has run!")
1242+
1243+ # reveal and hide hud several times over:
1244+ for i in range(3):
1245+ self.hud.ensure_visible()
1246+ sleep(0.5)
1247+ self.hud.ensure_hidden()
1248+ sleep(0.5)
1249+
1250+ # click application icons for running apps in the launcher:
1251+ icon = self.launcher.model.get_icon_by_desktop_id("gucharmap.desktop")
1252+ launcher.click_launcher_icon(icon)
1253+
1254+ # see how many apps are marked as being active:
1255+ num_active = self.get_num_active_launcher_icons()
1256+ self.assertLessEqual(num_active, 1, "More than one launcher icon active after test has run!")
1257+
1258+ def test_hud_does_not_change_launcher_status(self):
1259+ """Tests if the HUD reveal keeps the launcher in the status it was"""
1260+
1261+ launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
1262+
1263+ launcher_shows_pre = launcher.is_showing()
1264+ sleep(.25)
1265+
1266+ self.reveal_hud()
1267+ sleep(1)
1268+
1269+ launcher_shows_post = launcher.is_showing()
1270+ self.assertThat(launcher_shows_pre, Equals(launcher_shows_post))
1271+
1272+
1273+class HudLockedLauncherInteractionsTests(HudTestsBase):
1274+
1275+ scenarios = _make_monitor_scenarios()
1276+
1277+ def setUp(self):
1278+ super(HudLockedLauncherInteractionsTests, self).setUp()
1279+ # Locked Launchers on all monitors
1280+ self.set_unity_option('num_launchers', 0)
1281+ self.set_unity_option('launcher_hide_mode', 0)
1282+
1283+ self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
1284+ sleep(0.5)
1285+
1286+ def test_hud_launcher_icon_hides_bfb(self):
1287+ """Tests that the BFB icon is hidden when the HUD launcher icon is shown"""
1288+
1289+ hud_icon = self.get_hud_launcher_icon()
1290+ bfb_icon = self.launcher.model.get_bfb_icon()
1291+
1292+ self.assertTrue(bfb_icon.visible)
1293+ self.assertFalse(hud_icon.visible)
1294+ sleep(.25)
1295+
1296+ self.reveal_hud()
1297+ sleep(.5)
1298+
1299+ self.assertTrue(hud_icon.visible)
1300+ self.assertFalse(bfb_icon.visible)
1301+
1302+ def test_hud_desaturates_launcher_icons(self):
1303+ """Tests that the launcher icons are desaturates when HUD is open"""
1304+
1305+ self.reveal_hud()
1306+ sleep(.5)
1307+
1308+ for icon in self.launcher.model.get_launcher_icons():
1309+ if isinstance(icon, HudLauncherIcon):
1310+ self.assertFalse(icon.desaturated)
1311+ else:
1312+ self.assertTrue(icon.desaturated)
1313+
1314+
1315+class HudVisualTests(HudTestsBase):
1316+
1317+ launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
1318+ ('Launcher never hide', {'launcher_autohide': True})]
1319+
1320+ launcher_screen = [('Launcher on primary monitor', {'launcher_primary_only': False}),
1321+ ('Launcher on all monitors', {'launcher_primary_only': True})]
1322+
1323+ scenarios = multiply_scenarios(_make_monitor_scenarios(), launcher_modes, launcher_screen)
1324+
1325+ def setUp(self):
1326+ super(HudVisualTests, self).setUp()
1327+ self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
1328+ self.set_unity_option('launcher_hide_mode', int(self.launcher_autohide))
1329+ self.set_unity_option('num_launchers', int(self.launcher_primary_only))
1330+ self.hud_monitor_is_primary = (self.screen_geo.get_primary_monitor() == self.hud_monitor)
1331+ self.hud_locked = (not self.launcher_autohide and (not self.launcher_primary_only or self.hud_monitor_is_primary))
1332+ sleep(0.5)
1333+
1334+ def test_initially_hidden(self):
1335+ self.assertFalse(self.hud.visible)
1336+
1337+ def test_hud_is_on_right_monitor(self):
1338+ """Tests if the hud is shown and fits the monitor where it should be"""
1339+ self.reveal_hud()
1340+ self.assertThat(self.hud_monitor, Equals(self.hud.monitor))
1341+ self.assertTrue(self.screen_geo.is_rect_on_monitor(self.hud.monitor, self.hud.geometry))
1342+
1343+ def test_hud_geometries(self):
1344+ """Tests the HUD geometries for the given monitor and status"""
1345+ self.reveal_hud()
1346+ monitor_geo = self.screen_geo.get_monitor_geometry(self.hud_monitor)
1347+ monitor_x = monitor_geo[0]
1348+ monitor_w = monitor_geo[2]
1349+ hud_x = self.hud.geometry[0]
1350+ hud_w = self.hud.geometry[2]
1351+
1352+ if self.hud_locked:
1353+ self.assertThat(hud_x, GreaterThan(monitor_x))
1354+ self.assertThat(hud_x, LessThan(monitor_x + monitor_w))
1355+ self.assertThat(hud_w, Equals(monitor_x + monitor_w - hud_x))
1356+ else:
1357+ self.assertThat(hud_x, Equals(monitor_x))
1358+ self.assertThat(hud_w, Equals(monitor_w))
1359+
1360+ def test_hud_is_locked_to_launcher(self):
1361+ """Tests if the HUD is locked to launcher as we expect or not"""
1362+ self.reveal_hud()
1363+ sleep(.25)
1364+
1365+ self.assertThat(self.hud.is_locked_to_launcher, Equals(self.hud_locked))
1366+
1367+ def test_hud_icon_is_shown(self):
1368+ """Tests that the correct HUD icon is shown"""
1369+ self.reveal_hud()
1370+ sleep(.5)
1371+
1372+ hud_launcher_icon = self.get_hud_launcher_icon()
1373+ hud_embedded_icon = self.hud.get_embedded_icon()
1374+
1375+ # FIXME this should check self.hud.is_locked_to_launcher
1376+ # but the HUD icon is currently shared between launchers.
1377+ if not self.launcher_autohide:
1378+ self.assertTrue(hud_launcher_icon.visible)
1379+ self.assertFalse(hud_launcher_icon.desaturated)
1380+
1381+ # FIXME remove this once the issue above has been resolved
1382+ if self.hud.is_locked_to_launcher:
1383+ self.assertThat(hud_embedded_icon, Equals(None))
1384+ else:
1385+ self.assertThat(hud_embedded_icon, NotEquals(None))
1386+ self.assertFalse(hud_launcher_icon.visible)
1387+
1388+ def test_hud_icon_show_the_focused_application_emblem(self):
1389+ """Tests that the correct HUD icon is shown"""
1390+ self.start_app("Calculator")
1391+ calctools = self.get_app_instances("Calculator")
1392+ self.assertThat(len(calctools), GreaterThan(0))
1393+ calc = calctools[0]
1394+ self.assertTrue(calc.is_active)
1395+
1396+ self.reveal_hud()
1397+ sleep(.5)
1398+
1399+ if self.hud.is_locked_to_launcher:
1400+ hud_launcher_icon = self.get_hud_launcher_icon()
1401+ self.assertThat(hud_launcher_icon.icon_name, Equals(calc.icon))
1402+ else:
1403+ hud_embedded_icon = self.hud.get_embedded_icon()
1404+ self.assertThat(hud_embedded_icon.icon_name, Equals(calc.icon))
1405
1406=== modified file 'tests/autopilot/autopilot/tests/test_launcher.py'
1407--- tests/autopilot/autopilot/tests/test_launcher.py 2012-03-27 20:48:14 +0000
1408+++ tests/autopilot/autopilot/tests/test_launcher.py 2012-03-27 22:51:18 +0000
1409@@ -534,9 +534,8 @@
1410 def test_launcher_does_not_reveal_with_mouse_down(self):
1411 """Launcher must not reveal if have mouse button 1 down."""
1412 launcher_instance = self.get_launcher()
1413- screens = ScreenGeometry()
1414
1415- screens.move_mouse_to_monitor(launcher_instance.monitor)
1416+ self.screen_geo.move_mouse_to_monitor(launcher_instance.monitor)
1417 self.mouse.press(1)
1418 launcher_instance.mouse_reveal_launcher()
1419 self.assertThat(launcher_instance.is_showing(), Equals(False))
1420
1421=== modified file 'tests/autopilot/autopilot/tests/test_shortcut_hint.py'
1422--- tests/autopilot/autopilot/tests/test_shortcut_hint.py 2012-03-21 22:32:36 +0000
1423+++ tests/autopilot/autopilot/tests/test_shortcut_hint.py 2012-03-27 22:51:18 +0000
1424@@ -29,9 +29,8 @@
1425 sleep(1)
1426
1427 def skip_if_monitor_too_small(self):
1428- screen = ScreenGeometry();
1429- monitor = screen.get_primary_monitor()
1430- monitor_geo = screen.get_monitor_geometry(monitor);
1431+ monitor = self.screen_geo.get_primary_monitor()
1432+ monitor_geo = self.screen_geo.get_monitor_geometry(monitor);
1433 monitor_w = monitor_geo[2];
1434 monitor_h = monitor_geo[3];
1435 launcher_width = self.launcher.get_launcher_for_monitor(monitor).geometry[2];
1436@@ -49,8 +48,7 @@
1437 def get_launcher(self):
1438 # We could parameterise this so all tests run on both monitors (if MM is
1439 # set up), but I think it's fine to just always use monitor primary monitor:
1440- screen = ScreenGeometry();
1441- monitor = screen.get_primary_monitor()
1442+ monitor = self.screen_geo.get_primary_monitor()
1443 return self.launcher.get_launcher_for_monitor(monitor)
1444
1445
1446
1447=== modified file 'tests/autopilot/autopilot/tests/test_showdesktop.py'
1448--- tests/autopilot/autopilot/tests/test_showdesktop.py 2012-03-12 04:06:44 +0000
1449+++ tests/autopilot/autopilot/tests/test_showdesktop.py 2012-03-27 22:51:18 +0000
1450@@ -9,6 +9,7 @@
1451 from time import sleep
1452
1453 from autopilot.emulators.unity.switcher import Switcher
1454+from autopilot.emulators.unity.icons import DesktopLauncherIcon
1455 from autopilot.tests import AutopilotTestCase
1456
1457
1458@@ -23,8 +24,8 @@
1459
1460 def launch_test_apps(self):
1461 """Launch character map and calculator apps."""
1462- self.start_app('Character Map')
1463- self.start_app('Calculator')
1464+ self.start_app('Character Map', locale='C')
1465+ self.start_app('Calculator', locale='C')
1466 sleep(1)
1467
1468 def test_showdesktop_hides_apps(self):
1469@@ -75,7 +76,7 @@
1470 self.assertTrue(win.is_hidden, "Window '%s' is not hidden after show desktop activated." % (win.title))
1471
1472 # We'll un-minimise the character map - find it's launcherIcon in the launcher:
1473- charmap_icon = self.launcher.model.get_icon_by_tooltip_text('Character Map')
1474+ charmap_icon = self.launcher.model.get_icon_by_desktop_id("gucharmap.desktop")
1475 if charmap_icon:
1476 self.launcher.get_launcher_for_monitor(0).click_launcher_icon(charmap_icon)
1477 else:
1478@@ -108,7 +109,7 @@
1479 for i in range(switcher.get_model_size()):
1480 current_icon = switcher.current_icon
1481 self.assertIsNotNone(current_icon)
1482- if current_icon.tooltip_text == 'Show Desktop':
1483+ if isinstance(current_icon, DesktopLauncherIcon):
1484 found = True
1485 break
1486 switcher.previous_icon()
1487
1488=== modified file 'tests/autopilot/autopilot/tests/test_switcher.py'
1489--- tests/autopilot/autopilot/tests/test_switcher.py 2012-03-14 06:24:18 +0000
1490+++ tests/autopilot/autopilot/tests/test_switcher.py 2012-03-27 22:51:18 +0000
1491@@ -292,6 +292,11 @@
1492 class SwitcherWorkspaceTests(AutopilotTestCase):
1493 """Test Switcher behavior with respect to multiple workspaces."""
1494
1495+ def get_bamf_application(self, name):
1496+ apps = self.get_app_instances(name)
1497+ self.assertThat(len(apps), Equals(1))
1498+ return apps[0]
1499+
1500 def test_switcher_shows_current_workspace_only(self):
1501 """Switcher must show apps from the current workspace only."""
1502 self.close_all_app('Calculator')
1503@@ -308,8 +313,8 @@
1504 sleep(1)
1505 icon_names = [i.tooltip_text for i in self.switcher.get_switcher_icons()]
1506 self.switcher.terminate()
1507- self.assertThat(icon_names, Contains("Character Map"))
1508- self.assertThat(icon_names, Not(Contains("Calculator")))
1509+ self.assertThat(icon_names, Contains(self.get_bamf_application("Character Map").name))
1510+ self.assertThat(icon_names, Not(Contains(self.get_bamf_application("Calculator").name)))
1511
1512 def test_switcher_all_mode_shows_all_apps(self):
1513 """Test switcher 'show_all' mode shows apps from all workspaces."""
1514@@ -327,8 +332,8 @@
1515 sleep(1)
1516 icon_names = [i.tooltip_text for i in self.switcher.get_switcher_icons()]
1517 self.switcher.terminate()
1518- self.assertThat(icon_names, Contains("Character Map"))
1519- self.assertThat(icon_names, Contains("Calculator"))
1520+ self.assertThat(icon_names, Contains(self.get_bamf_application("Calculator").name))
1521+ self.assertThat(icon_names, Contains(self.get_bamf_application("Character Map").name))
1522
1523 def test_switcher_can_switch_to_minimised_window(self):
1524 """Switcher must be able to switch to a minimised window when there's
1525@@ -353,16 +358,14 @@
1526
1527 self.switcher.initiate()
1528 sleep(1)
1529- while self.switcher.current_icon.tooltip_text != 'Mahjongg':
1530+ while self.switcher.current_icon.tooltip_text != self.get_bamf_application("Mahjongg").name:
1531 self.switcher.next_icon()
1532 sleep(1)
1533 self.switcher.stop()
1534 sleep(1)
1535
1536- #get calculator windows - there should be only one:
1537- mahjongg_apps = self.get_app_instances("Mahjongg")
1538- self.assertThat(len(mahjongg_apps), Equals(1))
1539- wins = mahjongg_apps[0].get_windows()
1540+ #get mahjongg windows - there should be two:
1541+ wins = self.get_bamf_application("Mahjongg").get_windows()
1542 self.assertThat(len(wins), Equals(2))
1543 # Ideally we should be able to find the instance that is on the
1544 # current workspace and ask that one if it is hidden.