Merge lp:~azzar1/unity/set-startup-id into lp:unity

Proposed by Andrea Azzarone
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 3056
Proposed branch: lp:~azzar1/unity/set-startup-id
Merge into: lp:unity
Diff against target: 123 lines (+39/-5)
3 files modified
launcher/ApplicationLauncherIcon.cpp (+12/-5)
launcher/ApplicationLauncherIcon.h (+1/-0)
tests/autopilot/unity/tests/launcher/test_icon_behavior.py (+26/-0)
To merge this branch: bzr merge lp:~azzar1/unity/set-startup-id
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Thomi Richards (community) quality Approve
Marco Trevisan (Treviño) Approve
Review via email: mp+143624@code.launchpad.net

Commit message

Set startupId when launching application from the launcher.

Description of the change

== Problem ==
Removal of 21_correct_timestamp_.patch returns focus issues in Unity session.

== Fix ==
Set startupId when launching application from the launcher.
Please not that something similar needs to be done for the apps lens too.

== Test ==
AP test added.

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

92 + if self.app_is_running("Calculator"):
93 + self.skipTest("Calculator is already running.")

Why not closing it if, instead of skipping the test?

Anyway looks good.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> 92 + if self.app_is_running("Calculator"):
> 93 + self.skipTest("Calculator is already running.")
>
> Why not closing it if, instead of skipping the test?
>
> Anyway looks good.

Because a test should leave the system in the same state than it found it.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Ok, as you prefer...

review: Approve
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

Hi,

65 +

This probably doesn't need to be there...

77 + Time startup_notification_timestamp_;

This is inconsistent with the other member variables (trailing '_' rather than leading '_'). Please either follow the existing style, or update the other variables as well. Don't leave a file with both styles in place :)

92 + if self.app_is_running("Calculator"):
93 + self.skipTest("Calculator is already running.")

It's fine to kill the calculator if it's running - lots of tests do this already. In fact...

92 + if self.app_is_running("Calculator"):
93 + self.skipTest("Calculator is already running.")
94 +
95 + desktop_file = self.KNOWN_APPS["Calculator"]['desktop-file']
96 + calc_icon = self.launcher.model.get_icon(desktop_id=desktop_file)
97 +
98 + if calc_icon == None:
99 + calc = self.start_app("Calculator")
100 + desktop_file = calc.desktop_file
101 + calc_icon = self.launcher.model.get_icon(desktop_id=desktop_file)
102 +
103 + self.addCleanup(self.launcher_instance.unlock_from_launcher, calc_icon)
104 + self.launcher_instance.lock_to_launcher(calc_icon)
105 + self.close_all_app("Calculator")

This whole part should go in a utility function, and be called from the test. I think you want to refactor it slightly as well. Why not something like this:

def ensure_calculator_in_launcher_and_not_running(self):
 calc = self.start_app("Calculator")
 calc_icon = self.launcher.model.get_icon(desktop_id=calc.desktop_file)
 self.addCleanup(self.launcher_instance.unlock_from_launcher, calc_icon)
 self.launcher_instance.lock_to_launcher(calc_icon)
 self.close_all_app("Calculator")
 self.assertThat(lambda: self.app_is_running("Calculator"), Eventually(Equals(False)))
 return calc_icon

I think you should also move the X11 stuff into a separate function:

def get_startup_notification_timestamp(self, bamf_window):
 atom = display.Display().intern_atom('_NET_WM_USER_TIME')
 atom_type = display.Display().intern_atom('CARDINAL')
 return bamf_window.x_win.get_property(atom, atom_type, 0, 1024).value[0]

Then your test becomes a bit simpler:

def test_launcher_uses_startup_notification(self):
 """Tests that unity uses startup notification protocol."""
 calc_icon = self.ensure_calculator_in_launcher_and_not_running()
 self.addCleanup(self.close_all_app, "Calculator")
 self.launcher_instance.click_launcher_icon(calc_icon)

 # note - don't re-create bamf - just use it:
 calc_app = self.bamf.get_running_applications_by_desktop_file(desktop_file)[0]
 calc_window = calc_app.get_windows()[0]

 self.assertThat(lambda: self.get_startup_notification_timestamp(calc_window), Eventually(Equals(calc_icon.startup_notification_timestamp)))

Cheers,

review: Needs Fixing
Revision history for this message
Andrea Azzarone (azzar1) wrote :

