Merge lp:~desrt/indicator-appmenu/hud-rewrite-wip into lp:indicator-appmenu/0.4

Proposed by Allison Karlitskaya
Status: Merged
Approved by: Charles Kerr
Approved revision: 237
Merged at revision: 185
Proposed branch: lp:~desrt/indicator-appmenu/hud-rewrite-wip
Merge into: lp:indicator-appmenu/0.4
Diff against target: 1267 lines (+635/-44)
16 files modified
configure.ac (+3/-0)
src/Makefile.am (+23/-1)
src/hud-gtk.vala (+3/-1)
src/hud-service.c (+53/-2)
src/hudappindicatorsource.c (+34/-2)
src/huddbusmenucollector.c (+107/-18)
src/huddebugsource.c (+168/-0)
src/huddebugsource.h (+36/-0)
src/hudindicatorsource.c (+49/-5)
src/huditem.c (+1/-0)
src/hudmenumodelcollector.c (+19/-1)
src/hudquery.c (+14/-1)
src/hudsource.c (+46/-0)
src/hudsource.h (+5/-0)
src/hudsourcelist.c (+22/-0)
src/hudwindowsource.c (+52/-13)
To merge this branch: bzr merge lp:~desrt/indicator-appmenu/hud-rewrite-wip
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
Review via email: mp+97716@code.launchpad.net

Description of the change

Add support for XUL be emitting "Opened" signals when a query is active.

Fix a few leaks as well.

To post a comment you must log in.
227. By Allison Karlitskaya

hud-service: HudQuery: add some logging

228. By Allison Karlitskaya

hud-service: HudQuery: don't leak queries

Change the strategy for dealing with the HudQuery being unreffed in the
middle of a pending update in order to avoid leaking queries.

229. By Allison Karlitskaya

hud-service: Give OPENED event for menuitems that change into submenus while a query is in effect

230. By Allison Karlitskaya

Add some paranoid checking

We don't want dbusmenu delivering signals to us while we're iterating
our hashtable, so add an assert about that. It doesn't do so now, but
this will make it easier to detect the problem if it should start doing
so in the future.

231. By Allison Karlitskaya

hud-service: on startup, set the focus window as active

We were waiting for the first active-window-changed signal before we
started tracking window menus. Do it as soon as we start, using the
currently-active-window.

232. By Allison Karlitskaya

add a "debug" source for testing the update signal

we could use this for other testing purposes later on as well

Revision history for this message
Charles Kerr (charlesk) wrote :

Could you fix the text conflict?

review: Needs Fixing
Revision history for this message
Charles Kerr (charlesk) wrote :

* About the text conflict, we could use <glib/gi18n.h> instead of locale.h and libintl.h

* In hud_indicator_source_name_vanished(), I think you meant to invoke hud_source_unuse()?

* I think the answer is probably no, but wanted to ask if hud_window_source's dispose or finalize need to do anything about active_collector or its "changed" signal that hud_window_source connected to.

Revision history for this message
Allison Karlitskaya (desrt) wrote :

> * About the text conflict, we could use <glib/gi18n.h> instead of locale.h and
> libintl.h

How do I resolve conflicts that only exist in merge requests? Do I have to merge up my branch? I guess that's what I'll try...

The intl headers are from Seb's earlier unrelated patch -- they only conflict because I also added a header at the same place. He's not using _() so the glib header is not really required...

> * In hud_indicator_source_name_vanished(), I think you meant to invoke
> hud_source_unuse()?

Yes! Good catch. Thanks :)

> * I think the answer is probably no, but wanted to ask if hud_window_source's
> dispose or finalize need to do anything about active_collector or its
> "changed" signal that hud_window_source connected to.

Strictly speaking, the answer is that I should be doing this. At the same time, though, it's not a bug, because the window source finalizer is never run (since the hud service runs forever and quits by exiting, without freeing the sources). I was already planning to do a bit of a finalizer cleanup so that we could add support for freeing things on exit (to increase valgrindability) so I'll make this change now as well. Thanks.

Revision history for this message
Allison Karlitskaya (desrt) wrote :

Ah. Sorry. Haven't had my coffee yet.

The signal connection does _not_ need to be removed from finalize. If you use g_signal_connect_object() then the signal handler won't fire after the object that you connected it to is disposed. There is an ancient bug in glib where you lose a bit of memory when this happens but .. well, that's a bug in glib (and I hope we fix it some day).

The memory loss is not a leak -- you gain it back again when the object emitting the signal is destroyed.

233. By Allison Karlitskaya

hud-service: indicatorsource: on indicator disappearance *unuse* the dbusmenu instead of using it extra

