Merge lp:~3v1n0/unity/avoid-duplicate-icons into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Didier Roche-Tolomelli
Approved revision: no longer in the source branch.
Merged at revision: 2345
Proposed branch: lp:~3v1n0/unity/avoid-duplicate-icons
Merge into: lp:unity
Diff against target: 226 lines (+84/-17)
6 files modified
plugins/unityshell/src/BamfLauncherIcon.cpp (+2/-1)
plugins/unityshell/src/LauncherController.cpp (+4/-3)
tests/autopilot/autopilot/emulators/bamf.py (+10/-0)
tests/autopilot/autopilot/emulators/unity/launcher.py (+13/-11)
tests/autopilot/autopilot/tests/__init__.py (+6/-2)
tests/autopilot/autopilot/tests/test_launcher.py (+49/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/avoid-duplicate-icons
Reviewer Review Type Date Requested Status
Michal Hruby (community) Approve
Tim Penhey (community) Approve
Marco Trevisan (Treviño) Pending
Thomi Richards Pending
Review via email: mp+103611@code.launchpad.net

This proposal supersedes a proposal from 2012-04-26.

Commit message

We need to flag a bamf view that we control using an icon using the "unity-seen" qdata, or unity will duplicate it on bamfdaemon respawn. (LP: #928912)

Description of the change

We need to flag a bamf view that we control using an icon using the "unity-seen" qdata, or unity will duplicate it on bamfdaemon respawn.

AP tests included.

This MP was superseeded to use thomi's test fixes from lp:~thomir/unity/avoid-duplicate-icons

To post a comment you must log in.
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote : Posted in a previous version of this proposal

Hi,

Please try and replace the call() lines with this:

call("kill `pidof %s`" % (app['process-name']), shell=True)

Don't use pkill -f - it's dangerous. Once making these changes, please ensure that all the tests still pass.

130 + self.start_app("Calculator")
131 + self.start_app("System Settings")
132 + os.spawnlp(os.P_NOWAIT, "xterm", "xterm", "-title", "Autopilot XTerm", "-e", "sh")
133 + self.addCleanup(call, ["killall", "xterm"])
134 +
135 + # FIXME bamf emulator should wait until a window is open
136 + sleep(1)
137 + [xterm_win] = [w for w in self.bamf.get_open_windows() if w.name == "Autopilot XTerm"]
138 + self.assertTrue(xterm_win.is_focused)

Please put all this in a method called "start_test_apps or something similar, then call it from your test.

154 + same_desktop = [i for i in bamf_icons if i.desktop_file == icon.desktop_file]
155 + self.assertThat(len(same_desktop), Equals(1))

Can you use 'get_icon_by_desktop_file' on the launcher model, to avoid this?

157 + same_appid = [i for i in bamf_icons if i.application_id == icon.application_id]
158 + self.assertThat(len(same_appid), Equals(1))

Similar thing here... we should probable add something to the launcher model like this:

def get_icon_by_filter(self, **kwargs):
        """Gets a launcher icon that matches the filter specified.

        Returns None if there is no such launcher icon.
        """
        icons = self.get_children_by_type(SimpleLauncherIcon, **kwargs)
        if len(icons):
            return icons[0]

        return None

review: Needs Fixing
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal

+1

review: Approve
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote : Posted in a previous version of this proposal

This has a few problems:

1) I can't verify this without the libbamf fix (remember this isn't my branch, I'm just fixing the AP tests).
2) (possibly the same as above) - unity keeps the xclock icon around forever.

review: Needs Fixing
Revision history for this message
Tim Penhey (thumper) wrote :

Looks like the requested changes were done.

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

No commit message specified.

Revision history for this message
Michal Hruby (mhr3) wrote :