> Hi,
>
> 65 +
>
> This probably doesn't need to be there...
>
> 77 + Time startup_notification_timestamp_;
>
> This is inconsistent with the other member variables (trailing '_' rather than
> leading '_'). Please either follow the existing style, or update the other
> variables as well. Don't leave a file with both styles in place :)
>
> 92 + if self.app_is_running("Calculator"):
> 93 + self.skipTest("Calculator is already running.")
>
> It's fine to kill the calculator if it's running - lots of tests do this
> already. In fact...
>
> 92 + if self.app_is_running("Calculator"):
> 93 + self.skipTest("Calculator is already running.")
> 94 +
> 95 + desktop_file = self.KNOWN_APPS["Calculator"]['desktop-file']
> 96 + calc_icon = self.launcher.model.get_icon(desktop_id=desktop_file)
> 97 +
> 98 + if calc_icon == None:
> 99 + calc = self.start_app("Calculator")
> 100 + desktop_file = calc.desktop_file
> 101 + calc_icon = self.launcher.model.get_icon(desktop_id=desktop_file)
> 102 +
> 103 + self.addCleanup(self.launcher_instance.unlock_from_launcher,
> calc_icon)
> 104 + self.launcher_instance.lock_to_launcher(calc_icon)
> 105 + self.close_all_app("Calculator")
>
> This whole part should go in a utility function, and be called from the test.
> I think you want to refactor it slightly as well. Why not something like this:
>
>
> def ensure_calculator_in_launcher_and_not_running(self):
> calc = self.start_app("Calculator")
> calc_icon = self.launcher.model.get_icon(desktop_id=calc.desktop_file)
> self.addCleanup(self.launcher_instance.unlock_from_launcher,
> calc_icon)
> self.launcher_instance.lock_to_launcher(calc_icon)
> self.close_all_app("Calculator")
> self.assertThat(lambda: self.app_is_running("Calculator"),
> Eventually(Equals(False)))
> return calc_icon
>
> I think you should also move the X11 stuff into a separate function:
>
> def get_startup_notification_timestamp(self, bamf_window):
> atom = display.Display().intern_atom('_NET_WM_USER_TIME')
> atom_type = display.Display().intern_atom('CARDINAL')
> return bamf_window.x_win.get_property(atom, atom_type, 0,
> 1024).value[0]
>
> Then your test becomes a bit simpler:
>
> def test_launcher_uses_startup_notification(self):
> """Tests that unity uses startup notification protocol."""
> calc_icon = self.ensure_calculator_in_launcher_and_not_running()
> self.addCleanup(self.close_all_app, "Calculator")
> self.launcher_instance.click_launcher_icon(calc_icon)
>
> # note - don't re-create bamf - just use it:
> calc_app =
> self.bamf.get_running_applications_by_desktop_file(desktop_file)[0]
> calc_window = calc_app.get_windows()[0]
>
> self.assertThat(lambda:
> self.get_startup_notification_timestamp(calc_window),
> Eventually(Equals(calc_icon.startup_notification_timestamp)))
>
>
> Cheers,

Done.

Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