Probably this has absolutely zero impact since the source is going to be
destroyed one line later anyway, but it reads really badly (and strictly
speaking, the menus should be closed if they've been opened).

234. By Allison Karlitskaya

merge trunk

235. By Allison Karlitskaya

hud-service: add some debug output to the dbus front-end (to help debug unity issues)

236. By Allison Karlitskaya

add hud-gtk to the build system

This introduces a mandatory build-time dependency on Vala 0.15 and gtk3 (both needed for GtkApplication).

237. By Allison Karlitskaya

hud-service: delay dropping of query by 1 second

Unity sends a 'CloseQuery' followed immediately by a 'StartQuery' on
each keystroke in the search field. This results in a bunch of extra
dbusmenu messages being sent as the use count drops briefly to 0 only to
go immediately back to 1.

We can prevent that by delaying the destruction of the query.

This decreases the number of dbus messages resulting from a short search
by a factor of about 4 (on a number that measures in the 100s).

Revision history for this message
Charles Kerr (charlesk) :
review: Approve
238. By Allison Karlitskaya

hud-service: dbusmenu collector: hold a reference on the root menu item

In the root-changed case, the DbusmenuClient drops the reference on the
root item before alerting us that it has changed. We then go iterating
over our own (now-dead) copy of that item in order to remove it from our
internal hashtable.

Keep our own reference to it to ensure that this is safe.

This could explain lp:955937.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2012-03-14 19:39:48 +0000
3+++ configure.ac 2012-03-17 16:16:19 +0000
4@@ -20,6 +20,7 @@
5 # Check for programs
6 AC_PROG_CC
7 AM_PROG_CC_C_O
8+AM_PROG_VALAC([0.15.2])
9
10 # Initialize libtool
11 LT_PREREQ([2.2.6])
12@@ -86,6 +87,8 @@
13 [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
14 )
15
16+PKG_CHECK_MODULES(gtk, gtk+-3.0 >= $GTK3_REQUIRED_VERSION)
17+
18 AC_SUBST(INDICATOR_CFLAGS)
19 AC_SUBST(INDICATOR_LIBS)
20
21
22=== modified file 'src/Makefile.am'
23--- src/Makefile.am 2012-03-05 04:51:36 +0000
24+++ src/Makefile.am 2012-03-17 16:16:19 +0000
25@@ -6,7 +6,8 @@
26
27 bin_PROGRAMS = \
28 hud-dump-application \
29- hud-verify-app-info
30+ hud-verify-app-info \
31+ hud-gtk
32
33 bin_SCRIPTS = \
34 hud-list-applications
35@@ -104,6 +105,8 @@
36 hudindicatorsource.c \
37 hudwindowsource.h \
38 hudwindowsource.c \
39+ huddebugsource.h \
40+ huddebugsource.c \
41 hudsourcelist.h \
42 hudsourcelist.c \
43 hudsource.h \
44@@ -177,6 +180,25 @@
45 $(hud_cli_SOURCES)
46 endif
47
48+####################
49+# hud-gtk
50+####################
51+
52+hudgtkdatadir = $(datadir)/hud-gtk
53+hudgtkdata_DATA = hud-gtk.ui
54+EXTRA_DIST += hud-gtk.ui
55+
56+hud_gtk_SOURCES = \
57+ hud-gtk.vala
58+
59+hud_gtk_VALAFLAGS = --pkg gtk+-3.0
60+hud_gtk_CFLAGS = \
61+ -DHUD_GTK_DATADIR=\""$(hudgtkdatadir)"\" \
62+ $(gtk_CFLAGS)
63+
64+hud_gtk_LDADD = \
65+ $(gtk_LIBS)
66+
67 #######################
68 # HUD Dump Application
69 #######################
70
71=== modified file 'src/hud-gtk.vala'
72--- src/hud-gtk.vala 2012-02-28 15:22:00 +0000
73+++ src/hud-gtk.vala 2012-03-17 16:16:19 +0000
74@@ -1,3 +1,5 @@
75+extern const string HUD_GTK_DATADIR;
76+
77 namespace HudGtk {
78 public class CellRendererVariant : Gtk.CellRendererText {
79 public Variant value {
80@@ -85,7 +87,7 @@
81 try {
82 new CellRendererVariant ();
83 session = Bus.get_sync (BusType.SESSION, null);
84- builder.add_from_file ("hud-gtk.ui");
85+ builder.add_from_file (HUD_GTK_DATADIR + "/hud-gtk.ui");
86 } catch (Error e) {
87 error (e.message);
88 }
89
90=== modified file 'src/hud-service.c'
91--- src/hud-service.c 2012-03-15 18:34:44 +0000
92+++ src/hud-service.c 2012-03-17 16:16:19 +0000
93@@ -16,16 +16,20 @@
94 * Author: Ryan Lortie <desrt@desrt.ca>
95 */
96
97+#define G_LOG_DOMAIN "hud-service"
98+
99 #include "config.h"
100
101 #include <glib.h>
102 #include <gio/gio.h>
103+#include <stdlib.h>
104 #include <locale.h>
105 #include <libintl.h>
106
107 #include "hudappindicatorsource.h"
108 #include "hudindicatorsource.h"
109 #include "hudwindowsource.h"
110+#include "huddebugsource.h"
111 #include "hudsourcelist.h"
112 #include "hudsettings.h"
113
114@@ -79,6 +83,8 @@
115 {
116 GDBusConnection *connection = user_data;
117
118+ g_debug ("emit UpdatedQuery signal");
119+
120 g_dbus_connection_emit_signal (connection, NULL, DBUS_PATH,
121 DBUS_IFACE, "UpdatedQuery",
122 describe_query (query), NULL);
123@@ -99,6 +105,14 @@
124 return g_variant_ref_sink (platform_data);
125 }
126
127+static gboolean
128+drop_query_timeout (gpointer user_data)
129+{
130+ g_object_unref (user_data);
131+
132+ return G_SOURCE_REMOVE;
133+}
134+
135 static void
136 bus_method (GDBusConnection *connection,
137 const gchar *sender,
138@@ -118,6 +132,7 @@
139 HudQuery *query;
140
141 g_variant_get (parameters, "(&si)", &search_string, &num_results);
142+ g_debug ("'StartQuery' from %s: '%s', %d", sender, search_string, num_results);
143 query = hud_query_new (source, search_string, num_results);
144 g_signal_connect_object (query, "changed", G_CALLBACK (query_changed), connection, 0);
145 g_dbus_method_invocation_return_value (invocation, describe_query (query));
146@@ -128,21 +143,26 @@
147 {
148 GVariant *platform_data;
149 GVariant *item_key;
150+ guint64 key_value;
151 HudItem *item;
152
153 g_variant_get_child (parameters, 0, "v", &item_key);
154
155 if (!g_variant_is_of_type (item_key, G_VARIANT_TYPE_UINT64))
156 {
157+ g_debug ("'ExecuteQuery' from %s: incorrect item key (not uint64)", sender);
158 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
159 "item key has invalid format");
160 g_variant_unref (item_key);
161 return;
162 }
163
164- item = hud_item_lookup (g_variant_get_uint64 (item_key));
165+ key_value = g_variant_get_uint64 (item_key);
166 g_variant_unref (item_key);
167
168+ item = hud_item_lookup (key_value);
169+ g_debug ("'ExecuteQuery' from %s, item #%"G_GUINT64_FORMAT": %p", sender, key_value, item);
170+
171 if (item == NULL)
172 {
173 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
174@@ -162,6 +182,8 @@
175 GVariant *query_key;
176 HudQuery *query;
177
178+ g_debug ("Got 'CloseQuery' from %s", sender);
179+
180 g_variant_get (parameters, "(v)", &query_key);
181 query = hud_query_lookup (query_key);
182 g_variant_unref (query_key);
183@@ -169,6 +191,16 @@
184 if (query != NULL)
185 {
186 g_signal_handlers_disconnect_by_func (query, query_changed, connection);
187+ /* Unity does 'CloseQuery' immediately followed by
188+ * 'StartQuery' on every keystroke. Delay the destruction of
189+ * the query for a moment just in case a 'StartQuery' is on the
190+ * way.
191+ *
192+ * That way we can avoid allowing the use count to drop to
193+ * zero only to be increased again back to 1. This prevents a
194+ * bunch of dbusmenu "closed"/"opened" calls being sent.
195+ */
196+ g_timeout_add (1000, drop_query_timeout, g_object_ref (query));
197 hud_query_close (query);
198 }
199
200@@ -209,6 +241,8 @@
201 };
202 GError *error = NULL;
203
204+ g_debug ("Bus acquired (guid %s)", g_dbus_connection_get_guid (connection));
205+
206 if (!g_dbus_connection_register_object (connection, DBUS_PATH, get_iface_info (), &vtable, source, NULL, &error))
207 {
208 g_warning ("Unable to register path '"DBUS_PATH"': %s", error->message);
209@@ -218,6 +252,14 @@
210 }
211
212 static void
213+name_acquired_cb (GDBusConnection *connection,
214+ const gchar *name,
215+ gpointer user_data)
216+{
217+ g_debug ("Acquired bus name '%s'", name);
218+}
219+
220+static void
221 name_lost_cb (GDBusConnection *connection,
222 const gchar *name,
223 gpointer user_data)
224@@ -262,8 +304,17 @@
225 g_object_unref (source);
226 }
227
228+ if (getenv ("HUD_DEBUG_SOURCE"))
229+ {
230+ HudDebugSource *source;
231+
232+ source = hud_debug_source_new ();
233+ hud_source_list_add (source_list, HUD_SOURCE (source));
234+ g_object_unref (source);
235+ }
236+
237 g_bus_own_name (G_BUS_TYPE_SESSION, DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,
238- bus_acquired_cb, NULL, name_lost_cb, source_list, NULL);
239+ bus_acquired_cb, name_acquired_cb, name_lost_cb, source_list, NULL);
240
241 mainloop = g_main_loop_new (NULL, FALSE);
242 g_main_loop_run (mainloop);
243
244=== modified file 'src/hudappindicatorsource.c'
245--- src/hudappindicatorsource.c 2012-03-12 16:25:31 +0000
246+++ src/hudappindicatorsource.c 2012-03-17 16:16:19 +0000
247@@ -55,6 +55,7 @@
248 GSequence *indicators;
249 guint subscription;
250 GCancellable *cancellable;
251+ gint use_count;
252 gboolean ready;
253 };
254
255@@ -107,6 +108,10 @@
256 dbus_name, dbus_path);
257 g_signal_connect (collector, "changed", G_CALLBACK (hud_app_indicator_source_collector_changed), source);
258
259+ /* If query is active, mark new app indicator as used. */
260+ if (source->use_count)
261+ hud_source_use (HUD_SOURCE (collector));
262+
263 iter = g_sequence_get_iter_at_pos (source->indicators, position);
264 g_sequence_insert_before (iter, collector);
265 g_free (title);
266@@ -130,6 +135,9 @@
267
268 collector = g_sequence_get (iter);
269 g_signal_handlers_disconnect_by_func (collector, hud_app_indicator_source_collector_changed, source);
270+ /* Drop use count if we added one... */
271+ if (source->use_count)
272+ hud_source_unuse (HUD_SOURCE (collector));
273 g_sequence_remove (iter);
274 }
275 }
276@@ -313,6 +321,30 @@
277 }
278
279 static void
280+hud_app_indicator_source_use (HudSource *hud_source)
281+{
282+ HudAppIndicatorSource *source = HUD_APP_INDICATOR_SOURCE (hud_source);
283+
284+ if (source->use_count == 0)
285+ g_sequence_foreach (source->indicators, (GFunc) hud_source_use, NULL);
286+
287+ source->use_count++;
288+}
289+
290+static void
291+hud_app_indicator_source_unuse (HudSource *hud_source)
292+{
293+ HudAppIndicatorSource *source = HUD_APP_INDICATOR_SOURCE (hud_source);
294+
295+ g_return_if_fail (source->use_count > 0);
296+
297+ source->use_count--;
298+
299+ if (source->use_count == 0)
300+ g_sequence_foreach (source->indicators, (GFunc) hud_source_unuse, NULL);
301+}
302+
303+static void
304 hud_app_indicator_source_search (HudSource *hud_source,
305 GPtrArray *results_array,
306 const gchar *search_string)
307@@ -327,8 +359,6 @@
308 hud_source_search (g_sequence_get (iter), results_array, search_string);
309 iter = g_sequence_iter_next (iter);
310 }
311-
312-
313 }
314
315 static void
316@@ -351,6 +381,8 @@
317 static void
318 hud_app_indicator_source_iface_init (HudSourceInterface *iface)
319 {
320+ iface->use = hud_app_indicator_source_use;
321+ iface->unuse = hud_app_indicator_source_unuse;
322 iface->search = hud_app_indicator_source_search;
323 }
324
325
326=== modified file 'src/huddbusmenucollector.c'
327--- src/huddbusmenucollector.c 2012-03-13 14:33:02 +0000
328+++ src/huddbusmenucollector.c 2012-03-17 16:16:19 +0000
329@@ -61,6 +61,7 @@
330 HudItem parent_instance;
331
332 DbusmenuMenuitem *menuitem;
333+ gboolean is_opened;
334 } HudDbusmenuItem;
335
336 typedef HudItemClass HudDbusmenuItemClass;
337@@ -155,7 +156,7 @@
338 }
339
340
341-static HudItem *
342+static HudDbusmenuItem *
343 hud_dbusmenu_item_new (HudStringList *context,
344 const gchar *desktop_file,
345 DbusmenuMenuitem *menuitem)
346@@ -199,7 +200,7 @@
347
348 hud_string_list_unref (tokens);
349
350- return HUD_ITEM (item);
351+ return item;
352 }
353
354 struct _HudDbusmenuCollector
355@@ -214,6 +215,8 @@
356 guint penalty;
357 guint xid;
358 gboolean alive;
359+ gint use_count;
360+ gboolean reentrance_check;
361 };
362
363 typedef GObjectClass HudDbusmenuCollectorClass;
364@@ -223,6 +226,68 @@
365 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_dbusmenu_collector_iface_init))
366
367 static void
368+hud_dbusmenu_collector_open_submenu (gpointer key,
369+ gpointer value,
370+ gpointer user_data)
371+{
372+ DbusmenuMenuitem *menuitem = key;
373+ HudDbusmenuItem *item = value;
374+
375+ if (dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
376+ {
377+ dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
378+ item->is_opened = TRUE;
379+ }
380+}
381+
382+static void
383+hud_dbusmenu_collector_close_submenu (gpointer key,
384+ gpointer value,
385+ gpointer user_data)
386+{
387+ DbusmenuMenuitem *menuitem = key;
388+ HudDbusmenuItem *item = value;
389+
390+ if (item->is_opened)
391+ {
392+ dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_CLOSED, NULL, 0);
393+ item->is_opened = FALSE;
394+ }
395+}
396+
397+static void
398+hud_dbusmenu_collector_use (HudSource *source)
399+{
400+ HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
401+
402+ collector->reentrance_check = TRUE;
403+
404+ if (collector->use_count == 0)
405+ g_hash_table_foreach (collector->items, hud_dbusmenu_collector_open_submenu, NULL);
406+
407+ collector->use_count++;
408+
409+ collector->reentrance_check = FALSE;
410+}
411+
412+static void
413+hud_dbusmenu_collector_unuse (HudSource *source)
414+{
415+ HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
416+
417+ g_return_if_fail (collector->use_count > 0);
418+
419+ collector->reentrance_check = TRUE;
420+
421+ collector->use_count--;
422+
423+ if (collector->use_count == 0)
424+ g_hash_table_foreach (collector->items, hud_dbusmenu_collector_close_submenu, NULL);
425+
426+ collector->reentrance_check = FALSE;
427+}
428+
429+static void
430 hud_dbusmenu_collector_search (HudSource *source,
431 GPtrArray *results_array,
432 const gchar *search_string)
433@@ -260,6 +325,8 @@
434 HudStringList *context;
435 HudItem *item;
436
437+ g_assert (!collector->reentrance_check);
438+
439 item = g_hash_table_lookup (collector->items, menuitem);
440 g_assert (item != NULL);
441
442@@ -275,6 +342,8 @@
443 {
444 HudDbusmenuCollector *collector = user_data;
445
446+ g_assert (!collector->reentrance_check);
447+
448 hud_dbusmenu_collector_remove_item (collector, child);
449 }
450
451@@ -287,7 +356,9 @@
452 HudDbusmenuCollector *collector = user_data;
453 DbusmenuMenuitem *parent;
454 HudStringList *context;
455- HudItem *item;
456+ HudDbusmenuItem *item;
457+
458+ g_assert (!collector->reentrance_check);
459
460 parent = dbusmenu_menuitem_get_parent (menuitem);
461
462@@ -303,6 +374,13 @@
463
464 item = hud_dbusmenu_item_new (context, collector->application_id, menuitem);
465 g_hash_table_remove (collector->items, menuitem);
466+
467+ if (collector->use_count && dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
468+ {
469+ dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
470+ item->is_opened = TRUE;
471+ }
472+
473 g_hash_table_insert (collector->items, menuitem, item);
474
475 hud_source_changed (HUD_SOURCE (collector));
476@@ -313,15 +391,23 @@
477 HudStringList *context,
478 DbusmenuMenuitem *menuitem)
479 {
480- HudItem *item;
481+ HudDbusmenuItem *item;
482 GList *child;
483
484 item = hud_dbusmenu_item_new (context, NULL, menuitem);
485- context = hud_item_get_tokens (item);
486+ context = hud_item_get_tokens (HUD_ITEM (item));
487
488 g_signal_connect (menuitem, "property-changed", G_CALLBACK (hud_dbusmenu_collector_property_changed), collector);
489 g_signal_connect (menuitem, "child-added", G_CALLBACK (hud_dbusmenu_collector_child_added), collector);
490 g_signal_connect (menuitem, "child-removed", G_CALLBACK (hud_dbusmenu_collector_child_removed), collector);
491+
492+ /* If we're actively being queried and we add a new submenu item, open it. */
493+ if (collector->use_count && dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
494+ {
495+ dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
496+ item->is_opened = TRUE;
497+ }
498+
499 g_hash_table_insert (collector->items, menuitem, item);
500
501 for (child = dbusmenu_menuitem_get_children (menuitem); child; child = child->next)
502@@ -355,14 +441,21 @@
503 {
504 if (collector->root)
505 {
506+ /* If the collector has the submenus opened, close them before we
507+ * remove them all. The use_count being non-zero will cause them
508+ * to be reopened as they are added back below (if they will be).
509+ */
510+ if (collector->use_count > 0)
511+ g_hash_table_foreach (collector->items, hud_dbusmenu_collector_close_submenu, NULL);
512+
513 hud_dbusmenu_collector_remove_item (collector, collector->root);
514- collector->root = NULL;
515+ g_clear_object (&collector->root);
516 }
517
518 if (root)
519 {
520 hud_dbusmenu_collector_add_item (collector, collector->prefix, root);
521- collector->root = root;
522+ collector->root = g_object_ref (root);
523 }
524 }
525
526@@ -373,6 +466,8 @@
527 {
528 HudDbusmenuCollector *collector = user_data;
529
530+ g_assert (!collector->reentrance_check);
531+
532 hud_dbusmenu_collector_setup_root (collector, root);
533 }
534
535@@ -429,6 +524,8 @@
536 g_assert (g_hash_table_size (collector->items) == 0);
537 g_hash_table_unref (collector->items);
538
539+ g_free (collector->application_id);
540+
541 hud_string_list_unref (collector->prefix);
542 g_clear_object (&collector->client);
543
544@@ -445,6 +542,8 @@
545 static void
546 hud_dbusmenu_collector_iface_init (HudSourceInterface *iface)
547 {
548+ iface->use = hud_dbusmenu_collector_use;
549+ iface->unuse = hud_dbusmenu_collector_unuse;
550 iface->search = hud_dbusmenu_collector_search;
551 }
552
553@@ -515,7 +614,6 @@
554 const gchar *desktop_file)
555 {
556 HudDbusmenuCollector *collector;
557- BamfApplication *application;
558
559 collector = g_object_new (HUD_TYPE_DBUSMENU_COLLECTOR, NULL);
560 collector->application_id = g_strdup (desktop_file);
561@@ -524,10 +622,6 @@
562 hud_app_menu_registrar_add_observer (hud_app_menu_registrar_get (), collector->xid,
563 hud_dbusmenu_collector_registrar_observer_func, collector);
564
565- application = bamf_matcher_get_application_for_window (bamf_matcher_get_default (), window);
566- if (application != NULL)
567- collector->application_id = g_strdup (bamf_application_get_desktop_file (application));
568-
569 collector->alive = TRUE;
570
571 return collector;
572@@ -549,10 +643,5 @@
573 {
574 hud_string_list_unref (collector->prefix);
575 collector->prefix = hud_string_list_cons (prefix, NULL);
576-
577- if (collector->root)
578- {
579- hud_dbusmenu_collector_remove_item (collector, collector->root);
580- hud_dbusmenu_collector_add_item (collector, collector->prefix, collector->root);
581- }
582+ hud_dbusmenu_collector_setup_root (collector, collector->root);
583 }
584
585=== added file 'src/huddebugsource.c'
586--- src/huddebugsource.c 1970-01-01 00:00:00 +0000
587+++ src/huddebugsource.c 2012-03-17 16:16:19 +0000
588@@ -0,0 +1,168 @@
589+/*
590+ * Copyright © 2012 Canonical Ltd.
591+ *
592+ * This program is free software: you can redistribute it and/or modify it
593+ * under the terms of the GNU General Public License version 3, as
594+ * published by the Free Software Foundation.
595+ *
596+ * This program is distributed in the hope that it will be useful, but
597+ * WITHOUT ANY WARRANTY; without even the implied warranties of
598+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
599+ * PURPOSE. See the GNU General Public License for more details.
600+ *
601+ * You should have received a copy of the GNU General Public License along
602+ * with this program. If not, see <http://www.gnu.org/licenses/>.
603+ *
604+ * Author: Ryan Lortie <desrt@desrt.ca>
605+ */
606+
607+#include "huddebugsource.h"
608+
609+#include "hudsource.h"
610+#include "hudresult.h"
611+
612+/**
613+ * SECTION:huddebugsource
614+ * @title: HudDebugSource
615+ * @short_description: a source to assist with debugging
616+ *
617+ * #HudDebugSource is a source for debugging purposes. It is not
618+ * enabled by default but you can have it added to the global list of
619+ * sources by setting the HUD_DEBUG_SOURCE environment variable.
620+ *
621+ * Presently it creates a #HudItem corresponding to the current date and
622+ * time (and updates it as the time changes).
623+ **/
624+
625+/**
626+ * HudDebugSource:
627+ *
628+ * This is an opaque structure type.
629+ **/
630+
631+struct _HudDebugSource
632+{
633+ GObject parent_instance;
634+
635+ HudItem *item;
636+ gint use_count;
637+ gint timeout;
638+};
639+
640+typedef GObjectClass HudDebugSourceClass;
641+
642+static void hud_debug_source_iface_init (HudSourceInterface *iface);
643+G_DEFINE_TYPE_WITH_CODE (HudDebugSource, hud_debug_source, G_TYPE_OBJECT,
644+ G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_debug_source_iface_init))
645+
646+static gboolean
647+hud_debug_source_timeout (gpointer user_data)
648+{
649+ HudDebugSource *source = user_data;
650+ HudStringList *tokens;
651+ GDateTime *now;
652+ gchar *time;
653+
654+ g_clear_object (&source->item);
655+
656+ now = g_date_time_new_now_local ();
657+ time = g_date_time_format (now, "hud-debug time: %c");
658+ tokens = hud_string_list_cons (time, NULL);
659+ g_date_time_unref (now);
660+ g_free (time);
661+
662+ source->item = hud_item_new (tokens, NULL, TRUE);
663+ hud_string_list_unref (tokens);
664+
665+ hud_source_changed (HUD_SOURCE (source));
666+
667+ return TRUE;
668+}
669+
670+static void
671+hud_debug_source_use (HudSource *hud_source)
672+{
673+ HudDebugSource *source = HUD_DEBUG_SOURCE (hud_source);
674+
675+ if (source->use_count == 0)
676+ source->timeout = g_timeout_add (1000, hud_debug_source_timeout, source);
677+
678+ source->use_count++;
679+}
680+
681+static void
682+hud_debug_source_unuse (HudSource *hud_source)
683+{
684+ HudDebugSource *source = HUD_DEBUG_SOURCE (hud_source);
685+
686+ source->use_count--;
687+
688+ if (source->use_count == 0)
689+ {
690+ g_source_remove (source->timeout);
691+ source->timeout = 0;
692+ }
693+}
694+
695+static void
696+hud_debug_source_search (HudSource *hud_source,
697+ GPtrArray *results_array,
698+ const gchar *search_string)
699+{
700+ HudDebugSource *source = HUD_DEBUG_SOURCE (hud_source);
701+
702+ if (source->item)
703+ {
704+ HudResult *result;
705+
706+ result = hud_result_get_if_matched (source->item, search_string, 0);
707+ if (result != NULL)
708+ g_ptr_array_add (results_array, result);
709+ }
710+}
711+
712+static void
713+hud_debug_source_finalize (GObject *object)
714+{
715+ HudDebugSource *source = HUD_DEBUG_SOURCE (object);
716+
717+ g_clear_object (&source->item);
718+
719+ if (source->timeout)
720+ g_source_remove (source->timeout);
721+
722+ G_OBJECT_CLASS (hud_debug_source_parent_class)
723+ ->finalize (object);
724+}
725+
726+static void
727+hud_debug_source_init (HudDebugSource *source)
728+{
729+}
730+
731+static void
732+hud_debug_source_iface_init (HudSourceInterface *iface)
733+{
734+ iface->use = hud_debug_source_use;
735+ iface->unuse = hud_debug_source_unuse;
736+ iface->search = hud_debug_source_search;
737+}
738+
739+static void
740+hud_debug_source_class_init (HudDebugSourceClass *class)
741+{
742+ class->finalize = hud_debug_source_finalize;
743+}
744+
745+/**
746+ * hud_debug_source_new:
747+ *
748+ * Creates a #HudDebugSource.
749+ *
750+ * Returns: a new empty #HudDebugSource
751+ **/
752+HudDebugSource *
753+hud_debug_source_new (void)
754+{
755+ return g_object_new (HUD_TYPE_DEBUG_SOURCE, NULL);
756+}
757
758=== added file 'src/huddebugsource.h'
759--- src/huddebugsource.h 1970-01-01 00:00:00 +0000
760+++ src/huddebugsource.h 2012-03-17 16:16:19 +0000
761@@ -0,0 +1,36 @@
762+/*
763+ * Copyright © 2012 Canonical Ltd.
764+ *
765+ * This program is free software: you can redistribute it and/or modify it
766+ * under the terms of the GNU General Public License version 3, as
767+ * published by the Free Software Foundation.
768+ *
769+ * This program is distributed in the hope that it will be useful, but
770+ * WITHOUT ANY WARRANTY; without even the implied warranties of
771+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
772+ * PURPOSE. See the GNU General Public License for more details.
773+ *
774+ * You should have received a copy of the GNU General Public License along
775+ * with this program. If not, see <http://www.gnu.org/licenses/>.
776+ *
777+ * Author: Ryan Lortie <desrt@desrt.ca>
778+ */
779+
780+#ifndef __HUD_DEBUG_SOURCE_H__
781+#define __HUD_DEBUG_SOURCE_H__
782+
783+#include <glib-object.h>
784+
785+#define HUD_TYPE_DEBUG_SOURCE (hud_debug_source_get_type ())
786+#define HUD_DEBUG_SOURCE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
787+ HUD_TYPE_DEBUG_SOURCE, HudDebugSource))
788+#define HUD_IS_DEBUG_SOURCE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
789+ HUD_TYPE_DEBUG_SOURCE))
790+
791+typedef struct _HudDebugSource HudDebugSource;
792+
793+GType hud_debug_source_get_type (void);
794+
795+HudDebugSource * hud_debug_source_new (void);
796+
797+#endif /* __HUD_DEBUG_SOURCE_H__ */
798
799=== modified file 'src/hudindicatorsource.c'
800--- src/hudindicatorsource.c 2012-03-12 16:25:31 +0000
801+++ src/hudindicatorsource.c 2012-03-17 16:16:19 +0000
802@@ -92,7 +92,7 @@
803 typedef struct
804 {
805 const IndicatorInfo *info;
806- HudSource *source;
807+ HudIndicatorSource *source;
808 HudSource *collector;
809 } HudIndicatorSourceIndicator;
810
811@@ -102,6 +102,7 @@
812
813 HudIndicatorSourceIndicator *indicators;
814 gint n_indicators;
815+ gint use_count;
816 };
817
818 typedef GObjectClass HudIndicatorSourceClass;
819@@ -111,6 +112,40 @@
820 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_indicator_source_iface_init))
821
822 static void
823+hud_indicator_source_use (HudSource *hud_source)
824+{
825+ HudIndicatorSource *source = HUD_INDICATOR_SOURCE (hud_source);
826+ gint i;
827+
828+ if (source->use_count == 0)
829+ {
830+ for (i = 0; i < source->n_indicators; i++)
831+ if (source->indicators[i].collector)
832+ hud_source_use (source->indicators[i].collector);
833+ }
834+
835+ source->use_count++;
836+}
837+
838+static void
839+hud_indicator_source_unuse (HudSource *hud_source)
840+{
841+ HudIndicatorSource *source = HUD_INDICATOR_SOURCE (hud_source);
842+ gint i;
843+
844+ g_return_if_fail (source->use_count > 0);
845+
846+ source->use_count--;
847+
848+ if (source->use_count == 0)
849+ {
850+ for (i = 0; i < source->n_indicators; i++)
851+ if (source->indicators[i].collector)
852+ hud_source_unuse (source->indicators[i].collector);
853+ }
854+}
855+
856+static void
857 hud_indicator_source_search (HudSource *hud_source,
858 GPtrArray *results_array,
859 const gchar *search_string)
860@@ -135,7 +170,7 @@
861 {
862 HudIndicatorSourceIndicator *indicator = user_data;
863
864- hud_source_changed (indicator->source);
865+ hud_source_changed (HUD_SOURCE (indicator->source));
866 }
867
868 static void
869@@ -154,7 +189,11 @@
870 g_signal_connect (collector, "changed", G_CALLBACK (hud_indicator_source_collector_changed), indicator);
871 indicator->collector = HUD_SOURCE (collector);
872
873- hud_source_changed (indicator->source);
874+ /* Set initial use count on new indicator if query is active. */
875+ if (indicator->source->use_count)
876+ hud_source_use (indicator->collector);
877+
878+ hud_source_changed (HUD_SOURCE (indicator->source));
879 }
880
881 static void
882@@ -167,10 +206,13 @@
883 if (indicator->collector)
884 {
885 g_signal_handlers_disconnect_by_func (indicator->collector, hud_indicator_source_collector_changed, indicator);
886+ /* Drop our use count on dying indicator (if any) */
887+ if (indicator->source->use_count)
888+ hud_source_unuse (indicator->collector);
889 g_clear_object (&indicator->collector);
890 }
891
892- hud_source_changed (indicator->source);
893+ hud_source_changed (HUD_SOURCE (indicator->source));
894 }
895
896 static void
897@@ -186,7 +228,7 @@
898 HudIndicatorSourceIndicator *indicator = &source->indicators[i];
899
900 indicator->info = &indicator_info[i];
901- indicator->source = HUD_SOURCE (source);
902+ indicator->source = source;
903
904 g_bus_watch_name (G_BUS_TYPE_SESSION, indicator->info->dbus_name, G_BUS_NAME_WATCHER_FLAGS_NONE,
905 hud_indicator_source_name_appeared, hud_indicator_source_name_vanished, indicator, NULL);
906@@ -196,6 +238,8 @@
907 static void
908 hud_indicator_source_iface_init (HudSourceInterface *iface)
909 {
910+ iface->use = hud_indicator_source_use;
911+ iface->unuse = hud_indicator_source_unuse;
912 iface->search = hud_indicator_source_search;
913 }
914
915
916=== modified file 'src/huditem.c'
917--- src/huditem.c 2012-03-13 13:32:36 +0000
918+++ src/huditem.c 2012-03-17 16:16:19 +0000
919@@ -69,6 +69,7 @@
920 g_hash_table_remove (hud_item_table, &item->priv->id);
921 hud_string_list_unref (item->priv->tokens);
922 g_free (item->priv->desktop_file);
923+ g_free (item->priv->usage_tag);
924
925 G_OBJECT_CLASS (hud_item_parent_class)
926 ->finalize (object);
927
928=== modified file 'src/hudmenumodelcollector.c'
929--- src/hudmenumodelcollector.c 2012-03-12 16:25:31 +0000
930+++ src/hudmenumodelcollector.c 2012-03-17 16:16:19 +0000
931@@ -61,9 +61,9 @@
932
933 gchar *desktop_file;
934 GPtrArray *items;
935+ gint use_count;
936 };
937
938-
939 typedef struct
940 {
941 HudItem parent_instance;
942@@ -329,6 +329,22 @@
943 }
944
945 static void
946+hud_menu_model_collector_use (HudSource *source)
947+{
948+ HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
949+
950+ collector->use_count++;
951+}
952+
953+static void
954+hud_menu_model_collector_unuse (HudSource *source)
955+{
956+ HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
957+
958+ collector->use_count--;
959+}
960+
961+static void
962 hud_menu_model_collector_search (HudSource *source,
963 GPtrArray *results_array,
964 const gchar *search_string)
965@@ -381,6 +397,8 @@
966 static void
967 hud_menu_model_collector_iface_init (HudSourceInterface *iface)
968 {
969+ iface->use = hud_menu_model_collector_use;
970+ iface->unuse = hud_menu_model_collector_unuse;
971 iface->search = hud_menu_model_collector_search;
972 }
973
974
975=== modified file 'src/hudquery.c'
976--- src/hudquery.c 2012-03-07 21:55:41 +0000
977+++ src/hudquery.c 2012-03-17 16:16:19 +0000
978@@ -16,6 +16,8 @@
979 * Author: Ryan Lortie <desrt@desrt.ca>
980 */
981
982+#define G_LOG_DOMAIN "hudquery"
983+
984 #include "hudquery.h"
985
986 #include "hudresult.h"
987@@ -138,7 +140,7 @@
988 HudQuery *query = user_data;
989
990 if (!query->refresh_id)
991- query->refresh_id = g_idle_add (hud_query_dispatch_refresh, g_object_ref (query));
992+ query->refresh_id = g_idle_add (hud_query_dispatch_refresh, query);
993 }
994
995 static void
996@@ -146,6 +148,13 @@
997 {
998 HudQuery *query = HUD_QUERY (object);
999
1000+ g_debug ("Destroyed query '%s'", query->search_string);
1001+
1002+ if (query->refresh_id)
1003+ g_source_remove (query->refresh_id);
1004+
1005+ hud_source_unuse (query->source);
1006+
1007 g_object_unref (query->source);
1008 g_free (query->search_string);
1009 g_ptr_array_unref (query->results);
1010@@ -199,12 +208,16 @@
1011 {
1012 HudQuery *query;
1013
1014+ g_debug ("Created query '%s'", search_string);
1015+
1016 query = g_object_new (HUD_TYPE_QUERY, NULL);
1017 query->source = g_object_ref (source);
1018 query->results = g_ptr_array_new_with_free_func (g_object_unref);
1019 query->search_string = g_strdup (search_string);
1020 query->num_results = num_results;
1021
1022+ hud_source_use (query->source);
1023+
1024 hud_query_refresh (query);
1025
1026 g_signal_connect_object (source, "changed", G_CALLBACK (hud_query_source_changed), query, 0);
1027
1028=== modified file 'src/hudsource.c'
1029--- src/hudsource.c 2012-02-29 15:48:43 +0000
1030+++ src/hudsource.c 2012-03-17 16:16:19 +0000
1031@@ -85,6 +85,52 @@
1032 }
1033
1034 /**
1035+ * hud_source_use:
1036+ * @source; a #HudSource
1037+ *
1038+ * Mark a #HudSource as "in use" (ie: actively being queried).
1039+ *
1040+ * The source maintains a use count. You must call hud_source_unuse()
1041+ * for as many times as you called hud_source_use().
1042+ *
1043+ * The source may not emit change signals unless it is marked as being
1044+ * used (although it is free to ignore this hint and emit them anyway).
1045+ * Some data in the source may also be out of date. It is therefore
1046+ * recommended that calls to hud_source_search() be preceeded by a call
1047+ * to this function.
1048+ **/
1049+void
1050+hud_source_use (HudSource *source)
1051+{
1052+ g_return_if_fail (HUD_IS_SOURCE (source));
1053+
1054+ g_debug ("use on %s %p", G_OBJECT_TYPE_NAME (source), source);
1055+
1056+ HUD_SOURCE_GET_IFACE (source)
1057+ ->use (source);
1058+}
1059+
1060+/**
1061+ * hud_source_unuse:
1062+ * @source; a #HudSource
1063+ *
1064+ * Reverses the effect of a previous call to hud_source_use().
1065+ *
1066+ * The source maintains a use count. You must call hud_source_unuse()
1067+ * for as many times as you called hud_source_use().
1068+ **/
1069+void
1070+hud_source_unuse (HudSource *source)
1071+{
1072+ g_return_if_fail (HUD_IS_SOURCE (source));
1073+
1074+ g_debug ("unuse on %s %p", G_OBJECT_TYPE_NAME (source), source);
1075+
1076+ HUD_SOURCE_GET_IFACE (source)
1077+ ->unuse (source);
1078+}
1079+
1080+/**
1081 * hud_source_search:
1082 * @source: a #HudSource
1083 * @results_array: (element-type HudResult): array to append results to
1084
1085=== modified file 'src/hudsource.h'
1086--- src/hudsource.h 2012-02-28 18:29:03 +0000
1087+++ src/hudsource.h 2012-03-17 16:16:19 +0000
1088@@ -36,6 +36,8 @@
1089 {
1090 GTypeInterface g_iface;
1091
1092+ void (* use) (HudSource *source);
1093+ void (* unuse) (HudSource *source);
1094 void (* search) (HudSource *source,
1095 GPtrArray *results_array,
1096 const gchar *search_string);
1097@@ -43,6 +45,9 @@
1098
1099 GType hud_source_get_type (void);
1100
1101+void hud_source_use (HudSource *source);
1102+void hud_source_unuse (HudSource *source);
1103+
1104 void hud_source_search (HudSource *source,
1105 GPtrArray *results_array,
1106 const gchar *search_string);
1107
1108=== modified file 'src/hudsourcelist.c'
1109--- src/hudsourcelist.c 2012-02-28 18:29:03 +0000
1110+++ src/hudsourcelist.c 2012-03-17 16:16:19 +0000
1111@@ -63,6 +63,26 @@
1112 }
1113
1114 static void
1115+hud_source_list_use (HudSource *source)
1116+{
1117+ HudSourceList *list = HUD_SOURCE_LIST (source);
1118+ GSList *node;
1119+
1120+ for (node = list->list; node; node = node->next)
1121+ hud_source_use (node->data);
1122+}
1123+
1124+static void
1125+hud_source_list_unuse (HudSource *source)
1126+{
1127+ HudSourceList *list = HUD_SOURCE_LIST (source);
1128+ GSList *node;
1129+
1130+ for (node = list->list; node; node = node->next)
1131+ hud_source_unuse (node->data);
1132+}
1133+
1134+static void
1135 hud_source_list_search (HudSource *source,
1136 GPtrArray *results_array,
1137 const gchar *search_string)
1138@@ -94,6 +114,8 @@
1139 static void
1140 hud_source_list_iface_init (HudSourceInterface *iface)
1141 {
1142+ iface->use = hud_source_list_use;
1143+ iface->unuse = hud_source_list_unuse;
1144 iface->search = hud_source_list_search;
1145 }
1146
1147
1148=== modified file 'src/hudwindowsource.c'
1149--- src/hudwindowsource.c 2012-03-13 13:39:30 +0000
1150+++ src/hudwindowsource.c 2012-03-17 16:16:19 +0000
1151@@ -67,6 +67,8 @@
1152 BamfWindow *active_window;
1153 BamfApplication *active_application;
1154 const gchar *active_desktop_file;
1155+ HudSource *active_collector;
1156+ gint use_count;
1157 };
1158
1159 typedef GObjectClass HudWindowSourceClass;
1160@@ -194,7 +196,6 @@
1161 gpointer user_data)
1162 {
1163 HudWindowSource *source = user_data;
1164- HudSource *collector;
1165 BamfWindow *window;
1166 BamfApplication *application;
1167 const gchar *desktop_file;
1168@@ -239,34 +240,65 @@
1169
1170 g_debug ("new active window (xid %u)", bamf_window_get_xid (window));
1171
1172- collector = hud_window_source_get_collector (source);
1173- if (collector)
1174- g_signal_handlers_disconnect_by_func (collector, hud_window_source_collector_changed, source);
1175-
1176+
1177+ if (source->active_collector)
1178+ {
1179+ g_signal_handlers_disconnect_by_func (source->active_collector, hud_window_source_collector_changed, source);
1180+ if (source->use_count)
1181+ hud_source_unuse (source->active_collector);
1182+ }
1183+
1184+ g_clear_object (&source->active_collector);
1185 g_clear_object (&source->active_application);
1186 g_clear_object (&source->active_window);
1187 source->active_window = g_object_ref (window);
1188 source->active_application = g_object_ref (application);
1189 source->active_desktop_file = desktop_file;
1190+ source->active_collector = g_object_ref (hud_window_source_get_collector (source));
1191
1192- collector = hud_window_source_get_collector (source);
1193- g_signal_connect_object (collector, "changed", G_CALLBACK (hud_window_source_collector_changed), source, 0);
1194+ if (source->use_count)
1195+ hud_source_use (source->active_collector);
1196+ g_signal_connect_object (source->active_collector, "changed",
1197+ G_CALLBACK (hud_window_source_collector_changed), source, 0);
1198
1199 hud_source_changed (HUD_SOURCE (source));
1200 }
1201
1202 static void
1203+hud_window_source_use (HudSource *hud_source)
1204+{
1205+ HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);
1206+
1207+ if (source->use_count == 0)
1208+ if (source->active_collector)
1209+ hud_source_use (source->active_collector);
1210+
1211+ source->use_count++;
1212+}
1213+
1214+static void
1215+hud_window_source_unuse (HudSource *hud_source)
1216+{
1217+ HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);
1218+
1219+ g_return_if_fail (source->use_count > 0);
1220+
1221+ source->use_count--;
1222+
1223+ if (source->use_count == 0)
1224+ if (source->active_collector)
1225+ hud_source_unuse (source->active_collector);
1226+}
1227+
1228+static void
1229 hud_window_source_search (HudSource *hud_source,
1230 GPtrArray *results_array,
1231 const gchar *search_string)
1232 {
1233 HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);
1234- HudSource *collector;
1235-
1236- collector = hud_window_source_get_collector (source);
1237-
1238- if (collector)
1239- hud_source_search (collector, results_array, search_string);
1240+
1241+ if (source->active_collector)
1242+ hud_source_search (source->active_collector, results_array, search_string);
1243 }
1244
1245 static void
1246@@ -285,15 +317,22 @@
1247 static void
1248 hud_window_source_init (HudWindowSource *source)
1249 {
1250+ BamfWindow *window;
1251+
1252 source->matcher = bamf_matcher_get_default ();
1253
1254 g_signal_connect_object (source->matcher, "active-window-changed",
1255 G_CALLBACK (hud_window_source_active_window_changed), source, 0);
1256+ window = bamf_matcher_get_active_window (source->matcher);
1257+ if (window != NULL)
1258+ hud_window_source_active_window_changed (source->matcher, NULL, BAMF_VIEW (window), source);
1259 }
1260
1261 static void
1262 hud_window_source_iface_init (HudSourceInterface *iface)
1263 {
1264+ iface->use = hud_window_source_use;
1265+ iface->unuse = hud_window_source_unuse;
1266 iface->search = hud_window_source_search;
1267 }
1268

Subscribers

People subscribed via source and target branches