Merge lp:~3v1n0/unity/app-icon-ensure-on-running into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 2836
Proposed branch: lp:~3v1n0/unity/app-icon-ensure-on-running
Merge into: lp:unity
Diff against target: 508 lines (+347/-18)
6 files modified
launcher/ApplicationLauncherIcon.cpp (+22/-8)
tests/CMakeLists.txt (+1/-0)
tests/bamf-mock-application.c (+201/-0)
tests/bamf-mock-application.h (+77/-0)
tests/test_application_launcher_icon.cpp (+43/-8)
tests/test_launcher_controller.cpp (+3/-2)
To merge this branch: bzr merge lp:~3v1n0/unity/app-icon-ensure-on-running
Reviewer Review Type Date Requested Status
jenkins (community) continuous-integration Needs Fixing
Brandon Schaefer (community) Approve
Review via email: mp+129469@code.launchpad.net

Commit message

ApplicationLauncherIcon: ensure the icon and name values when the running state changes

This avoids to get "?" icons

Description of the change

It can happen that a bamf view is opened for very few ms after being closed and again reopened, in that case unity is sometimes not enough fast to cache the view's name and icon.
So as soon as this gets running again we should update these values.

Added a new mock bamf application to allow testing of this, plus new unit tests.

To post a comment you must log in.
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

The code looks good, the fix is in the first 80 line of the diff. Most of it is testing, which is good :)

