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

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

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

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'manual-tests/Hud.txt'
--- manual-tests/Hud.txt 2012-03-26 21:04:10 +0000
+++ manual-tests/Hud.txt 2012-03-27 22:51:18 +0000
@@ -49,22 +49,6 @@
49 After pressing escape in step three, the text "test" should be removed from the hud search49 After pressing escape in step three, the text "test" should be removed from the hud search
50 After step four, the hud should dismiss itself and not be present.50 After step four, the hud should dismiss itself and not be present.
5151
52Hud Reveal Behaviour
53---------
54This test ensures that the hud behaves correctly with a locked out launcher
55
56Setup:
57#. Ensure the launchers hide mode is set to "Never"
58
59Action:
60#. Tap Alt
61
62Outcome:
63 The Launcher should stick be locked out.
64 The Launcher icons should be desaturated.
65 The top most Launcher icon should be an icon related the the focused window
66 The BFB should not be present
67
68Alt+Arrow keys not passed to application52Alt+Arrow keys not passed to application
69----------------------------------------53----------------------------------------
70Tests that Alt+ArrowKey events are correctly passed to the active window54Tests that Alt+ArrowKey events are correctly passed to the active window
7155
=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
--- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-03-22 15:14:49 +0000
+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-03-27 22:51:18 +0000
@@ -335,7 +335,7 @@
335335
336std::vector<Window> BamfLauncherIcon::WindowsOnViewport()336std::vector<Window> BamfLauncherIcon::WindowsOnViewport()
337{337{
338 WindowFilterMask filter;338 WindowFilterMask filter = 0;
339 filter |= WindowFilter::MAPPED;339 filter |= WindowFilter::MAPPED;
340 filter |= WindowFilter::USER_VISIBLE;340 filter |= WindowFilter::USER_VISIBLE;
341 filter |= WindowFilter::ON_CURRENT_DESKTOP;341 filter |= WindowFilter::ON_CURRENT_DESKTOP;
@@ -346,7 +346,7 @@
346346
347std::vector<Window> BamfLauncherIcon::WindowsForMonitor(int monitor)347std::vector<Window> BamfLauncherIcon::WindowsForMonitor(int monitor)
348{348{
349 WindowFilterMask filter;349 WindowFilterMask filter = 0;
350 filter |= WindowFilter::MAPPED;350 filter |= WindowFilter::MAPPED;
351 filter |= WindowFilter::USER_VISIBLE;351 filter |= WindowFilter::USER_VISIBLE;
352 filter |= WindowFilter::ON_CURRENT_DESKTOP;352 filter |= WindowFilter::ON_CURRENT_DESKTOP;
@@ -455,26 +455,18 @@
455455
456void BamfLauncherIcon::AddProperties(GVariantBuilder* builder)456void BamfLauncherIcon::AddProperties(GVariantBuilder* builder)
457{457{
458 LauncherIcon::AddProperties(builder);458 SimpleLauncherIcon::AddProperties(builder);
459459
460 GList* children, *l;460 GVariantBuilder xids_builder;
461 children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));461 g_variant_builder_init(&xids_builder, G_VARIANT_TYPE ("au"));
462 GVariant* xids[(int) g_list_length(children)];462
463463 for (auto xid : GetWindows())
464 int i = 0;464 g_variant_builder_add(&xids_builder, "u", xid);
465 for (l = children; l; l = l->next)
466 {
467 if (!BAMF_IS_WINDOW(l->data))
468 continue;
469
470 Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
471 xids[i++] = g_variant_new_uint32(xid);
472 }
473 g_list_free(children);
474465
475 variant::BuilderWrapper(builder)466 variant::BuilderWrapper(builder)
476 .add("desktop-file", DesktopFile())467 .add("desktop_file", DesktopFile())
477 .add("xids", g_variant_new_array(G_VARIANT_TYPE_UINT32, xids, i))468 .add("desktop_id", GetDesktopID())
469 .add("xids", g_variant_builder_end(&xids_builder))
478 .add("sticky", IsSticky());470 .add("sticky", IsSticky());
479}471}
480472
@@ -627,26 +619,8 @@
627619
628bool BamfLauncherIcon::Spread(bool current_desktop, int state, bool force)620bool BamfLauncherIcon::Spread(bool current_desktop, int state, bool force)
629{621{
630 GList* children, *l;622 auto windows = GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0);
631 children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));623 return WindowManager::Default()->ScaleWindowGroup(windows, state, force);
632 WindowManager* wm = WindowManager::Default();
633
634 std::vector<Window> windowList;
635 for (l = children; l; l = l->next)
636 {
637 if (!BAMF_IS_WINDOW(l->data))
638 continue;
639
640 Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
641
642 if (!current_desktop || (current_desktop && wm->IsWindowOnCurrentDesktop(xid)))
643 {
644 windowList.push_back(xid);
645 }
646 }
647
648 g_list_free(children);
649 return WindowManager::Default()->ScaleWindowGroup(windowList, state, force);
650}624}
651625
652void BamfLauncherIcon::EnsureWindowState()626void BamfLauncherIcon::EnsureWindowState()
@@ -1049,16 +1023,35 @@
1049 UpdateIconGeometries(center);1023 UpdateIconGeometries(center);
1050}1024}
10511025
1026std::string BamfLauncherIcon::GetDesktopID()
1027{
1028 std::string const& desktop_file = DesktopFile();
1029
1030 if (!desktop_file.empty())
1031 {
1032 size_t id_pos = desktop_file.rfind('/');
1033
1034 if (id_pos != std::string::npos)
1035 {
1036 size_t id_start = id_pos + 1;
1037
1038 return (id_start < desktop_file.length()) ? desktop_file.substr(id_start) : "";
1039 }
1040 }
1041
1042 return desktop_file;
1043}
1044
1052const gchar* BamfLauncherIcon::GetRemoteUri()1045const gchar* BamfLauncherIcon::GetRemoteUri()
1053{1046{
1054 if (_remote_uri.empty())1047 if (_remote_uri.empty())
1055 {1048 {
1056 const std::string prefix = "application://";1049 const std::string prefix = "application://";
1057 glib::String basename(g_path_get_basename(DesktopFile().c_str()));1050 std::string const& desktop_id = GetDesktopID();
10581051
1059 if (!basename.Str().empty())1052 if (!desktop_id.empty())
1060 {1053 {
1061 _remote_uri = prefix + basename.Str();1054 _remote_uri = prefix + desktop_id;
1062 }1055 }
1063 }1056 }
10641057
10651058
=== modified file 'plugins/unityshell/src/BamfLauncherIcon.h'
--- plugins/unityshell/src/BamfLauncherIcon.h 2012-03-22 15:14:49 +0000
+++ plugins/unityshell/src/BamfLauncherIcon.h 2012-03-27 22:51:18 +0000
@@ -113,8 +113,9 @@
113113
114 bool OwnsWindow(Window w) const;114 bool OwnsWindow(Window w) const;
115115
116 std::vector<Window> GetWindows(WindowFilterMask filter, int monitor = -1);116 std::vector<Window> GetWindows(WindowFilterMask filter = 0, int monitor = -1);
117 const std::set<std::string>& GetSupportedTypes();117 const std::set<std::string>& GetSupportedTypes();
118 std::string GetDesktopID();
118119
119120
120 glib::Object<BamfApplication> _bamf_app;121 glib::Object<BamfApplication> _bamf_app;
121122
=== modified file 'plugins/unityshell/src/HudController.cpp'
--- plugins/unityshell/src/HudController.cpp 2012-03-21 15:30:49 +0000
+++ plugins/unityshell/src/HudController.cpp 2012-03-27 22:51:18 +0000
@@ -40,6 +40,8 @@
4040
41Controller::Controller()41Controller::Controller()
42 : launcher_width(65)42 : launcher_width(65)
43 , launcher_locked_out(false)
44 , multiple_launchers(true)
43 , hud_service_("com.canonical.hud", "/com/canonical/hud")45 , hud_service_("com.canonical.hud", "/com/canonical/hud")
44 , window_(nullptr)46 , window_(nullptr)
45 , visible_(false)47 , visible_(false)
@@ -47,12 +49,11 @@
47 , timeline_id_(0)49 , timeline_id_(0)
48 , last_opacity_(0.0f)50 , last_opacity_(0.0f)
49 , start_time_(0)51 , start_time_(0)
50 , launcher_is_locked_out_(false)
51 , view_(nullptr)52 , view_(nullptr)
52 , monitor_index_(0)53 , monitor_index_(0)
53{54{
54 LOG_DEBUG(logger) << "hud startup";55 LOG_DEBUG(logger) << "hud startup";
55 SetupRelayoutCallbacks();56 UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(); });
5657
57 ubus.RegisterInterest(UBUS_HUD_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));58 ubus.RegisterInterest(UBUS_HUD_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));
5859
@@ -65,13 +66,13 @@
65 gint32 overlay_monitor = 0;66 gint32 overlay_monitor = 0;
66 g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING, &overlay_identity, &can_maximise, &overlay_monitor);67 g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING, &overlay_identity, &can_maximise, &overlay_monitor);
6768
68 if (g_strcmp0(overlay_identity, "hud"))69 if (overlay_identity.Str() != "hud")
69 {70 {
70 HideHud(true);71 HideHud(true);
71 }72 }
72 });73 });
7374
74 launcher_width.changed.connect([this] (int new_width) { Relayout(); });75 launcher_width.changed.connect([&] (int new_width) { Relayout(); });
7576
76 PluginAdapter::Default()->compiz_screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));77 PluginAdapter::Default()->compiz_screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
7778
@@ -120,14 +121,24 @@
120 AddChild(view_);121 AddChild(view_);
121}122}
122123
123void Controller::SetupRelayoutCallbacks()124int Controller::GetTargetMonitor()
124{125{
125 GdkScreen* screen = gdk_screen_get_default();126 return UScreen::GetDefault()->GetMonitorWithMouse();
126127}
127 sig_manager_.Add(new glib::Signal<void, GdkScreen*>(screen,128
128 "monitors-changed", sigc::mem_fun(this, &Controller::Relayout)));129bool Controller::IsLockedToLauncher(int monitor)
129 sig_manager_.Add(new glib::Signal<void, GdkScreen*>(screen,130{
130 "size-changed", sigc::mem_fun(this, &Controller::Relayout)));131 if (launcher_locked_out)
132 {
133 int primary_monitor = UScreen::GetDefault()->GetPrimaryMonitor();
134
135 if (multiple_launchers || (!multiple_launchers && primary_monitor == monitor))
136 {
137 return true;
138 }
139 }
140
141 return false;
131}142}
132143
133void Controller::EnsureHud()144void Controller::EnsureHud()
@@ -158,30 +169,31 @@
158169
159nux::Geometry Controller::GetIdealWindowGeometry()170nux::Geometry Controller::GetIdealWindowGeometry()
160{171{
161 UScreen *uscreen = UScreen::GetDefault();172 int target_monitor = GetTargetMonitor();
162 int primary_monitor = uscreen->GetMonitorWithMouse();173 auto monitor_geo = UScreen::GetDefault()->GetMonitorGeometry(target_monitor);
163 auto monitor_geo = uscreen->GetMonitorGeometry(primary_monitor);
164174
165 // We want to cover as much of the screen as possible to grab any mouse events outside175 // We want to cover as much of the screen as possible to grab any mouse events
166 // of our window176 // outside of our window
167 panel::Style &panel_style = panel::Style::Instance();177 panel::Style &panel_style = panel::Style::Instance();
168 nux::Geometry geo(monitor_geo.x,178 nux::Geometry geo(monitor_geo.x,
169 monitor_geo.y + panel_style.panel_height,179 monitor_geo.y + panel_style.panel_height,
170 monitor_geo.width,180 monitor_geo.width,
171 monitor_geo.height - panel_style.panel_height);181 monitor_geo.height - panel_style.panel_height);
172 if (launcher_is_locked_out_)182
183 if (IsLockedToLauncher(target_monitor))
173 {184 {
174 geo.x += launcher_width;185 geo.x += launcher_width;
175 geo.width -= launcher_width;186 geo.width -= launcher_width;
176 }187 }
188
177 return geo;189 return geo;
178}190}
179191
180void Controller::Relayout(GdkScreen*screen)192void Controller::Relayout()
181{193{
182 EnsureHud();194 EnsureHud();
183 nux::Geometry content_geo = view_->GetGeometry();195 nux::Geometry const& content_geo = view_->GetGeometry();
184 nux::Geometry geo = GetIdealWindowGeometry();196 nux::Geometry const& geo = GetIdealWindowGeometry();
185197
186 window_->SetGeometry(geo);198 window_->SetGeometry(geo);
187 layout_->SetMinMaxSize(content_geo.width, content_geo.height);199 layout_->SetMinMaxSize(content_geo.width, content_geo.height);
@@ -190,7 +202,7 @@
190}202}
191203
192void Controller::OnMouseDownOutsideWindow(int x, int y,204void Controller::OnMouseDownOutsideWindow(int x, int y,
193 unsigned long bflags, unsigned long kflags)205 unsigned long bflags, unsigned long kflags)
194{206{
195 LOG_DEBUG(logger) << "OnMouseDownOutsideWindow called";207 LOG_DEBUG(logger) << "OnMouseDownOutsideWindow called";
196 HideHud();208 HideHud();
@@ -234,16 +246,6 @@
234 return visible_;246 return visible_;
235}247}
236248
237void Controller::SetLauncherIsLockedOut(bool launcher_is_locked_out)
238{
239 launcher_is_locked_out_ = launcher_is_locked_out;
240 if (launcher_is_locked_out_)
241 view_->SetHideIcon(IconHideState::HIDE);
242 else
243 view_->SetHideIcon(IconHideState::SHOW);
244 Relayout();
245}
246
247void Controller::ShowHud()249void Controller::ShowHud()
248{250{
249 PluginAdapter* adaptor = PluginAdapter::Default();251 PluginAdapter* adaptor = PluginAdapter::Default();
@@ -259,6 +261,15 @@
259 return;261 return;
260 }262 }
261263
264 unsigned int target_monitor = GetTargetMonitor();
265
266 if (target_monitor != monitor_index_)
267 {
268 Relayout();
269 monitor_index_ = target_monitor;
270 }
271
272 view_->ShowEmbeddedIcon(!IsLockedToLauncher(monitor_index_));
262 view_->AboutToShow();273 view_->AboutToShow();
263274
264 // we first want to grab the currently active window, luckly we can just ask the jason interface(bamf)275 // we first want to grab the currently active window, luckly we can just ask the jason interface(bamf)
@@ -289,7 +300,6 @@
289 // hide the launcher300 // hide the launcher
290 GVariant* message_data = g_variant_new("(b)", TRUE);301 GVariant* message_data = g_variant_new("(b)", TRUE);
291 ubus.SendMessage(UBUS_LAUNCHER_LOCK_HIDE, message_data);302 ubus.SendMessage(UBUS_LAUNCHER_LOCK_HIDE, message_data);
292 monitor_index_ = UScreen::GetDefault()->GetMonitorWithMouse();
293 GVariant* info = g_variant_new(UBUS_OVERLAY_FORMAT_STRING, "hud", FALSE, monitor_index_);303 GVariant* info = g_variant_new(UBUS_OVERLAY_FORMAT_STRING, "hud", FALSE, monitor_index_);
294 ubus.SendMessage(UBUS_OVERLAY_SHOWN, info);304 ubus.SendMessage(UBUS_OVERLAY_SHOWN, info);
295305
@@ -410,7 +420,6 @@
410 ubus.SendMessage(UBUS_HUD_ICON_CHANGED, g_variant_new_string(query->icon_name.c_str()));420 ubus.SendMessage(UBUS_HUD_ICON_CHANGED, g_variant_new_string(query->icon_name.c_str()));
411}421}
412422
413
414void Controller::OnQueriesFinished(Hud::Queries queries)423void Controller::OnQueriesFinished(Hud::Queries queries)
415{424{
416 view_->SetQueries(queries);425 view_->SetQueries(queries);
@@ -438,7 +447,10 @@
438void Controller::AddProperties(GVariantBuilder* builder)447void Controller::AddProperties(GVariantBuilder* builder)
439{448{
440 variant::BuilderWrapper(builder)449 variant::BuilderWrapper(builder)
441 .add("visible", visible_);450 .add(window_ ? window_->GetGeometry() : nux::Geometry())
451 .add("visible", visible_)
452 .add("hud_monitor", monitor_index_)
453 .add("locked_to_launcher", IsLockedToLauncher(monitor_index_));
442}454}
443455
444456
445457
=== modified file 'plugins/unityshell/src/HudController.h'
--- plugins/unityshell/src/HudController.h 2012-03-21 15:30:49 +0000
+++ plugins/unityshell/src/HudController.h 2012-03-27 22:51:18 +0000
@@ -22,7 +22,6 @@
22#include <memory>22#include <memory>
2323
24#include <gdk/gdk.h>24#include <gdk/gdk.h>
25#include <UnityCore/GLibSignal.h>
26#include <UnityCore/Hud.h>25#include <UnityCore/Hud.h>
2726
28#include <NuxCore/Property.h>27#include <NuxCore/Property.h>
@@ -49,12 +48,13 @@
49 nux::BaseWindow* window() const;48 nux::BaseWindow* window() const;
5049
51 nux::Property<int> launcher_width;50 nux::Property<int> launcher_width;
51 nux::Property<bool> launcher_locked_out;
52 nux::Property<bool> multiple_launchers;
5253
53 void ShowHideHud();54 void ShowHideHud();
54 void ShowHud();55 void ShowHud();
55 void HideHud(bool restore_focus = true);56 void HideHud(bool restore_focus = true);
56 bool IsVisible();57 bool IsVisible();
57 void SetLauncherIsLockedOut(bool launcher_is_locked_out);
5858
59protected:59protected:
60 std::string GetName() const;60 std::string GetName() const;
@@ -64,11 +64,13 @@
64 void EnsureHud();64 void EnsureHud();
65 void SetupWindow();65 void SetupWindow();
66 void SetupHudView();66 void SetupHudView();
67 void SetupRelayoutCallbacks();
68 void RegisterUBusInterests();67 void RegisterUBusInterests();
6968
69 int GetTargetMonitor();
70 bool IsLockedToLauncher(int monitor);
71
70 nux::Geometry GetIdealWindowGeometry();72 nux::Geometry GetIdealWindowGeometry();
71 void Relayout(GdkScreen*screen=NULL);73 void Relayout();
7274
73 void OnMouseDownOutsideWindow(int x, int y, unsigned long bflags, unsigned long kflags);75 void OnMouseDownOutsideWindow(int x, int y, unsigned long bflags, unsigned long kflags);
74 void OnScreenUngrabbed();76 void OnScreenUngrabbed();
@@ -81,8 +83,6 @@
81 void OnQueryActivated(Query::Ptr query);83 void OnQueryActivated(Query::Ptr query);
82 void OnQuerySelected(Query::Ptr query);84 void OnQuerySelected(Query::Ptr query);
8385
84
85private:
86 void StartShowHideTimeline();86 void StartShowHideTimeline();
87 static gboolean OnViewShowHideFrame(Controller* self);87 static gboolean OnViewShowHideFrame(Controller* self);
8888
@@ -93,7 +93,6 @@
93private:93private:
94 UBusManager ubus;94 UBusManager ubus;
95 Hud hud_service_;95 Hud hud_service_;
96 glib::SignalManager sig_manager_;
97 nux::BaseWindow* window_;96 nux::BaseWindow* window_;
98 bool visible_;97 bool visible_;
99 bool need_show_;98 bool need_show_;
@@ -101,8 +100,6 @@
101 guint timeline_id_;100 guint timeline_id_;
102 float last_opacity_;101 float last_opacity_;
103 gint64 start_time_;102 gint64 start_time_;
104
105 bool launcher_is_locked_out_;
106103
107 View* view_;104 View* view_;
108 guint ensure_id_;105 guint ensure_id_;
109106
=== modified file 'plugins/unityshell/src/HudIcon.cpp'
--- plugins/unityshell/src/HudIcon.cpp 2012-03-26 22:43:48 +0000
+++ plugins/unityshell/src/HudIcon.cpp 2012-03-27 22:51:18 +0000
@@ -42,10 +42,6 @@
42 Init();42 Init();
43}43}
4444
45Icon::~Icon()
46{
47}
48
49void Icon::Init()45void Icon::Init()
50{46{
51 SetMinimumWidth(66);47 SetMinimumWidth(66);
@@ -89,6 +85,10 @@
89 icon_renderer_.RenderIcon(GfxContext, arg, toplevel->GetGeometry(), toplevel->GetGeometry());85 icon_renderer_.RenderIcon(GfxContext, arg, toplevel->GetGeometry(), toplevel->GetGeometry());
90}86}
9187
88std::string Icon::GetName() const
89{
90 return "EmbeddedIcon";
91}
9292
93}93}
94}94}
9595
=== modified file 'plugins/unityshell/src/HudIcon.h'
--- plugins/unityshell/src/HudIcon.h 2012-03-26 22:43:48 +0000
+++ plugins/unityshell/src/HudIcon.h 2012-03-27 22:51:18 +0000
@@ -53,12 +53,13 @@
53 typedef nux::ObjectPtr<IconTexture> Ptr;53 typedef nux::ObjectPtr<IconTexture> Ptr;
54 Icon(nux::BaseTexture* texture, guint width, guint height);54 Icon(nux::BaseTexture* texture, guint width, guint height);
55 Icon(std::string const& icon_name, unsigned int size, bool defer_icon_loading = false);55 Icon(std::string const& icon_name, unsigned int size, bool defer_icon_loading = false);
56 ~Icon();
5756
58protected:57protected:
59 void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);58 void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
60 void Init();59 void Init();
6160
61 std::string GetName() const;
62
62 nux::ObjectPtr<nux::BaseTexture> background_;63 nux::ObjectPtr<nux::BaseTexture> background_;
63 nux::ObjectPtr<nux::BaseTexture> gloss_;64 nux::ObjectPtr<nux::BaseTexture> gloss_;
64 nux::ObjectPtr<nux::BaseTexture> edge_;65 nux::ObjectPtr<nux::BaseTexture> edge_;
6566
=== modified file 'plugins/unityshell/src/HudView.cpp'
--- plugins/unityshell/src/HudView.cpp 2012-03-21 15:07:29 +0000
+++ plugins/unityshell/src/HudView.cpp 2012-03-27 22:51:18 +0000
@@ -64,7 +64,7 @@
64 , current_height_(0)64 , current_height_(0)
65 , timeline_need_more_draw_(false)65 , timeline_need_more_draw_(false)
66 , selected_button_(0)66 , selected_button_(0)
67 , icon_state_(IconHideState::SHOW)67 , show_embedded_icon_(true)
68 , activated_signal_sent_(false)68 , activated_signal_sent_(false)
69{69{
70 renderer_.SetOwner(this);70 renderer_.SetOwner(this);
@@ -127,7 +127,6 @@
127127
128View::~View()128View::~View()
129{129{
130 RemoveChild(search_bar_.GetPointer());
131 for (auto button = buttons_.begin(); button != buttons_.end(); button++)130 for (auto button = buttons_.begin(); button != buttons_.end(); button++)
132 {131 {
133 RemoveChild((*button).GetPointer());132 RemoveChild((*button).GetPointer());
@@ -272,22 +271,30 @@
272void View::SetIcon(std::string icon_name)271void View::SetIcon(std::string icon_name)
273{272{
274 LOG_DEBUG(logger) << "Setting icon to " << icon_name;273 LOG_DEBUG(logger) << "Setting icon to " << icon_name;
275 icon_->SetByIconName(icon_name.c_str(), icon_size);274 icon_->SetByIconName(icon_name, icon_size);
276 QueueDraw();275 QueueDraw();
277}276}
278277
279void View::SetHideIcon(IconHideState hide_icon)278void View::ShowEmbeddedIcon(bool show)
280{279{
281 LOG_DEBUG(logger) << "Hide icon called";280 LOG_DEBUG(logger) << "Hide icon called";
282 if (hide_icon == icon_state_)281 if (show == show_embedded_icon_)
283 return;282 return;
284283
285 icon_state_ = hide_icon;284 show_embedded_icon_ = show;
286285
287 if (icon_state_ == IconHideState::HIDE)286 if (show_embedded_icon_)
288 layout_->RemoveChildObject(dynamic_cast<nux::Area*>(icon_layout_.GetPointer()));287 {
288 layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP,
289 nux::MINOR_SIZE_MATCHCONTENT, 100.0f, nux::LayoutPosition::NUX_LAYOUT_BEGIN);
290
291 AddChild(icon_.GetPointer());
292 }
289 else293 else
290 layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP, nux::MINOR_SIZE_MATCHCONTENT, 100.0f, nux::LayoutPosition::NUX_LAYOUT_BEGIN);294 {
295 layout_->RemoveChildObject(static_cast<nux::Area*>(icon_layout_.GetPointer()));
296 RemoveChild(icon_.GetPointer());
297 }
291298
292 Relayout();299 Relayout();
293}300}
@@ -303,7 +310,7 @@
303 width = 1024;310 width = 1024;
304 height = 276;311 height = 276;
305312
306 if (icon_state_ == IconHideState::HIDE)313 if (!show_embedded_icon_)
307 {314 {
308 width -= icon_layout_->GetGeometry().width;315 width -= icon_layout_->GetGeometry().width;
309 }316 }
@@ -351,6 +358,7 @@
351 icon_ = new Icon("", icon_size, true);358 icon_ = new Icon("", icon_size, true);
352 icon_layout_ = new nux::VLayout();359 icon_layout_ = new nux::VLayout();
353 {360 {
361 AddChild(icon_.GetPointer());
354 icon_layout_->SetVerticalExternalMargin(icon_vertical_margin);362 icon_layout_->SetVerticalExternalMargin(icon_vertical_margin);
355 icon_layout_->AddView(icon_.GetPointer(), 0, nux::MINOR_POSITION_LEFT, nux::MINOR_SIZE_FULL);363 icon_layout_->AddView(icon_.GetPointer(), 0, nux::MINOR_POSITION_LEFT, nux::MINOR_SIZE_FULL);
356 layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP, nux::MINOR_SIZE_MATCHCONTENT);364 layout_->AddLayout(icon_layout_.GetPointer(), 0, nux::MINOR_POSITION_TOP, nux::MINOR_SIZE_MATCHCONTENT);
@@ -491,6 +499,7 @@
491{499{
492 unsigned num_buttons = buttons_.size();500 unsigned num_buttons = buttons_.size();
493 variant::BuilderWrapper(builder)501 variant::BuilderWrapper(builder)
502 .add(GetGeometry())
494 .add("selected_button", selected_button_)503 .add("selected_button", selected_button_)
495 .add("num_buttons", num_buttons);504 .add("num_buttons", num_buttons);
496}505}
497506
=== modified file 'plugins/unityshell/src/HudView.h'
--- plugins/unityshell/src/HudView.h 2012-03-21 14:44:41 +0000
+++ plugins/unityshell/src/HudView.h 2012-03-27 22:51:18 +0000
@@ -44,12 +44,6 @@
44namespace hud44namespace hud
45{45{
4646
47enum IconHideState
48{
49 HIDE,
50 SHOW
51};
52
53class View : public nux::View, public unity::debug::Introspectable47class View : public nux::View, public unity::debug::Introspectable
54{48{
55 NUX_DECLARE_OBJECT_TYPE(HudView, nux::View);49 NUX_DECLARE_OBJECT_TYPE(HudView, nux::View);
@@ -65,7 +59,7 @@
6559
66 void SetQueries(Hud::Queries queries);60 void SetQueries(Hud::Queries queries);
67 void SetIcon(std::string icon_name);61 void SetIcon(std::string icon_name);
68 void SetHideIcon(IconHideState hide_icon);62 void ShowEmbeddedIcon(bool show);
6963
70 void AboutToShow();64 void AboutToShow();
71 void AboutToHide();65 void AboutToHide();
@@ -126,7 +120,7 @@
126 int current_height_;120 int current_height_;
127 bool timeline_need_more_draw_;121 bool timeline_need_more_draw_;
128 int selected_button_;122 int selected_button_;
129 IconHideState icon_state_;123 bool show_embedded_icon_;
130 bool activated_signal_sent_;124 bool activated_signal_sent_;
131};125};
132126
133127
=== modified file 'plugins/unityshell/src/IconTexture.cpp'
--- plugins/unityshell/src/IconTexture.cpp 2012-03-27 01:38:08 +0000
+++ plugins/unityshell/src/IconTexture.cpp 2012-03-27 22:51:18 +0000
@@ -57,44 +57,47 @@
57}57}
5858
59IconTexture::IconTexture(std::string const& icon_name, unsigned int size, bool defer_icon_loading)59IconTexture::IconTexture(std::string const& icon_name, unsigned int size, bool defer_icon_loading)
60 : TextureArea(NUX_TRACKER_LOCATION)60 : TextureArea(NUX_TRACKER_LOCATION),
61 , _accept_key_nav_focus(false)61 _accept_key_nav_focus(false),
62 , _icon_name(icon_name.empty() ? DEFAULT_ICON : icon_name)62 _icon_name(!icon_name.empty() ? icon_name : DEFAULT_ICON),
63 , _size(size)63 _size(size),
64 , _texture_width(0)64 _texture_width(0),
65 , _texture_height(0)65 _texture_height(0),
66 , _loading(false)66 _loading(false),
67 , _opacity(1.0f)67 _opacity(1.0f)
68{68{
6969 if (!defer_icon_loading)
70 if (_icon_name != "" && !defer_icon_loading)
71 LoadIcon();70 LoadIcon();
72}71}
7372
73IconTexture::~IconTexture()
74{}
75
74void IconTexture::SetByIconName(std::string const& icon_name, unsigned int size)76void IconTexture::SetByIconName(std::string const& icon_name, unsigned int size)
75{77{
78 if (_icon_name == icon_name && _size == size)
79 return;
80
76 _icon_name = icon_name;81 _icon_name = icon_name;
77 _size = size;82 _size = size;
83
78 LoadIcon();84 LoadIcon();
79}85}
8086
87
81void IconTexture::SetByFilePath(std::string const& file_path, unsigned int size)88void IconTexture::SetByFilePath(std::string const& file_path, unsigned int size)
82{89{
83 _icon_name = file_path;90 SetByIconName(file_path, size);
84 _size = size;
85
86 LoadIcon();
87}91}
8892
89void IconTexture::LoadIcon()93void IconTexture::LoadIcon()
90{94{
91 LOG_DEBUG(logger) << "LoadIcon called (" << _icon_name << ") - loading: " << _loading;95 LOG_DEBUG(logger) << "LoadIcon called (" << _icon_name << ") - loading: " << _loading;
92static const char* const DEFAULT_GICON = ". GThemedIcon text-x-preview";96 static const char* const DEFAULT_GICON = ". GThemedIcon text-x-preview";
93 if (_icon_name.empty())
94 return;
9597
96 if (_loading)98 if (_loading)
97 return;99 return;
100
98 _loading = true;101 _loading = true;
99102
100 glib::Object<GIcon> icon(::g_icon_new_for_string(_icon_name.empty() ? DEFAULT_GICON : _icon_name.c_str(), NULL));103 glib::Object<GIcon> icon(::g_icon_new_for_string(_icon_name.empty() ? DEFAULT_GICON : _icon_name.c_str(), NULL));
@@ -231,7 +234,7 @@
231{234{
232 unity::variant::BuilderWrapper(builder)235 unity::variant::BuilderWrapper(builder)
233 .add(GetGeometry())236 .add(GetGeometry())
234 .add("iconname", _icon_name);237 .add("icon_name", _icon_name);
235}238}
236239
237//240//
238241
=== modified file 'plugins/unityshell/src/IconTexture.h'
--- plugins/unityshell/src/IconTexture.h 2012-03-26 22:43:48 +0000
+++ plugins/unityshell/src/IconTexture.h 2012-03-27 22:51:18 +0000
@@ -38,6 +38,7 @@
38public:38public:
39 IconTexture(nux::BaseTexture* texture, guint width, guint height);39 IconTexture(nux::BaseTexture* texture, guint width, guint height);
40 IconTexture(std::string const& icon_name, unsigned int size, bool defer_icon_loading = false);40 IconTexture(std::string const& icon_name, unsigned int size, bool defer_icon_loading = false);
41 virtual ~IconTexture();
4142
42 void SetByIconName(std::string const& icon_name, unsigned int size);43 void SetByIconName(std::string const& icon_name, unsigned int size);
43 void SetByFilePath(std::string const& file_path, unsigned int size);44 void SetByFilePath(std::string const& file_path, unsigned int size);
4445
=== modified file 'plugins/unityshell/src/LauncherIcon.cpp'
--- plugins/unityshell/src/LauncherIcon.cpp 2012-03-26 23:23:42 +0000
+++ plugins/unityshell/src/LauncherIcon.cpp 2012-03-27 22:51:18 +0000
@@ -185,18 +185,20 @@
185LauncherIcon::AddProperties(GVariantBuilder* builder)185LauncherIcon::AddProperties(GVariantBuilder* builder)
186{186{
187 unity::variant::BuilderWrapper(builder)187 unity::variant::BuilderWrapper(builder)
188 .add("x", _center[0].x)188 .add("center_x", _center[0].x)
189 .add("y", _center[0].y)189 .add("center_y", _center[0].y)
190 .add("z", _center[0].z)190 .add("center_z", _center[0].z)
191 .add("related-windows", (int)Windows().size())191 .add("related_windows", static_cast<unsigned int>(Windows().size()))
192 .add("icon-type", _icon_type)192 .add("icon_type", _icon_type)
193 .add("tooltip-text", tooltip_text())193 .add("tooltip_text", tooltip_text())
194 .add("sort-priority", _sort_priority)194 .add("sort_priority", _sort_priority)
195 .add("quirk-active", GetQuirk(QUIRK_ACTIVE))195 .add("active", GetQuirk(QUIRK_ACTIVE))
196 .add("quirk-visible", GetQuirk(QUIRK_VISIBLE))196 .add("visible", GetQuirk(QUIRK_VISIBLE))
197 .add("quirk-urgent", GetQuirk(QUIRK_URGENT))197 .add("urgent", GetQuirk(QUIRK_URGENT))
198 .add("quirk-running", GetQuirk(QUIRK_RUNNING))198 .add("running", GetQuirk(QUIRK_RUNNING))
199 .add("quirk-presented", GetQuirk(QUIRK_PRESENTED));199 .add("starting", GetQuirk(QUIRK_STARTING))
200 .add("desaturated", GetQuirk(QUIRK_DESAT))
201 .add("presented", GetQuirk(QUIRK_PRESENTED));
200}202}
201203
202void204void
203205
=== modified file 'plugins/unityshell/src/SimpleLauncherIcon.cpp'
--- plugins/unityshell/src/SimpleLauncherIcon.cpp 2012-03-14 06:24:18 +0000
+++ plugins/unityshell/src/SimpleLauncherIcon.cpp 2012-03-27 22:51:18 +0000
@@ -23,6 +23,7 @@
23#include <NuxCore/Logger.h>23#include <NuxCore/Logger.h>
24#include <Nux/Nux.h>24#include <Nux/Nux.h>
25#include <Nux/BaseWindow.h>25#include <Nux/BaseWindow.h>
26#include <UnityCore/Variant.h>
2627
27#include "SimpleLauncherIcon.h"28#include "SimpleLauncherIcon.h"
28#include "PluginAdapter.h"29#include "PluginAdapter.h"
@@ -148,6 +149,12 @@
148 return "SimpleLauncherIcon";149 return "SimpleLauncherIcon";
149}150}
150151
152void SimpleLauncherIcon::AddProperties(GVariantBuilder* builder)
153{
154 LauncherIcon::AddProperties(builder);
155 variant::BuilderWrapper(builder).add("icon_name", icon_name);
156}
157
151} // namespace launcher158} // namespace launcher
152} // namespace unity159} // namespace unity
153160
154161
=== modified file 'plugins/unityshell/src/SimpleLauncherIcon.h'
--- plugins/unityshell/src/SimpleLauncherIcon.h 2012-03-14 06:24:18 +0000
+++ plugins/unityshell/src/SimpleLauncherIcon.h 2012-03-27 22:51:18 +0000
@@ -47,6 +47,8 @@
4747
48protected:48protected:
49 std::string GetName() const;49 std::string GetName() const;
50 void AddProperties(GVariantBuilder* builder);
51
50 virtual void OnMouseDown(int button, int monitor);52 virtual void OnMouseDown(int button, int monitor);
51 virtual void OnMouseUp(int button, int monitor);53 virtual void OnMouseUp(int button, int monitor);
52 virtual void OnMouseClick(int button, int monitor);54 virtual void OnMouseClick(int button, int monitor);
5355
=== modified file 'plugins/unityshell/src/unityshell.cpp'
--- plugins/unityshell/src/unityshell.cpp 2012-03-26 21:52:33 +0000
+++ plugins/unityshell/src/unityshell.cpp 2012-03-27 22:51:18 +0000
@@ -2520,6 +2520,7 @@
2520 case UnityshellOptions::NumLaunchers:2520 case UnityshellOptions::NumLaunchers:
2521 launcher_controller_->multiple_launchers = optionGetNumLaunchers() == 0;2521 launcher_controller_->multiple_launchers = optionGetNumLaunchers() == 0;
2522 dash_controller_->use_primary = !launcher_controller_->multiple_launchers();2522 dash_controller_->use_primary = !launcher_controller_->multiple_launchers();
2523 hud_controller_->multiple_launchers = launcher_controller_->multiple_launchers();
2523 break;2524 break;
2524 case UnityshellOptions::LauncherCaptureMouse:2525 case UnityshellOptions::LauncherCaptureMouse:
2525 launcher_options->edge_resist = optionGetLauncherCaptureMouse();2526 launcher_options->edge_resist = optionGetLauncherCaptureMouse();
@@ -2540,7 +2541,7 @@
2540 case UnityshellOptions::LauncherHideMode:2541 case UnityshellOptions::LauncherHideMode:
2541 {2542 {
2542 launcher_options->hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();2543 launcher_options->hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
2543 hud_controller_->SetLauncherIsLockedOut(launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);2544 hud_controller_->launcher_locked_out = (launcher_options->hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
2544 break;2545 break;
2545 }2546 }
2546 case UnityshellOptions::BacklightMode:2547 case UnityshellOptions::BacklightMode:
@@ -2775,7 +2776,8 @@
2775 /* Setup Hud */2776 /* Setup Hud */
2776 hud_controller_.reset(new hud::Controller());2777 hud_controller_.reset(new hud::Controller());
2777 auto hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();2778 auto hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode();
2778 hud_controller_->SetLauncherIsLockedOut(hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);2779 hud_controller_->launcher_locked_out = (hide_mode == unity::launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER);
2780 hud_controller_->multiple_launchers = (optionGetNumLaunchers() == 0);
2779 AddChild(hud_controller_.get());2781 AddChild(hud_controller_.get());
2780 LOG_INFO(logger) << "initLauncher-hud " << timer.ElapsedSeconds() << "s";2782 LOG_INFO(logger) << "initLauncher-hud " << timer.ElapsedSeconds() << "s";
2781 2783
27822784
=== modified file 'tests/autopilot/autopilot/emulators/X11.py'
--- tests/autopilot/autopilot/emulators/X11.py 2012-03-25 20:50:33 +0000
+++ tests/autopilot/autopilot/emulators/X11.py 2012-03-27 22:51:18 +0000
@@ -360,10 +360,20 @@
360 Returns a tuple containing (x,y,width,height).360 Returns a tuple containing (x,y,width,height).
361361
362 """362 """
363 if monitor_number >= self.get_num_monitors():363 if monitor_number < 0 or monitor_number >= self.get_num_monitors():
364 raise ValueError('Specified monitor number is out of range.')364 raise ValueError('Specified monitor number is out of range.')
365 return tuple(self._default_screen.get_monitor_geometry(monitor_number))365 return tuple(self._default_screen.get_monitor_geometry(monitor_number))
366366
367 def is_rect_on_monitor(self, monitor_number, rect):
368 """Returns True if `rect` is _entirely_ on the specified monitor, with no overlap."""
369
370 if type(rect) is not tuple or len(rect) != 4:
371 raise TypeError("rect must be a tuple of 4 int elements.")
372
373 (x, y, w, h) = rect
374 (m_x, m_y, m_w, m_h) = self.get_monitor_geometry(monitor_number)
375 return (x >= m_x and x + w <= m_x + m_w and y >= m_y and y + h <= m_y + m_h)
376
367 def move_mouse_to_monitor(self, monitor_number):377 def move_mouse_to_monitor(self, monitor_number):
368 """Move the mouse to the center of the specified monitor."""378 """Move the mouse to the center of the specified monitor."""
369 geo = self.get_monitor_geometry(monitor_number)379 geo = self.get_monitor_geometry(monitor_number)
370380
=== modified file 'tests/autopilot/autopilot/emulators/bamf.py'
--- tests/autopilot/autopilot/emulators/bamf.py 2012-03-20 00:21:52 +0000
+++ tests/autopilot/autopilot/emulators/bamf.py 2012-03-27 22:51:18 +0000
@@ -184,6 +184,11 @@
184 return self._view_iface.Name()184 return self._view_iface.Name()
185185
186 @property186 @property
187 def icon(self):
188 """Get the application icon."""
189 return self._view_iface.Icon()
190
191 @property
187 def is_active(self):192 def is_active(self):
188 """Is the application active (i.e.- has keyboard focus)?"""193 """Is the application active (i.e.- has keyboard focus)?"""
189 return self._view_iface.IsActive()194 return self._view_iface.IsActive()
190195
=== modified file 'tests/autopilot/autopilot/emulators/unity/hud.py'
--- tests/autopilot/autopilot/emulators/unity/hud.py 2012-03-04 23:12:19 +0000
+++ tests/autopilot/autopilot/emulators/unity/hud.py 2012-03-27 22:51:18 +0000
@@ -14,6 +14,16 @@
14class HudView(UnityIntrospectionObject):14class HudView(UnityIntrospectionObject):
15 """Proxy object for the hud view child of the controller."""15 """Proxy object for the hud view child of the controller."""
1616
17 @property
18 def geometry(self):
19 return (self.x, self.y, self.width, self.height)
20
21class EmbeddedIcon(UnityIntrospectionObject):
22 """Proxy object for the hud embedded icon child of the view."""
23
24 @property
25 def geometry(self):
26 return (self.x, self.y, self.width, self.height)
1727
18class HudController(UnityIntrospectionObject, KeybindingsHelper):28class HudController(UnityIntrospectionObject, KeybindingsHelper):
19 """Proxy object for the Unity Hud Controller."""29 """Proxy object for the Unity Hud Controller."""
@@ -35,11 +45,24 @@
35 """Tap the 'Alt' key to toggle the hud visibility."""45 """Tap the 'Alt' key to toggle the hud visibility."""
36 self.keybinding("hud/reveal", tap_delay)46 self.keybinding("hud/reveal", tap_delay)
3747
48 def get_embedded_icon(self):
49 """Returns the HUD view embedded icon or None if is not shown."""
50 view = self._get_view()
51 if (not view):
52 return None
53
54 icons = view.get_children_by_type(EmbeddedIcon)
55 return icons[0] if icons else None
56
38 def _get_view(self):57 def _get_view(self):
39 views = self.get_children_by_type(HudView)58 views = self.get_children_by_type(HudView)
40 return views[0] if views else None59 return views[0] if views else None
4160
42 @property61 @property
62 def geometry(self):
63 return (self.x, self.y, self.width, self.height)
64
65 @property
43 def selected_button(self):66 def selected_button(self):
44 view = self._get_view()67 view = self._get_view()
45 if view:68 if view:
@@ -54,3 +77,15 @@
54 return view.num_buttons77 return view.num_buttons
55 else:78 else:
56 return 079 return 0
80
81 @property
82 def is_locked_to_launcher(self):
83 return bool(self.locked_to_launcher)
84
85 @property
86 def monitor(self):
87 return int(self.hud_monitor)
88
89 @property
90 def has_embedded_icon(self):
91 return (self.get_embedded_icon() != None)
5792
=== modified file 'tests/autopilot/autopilot/emulators/unity/icons.py'
--- tests/autopilot/autopilot/emulators/unity/icons.py 2012-03-04 23:12:19 +0000
+++ tests/autopilot/autopilot/emulators/unity/icons.py 2012-03-27 22:51:18 +0000
@@ -19,6 +19,11 @@
1919
20 """20 """
2121
22 @property
23 def center_position(self):
24 """Get the center point of an icon, returns a tuple with (x, y, z)"""
25 return (self.center_x, self.center_y, self.center_z)
26
22 def get_quicklist(self):27 def get_quicklist(self):
23 """Get the quicklist for this launcher icon.28 """Get the quicklist for this launcher icon.
2429
@@ -34,6 +39,10 @@
34 """Represents the BFB button in the launcher."""39 """Represents the BFB button in the launcher."""
3540
3641
42class HudLauncherIcon(SimpleLauncherIcon):
43 """Represents the HUD button in the launcher."""
44
45
37class BamfLauncherIcon(SimpleLauncherIcon):46class BamfLauncherIcon(SimpleLauncherIcon):
38 """Represents a launcher icon with BAMF integration."""47 """Represents a launcher icon with BAMF integration."""
3948
4049
=== modified file 'tests/autopilot/autopilot/emulators/unity/launcher.py'
--- tests/autopilot/autopilot/emulators/unity/launcher.py 2012-03-25 21:25:54 +0000
+++ tests/autopilot/autopilot/emulators/unity/launcher.py 2012-03-27 22:51:18 +0000
@@ -12,7 +12,7 @@
1212
13from autopilot.keybindings import KeybindingsHelper13from autopilot.keybindings import KeybindingsHelper
14from autopilot.emulators.unity import UnityIntrospectionObject14from autopilot.emulators.unity import UnityIntrospectionObject
15from autopilot.emulators.unity.icons import BamfLauncherIcon, SimpleLauncherIcon15from autopilot.emulators.unity.icons import BFBLauncherIcon, BamfLauncherIcon, SimpleLauncherIcon
16from autopilot.emulators.X11 import Mouse, ScreenGeometry16from autopilot.emulators.X11 import Mouse, ScreenGeometry
1717
1818
@@ -200,8 +200,8 @@
200 logger.debug("Clicking launcher icon %r on monitor %d with mouse button %d",200 logger.debug("Clicking launcher icon %r on monitor %d with mouse button %d",
201 icon, self.monitor, button)201 icon, self.monitor, button)
202 self.mouse_reveal_launcher()202 self.mouse_reveal_launcher()
203 target_x = icon.x + self.x203 target_x = icon.center_x + self.x
204 target_y = icon.y + (self.icon_size / 2)204 target_y = icon.center_y
205 self._mouse.move(target_x, target_y )205 self._mouse.move(target_x, target_y )
206 self._mouse.click(button)206 self._mouse.click(button)
207 self.move_mouse_to_right_of_launcher()207 self.move_mouse_to_right_of_launcher()
@@ -258,10 +258,15 @@
258class LauncherModel(UnityIntrospectionObject):258class LauncherModel(UnityIntrospectionObject):
259 """THe launcher model. Contains all launcher icons as children."""259 """THe launcher model. Contains all launcher icons as children."""
260260
261 def get_bfb_icon(self):
262 icons = BFBLauncherIcon.get_all_instances()
263 assert(len(icons) == 1)
264 return icons[0]
265
261 def get_launcher_icons(self, visible_only=True):266 def get_launcher_icons(self, visible_only=True):
262 """Get a list of launcher icons in this launcher."""267 """Get a list of launcher icons in this launcher."""
263 if visible_only:268 if visible_only:
264 return self.get_children_by_type(SimpleLauncherIcon, quirk_visible=True)269 return self.get_children_by_type(SimpleLauncherIcon, visible=True)
265 else:270 else:
266 return self.get_children_by_type(SimpleLauncherIcon)271 return self.get_children_by_type(SimpleLauncherIcon)
267272
@@ -281,7 +286,21 @@
281 Returns None if there is no such launcher icon.286 Returns None if there is no such launcher icon.
282 """287 """
283 icons = self.get_children_by_type(SimpleLauncherIcon, desktop_file=desktop_file)288 icons = self.get_children_by_type(SimpleLauncherIcon, desktop_file=desktop_file)
284 return icons or None289 if len(icons):
290 return icons[0]
291
292 return None
293
294 def get_icon_by_desktop_id(self, desktop_id):
295 """Gets a launcher icon with the specified desktop id.
296
297 Returns None if there is no such launcher icon.
298 """
299 icons = self.get_children_by_type(SimpleLauncherIcon, desktop_id=desktop_id)
300 if len(icons):
301 return icons[0]
302
303 return None
285304
286 def num_launcher_icons(self):305 def num_launcher_icons(self):
287 """Get the number of icons in the launcher model."""306 """Get the number of icons in the launcher model."""
288307
=== modified file 'tests/autopilot/autopilot/emulators/unity/switcher.py'
--- tests/autopilot/autopilot/emulators/unity/switcher.py 2012-03-07 17:24:15 +0000
+++ tests/autopilot/autopilot/emulators/unity/switcher.py 2012-03-27 22:51:18 +0000
@@ -136,11 +136,11 @@
136 return None136 return None
137137
138 def get_icon_name(self, index):138 def get_icon_name(self, index):
139 return self.__get_icon(index)['tooltip-text']139 return self.__get_icon(index)['tooltip_text']
140140
141 def get_icon_desktop_file(self, index):141 def get_icon_desktop_file(self, index):
142 try:142 try:
143 return self.__get_icon(index)['desktop-file']143 return self.__get_icon(index)['desktop_file']
144 except:144 except:
145 return None145 return None
146146
147147
=== modified file 'tests/autopilot/autopilot/tests/__init__.py'
--- tests/autopilot/autopilot/tests/__init__.py 2012-03-27 20:48:14 +0000
+++ tests/autopilot/autopilot/tests/__init__.py 2012-03-27 22:51:18 +0000
@@ -25,7 +25,7 @@
25from autopilot.emulators.unity.launcher import LauncherController25from autopilot.emulators.unity.launcher import LauncherController
26from autopilot.emulators.unity.switcher import Switcher26from autopilot.emulators.unity.switcher import Switcher
27from autopilot.emulators.unity.workspace import WorkspaceManager27from autopilot.emulators.unity.workspace import WorkspaceManager
28from autopilot.emulators.X11 import Keyboard, Mouse28from autopilot.emulators.X11 import ScreenGeometry, Keyboard, Mouse
29from autopilot.glibrunner import GlibRunner29from autopilot.glibrunner import GlibRunner
30from autopilot.globals import (global_context,30from autopilot.globals import (global_context,
31 video_recording_enabled,31 video_recording_enabled,
@@ -229,17 +229,25 @@
229 self.dash = Dash()229 self.dash = Dash()
230 self.switcher = Switcher()230 self.switcher = Switcher()
231 self.workspace = WorkspaceManager()231 self.workspace = WorkspaceManager()
232 self.screen_geo = ScreenGeometry()
232 self.launcher = self._get_launcher_controller()233 self.launcher = self._get_launcher_controller()
233 self.addCleanup(self.workspace.switch_to, self.workspace.current_workspace)234 self.addCleanup(self.workspace.switch_to, self.workspace.current_workspace)
234 self.addCleanup(Keyboard.cleanup)235 self.addCleanup(Keyboard.cleanup)
235 self.addCleanup(Mouse.cleanup)236 self.addCleanup(Mouse.cleanup)
236237
237 def start_app(self, app_name, files=[]):238 def start_app(self, app_name, files=[], locale=None):
238 """Start one of the known apps, and kill it on tear down.239 """Start one of the known apps, and kill it on tear down.
239240
240 if files is specified, start the application with the specified files.241 If files is specified, start the application with the specified files.
242 If locale is specified, the locale will be set when the application is launched.
241 """243 """
242 logger.info("Starting application '%s'", app_name)244 if locale:
245 os.putenv("LC_ALL", locale)
246 self.addCleanup(os.unsetenv, "LC_ALL")
247 logger.info("Starting application '%s' with files %r in locale %s", app_name, files, locale)
248 else:
249 logger.info("Starting application '%s' with files %r", app_name, files)
250
243 app = self.KNOWN_APPS[app_name]251 app = self.KNOWN_APPS[app_name]
244 self.bamf.launch_application(app['desktop-file'], files)252 self.bamf.launch_application(app['desktop-file'], files)
245 self.addCleanup(call, ["killall", app['process-name']])253 self.addCleanup(call, ["killall", app['process-name']])
246254
=== modified file 'tests/autopilot/autopilot/tests/test_hud.py'
--- tests/autopilot/autopilot/tests/test_hud.py 2012-03-21 14:44:41 +0000
+++ tests/autopilot/autopilot/tests/test_hud.py 2012-03-27 22:51:18 +0000
@@ -1,58 +1,81 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2# Copyright 2010 Canonical2# Copyright 2012 Canonical
3# Author: Alex Launi3# Author: Alex Launi,
4# Marco Trevisan
4#5#
5# This program is free software: you can redistribute it and/or modify it6# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published7# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.8# by the Free Software Foundation.
89
9from testtools.matchers import Equals, LessThan10from testtools.matchers import Equals, NotEquals, LessThan, GreaterThan
10from time import sleep11from time import sleep
1112
13from autopilot.emulators.X11 import ScreenGeometry
12from autopilot.emulators.unity.hud import HudController14from autopilot.emulators.unity.hud import HudController
13from autopilot.tests import AutopilotTestCase15from autopilot.emulators.unity.icons import HudLauncherIcon
16from autopilot.tests import AutopilotTestCase, multiply_scenarios
14from os import remove17from os import remove
1518
16class HudTests(AutopilotTestCase):19def _make_monitor_scenarios():
1720 num_monitors = ScreenGeometry().get_num_monitors()
18 scenarios = [21 scenarios = []
19 ('Launcher never hide', {'launcher_hide_mode': 0}),22
20 ('Launcher autohide', {'launcher_hide_mode': 1}),23 if num_monitors == 1:
21 ]24 scenarios = [('Single Monitor', {'hud_monitor': 0})]
25
26 else:
27 for i in range(num_monitors):
28 scenarios += [('Monitor %d' % (i), {'hud_monitor': i})]
29
30 return scenarios
31
32class HudTestsBase(AutopilotTestCase):
2233
23 def setUp(self):34 def setUp(self):
24 super(HudTests, self).setUp()35 super(HudTestsBase, self).setUp()
25 self.set_unity_option('launcher_hide_mode', self.launcher_hide_mode)36
26 sleep(0.5)37 sleep(0.25)
27 self.hud = self.get_hud_controller()38 self.hud = self.get_hud_controller()
2839
29 def tearDown(self):40 def tearDown(self):
30 self.hud.ensure_hidden()41 self.hud.ensure_hidden()
31 super(HudTests, self).tearDown()42 super(HudTestsBase, self).tearDown()
3243
33 def get_hud_controller(self):44 def get_hud_controller(self):
34 controllers = HudController.get_all_instances()45 controllers = HudController.get_all_instances()
35 self.assertEqual(1, len(controllers))46 self.assertEqual(1, len(controllers))
36 return controllers[0]47 return controllers[0]
3748
49 def get_hud_launcher_icon(self):
50 icons = HudLauncherIcon.get_all_instances()
51 self.assertEqual(1, len(icons))
52 return icons[0]
53
38 def get_num_active_launcher_icons(self):54 def get_num_active_launcher_icons(self):
39 num_active = 055 num_active = 0
40 for icon in self.launcher.model.get_launcher_icons():56 for icon in self.launcher.model.get_launcher_icons():
41 if icon.quirk_active and icon.quirk_visible:57 if icon.active and icon.visible:
42 num_active += 158 num_active += 1
43 return num_active59 return num_active
4460
45 def test_initially_hidden(self):
46 self.assertFalse(self.hud.visible)
47
48 def reveal_hud(self):61 def reveal_hud(self):
49 self.hud.toggle_reveal()62 self.hud.toggle_reveal()
50 for counter in range(10):63 for counter in range(10):
51 sleep(1)64 sleep(1)
52 if self.hud.visible:65 if self.hud.visible:
53 break66 break
67
54 self.assertTrue(self.hud.visible, "HUD did not appear.")68 self.assertTrue(self.hud.visible, "HUD did not appear.")
5569
70
71class HudBehaviorTests(HudTestsBase):
72
73 def setUp(self):
74 super(HudBehaviorTests, self).setUp()
75
76 self.hud_monitor = self.screen_geo.get_primary_monitor()
77 self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
78
56 def test_no_initial_values(self):79 def test_no_initial_values(self):
57 self.reveal_hud()80 self.reveal_hud()
58 self.assertThat(self.hud.num_buttons, Equals(0))81 self.assertThat(self.hud.num_buttons, Equals(0))
@@ -121,36 +144,6 @@
121 sleep(1)144 sleep(1)
122 self.assertFalse(self.hud.visible)145 self.assertFalse(self.hud.visible)
123146
124 def test_multiple_hud_reveal_does_not_break_launcher(self):
125 """Multiple Hud reveals must not cause the launcher to set multiple
126 apps as active.
127
128 """
129 # We need an app to switch to:
130 self.start_app('Character Map')
131 # We need an application to play with - I'll use the calculator.
132 self.start_app('Calculator')
133 sleep(1)
134
135 # before we start, make sure there's zero or one active icon:
136 num_active = self.get_num_active_launcher_icons()
137 self.assertThat(num_active, LessThan(2), "Invalid number of launcher icons active before test has run!")
138
139 # reveal and hide hud several times over:
140 for i in range(3):
141 self.hud.ensure_visible()
142 sleep(0.5)
143 self.hud.ensure_hidden()
144 sleep(0.5)
145
146 # click application icons for running apps in the launcher:
147 icon = self.launcher.model.get_icon_by_tooltip_text("Character Map")
148 self.launcher.get_launcher_for_monitor(0).click_launcher_icon(icon)
149
150 # see how many apps are marked as being active:
151 num_active = self.get_num_active_launcher_icons()
152 self.assertLessEqual(num_active, 1, "More than one launcher icon active after test has run!")
153
154 def test_restore_focus(self):147 def test_restore_focus(self):
155 """Ensures that once the hud is dismissed, the same application148 """Ensures that once the hud is dismissed, the same application
156 that was focused before hud invocation is refocused149 that was focused before hud invocation is refocused
@@ -191,7 +184,7 @@
191 """Read the saved file. The content should be "0 "."""184 """Read the saved file. The content should be "0 "."""
192185
193 self.addCleanup(remove, '/tmp/autopilot_gedit_undo_test_temp_file.txt')186 self.addCleanup(remove, '/tmp/autopilot_gedit_undo_test_temp_file.txt')
194 self.start_app('Text Editor', files=['/tmp/autopilot_gedit_undo_test_temp_file.txt'])187 self.start_app('Text Editor', files=['/tmp/autopilot_gedit_undo_test_temp_file.txt'], locale='C')
195188
196 sleep(1)189 sleep(1)
197 self.keyboard.type("0")190 self.keyboard.type("0")
@@ -202,8 +195,9 @@
202 sleep(1)195 sleep(1)
203196
204 self.keyboard.type("undo")197 self.keyboard.type("undo")
198 sleep(1)
205 self.keyboard.press_and_release('Return')199 self.keyboard.press_and_release('Return')
206 sleep(1)200 sleep(.5)
207201
208 self.keyboard.press_and_release("Ctrl+s")202 self.keyboard.press_and_release("Ctrl+s")
209 sleep(1)203 sleep(1)
@@ -211,3 +205,199 @@
211 contents = open("/tmp/autopilot_gedit_undo_test_temp_file.txt").read().strip('\n')205 contents = open("/tmp/autopilot_gedit_undo_test_temp_file.txt").read().strip('\n')
212 self.assertEqual("0 ", contents)206 self.assertEqual("0 ", contents)
213207
208
209class HudLauncherInteractionsTests(HudTestsBase):
210
211 launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
212 ('Launcher never hide', {'launcher_autohide': True})]
213
214 scenarios = multiply_scenarios(_make_monitor_scenarios(), launcher_modes)
215
216 def setUp(self):
217 super(HudLauncherInteractionsTests, self).setUp()
218 # Launchers on all monitors
219 self.set_unity_option('num_launchers', 0)
220 self.set_unity_option('launcher_hide_mode', int(self.launcher_autohide))
221
222 self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
223 sleep(0.5)
224
225 def test_multiple_hud_reveal_does_not_break_launcher(self):
226 """Multiple Hud reveals must not cause the launcher to set multiple
227 apps as active.
228
229 """
230 launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
231
232 # We need an app to switch to:
233 self.start_app('Character Map')
234 # We need an application to play with - I'll use the calculator.
235 self.start_app('Calculator')
236 sleep(1)
237
238 # before we start, make sure there's zero or one active icon:
239 num_active = self.get_num_active_launcher_icons()
240 self.assertThat(num_active, LessThan(2), "Invalid number of launcher icons active before test has run!")
241
242 # reveal and hide hud several times over:
243 for i in range(3):
244 self.hud.ensure_visible()
245 sleep(0.5)
246 self.hud.ensure_hidden()
247 sleep(0.5)
248
249 # click application icons for running apps in the launcher:
250 icon = self.launcher.model.get_icon_by_desktop_id("gucharmap.desktop")
251 launcher.click_launcher_icon(icon)
252
253 # see how many apps are marked as being active:
254 num_active = self.get_num_active_launcher_icons()
255 self.assertLessEqual(num_active, 1, "More than one launcher icon active after test has run!")
256
257 def test_hud_does_not_change_launcher_status(self):
258 """Tests if the HUD reveal keeps the launcher in the status it was"""
259
260 launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
261
262 launcher_shows_pre = launcher.is_showing()
263 sleep(.25)
264
265 self.reveal_hud()
266 sleep(1)
267
268 launcher_shows_post = launcher.is_showing()
269 self.assertThat(launcher_shows_pre, Equals(launcher_shows_post))
270
271
272class HudLockedLauncherInteractionsTests(HudTestsBase):
273
274 scenarios = _make_monitor_scenarios()
275
276 def setUp(self):
277 super(HudLockedLauncherInteractionsTests, self).setUp()
278 # Locked Launchers on all monitors
279 self.set_unity_option('num_launchers', 0)
280 self.set_unity_option('launcher_hide_mode', 0)
281
282 self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
283 sleep(0.5)
284
285 def test_hud_launcher_icon_hides_bfb(self):
286 """Tests that the BFB icon is hidden when the HUD launcher icon is shown"""
287
288 hud_icon = self.get_hud_launcher_icon()
289 bfb_icon = self.launcher.model.get_bfb_icon()
290
291 self.assertTrue(bfb_icon.visible)
292 self.assertFalse(hud_icon.visible)
293 sleep(.25)
294
295 self.reveal_hud()
296 sleep(.5)
297
298 self.assertTrue(hud_icon.visible)
299 self.assertFalse(bfb_icon.visible)
300
301 def test_hud_desaturates_launcher_icons(self):
302 """Tests that the launcher icons are desaturates when HUD is open"""
303
304 self.reveal_hud()
305 sleep(.5)
306
307 for icon in self.launcher.model.get_launcher_icons():
308 if isinstance(icon, HudLauncherIcon):
309 self.assertFalse(icon.desaturated)
310 else:
311 self.assertTrue(icon.desaturated)
312
313
314class HudVisualTests(HudTestsBase):
315
316 launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
317 ('Launcher never hide', {'launcher_autohide': True})]
318
319 launcher_screen = [('Launcher on primary monitor', {'launcher_primary_only': False}),
320 ('Launcher on all monitors', {'launcher_primary_only': True})]
321
322 scenarios = multiply_scenarios(_make_monitor_scenarios(), launcher_modes, launcher_screen)
323
324 def setUp(self):
325 super(HudVisualTests, self).setUp()
326 self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
327 self.set_unity_option('launcher_hide_mode', int(self.launcher_autohide))
328 self.set_unity_option('num_launchers', int(self.launcher_primary_only))
329 self.hud_monitor_is_primary = (self.screen_geo.get_primary_monitor() == self.hud_monitor)
330 self.hud_locked = (not self.launcher_autohide and (not self.launcher_primary_only or self.hud_monitor_is_primary))
331 sleep(0.5)
332
333 def test_initially_hidden(self):
334 self.assertFalse(self.hud.visible)
335
336 def test_hud_is_on_right_monitor(self):
337 """Tests if the hud is shown and fits the monitor where it should be"""
338 self.reveal_hud()
339 self.assertThat(self.hud_monitor, Equals(self.hud.monitor))
340 self.assertTrue(self.screen_geo.is_rect_on_monitor(self.hud.monitor, self.hud.geometry))
341
342 def test_hud_geometries(self):
343 """Tests the HUD geometries for the given monitor and status"""
344 self.reveal_hud()
345 monitor_geo = self.screen_geo.get_monitor_geometry(self.hud_monitor)
346 monitor_x = monitor_geo[0]
347 monitor_w = monitor_geo[2]
348 hud_x = self.hud.geometry[0]
349 hud_w = self.hud.geometry[2]
350
351 if self.hud_locked:
352 self.assertThat(hud_x, GreaterThan(monitor_x))
353 self.assertThat(hud_x, LessThan(monitor_x + monitor_w))
354 self.assertThat(hud_w, Equals(monitor_x + monitor_w - hud_x))
355 else:
356 self.assertThat(hud_x, Equals(monitor_x))
357 self.assertThat(hud_w, Equals(monitor_w))
358
359 def test_hud_is_locked_to_launcher(self):
360 """Tests if the HUD is locked to launcher as we expect or not"""
361 self.reveal_hud()
362 sleep(.25)
363
364 self.assertThat(self.hud.is_locked_to_launcher, Equals(self.hud_locked))
365
366 def test_hud_icon_is_shown(self):
367 """Tests that the correct HUD icon is shown"""
368 self.reveal_hud()
369 sleep(.5)
370
371 hud_launcher_icon = self.get_hud_launcher_icon()
372 hud_embedded_icon = self.hud.get_embedded_icon()
373
374 # FIXME this should check self.hud.is_locked_to_launcher
375 # but the HUD icon is currently shared between launchers.
376 if not self.launcher_autohide:
377 self.assertTrue(hud_launcher_icon.visible)
378 self.assertFalse(hud_launcher_icon.desaturated)
379
380 # FIXME remove this once the issue above has been resolved
381 if self.hud.is_locked_to_launcher:
382 self.assertThat(hud_embedded_icon, Equals(None))
383 else:
384 self.assertThat(hud_embedded_icon, NotEquals(None))
385 self.assertFalse(hud_launcher_icon.visible)
386
387 def test_hud_icon_show_the_focused_application_emblem(self):
388 """Tests that the correct HUD icon is shown"""
389 self.start_app("Calculator")
390 calctools = self.get_app_instances("Calculator")
391 self.assertThat(len(calctools), GreaterThan(0))
392 calc = calctools[0]
393 self.assertTrue(calc.is_active)
394
395 self.reveal_hud()
396 sleep(.5)
397
398 if self.hud.is_locked_to_launcher:
399 hud_launcher_icon = self.get_hud_launcher_icon()
400 self.assertThat(hud_launcher_icon.icon_name, Equals(calc.icon))
401 else:
402 hud_embedded_icon = self.hud.get_embedded_icon()
403 self.assertThat(hud_embedded_icon.icon_name, Equals(calc.icon))
214404
=== modified file 'tests/autopilot/autopilot/tests/test_launcher.py'
--- tests/autopilot/autopilot/tests/test_launcher.py 2012-03-27 20:48:14 +0000
+++ tests/autopilot/autopilot/tests/test_launcher.py 2012-03-27 22:51:18 +0000
@@ -534,9 +534,8 @@
534 def test_launcher_does_not_reveal_with_mouse_down(self):534 def test_launcher_does_not_reveal_with_mouse_down(self):
535 """Launcher must not reveal if have mouse button 1 down."""535 """Launcher must not reveal if have mouse button 1 down."""
536 launcher_instance = self.get_launcher()536 launcher_instance = self.get_launcher()
537 screens = ScreenGeometry()
538537
539 screens.move_mouse_to_monitor(launcher_instance.monitor)538 self.screen_geo.move_mouse_to_monitor(launcher_instance.monitor)
540 self.mouse.press(1)539 self.mouse.press(1)
541 launcher_instance.mouse_reveal_launcher()540 launcher_instance.mouse_reveal_launcher()
542 self.assertThat(launcher_instance.is_showing(), Equals(False))541 self.assertThat(launcher_instance.is_showing(), Equals(False))
543542
=== modified file 'tests/autopilot/autopilot/tests/test_shortcut_hint.py'
--- tests/autopilot/autopilot/tests/test_shortcut_hint.py 2012-03-21 22:32:36 +0000
+++ tests/autopilot/autopilot/tests/test_shortcut_hint.py 2012-03-27 22:51:18 +0000
@@ -29,9 +29,8 @@
29 sleep(1)29 sleep(1)
3030
31 def skip_if_monitor_too_small(self):31 def skip_if_monitor_too_small(self):
32 screen = ScreenGeometry();32 monitor = self.screen_geo.get_primary_monitor()
33 monitor = screen.get_primary_monitor()33 monitor_geo = self.screen_geo.get_monitor_geometry(monitor);
34 monitor_geo = screen.get_monitor_geometry(monitor);
35 monitor_w = monitor_geo[2];34 monitor_w = monitor_geo[2];
36 monitor_h = monitor_geo[3];35 monitor_h = monitor_geo[3];
37 launcher_width = self.launcher.get_launcher_for_monitor(monitor).geometry[2];36 launcher_width = self.launcher.get_launcher_for_monitor(monitor).geometry[2];
@@ -49,8 +48,7 @@
49 def get_launcher(self):48 def get_launcher(self):
50 # We could parameterise this so all tests run on both monitors (if MM is49 # We could parameterise this so all tests run on both monitors (if MM is
51 # set up), but I think it's fine to just always use monitor primary monitor:50 # set up), but I think it's fine to just always use monitor primary monitor:
52 screen = ScreenGeometry();51 monitor = self.screen_geo.get_primary_monitor()
53 monitor = screen.get_primary_monitor()
54 return self.launcher.get_launcher_for_monitor(monitor)52 return self.launcher.get_launcher_for_monitor(monitor)
5553
5654
5755
=== modified file 'tests/autopilot/autopilot/tests/test_showdesktop.py'
--- tests/autopilot/autopilot/tests/test_showdesktop.py 2012-03-12 04:06:44 +0000
+++ tests/autopilot/autopilot/tests/test_showdesktop.py 2012-03-27 22:51:18 +0000
@@ -9,6 +9,7 @@
9from time import sleep9from time import sleep
1010
11from autopilot.emulators.unity.switcher import Switcher11from autopilot.emulators.unity.switcher import Switcher
12from autopilot.emulators.unity.icons import DesktopLauncherIcon
12from autopilot.tests import AutopilotTestCase13from autopilot.tests import AutopilotTestCase
1314
1415
@@ -23,8 +24,8 @@
2324
24 def launch_test_apps(self):25 def launch_test_apps(self):
25 """Launch character map and calculator apps."""26 """Launch character map and calculator apps."""
26 self.start_app('Character Map')27 self.start_app('Character Map', locale='C')
27 self.start_app('Calculator')28 self.start_app('Calculator', locale='C')
28 sleep(1)29 sleep(1)
2930
30 def test_showdesktop_hides_apps(self):31 def test_showdesktop_hides_apps(self):
@@ -75,7 +76,7 @@
75 self.assertTrue(win.is_hidden, "Window '%s' is not hidden after show desktop activated." % (win.title))76 self.assertTrue(win.is_hidden, "Window '%s' is not hidden after show desktop activated." % (win.title))
7677
77 # We'll un-minimise the character map - find it's launcherIcon in the launcher:78 # We'll un-minimise the character map - find it's launcherIcon in the launcher:
78 charmap_icon = self.launcher.model.get_icon_by_tooltip_text('Character Map')79 charmap_icon = self.launcher.model.get_icon_by_desktop_id("gucharmap.desktop")
79 if charmap_icon:80 if charmap_icon:
80 self.launcher.get_launcher_for_monitor(0).click_launcher_icon(charmap_icon)81 self.launcher.get_launcher_for_monitor(0).click_launcher_icon(charmap_icon)
81 else:82 else:
@@ -108,7 +109,7 @@
108 for i in range(switcher.get_model_size()):109 for i in range(switcher.get_model_size()):
109 current_icon = switcher.current_icon110 current_icon = switcher.current_icon
110 self.assertIsNotNone(current_icon)111 self.assertIsNotNone(current_icon)
111 if current_icon.tooltip_text == 'Show Desktop':112 if isinstance(current_icon, DesktopLauncherIcon):
112 found = True113 found = True
113 break114 break
114 switcher.previous_icon()115 switcher.previous_icon()
115116
=== modified file 'tests/autopilot/autopilot/tests/test_switcher.py'
--- tests/autopilot/autopilot/tests/test_switcher.py 2012-03-14 06:24:18 +0000
+++ tests/autopilot/autopilot/tests/test_switcher.py 2012-03-27 22:51:18 +0000
@@ -292,6 +292,11 @@
292class SwitcherWorkspaceTests(AutopilotTestCase):292class SwitcherWorkspaceTests(AutopilotTestCase):
293 """Test Switcher behavior with respect to multiple workspaces."""293 """Test Switcher behavior with respect to multiple workspaces."""
294294
295 def get_bamf_application(self, name):
296 apps = self.get_app_instances(name)
297 self.assertThat(len(apps), Equals(1))
298 return apps[0]
299
295 def test_switcher_shows_current_workspace_only(self):300 def test_switcher_shows_current_workspace_only(self):
296 """Switcher must show apps from the current workspace only."""301 """Switcher must show apps from the current workspace only."""
297 self.close_all_app('Calculator')302 self.close_all_app('Calculator')
@@ -308,8 +313,8 @@
308 sleep(1)313 sleep(1)
309 icon_names = [i.tooltip_text for i in self.switcher.get_switcher_icons()]314 icon_names = [i.tooltip_text for i in self.switcher.get_switcher_icons()]
310 self.switcher.terminate()315 self.switcher.terminate()
311 self.assertThat(icon_names, Contains("Character Map"))316 self.assertThat(icon_names, Contains(self.get_bamf_application("Character Map").name))
312 self.assertThat(icon_names, Not(Contains("Calculator")))317 self.assertThat(icon_names, Not(Contains(self.get_bamf_application("Calculator").name)))
313318
314 def test_switcher_all_mode_shows_all_apps(self):319 def test_switcher_all_mode_shows_all_apps(self):
315 """Test switcher 'show_all' mode shows apps from all workspaces."""320 """Test switcher 'show_all' mode shows apps from all workspaces."""
@@ -327,8 +332,8 @@
327 sleep(1)332 sleep(1)
328 icon_names = [i.tooltip_text for i in self.switcher.get_switcher_icons()]333 icon_names = [i.tooltip_text for i in self.switcher.get_switcher_icons()]
329 self.switcher.terminate()334 self.switcher.terminate()
330 self.assertThat(icon_names, Contains("Character Map"))335 self.assertThat(icon_names, Contains(self.get_bamf_application("Calculator").name))
331 self.assertThat(icon_names, Contains("Calculator"))336 self.assertThat(icon_names, Contains(self.get_bamf_application("Character Map").name))
332337
333 def test_switcher_can_switch_to_minimised_window(self):338 def test_switcher_can_switch_to_minimised_window(self):
334 """Switcher must be able to switch to a minimised window when there's339 """Switcher must be able to switch to a minimised window when there's
@@ -353,16 +358,14 @@
353358
354 self.switcher.initiate()359 self.switcher.initiate()
355 sleep(1)360 sleep(1)
356 while self.switcher.current_icon.tooltip_text != 'Mahjongg':361 while self.switcher.current_icon.tooltip_text != self.get_bamf_application("Mahjongg").name:
357 self.switcher.next_icon()362 self.switcher.next_icon()
358 sleep(1)363 sleep(1)
359 self.switcher.stop()364 self.switcher.stop()
360 sleep(1)365 sleep(1)
361366
362 #get calculator windows - there should be only one:367 #get mahjongg windows - there should be two:
363 mahjongg_apps = self.get_app_instances("Mahjongg")368 wins = self.get_bamf_application("Mahjongg").get_windows()
364 self.assertThat(len(mahjongg_apps), Equals(1))
365 wins = mahjongg_apps[0].get_windows()
366 self.assertThat(len(wins), Equals(2))369 self.assertThat(len(wins), Equals(2))
367 # Ideally we should be able to find the instance that is on the370 # Ideally we should be able to find the instance that is on the
368 # current workspace and ask that one if it is hidden.371 # current workspace and ask that one if it is hidden.