Merge lp:~desrt/indicator-appmenu/hud-rewrite-wip into lp:indicator-appmenu/0.4
- hud-rewrite-wip
- Merge into trunk.0.4
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 | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Charles Kerr (community) | Approve | ||
Review via email: mp+97716@code.launchpad.net |
Commit message
Description of the change
Add support for XUL be emitting "Opened" signals when a query is active.
Fix a few leaks as well.
- 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
Charles Kerr (charlesk) wrote : | # |
* About the text conflict, we could use <glib/gi18n.h> instead of locale.h and libintl.h
* In hud_indicator_
* 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.
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_
> 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.
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_
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).
Charles Kerr (charlesk) : | # |
- 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
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 |
Could you fix the text conflict?