The unity side looks safe, tests pass with the not-yet-merged bamf branch.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
2--- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-04-26 05:56:55 +0000
3+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-04-26 06:48:19 +0000
4@@ -144,7 +144,7 @@
5 {
6 g_object_set_qdata(G_OBJECT(_bamf_app.RawPtr()),
7 g_quark_from_static_string("unity-seen"),
8- GINT_TO_POINTER(0));
9+ GUINT_TO_POINTER(0));
10
11 if (_fill_supported_types_id != 0)
12 g_source_remove(_fill_supported_types_id);
13@@ -500,6 +500,7 @@
14 variant::BuilderWrapper(builder)
15 .add("desktop_file", DesktopFile())
16 .add("desktop_id", GetDesktopID())
17+ .add("application_id", GPOINTER_TO_UINT(_bamf_app.RawPtr()))
18 .add("xids", g_variant_builder_end(&xids_builder))
19 .add("sticky", IsSticky());
20 }
21
22=== modified file 'plugins/unityshell/src/LauncherController.cpp'
23--- plugins/unityshell/src/LauncherController.cpp 2012-04-24 21:57:01 +0000
24+++ plugins/unityshell/src/LauncherController.cpp 2012-04-26 06:48:19 +0000
25@@ -740,6 +740,7 @@
26 return;
27 }
28
29+ g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GUINT_TO_POINTER(1));
30 AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
31 icon->visibility_changed.connect(sigc::mem_fun(self, &Impl::SortAndUpdate));
32 icon->SetSortPriority(self->sort_priority_++);
33@@ -762,9 +763,8 @@
34 return result;
35 }
36
37- g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1));
38-
39 bamf_view_set_sticky(BAMF_VIEW(app), true);
40+ g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GUINT_TO_POINTER(1));
41 AbstractLauncherIcon::Ptr icon (new BamfLauncherIcon(app));
42 icon->SetSortPriority(sort_priority_++);
43 result = icon;
44@@ -790,6 +790,7 @@
45 }
46
47 bamf_view_set_sticky(BAMF_VIEW(app), true);
48+ g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GUINT_TO_POINTER(1));
49 result = new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path);
50 result->SetSortPriority(sort_priority_++);
51
52@@ -831,8 +832,8 @@
53
54 if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
55 continue;
56- g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1));
57
58+ g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GUINT_TO_POINTER(1));
59 AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
60 icon->SetSortPriority(sort_priority_++);
61 RegisterIcon(icon);
62
63=== modified file 'tests/autopilot/autopilot/emulators/bamf.py'
64--- tests/autopilot/autopilot/emulators/bamf.py 2012-04-16 00:34:04 +0000
65+++ tests/autopilot/autopilot/emulators/bamf.py 2012-04-26 06:48:19 +0000
66@@ -254,6 +254,16 @@
67 return self._x_win
68
69 @property
70+ def name(self):
71+ """Get the window name.
72+
73+ Note: This may change according to the current locale. If you want a unique
74+ string to match windows against, use the x_id instead.
75+
76+ """
77+ return self._view_iface.Name()
78+
79+ @property
80 def title(self):
81 """Get the window title.
82
83
84=== modified file 'tests/autopilot/autopilot/emulators/unity/launcher.py'
85--- tests/autopilot/autopilot/emulators/unity/launcher.py 2012-04-23 16:41:53 +0000
86+++ tests/autopilot/autopilot/emulators/unity/launcher.py 2012-04-26 06:48:19 +0000
87@@ -327,17 +327,6 @@
88 return icon
89 return None
90
91- def get_icon_by_desktop_file(self, desktop_file):
92- """Gets a launcher icon with the specified desktop file.
93-
94- Returns None if there is no such launcher icon.
95- """
96- icons = self.get_children_by_type(SimpleLauncherIcon, desktop_file=desktop_file)
97- if len(icons):
98- return icons[0]
99-
100- return None
101-
102 def get_icon_by_desktop_id(self, desktop_id):
103 """Gets a launcher icon with the specified desktop id.
104
105@@ -349,6 +338,19 @@
106
107 return None
108
109+ def get_icons_by_filter(self, **kwargs):
110+ """Get a list of icons that satisfy the given filters.
111+
112+ For example:
113+
114+ >>> get_icons_by_filter(tooltip_text="My Application")
115+ ... [...]
116+
117+ Returns an empty list if no icons matched the filter.
118+
119+ """
120+ return self.get_children_by_type(SimpleLauncherIcon, **kwargs)
121+
122 def num_launcher_icons(self):
123 """Get the number of icons in the launcher model."""
124 return len(self.get_launcher_icons())
125
126=== modified file 'tests/autopilot/autopilot/tests/__init__.py'
127--- tests/autopilot/autopilot/tests/__init__.py 2012-04-24 22:26:55 +0000
128+++ tests/autopilot/autopilot/tests/__init__.py 2012-04-26 06:48:19 +0000
129@@ -224,6 +224,10 @@
130 'desktop-file': 'remmina.desktop',
131 'process-name': 'remmina',
132 },
133+ 'System Settings' : {
134+ 'desktop-file': 'gnome-control-center.desktop',
135+ 'process-name': 'gnome-control-center',
136+ },
137 'Text Editor' : {
138 'desktop-file': 'gedit.desktop',
139 'process-name': 'gedit',
140@@ -266,14 +270,14 @@
141 app = self.KNOWN_APPS[app_name]
142 self.bamf.launch_application(app['desktop-file'], files)
143 apps = self.bamf.get_running_applications_by_desktop_file(app['desktop-file'])
144- self.addCleanup(call, ["killall", app['process-name']])
145+ self.addCleanup(call, "kill `pidof %s`" % (app['process-name']), shell=True)
146 self.assertThat(len(apps), Equals(1))
147 return apps[0]
148
149 def close_all_app(self, app_name):
150 """Close all instances of the app_name."""
151 app = self.KNOWN_APPS[app_name]
152- call(["killall", app['process-name']])
153+ self.addCleanup(call, "kill `pidof %s`" % (app['process-name']), shell=True)
154 super(LoggedTestCase, self).tearDown()
155
156 def get_app_instances(self, app_name):
157
158=== modified file 'tests/autopilot/autopilot/tests/test_launcher.py'
159--- tests/autopilot/autopilot/tests/test_launcher.py 2012-04-23 16:41:53 +0000
160+++ tests/autopilot/autopilot/tests/test_launcher.py 2012-04-26 06:48:19 +0000
161@@ -8,9 +8,12 @@
162 # by the Free Software Foundation.
163
164 import logging
165+import os
166+from subprocess import call
167 from testtools.matchers import Equals, NotEquals, LessThan, GreaterThan
168 from time import sleep
169
170+from autopilot.emulators.bamf import Bamf
171 from autopilot.emulators.unity.icons import BFBLauncherIcon
172 from autopilot.emulators.X11 import ScreenGeometry
173 from autopilot.matchers import Eventually
174@@ -568,6 +571,52 @@
175 for icon in self.launcher.model.get_launcher_icons():
176 self.assertThat(icon.desaturated, Eventually(Equals(False)))
177
178+class BamfDaemonTests(LauncherTestCase):
179+ """Test interaction between the launcher and the BAMF Daemon."""
180+
181+ def start_test_apps(self):
182+ """Starts some test applications."""
183+ self.start_app("Calculator")
184+ self.start_app("System Settings")
185+
186+ def get_test_apps(self):
187+ """Return a tuple of test application instances.
188+
189+ We don't store these since when we kill the bamf daemon all references
190+ to the old apps will die.
191+
192+ """
193+ [calc] = self.get_app_instances("Calculator")
194+ [sys_settings] = self.get_app_instances("System Settings")
195+ return (calc, sys_settings)
196+
197+ def assertOnlyOneLauncherIcon(self, **kwargs):
198+ """Asserts that there is only one launcher icon with the given filter."""
199+ icons = self.launcher.model.get_icons_by_filter(**kwargs)
200+ self.assertThat(len(icons), Equals(1))
201+
202+ def wait_for_bamf_daemon(self):
203+ """Wait until the bamf daemon has been started."""
204+ for i in range(10):
205+ #pgrep returns 0 if it matched something:
206+ if call(["pgrep", "bamfdaemon"]) == 0:
207+ return
208+ sleep(1)
209+
210+ def test_killing_bamfdaemon_does_not_duplicate_desktop_ids(self):
211+ """Killing bamfdaemon should not duplicate any desktop ids in the model."""
212+ self.start_test_apps()
213+
214+ call(["pkill", "bamfdaemon"])
215+ sleep(1)
216+
217+ # trigger the bamfdaemon to be reloaded again, and wait for it to appear:
218+ self.bamf = Bamf()
219+ self.wait_for_bamf_daemon()
220+
221+ for test_app in self.get_test_apps():
222+ self.assertOnlyOneLauncherIcon(desktop_id=test_app.desktop_file)
223+
224
225 class LauncherCaptureTests(AutopilotTestCase):
226 """Test the launchers ability to capture/not capture the mouse."""