Looks super-awesome.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'launcher/ApplicationLauncherIcon.cpp'
--- launcher/ApplicationLauncherIcon.cpp 2012-12-18 17:57:48 +0000
+++ launcher/ApplicationLauncherIcon.cpp 2013-01-22 01:30:30 +0000
@@ -58,6 +58,7 @@
58ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)58ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
59 : SimpleLauncherIcon(IconType::APPLICATION)59 : SimpleLauncherIcon(IconType::APPLICATION)
60 , app_(app)60 , app_(app)
61 , _startup_notification_timestamp(0)
61 , use_custom_bg_color_(false)62 , use_custom_bg_color_(false)
62 , bg_color_(nux::color::White)63 , bg_color_(nux::color::White)
63{64{
@@ -479,16 +480,22 @@
479 .add("desktop_file", DesktopFile())480 .add("desktop_file", DesktopFile())
480 .add("desktop_id", GetDesktopID())481 .add("desktop_id", GetDesktopID())
481 .add("xids", g_variant_builder_end(&xids_builder))482 .add("xids", g_variant_builder_end(&xids_builder))
482 .add("sticky", IsSticky());483 .add("sticky", IsSticky())
484 .add("startup_notification_timestamp", _startup_notification_timestamp);
483}485}
484486
485
486void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris)487void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris)
487{488{
488 glib::Error error;489 glib::Error error;
489 glib::Object<GDesktopAppInfo> desktopInfo(g_desktop_app_info_new_from_filename(DesktopFile().c_str()));490 glib::Object<GDesktopAppInfo> desktopInfo(g_desktop_app_info_new_from_filename(DesktopFile().c_str()));
490 auto appInfo = glib::object_cast<GAppInfo>(desktopInfo);491 auto appInfo = glib::object_cast<GAppInfo>(desktopInfo);
491492
493 GdkDisplay* display = gdk_display_get_default();
494 glib::Object<GdkAppLaunchContext> app_launch_context(gdk_display_get_app_launch_context(display));
495
496 _startup_notification_timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
497 gdk_app_launch_context_set_timestamp(app_launch_context, _startup_notification_timestamp);
498
492 if (g_app_info_supports_uris(appInfo))499 if (g_app_info_supports_uris(appInfo))
493 {500 {
494 GList* list = nullptr;501 GList* list = nullptr;
@@ -496,7 +503,7 @@
496 for (auto it : uris)503 for (auto it : uris)
497 list = g_list_prepend(list, g_strdup(it.c_str()));504 list = g_list_prepend(list, g_strdup(it.c_str()));
498505
499 g_app_info_launch_uris(appInfo, list, nullptr, &error);506 g_app_info_launch_uris(appInfo, list, glib::object_cast<GAppLaunchContext>(app_launch_context), &error);
500 g_list_free_full(list, g_free);507 g_list_free_full(list, g_free);
501 }508 }
502 else if (g_app_info_supports_files(appInfo))509 else if (g_app_info_supports_files(appInfo))
@@ -509,12 +516,12 @@
509 list = g_list_prepend(list, file);516 list = g_list_prepend(list, file);
510 }517 }
511518
512 g_app_info_launch(appInfo, list, nullptr, &error);519 g_app_info_launch(appInfo, list, glib::object_cast<GAppLaunchContext>(app_launch_context), &error);
513 g_list_free_full(list, g_object_unref);520 g_list_free_full(list, g_object_unref);
514 }521 }
515 else522 else
516 {523 {
517 g_app_info_launch(appInfo, nullptr, nullptr, &error);524 g_app_info_launch(appInfo, nullptr, glib::object_cast<GAppLaunchContext>(app_launch_context), &error);
518 }525 }
519526
520 if (error)527 if (error)
521528
=== modified file 'launcher/ApplicationLauncherIcon.h'
--- launcher/ApplicationLauncherIcon.h 2012-12-05 10:24:53 +0000
+++ launcher/ApplicationLauncherIcon.h 2013-01-22 01:30:30 +0000
@@ -123,6 +123,7 @@
123 std::string GetDesktopID();123 std::string GetDesktopID();
124124
125 std::string _remote_uri;125 std::string _remote_uri;
126 Time _startup_notification_timestamp;
126 std::set<std::string> _supported_types;127 std::set<std::string> _supported_types;
127 std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients;128 std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients;
128 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items;129 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items;
129130
=== modified file 'tests/autopilot/unity/tests/launcher/test_icon_behavior.py'
--- tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2013-01-14 10:58:35 +0000
+++ tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2013-01-22 01:30:30 +0000
@@ -19,6 +19,7 @@
19from unity.emulators.launcher import IconDragType19from unity.emulators.launcher import IconDragType
20from unity.tests.launcher import LauncherTestCase, _make_scenarios20from unity.tests.launcher import LauncherTestCase, _make_scenarios
2121
22from Xlib import display
22from Xlib import Xutil23from Xlib import Xutil
2324
24logger = logging.getLogger(__name__)25logger = logging.getLogger(__name__)
@@ -50,6 +51,20 @@
5051
51 return icon52 return icon
5253
54 def ensure_calculator_in_launcher_and_not_running(self):
55 calc = self.start_app("Calculator")
56 calc_icon = self.launcher.model.get_icon(desktop_id=calc.desktop_file)
57 self.addCleanup(self.launcher_instance.unlock_from_launcher, calc_icon)
58 self.launcher_instance.lock_to_launcher(calc_icon)
59 self.close_all_app("Calculator")
60 self.assertThat(lambda: self.app_is_running("Calculator"), Eventually(Equals(False)))
61 return calc_icon
62
63 def get_startup_notification_timestamp(self, bamf_window):
64 atom = display.Display().intern_atom('_NET_WM_USER_TIME')
65 atom_type = display.Display().intern_atom('CARDINAL')
66 return bamf_window.x_win.get_property(atom, atom_type, 0, 1024).value[0]
67
53 def test_bfb_tooltip_disappear_when_dash_is_opened(self):68 def test_bfb_tooltip_disappear_when_dash_is_opened(self):
54 """Tests that the bfb tooltip disappear when the dash is opened."""69 """Tests that the bfb tooltip disappear when the dash is opened."""
55 bfb = self.launcher.model.get_bfb_icon()70 bfb = self.launcher.model.get_bfb_icon()
@@ -123,6 +138,17 @@
123 self.assertThat(lambda: char_win2.is_hidden, Eventually(Equals(True)))138 self.assertThat(lambda: char_win2.is_hidden, Eventually(Equals(True)))
124 self.assertVisibleWindowStack([char_win1, calc_win])139 self.assertVisibleWindowStack([char_win1, calc_win])
125140
141 def test_launcher_uses_startup_notification(self):
142 """Tests that unity uses startup notification protocol."""
143 calc_icon = self.ensure_calculator_in_launcher_and_not_running()
144 self.addCleanup(self.close_all_app, "Calculator")
145 self.launcher_instance.click_launcher_icon(calc_icon)
146
147 calc_app = self.bamf.get_running_applications_by_desktop_file(calc_icon.desktop_id)[0]
148 calc_window = calc_app.get_windows()[0]
149
150 self.assertThat(lambda: self.get_startup_notification_timestamp(calc_window), Eventually(Equals(calc_icon.startup_notification_timestamp)))
151
126 def test_clicking_icon_twice_initiates_spread(self):152 def test_clicking_icon_twice_initiates_spread(self):
127 """This tests shows that when you click on a launcher icon twice,153 """This tests shows that when you click on a launcher icon twice,
128 when an application window is focused, the spread is initiated.154 when an application window is focused, the spread is initiated.