review: Approve
Revision history for this message
jenkins (martin-mrazik+qa) 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-10-04 08:00:29 +0000
3+++ launcher/ApplicationLauncherIcon.cpp 2012-10-12 16:30:44 +0000
4@@ -79,7 +79,7 @@
5 glib::SignalBase* sig;
6
7 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-added",
8- [&] (BamfView*, BamfView*) {
9+ [this] (BamfView*, BamfView*) {
10 EnsureWindowState();
11 UpdateMenus();
12 UpdateIconGeometries(GetCenters());
13@@ -87,7 +87,7 @@
14 _gsignals.Add(sig);
15
16 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",
17- [&] (BamfView*, BamfView*) { EnsureWindowState(); });
18+ [this] (BamfView*, BamfView*) { EnsureWindowState(); });
19 _gsignals.Add(sig);
20
21 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-moved",
22@@ -97,39 +97,53 @@
23 _gsignals.Add(sig);
24
25 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "urgent-changed",
26- [&] (BamfView*, gboolean urgent) {
27+ [this] (BamfView*, gboolean urgent) {
28 SetQuirk(Quirk::URGENT, urgent);
29 });
30 _gsignals.Add(sig);
31
32 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "active-changed",
33- [&] (BamfView*, gboolean active) {
34+ [this] (BamfView*, gboolean active) {
35 SetQuirk(Quirk::ACTIVE, active);
36 });
37 _gsignals.Add(sig);
38
39 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "running-changed",
40- [&] (BamfView*, gboolean running) {
41+ [this] (BamfView* view, gboolean running) {
42 SetQuirk(Quirk::RUNNING, running);
43
44 if (running)
45 {
46+ _source_manager.Remove(ICON_REMOVE_TIMEOUT);
47+
48+ /* It can happen that these values are not set
49+ * during initialization if the view is closed
50+ * very early, so we need to make sure that they
51+ * are updated as soon as the view is re-opened. */
52+ if (tooltip_text().empty())
53+ tooltip_text = BamfName();
54+
55+ if (icon_name == DEFAULT_ICON)
56+ {
57+ glib::String icon(bamf_view_get_icon(view));
58+ icon_name = (icon ? icon.Str() : DEFAULT_ICON);
59+ }
60+
61 EnsureWindowState();
62 UpdateIconGeometries(GetCenters());
63- _source_manager.Remove(ICON_REMOVE_TIMEOUT);
64 }
65 });
66 _gsignals.Add(sig);
67
68 sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "user-visible-changed",
69- [&] (BamfView*, gboolean visible) {
70+ [this] (BamfView*, gboolean visible) {
71 if (!IsSticky())
72 SetQuirk(Quirk::VISIBLE, visible);
73 });
74 _gsignals.Add(sig);
75
76 sig = new glib::Signal<void, BamfView*>(bamf_view, "closed",
77- [&] (BamfView*) {
78+ [this] (BamfView*) {
79 if (!IsSticky())
80 {
81 SetQuirk(Quirk::VISIBLE, false);
82
83=== modified file 'tests/CMakeLists.txt'
84--- tests/CMakeLists.txt 2012-10-09 09:48:07 +0000
85+++ tests/CMakeLists.txt 2012-10-12 16:30:44 +0000
86@@ -244,6 +244,7 @@
87 test_unity_settings.cpp
88 test_volume_imp.cpp
89 test_volume_launcher_icon.cpp
90+ bamf-mock-application.c
91 gmockmount.c
92 gmockvolume.c
93 ${CMAKE_SOURCE_DIR}/dash/DashViewPrivate.cpp
94
95=== added file 'tests/bamf-mock-application.c'
96--- tests/bamf-mock-application.c 1970-01-01 00:00:00 +0000
97+++ tests/bamf-mock-application.c 2012-10-12 16:30:44 +0000
98@@ -0,0 +1,201 @@
99+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
100+/*
101+ * Copyright 2012 Canonical Ltd.
102+ *
103+ * This program is free software: you can redistribute it and/or modify it
104+ * under the terms of the GNU Lesser General Public License version 3, as
105+ * published by the Free Software Foundation.
106+ *
107+ * This program is distributed in the hope that it will be useful, but
108+ * WITHOUT ANY WARRANTY; without even the implied warranties of
109+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
110+ * PURPOSE. See the applicable version of the GNU Lesser General Public
111+ * License for more details.
112+ *
113+ * You should have received a copy of both the GNU Lesser General Public
114+ * License version 3 along with this program. If not, see
115+ * <http://www.gnu.org/licenses/>
116+ *
117+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
118+ *
119+ */
120+
121+#include "bamf-mock-application.h"
122+
123+G_DEFINE_TYPE (BamfMockApplication, bamf_mock_application, BAMF_TYPE_APPLICATION);
124+
125+#define BAMF_MOCK_APPLICATION_GET_PRIVATE(o) \
126+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), BAMF_TYPE_MOCK_APPLICATION, BamfMockApplicationPrivate))
127+
128+struct _BamfMockApplicationPrivate
129+{
130+ gboolean active;
131+ gboolean running;
132+ gboolean urgent;
133+ gchar * name;
134+ gchar * icon;
135+ GList * children;
136+};
137+
138+void
139+bamf_mock_application_set_active (BamfMockApplication * self, gboolean active)
140+{
141+ g_return_if_fail (BAMF_IS_MOCK_APPLICATION (self));
142+
143+ if (self->priv->active != active)
144+ {
145+ self->priv->active = active;
146+ g_signal_emit_by_name (G_OBJECT (self), "active-changed", active, NULL);
147+ }
148+}
149+
150+void
151+bamf_mock_application_set_running (BamfMockApplication * self, gboolean running)
152+{
153+ g_return_if_fail (BAMF_IS_MOCK_APPLICATION (self));
154+
155+ if (self->priv->running != running)
156+ {
157+ self->priv->running = running;
158+ g_signal_emit_by_name (G_OBJECT (self), "running-changed", running, NULL);
159+ }
160+}
161+
162+void
163+bamf_mock_application_set_urgent (BamfMockApplication * self, gboolean urgent)
164+{
165+ g_return_if_fail (BAMF_IS_MOCK_APPLICATION (self));
166+
167+ if (self->priv->urgent != urgent)
168+ {
169+ self->priv->urgent = urgent;
170+ g_signal_emit_by_name (G_OBJECT (self), "urgent-changed", urgent, NULL);
171+ }
172+}
173+
174+void
175+bamf_mock_application_set_name (BamfMockApplication * self, const gchar * name)
176+{
177+ g_return_if_fail (BAMF_IS_MOCK_APPLICATION (self));
178+
179+ if (g_strcmp0 (self->priv->name, name) != 0)
180+ {
181+ char *old = self->priv->name;
182+ self->priv->name = g_strdup (name);
183+ g_signal_emit_by_name (G_OBJECT (self), "name-changed", old, self->priv->name, NULL);
184+ g_free (old);
185+ }
186+}
187+
188+void
189+bamf_mock_application_set_icon (BamfMockApplication * self, const gchar * icon)
190+{
191+ g_return_if_fail (BAMF_IS_MOCK_APPLICATION (self));
192+
193+ g_free (self->priv->icon);
194+ self->priv->icon = g_strdup (icon);
195+}
196+
197+void
198+bamf_mock_application_set_children (BamfMockApplication * self, GList * children)
199+{
200+ g_return_if_fail (BAMF_IS_MOCK_APPLICATION (self));
201+
202+ g_list_free (self->priv->children);
203+ self->priv->children = g_list_copy (children);
204+}
205+
206+static void
207+bamf_mock_application_finalize (GObject *object)
208+{
209+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (object);
210+
211+ g_free (self->priv->name);
212+ g_free (self->priv->icon);
213+ g_list_free (self->priv->children);
214+}
215+
216+static GList *
217+bamf_mock_application_get_children (BamfView *view)
218+{
219+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), NULL);
220+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (view);
221+ return g_list_copy (self->priv->children);
222+}
223+
224+static gboolean
225+bamf_mock_application_is_active (BamfView *view)
226+{
227+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), FALSE);
228+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (view);
229+ return self->priv->active;
230+}
231+
232+static gboolean
233+bamf_mock_application_is_running (BamfView *view)
234+{
235+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), FALSE);
236+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (view);
237+ return self->priv->running;
238+}
239+
240+static gboolean
241+bamf_mock_application_is_urgent (BamfView *view)
242+{
243+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), FALSE);
244+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (view);
245+ return self->priv->urgent;
246+}
247+
248+static char *
249+bamf_mock_application_get_name (BamfView *view)
250+{
251+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), NULL);
252+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (view);
253+ return g_strdup (self->priv->name);
254+}
255+
256+static char *
257+bamf_mock_application_get_icon (BamfView *view)
258+{
259+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), NULL);
260+ BamfMockApplication *self = BAMF_MOCK_APPLICATION (view);
261+ return g_strdup (self->priv->icon);
262+}
263+
264+static const char *
265+bamf_mock_application_view_type (BamfView *view)
266+{
267+ g_return_val_if_fail (BAMF_IS_MOCK_APPLICATION (view), NULL);
268+ return "mock-application";
269+}
270+
271+static void
272+bamf_mock_application_class_init (BamfMockApplicationClass *klass)
273+{
274+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
275+ BamfViewClass *view_class = BAMF_VIEW_CLASS (klass);
276+
277+ obj_class->finalize = bamf_mock_application_finalize;
278+ view_class->get_children = bamf_mock_application_get_children;
279+ view_class->is_active = bamf_mock_application_is_active;
280+ view_class->is_running = bamf_mock_application_is_running;
281+ view_class->is_urgent = bamf_mock_application_is_urgent;
282+ view_class->get_name = bamf_mock_application_get_name;
283+ view_class->get_icon = bamf_mock_application_get_icon;
284+ view_class->view_type = bamf_mock_application_view_type;
285+
286+ g_type_class_add_private (obj_class, sizeof (BamfMockApplicationPrivate));
287+}
288+
289+static void
290+bamf_mock_application_init (BamfMockApplication *self)
291+{
292+ self->priv = BAMF_MOCK_APPLICATION_GET_PRIVATE (self);
293+}
294+
295+BamfMockApplication *
296+bamf_mock_application_new ()
297+{
298+ return g_object_new (BAMF_TYPE_MOCK_APPLICATION, NULL);
299+}
300\ No newline at end of file
301
302=== added file 'tests/bamf-mock-application.h'
303--- tests/bamf-mock-application.h 1970-01-01 00:00:00 +0000
304+++ tests/bamf-mock-application.h 2012-10-12 16:30:44 +0000
305@@ -0,0 +1,77 @@
306+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
307+/*
308+ * Copyright 2012 Canonical Ltd.
309+ *
310+ * This program is free software: you can redistribute it and/or modify it
311+ * under the terms of the GNU Lesser General Public License version 3, as
312+ * published by the Free Software Foundation.
313+ *
314+ * This program is distributed in the hope that it will be useful, but
315+ * WITHOUT ANY WARRANTY; without even the implied warranties of
316+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
317+ * PURPOSE. See the applicable version of the GNU Lesser General Public
318+ * License for more details.
319+ *
320+ * You should have received a copy of both the GNU Lesser General Public
321+ * License version 3 along with this program. If not, see
322+ * <http://www.gnu.org/licenses/>
323+ *
324+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
325+ *
326+ */
327+
328+#ifndef MOCK_BAMF_MOCK_APPLICATION
329+#define MOCK_BAMF_MOCK_APPLICATION
330+
331+#include <libbamf/libbamf.h>
332+
333+G_BEGIN_DECLS
334+
335+#define BAMF_TYPE_MOCK_APPLICATION (bamf_mock_application_get_type ())
336+
337+#define BAMF_MOCK_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
338+ BAMF_TYPE_MOCK_APPLICATION, BamfMockApplication))
339+
340+#define BAMF_MOCK_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
341+ BAMF_TYPE_MOCK_APPLICATION, BamfMockApplicationClass))
342+
343+#define BAMF_IS_MOCK_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
344+ BAMF_TYPE_MOCK_APPLICATION))
345+
346+#define BAMF_IS_MOCK_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
347+ BAMF_TYPE_MOCK_APPLICATION))
348+
349+#define BAMF_MOCK_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
350+ BAMF_TYPE_MOCK_APPLICATION, BamfMockApplicationClass))
351+
352+typedef struct _BamfMockApplication BamfMockApplication;
353+typedef struct _BamfMockApplicationClass BamfMockApplicationClass;
354+typedef struct _BamfMockApplicationPrivate BamfMockApplicationPrivate;
355+
356+struct _BamfMockApplication
357+{
358+ BamfApplication parent;
359+
360+ BamfMockApplicationPrivate *priv;
361+};
362+
363+struct _BamfMockApplicationClass
364+{
365+ BamfApplicationClass parent_class;
366+};
367+
368+GType bamf_mock_application_get_type (void) G_GNUC_CONST;
369+
370+BamfMockApplication * bamf_mock_application_new ();
371+
372+void bamf_mock_application_set_active (BamfMockApplication * self, gboolean active);
373+void bamf_mock_application_set_running (BamfMockApplication * self, gboolean running);
374+void bamf_mock_application_set_urgent (BamfMockApplication * self, gboolean urgent);
375+void bamf_mock_application_set_name (BamfMockApplication * self, const gchar * name);
376+void bamf_mock_application_set_icon (BamfMockApplication * self, const gchar * icon);
377+void bamf_mock_application_set_children (BamfMockApplication * self, GList * children);
378+
379+G_END_DECLS
380+
381+#endif
382+
383
384=== modified file 'tests/test_application_launcher_icon.cpp'
385--- tests/test_application_launcher_icon.cpp 2012-10-04 08:00:29 +0000
386+++ tests/test_application_launcher_icon.cpp 2012-10-12 16:30:44 +0000
387@@ -27,6 +27,7 @@
388
389 #include "ApplicationLauncherIcon.h"
390 #include "FavoriteStore.h"
391+#include "bamf-mock-application.h"
392
393 using namespace unity;
394 using namespace unity::launcher;
395@@ -34,6 +35,7 @@
396 namespace
397 {
398
399+const std::string DEFAULT_EMPTY_ICON = "application-default-icon";
400 const std::string USC_DESKTOP = BUILDDIR"/tests/data/applications/ubuntu-software-center.desktop";
401 const std::string NO_ICON_DESKTOP = BUILDDIR"/tests/data/applications/no-icon.desktop";
402
403@@ -53,15 +55,16 @@
404 empty_icon = new launcher::ApplicationLauncherIcon(bamf_app);
405 ASSERT_EQ(empty_icon->DesktopFile(), NO_ICON_DESKTOP);
406
407- bamf_app = static_cast<BamfApplication*>(g_object_new(BAMF_TYPE_APPLICATION, nullptr));
408- empty_app = new launcher::ApplicationLauncherIcon(bamf_app);
409- ASSERT_TRUE(empty_app->DesktopFile().empty());
410+ mock_app = bamf_mock_application_new();
411+ mock_icon = new launcher::ApplicationLauncherIcon(glib::object_cast<BamfApplication>(mock_app));
412+ ASSERT_TRUE(mock_icon->DesktopFile().empty());
413 }
414
415 glib::Object<BamfMatcher> bamf_matcher;
416+ glib::Object<BamfMockApplication> mock_app;
417 nux::ObjectPtr<launcher::ApplicationLauncherIcon> usc_icon;
418 nux::ObjectPtr<launcher::ApplicationLauncherIcon> empty_icon;
419- nux::ObjectPtr<launcher::ApplicationLauncherIcon> empty_app;
420+ nux::ObjectPtr<launcher::ApplicationLauncherIcon> mock_icon;
421 };
422
423 TEST_F(TestApplicationLauncherIcon, Position)
424@@ -81,9 +84,9 @@
425
426 TEST_F(TestApplicationLauncherIcon, TestDefaultIcon)
427 {
428- EXPECT_EQ(usc_icon->icon_name.Get(), "softwarecenter");
429- EXPECT_EQ(empty_icon->icon_name.Get(), "application-default-icon");
430- EXPECT_EQ(empty_app->icon_name.Get(), "application-default-icon");
431+ EXPECT_EQ(usc_icon->icon_name(), "softwarecenter");
432+ EXPECT_EQ(empty_icon->icon_name(), DEFAULT_EMPTY_ICON);
433+ EXPECT_EQ(mock_icon->icon_name(), DEFAULT_EMPTY_ICON);
434 }
435
436 TEST_F(TestApplicationLauncherIcon, Stick)
437@@ -143,7 +146,39 @@
438 TEST_F(TestApplicationLauncherIcon, RemoteUri)
439 {
440 EXPECT_EQ(usc_icon->RemoteUri(), FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(USC_DESKTOP));
441- EXPECT_TRUE(empty_app->RemoteUri().empty());
442+ EXPECT_TRUE(mock_icon->RemoteUri().empty());
443+}
444+
445+TEST_F(TestApplicationLauncherIcon, EmptyTooltipUpdatesOnRunning)
446+{
447+ ASSERT_TRUE(mock_icon->tooltip_text().empty());
448+ bamf_mock_application_set_name (mock_app, "Got Name");
449+
450+ ASSERT_TRUE(mock_icon->tooltip_text().empty());
451+
452+ bamf_mock_application_set_running(mock_app, TRUE);
453+ EXPECT_EQ(mock_icon->tooltip_text(), "Got Name");
454+
455+ bamf_mock_application_set_running(mock_app, FALSE);
456+ bamf_mock_application_set_name (mock_app, "New Name");
457+ bamf_mock_application_set_running(mock_app, TRUE);
458+ EXPECT_EQ(mock_icon->tooltip_text(), "Got Name");
459+}
460+
461+TEST_F(TestApplicationLauncherIcon, InvalidIconUpdatesOnRunning)
462+{
463+ ASSERT_EQ(mock_icon->icon_name(), DEFAULT_EMPTY_ICON);
464+ bamf_mock_application_set_icon (mock_app, "icon-name");
465+
466+ ASSERT_EQ(mock_icon->icon_name(), DEFAULT_EMPTY_ICON);
467+
468+ bamf_mock_application_set_running(mock_app, TRUE);
469+ EXPECT_EQ(mock_icon->icon_name(), "icon-name");
470+
471+ bamf_mock_application_set_running(mock_app, FALSE);
472+ bamf_mock_application_set_icon (mock_app, "new-icon-name");
473+ bamf_mock_application_set_running(mock_app, TRUE);
474+ EXPECT_EQ(mock_icon->icon_name(), "icon-name");
475 }
476
477 }
478
479=== modified file 'tests/test_launcher_controller.cpp'
480--- tests/test_launcher_controller.cpp 2012-10-04 08:00:29 +0000
481+++ tests/test_launcher_controller.cpp 2012-10-12 16:30:44 +0000
482@@ -18,7 +18,6 @@
483 */
484
485 #include <gmock/gmock.h>
486-#include "test_uscreen_mock.h"
487
488 #include "FavoriteStore.h"
489 #include "LauncherController.h"
490@@ -34,7 +33,9 @@
491 #include "PanelStyle.h"
492 #include "UnitySettings.h"
493 #include "test_utils.h"
494+#include "test_uscreen_mock.h"
495 #include "test_mock_devices.h"
496+#include "bamf-mock-application.h"
497
498 using namespace unity::launcher;
499 using namespace testing;
500@@ -131,7 +132,7 @@
501 typedef bool Fake;
502
503 MockApplicationLauncherIcon(Fake = true, std::string const& remote_uri = "")
504- : ApplicationLauncherIcon(static_cast<BamfApplication*>(g_object_new(BAMF_TYPE_APPLICATION, nullptr)))
505+ : ApplicationLauncherIcon(BAMF_APPLICATION(bamf_mock_application_new()))
506 , remote_uri_(remote_uri)
507 {
508 InitMock();