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
1=== modified file 'launcher/ApplicationLauncherIcon.cpp'
2--- launcher/ApplicationLauncherIcon.cpp 2012-12-18 17:57:48 +0000
3+++ launcher/ApplicationLauncherIcon.cpp 2013-01-22 01:30:30 +0000
4@@ -58,6 +58,7 @@
5 ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
6 : SimpleLauncherIcon(IconType::APPLICATION)
7 , app_(app)
8+ , _startup_notification_timestamp(0)
9 , use_custom_bg_color_(false)
10 , bg_color_(nux::color::White)
11 {
12@@ -479,16 +480,22 @@
13 .add("desktop_file", DesktopFile())
14 .add("desktop_id", GetDesktopID())
15 .add("xids", g_variant_builder_end(&xids_builder))
16- .add("sticky", IsSticky());
17+ .add("sticky", IsSticky())
18+ .add("startup_notification_timestamp", _startup_notification_timestamp);
19 }
20
21-
22 void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris)
23 {
24 glib::Error error;
25 glib::Object<GDesktopAppInfo> desktopInfo(g_desktop_app_info_new_from_filename(DesktopFile().c_str()));
26 auto appInfo = glib::object_cast<GAppInfo>(desktopInfo);
27
28+ GdkDisplay* display = gdk_display_get_default();
29+ glib::Object<GdkAppLaunchContext> app_launch_context(gdk_display_get_app_launch_context(display));
30+
31+ _startup_notification_timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
32+ gdk_app_launch_context_set_timestamp(app_launch_context, _startup_notification_timestamp);
33+
34 if (g_app_info_supports_uris(appInfo))
35 {
36 GList* list = nullptr;
37@@ -496,7 +503,7 @@
38 for (auto it : uris)
39 list = g_list_prepend(list, g_strdup(it.c_str()));
40
41- g_app_info_launch_uris(appInfo, list, nullptr, &error);
42+ g_app_info_launch_uris(appInfo, list, glib::object_cast<GAppLaunchContext>(app_launch_context), &error);
43 g_list_free_full(list, g_free);
44 }
45 else if (g_app_info_supports_files(appInfo))
46@@ -509,12 +516,12 @@
47 list = g_list_prepend(list, file);
48 }
49
50- g_app_info_launch(appInfo, list, nullptr, &error);
51+ g_app_info_launch(appInfo, list, glib::object_cast<GAppLaunchContext>(app_launch_context), &error);
52 g_list_free_full(list, g_object_unref);
53 }
54 else
55 {
56- g_app_info_launch(appInfo, nullptr, nullptr, &error);
57+ g_app_info_launch(appInfo, nullptr, glib::object_cast<GAppLaunchContext>(app_launch_context), &error);
58 }
59
60 if (error)
61
62=== modified file 'launcher/ApplicationLauncherIcon.h'
63--- launcher/ApplicationLauncherIcon.h 2012-12-05 10:24:53 +0000
64+++ launcher/ApplicationLauncherIcon.h 2013-01-22 01:30:30 +0000
65@@ -123,6 +123,7 @@
66 std::string GetDesktopID();
67
68 std::string _remote_uri;
69+ Time _startup_notification_timestamp;
70 std::set<std::string> _supported_types;
71 std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients;
72 std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items;
73
74=== modified file 'tests/autopilot/unity/tests/launcher/test_icon_behavior.py'
75--- tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2013-01-14 10:58:35 +0000
76+++ tests/autopilot/unity/tests/launcher/test_icon_behavior.py 2013-01-22 01:30:30 +0000
77@@ -19,6 +19,7 @@
78 from unity.emulators.launcher import IconDragType
79 from unity.tests.launcher import LauncherTestCase, _make_scenarios
80
81+from Xlib import display
82 from Xlib import Xutil
83
84 logger = logging.getLogger(__name__)
85@@ -50,6 +51,20 @@
86
87 return icon
88
89+ def ensure_calculator_in_launcher_and_not_running(self):
90+ calc = self.start_app("Calculator")
91+ calc_icon = self.launcher.model.get_icon(desktop_id=calc.desktop_file)
92+ self.addCleanup(self.launcher_instance.unlock_from_launcher, calc_icon)
93+ self.launcher_instance.lock_to_launcher(calc_icon)
94+ self.close_all_app("Calculator")
95+ self.assertThat(lambda: self.app_is_running("Calculator"), Eventually(Equals(False)))
96+ return calc_icon
97+
98+ def get_startup_notification_timestamp(self, bamf_window):
99+ atom = display.Display().intern_atom('_NET_WM_USER_TIME')
100+ atom_type = display.Display().intern_atom('CARDINAL')
101+ return bamf_window.x_win.get_property(atom, atom_type, 0, 1024).value[0]
102+
103 def test_bfb_tooltip_disappear_when_dash_is_opened(self):
104 """Tests that the bfb tooltip disappear when the dash is opened."""
105 bfb = self.launcher.model.get_bfb_icon()
106@@ -123,6 +138,17 @@
107 self.assertThat(lambda: char_win2.is_hidden, Eventually(Equals(True)))
108 self.assertVisibleWindowStack([char_win1, calc_win])
109
110+ def test_launcher_uses_startup_notification(self):
111+ """Tests that unity uses startup notification protocol."""
112+ calc_icon = self.ensure_calculator_in_launcher_and_not_running()
113+ self.addCleanup(self.close_all_app, "Calculator")
114+ self.launcher_instance.click_launcher_icon(calc_icon)
115+
116+ calc_app = self.bamf.get_running_applications_by_desktop_file(calc_icon.desktop_id)[0]
117+ calc_window = calc_app.get_windows()[0]
118+
119+ self.assertThat(lambda: self.get_startup_notification_timestamp(calc_window), Eventually(Equals(calc_icon.startup_notification_timestamp)))
120+
121 def test_clicking_icon_twice_initiates_spread(self):
122 """This tests shows that when you click on a launcher icon twice,
123 when an application window is focused, the spread is initiated.