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
=== modified file 'configure.ac'
--- configure.ac 2012-03-14 19:39:48 +0000
+++ configure.ac 2012-03-17 16:16:19 +0000
@@ -20,6 +20,7 @@
20# Check for programs20# Check for programs
21AC_PROG_CC21AC_PROG_CC
22AM_PROG_CC_C_O22AM_PROG_CC_C_O
23AM_PROG_VALAC([0.15.2])
2324
24# Initialize libtool25# Initialize libtool
25LT_PREREQ([2.2.6])26LT_PREREQ([2.2.6])
@@ -86,6 +87,8 @@
86 [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]87 [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
87)88)
8889
90PKG_CHECK_MODULES(gtk, gtk+-3.0 >= $GTK3_REQUIRED_VERSION)
91
89AC_SUBST(INDICATOR_CFLAGS)92AC_SUBST(INDICATOR_CFLAGS)
90AC_SUBST(INDICATOR_LIBS)93AC_SUBST(INDICATOR_LIBS)
9194
9295
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2012-03-05 04:51:36 +0000
+++ src/Makefile.am 2012-03-17 16:16:19 +0000
@@ -6,7 +6,8 @@
66
7bin_PROGRAMS = \7bin_PROGRAMS = \
8 hud-dump-application \8 hud-dump-application \
9 hud-verify-app-info9 hud-verify-app-info \
10 hud-gtk
1011
11bin_SCRIPTS = \12bin_SCRIPTS = \
12 hud-list-applications13 hud-list-applications
@@ -104,6 +105,8 @@
104 hudindicatorsource.c \105 hudindicatorsource.c \
105 hudwindowsource.h \106 hudwindowsource.h \
106 hudwindowsource.c \107 hudwindowsource.c \
108 huddebugsource.h \
109 huddebugsource.c \
107 hudsourcelist.h \110 hudsourcelist.h \
108 hudsourcelist.c \111 hudsourcelist.c \
109 hudsource.h \112 hudsource.h \
@@ -177,6 +180,25 @@
177 $(hud_cli_SOURCES)180 $(hud_cli_SOURCES)
178endif181endif
179182
183####################
184# hud-gtk
185####################
186
187hudgtkdatadir = $(datadir)/hud-gtk
188hudgtkdata_DATA = hud-gtk.ui
189EXTRA_DIST += hud-gtk.ui
190
191hud_gtk_SOURCES = \
192 hud-gtk.vala
193
194hud_gtk_VALAFLAGS = --pkg gtk+-3.0
195hud_gtk_CFLAGS = \
196 -DHUD_GTK_DATADIR=\""$(hudgtkdatadir)"\" \
197 $(gtk_CFLAGS)
198
199hud_gtk_LDADD = \
200 $(gtk_LIBS)
201
180#######################202#######################
181# HUD Dump Application203# HUD Dump Application
182#######################204#######################
183205
=== modified file 'src/hud-gtk.vala'
--- src/hud-gtk.vala 2012-02-28 15:22:00 +0000
+++ src/hud-gtk.vala 2012-03-17 16:16:19 +0000
@@ -1,3 +1,5 @@
1extern const string HUD_GTK_DATADIR;
2
1namespace HudGtk {3namespace HudGtk {
2 public class CellRendererVariant : Gtk.CellRendererText {4 public class CellRendererVariant : Gtk.CellRendererText {
3 public Variant value {5 public Variant value {
@@ -85,7 +87,7 @@
85 try {87 try {
86 new CellRendererVariant ();88 new CellRendererVariant ();
87 session = Bus.get_sync (BusType.SESSION, null);89 session = Bus.get_sync (BusType.SESSION, null);
88 builder.add_from_file ("hud-gtk.ui");90 builder.add_from_file (HUD_GTK_DATADIR + "/hud-gtk.ui");
89 } catch (Error e) {91 } catch (Error e) {
90 error (e.message);92 error (e.message);
91 }93 }
9294
=== modified file 'src/hud-service.c'
--- src/hud-service.c 2012-03-15 18:34:44 +0000
+++ src/hud-service.c 2012-03-17 16:16:19 +0000
@@ -16,16 +16,20 @@
16 * Author: Ryan Lortie <desrt@desrt.ca>16 * Author: Ryan Lortie <desrt@desrt.ca>
17 */17 */
1818
19#define G_LOG_DOMAIN "hud-service"
20
19#include "config.h"21#include "config.h"
2022
21#include <glib.h>23#include <glib.h>
22#include <gio/gio.h>24#include <gio/gio.h>
25#include <stdlib.h>
23#include <locale.h>26#include <locale.h>
24#include <libintl.h>27#include <libintl.h>
2528
26#include "hudappindicatorsource.h"29#include "hudappindicatorsource.h"
27#include "hudindicatorsource.h"30#include "hudindicatorsource.h"
28#include "hudwindowsource.h"31#include "hudwindowsource.h"
32#include "huddebugsource.h"
29#include "hudsourcelist.h"33#include "hudsourcelist.h"
30#include "hudsettings.h"34#include "hudsettings.h"
3135
@@ -79,6 +83,8 @@
79{83{
80 GDBusConnection *connection = user_data;84 GDBusConnection *connection = user_data;
8185
86 g_debug ("emit UpdatedQuery signal");
87
82 g_dbus_connection_emit_signal (connection, NULL, DBUS_PATH,88 g_dbus_connection_emit_signal (connection, NULL, DBUS_PATH,
83 DBUS_IFACE, "UpdatedQuery",89 DBUS_IFACE, "UpdatedQuery",
84 describe_query (query), NULL);90 describe_query (query), NULL);
@@ -99,6 +105,14 @@
99 return g_variant_ref_sink (platform_data);105 return g_variant_ref_sink (platform_data);
100}106}
101107
108static gboolean
109drop_query_timeout (gpointer user_data)
110{
111 g_object_unref (user_data);
112
113 return G_SOURCE_REMOVE;
114}
115
102static void116static void
103bus_method (GDBusConnection *connection,117bus_method (GDBusConnection *connection,
104 const gchar *sender,118 const gchar *sender,
@@ -118,6 +132,7 @@
118 HudQuery *query;132 HudQuery *query;
119133
120 g_variant_get (parameters, "(&si)", &search_string, &num_results);134 g_variant_get (parameters, "(&si)", &search_string, &num_results);
135 g_debug ("'StartQuery' from %s: '%s', %d", sender, search_string, num_results);
121 query = hud_query_new (source, search_string, num_results);136 query = hud_query_new (source, search_string, num_results);
122 g_signal_connect_object (query, "changed", G_CALLBACK (query_changed), connection, 0);137 g_signal_connect_object (query, "changed", G_CALLBACK (query_changed), connection, 0);
123 g_dbus_method_invocation_return_value (invocation, describe_query (query));138 g_dbus_method_invocation_return_value (invocation, describe_query (query));
@@ -128,21 +143,26 @@
128 {143 {
129 GVariant *platform_data;144 GVariant *platform_data;
130 GVariant *item_key;145 GVariant *item_key;
146 guint64 key_value;
131 HudItem *item;147 HudItem *item;
132148
133 g_variant_get_child (parameters, 0, "v", &item_key);149 g_variant_get_child (parameters, 0, "v", &item_key);
134150
135 if (!g_variant_is_of_type (item_key, G_VARIANT_TYPE_UINT64))151 if (!g_variant_is_of_type (item_key, G_VARIANT_TYPE_UINT64))
136 {152 {
153 g_debug ("'ExecuteQuery' from %s: incorrect item key (not uint64)", sender);
137 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,154 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
138 "item key has invalid format");155 "item key has invalid format");
139 g_variant_unref (item_key);156 g_variant_unref (item_key);
140 return;157 return;
141 }158 }
142159
143 item = hud_item_lookup (g_variant_get_uint64 (item_key));160 key_value = g_variant_get_uint64 (item_key);
144 g_variant_unref (item_key);161 g_variant_unref (item_key);
145162
163 item = hud_item_lookup (key_value);
164 g_debug ("'ExecuteQuery' from %s, item #%"G_GUINT64_FORMAT": %p", sender, key_value, item);
165
146 if (item == NULL)166 if (item == NULL)
147 {167 {
148 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,168 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
@@ -162,6 +182,8 @@
162 GVariant *query_key;182 GVariant *query_key;
163 HudQuery *query;183 HudQuery *query;
164184
185 g_debug ("Got 'CloseQuery' from %s", sender);
186
165 g_variant_get (parameters, "(v)", &query_key);187 g_variant_get (parameters, "(v)", &query_key);
166 query = hud_query_lookup (query_key);188 query = hud_query_lookup (query_key);
167 g_variant_unref (query_key);189 g_variant_unref (query_key);
@@ -169,6 +191,16 @@
169 if (query != NULL)191 if (query != NULL)
170 {192 {
171 g_signal_handlers_disconnect_by_func (query, query_changed, connection);193 g_signal_handlers_disconnect_by_func (query, query_changed, connection);
194 /* Unity does 'CloseQuery' immediately followed by
195 * 'StartQuery' on every keystroke. Delay the destruction of
196 * the query for a moment just in case a 'StartQuery' is on the
197 * way.
198 *
199 * That way we can avoid allowing the use count to drop to
200 * zero only to be increased again back to 1. This prevents a
201 * bunch of dbusmenu "closed"/"opened" calls being sent.
202 */
203 g_timeout_add (1000, drop_query_timeout, g_object_ref (query));
172 hud_query_close (query);204 hud_query_close (query);
173 }205 }
174206
@@ -209,6 +241,8 @@
209 };241 };
210 GError *error = NULL;242 GError *error = NULL;
211243
244 g_debug ("Bus acquired (guid %s)", g_dbus_connection_get_guid (connection));
245
212 if (!g_dbus_connection_register_object (connection, DBUS_PATH, get_iface_info (), &vtable, source, NULL, &error))246 if (!g_dbus_connection_register_object (connection, DBUS_PATH, get_iface_info (), &vtable, source, NULL, &error))
213 {247 {
214 g_warning ("Unable to register path '"DBUS_PATH"': %s", error->message);248 g_warning ("Unable to register path '"DBUS_PATH"': %s", error->message);
@@ -218,6 +252,14 @@
218}252}
219253
220static void254static void
255name_acquired_cb (GDBusConnection *connection,
256 const gchar *name,
257 gpointer user_data)
258{
259 g_debug ("Acquired bus name '%s'", name);
260}
261
262static void
221name_lost_cb (GDBusConnection *connection,263name_lost_cb (GDBusConnection *connection,
222 const gchar *name,264 const gchar *name,
223 gpointer user_data)265 gpointer user_data)
@@ -262,8 +304,17 @@
262 g_object_unref (source);304 g_object_unref (source);
263 }305 }
264306
307 if (getenv ("HUD_DEBUG_SOURCE"))
308 {
309 HudDebugSource *source;
310
311 source = hud_debug_source_new ();
312 hud_source_list_add (source_list, HUD_SOURCE (source));
313 g_object_unref (source);
314 }
315
265 g_bus_own_name (G_BUS_TYPE_SESSION, DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,316 g_bus_own_name (G_BUS_TYPE_SESSION, DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,
266 bus_acquired_cb, NULL, name_lost_cb, source_list, NULL);317 bus_acquired_cb, name_acquired_cb, name_lost_cb, source_list, NULL);
267318
268 mainloop = g_main_loop_new (NULL, FALSE);319 mainloop = g_main_loop_new (NULL, FALSE);
269 g_main_loop_run (mainloop);320 g_main_loop_run (mainloop);
270321
=== modified file 'src/hudappindicatorsource.c'
--- src/hudappindicatorsource.c 2012-03-12 16:25:31 +0000
+++ src/hudappindicatorsource.c 2012-03-17 16:16:19 +0000
@@ -55,6 +55,7 @@
55 GSequence *indicators;55 GSequence *indicators;
56 guint subscription;56 guint subscription;
57 GCancellable *cancellable;57 GCancellable *cancellable;
58 gint use_count;
58 gboolean ready;59 gboolean ready;
59};60};
6061
@@ -107,6 +108,10 @@
107 dbus_name, dbus_path);108 dbus_name, dbus_path);
108 g_signal_connect (collector, "changed", G_CALLBACK (hud_app_indicator_source_collector_changed), source);109 g_signal_connect (collector, "changed", G_CALLBACK (hud_app_indicator_source_collector_changed), source);
109110
111 /* If query is active, mark new app indicator as used. */
112 if (source->use_count)
113 hud_source_use (HUD_SOURCE (collector));
114
110 iter = g_sequence_get_iter_at_pos (source->indicators, position);115 iter = g_sequence_get_iter_at_pos (source->indicators, position);
111 g_sequence_insert_before (iter, collector);116 g_sequence_insert_before (iter, collector);
112 g_free (title);117 g_free (title);
@@ -130,6 +135,9 @@
130135
131 collector = g_sequence_get (iter);136 collector = g_sequence_get (iter);
132 g_signal_handlers_disconnect_by_func (collector, hud_app_indicator_source_collector_changed, source);137 g_signal_handlers_disconnect_by_func (collector, hud_app_indicator_source_collector_changed, source);
138 /* Drop use count if we added one... */
139 if (source->use_count)
140 hud_source_unuse (HUD_SOURCE (collector));
133 g_sequence_remove (iter);141 g_sequence_remove (iter);
134 }142 }
135}143}
@@ -313,6 +321,30 @@
313}321}
314322
315static void323static void
324hud_app_indicator_source_use (HudSource *hud_source)
325{
326 HudAppIndicatorSource *source = HUD_APP_INDICATOR_SOURCE (hud_source);
327
328 if (source->use_count == 0)
329 g_sequence_foreach (source->indicators, (GFunc) hud_source_use, NULL);
330
331 source->use_count++;
332}
333
334static void
335hud_app_indicator_source_unuse (HudSource *hud_source)
336{
337 HudAppIndicatorSource *source = HUD_APP_INDICATOR_SOURCE (hud_source);
338
339 g_return_if_fail (source->use_count > 0);
340
341 source->use_count--;
342
343 if (source->use_count == 0)
344 g_sequence_foreach (source->indicators, (GFunc) hud_source_unuse, NULL);
345}
346
347static void
316hud_app_indicator_source_search (HudSource *hud_source,348hud_app_indicator_source_search (HudSource *hud_source,
317 GPtrArray *results_array,349 GPtrArray *results_array,
318 const gchar *search_string)350 const gchar *search_string)
@@ -327,8 +359,6 @@
327 hud_source_search (g_sequence_get (iter), results_array, search_string);359 hud_source_search (g_sequence_get (iter), results_array, search_string);
328 iter = g_sequence_iter_next (iter);360 iter = g_sequence_iter_next (iter);
329 }361 }
330
331
332}362}
333363
334static void364static void
@@ -351,6 +381,8 @@
351static void381static void
352hud_app_indicator_source_iface_init (HudSourceInterface *iface)382hud_app_indicator_source_iface_init (HudSourceInterface *iface)
353{383{
384 iface->use = hud_app_indicator_source_use;
385 iface->unuse = hud_app_indicator_source_unuse;
354 iface->search = hud_app_indicator_source_search;386 iface->search = hud_app_indicator_source_search;
355}387}
356388
357389
=== modified file 'src/huddbusmenucollector.c'
--- src/huddbusmenucollector.c 2012-03-13 14:33:02 +0000
+++ src/huddbusmenucollector.c 2012-03-17 16:16:19 +0000
@@ -61,6 +61,7 @@
61 HudItem parent_instance;61 HudItem parent_instance;
6262
63 DbusmenuMenuitem *menuitem;63 DbusmenuMenuitem *menuitem;
64 gboolean is_opened;
64} HudDbusmenuItem;65} HudDbusmenuItem;
6566
66typedef HudItemClass HudDbusmenuItemClass;67typedef HudItemClass HudDbusmenuItemClass;
@@ -155,7 +156,7 @@
155}156}
156157
157158
158static HudItem *159static HudDbusmenuItem *
159hud_dbusmenu_item_new (HudStringList *context,160hud_dbusmenu_item_new (HudStringList *context,
160 const gchar *desktop_file,161 const gchar *desktop_file,
161 DbusmenuMenuitem *menuitem)162 DbusmenuMenuitem *menuitem)
@@ -199,7 +200,7 @@
199200
200 hud_string_list_unref (tokens);201 hud_string_list_unref (tokens);
201202
202 return HUD_ITEM (item);203 return item;
203}204}
204205
205struct _HudDbusmenuCollector206struct _HudDbusmenuCollector
@@ -214,6 +215,8 @@
214 guint penalty;215 guint penalty;
215 guint xid;216 guint xid;
216 gboolean alive;217 gboolean alive;
218 gint use_count;
219 gboolean reentrance_check;
217};220};
218221
219typedef GObjectClass HudDbusmenuCollectorClass;222typedef GObjectClass HudDbusmenuCollectorClass;
@@ -223,6 +226,68 @@
223 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_dbusmenu_collector_iface_init))226 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_dbusmenu_collector_iface_init))
224227
225static void228static void
229hud_dbusmenu_collector_open_submenu (gpointer key,
230 gpointer value,
231 gpointer user_data)
232{
233 DbusmenuMenuitem *menuitem = key;
234 HudDbusmenuItem *item = value;
235
236 if (dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
237 {
238 dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
239 item->is_opened = TRUE;
240 }
241}
242
243static void
244hud_dbusmenu_collector_close_submenu (gpointer key,
245 gpointer value,
246 gpointer user_data)
247{
248 DbusmenuMenuitem *menuitem = key;
249 HudDbusmenuItem *item = value;
250
251 if (item->is_opened)
252 {
253 dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_CLOSED, NULL, 0);
254 item->is_opened = FALSE;
255 }
256}
257
258static void
259hud_dbusmenu_collector_use (HudSource *source)
260{
261 HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
262
263 collector->reentrance_check = TRUE;
264
265 if (collector->use_count == 0)
266 g_hash_table_foreach (collector->items, hud_dbusmenu_collector_open_submenu, NULL);
267
268 collector->use_count++;
269
270 collector->reentrance_check = FALSE;
271}
272
273static void
274hud_dbusmenu_collector_unuse (HudSource *source)
275{
276 HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
277
278 g_return_if_fail (collector->use_count > 0);
279
280 collector->reentrance_check = TRUE;
281
282 collector->use_count--;
283
284 if (collector->use_count == 0)
285 g_hash_table_foreach (collector->items, hud_dbusmenu_collector_close_submenu, NULL);
286
287 collector->reentrance_check = FALSE;
288}
289
290static void
226hud_dbusmenu_collector_search (HudSource *source,291hud_dbusmenu_collector_search (HudSource *source,
227 GPtrArray *results_array,292 GPtrArray *results_array,
228 const gchar *search_string)293 const gchar *search_string)
@@ -260,6 +325,8 @@
260 HudStringList *context;325 HudStringList *context;
261 HudItem *item;326 HudItem *item;
262327
328 g_assert (!collector->reentrance_check);
329
263 item = g_hash_table_lookup (collector->items, menuitem);330 item = g_hash_table_lookup (collector->items, menuitem);
264 g_assert (item != NULL);331 g_assert (item != NULL);
265332
@@ -275,6 +342,8 @@
275{342{
276 HudDbusmenuCollector *collector = user_data;343 HudDbusmenuCollector *collector = user_data;
277344
345 g_assert (!collector->reentrance_check);
346
278 hud_dbusmenu_collector_remove_item (collector, child);347 hud_dbusmenu_collector_remove_item (collector, child);
279}348}
280349
@@ -287,7 +356,9 @@
287 HudDbusmenuCollector *collector = user_data;356 HudDbusmenuCollector *collector = user_data;
288 DbusmenuMenuitem *parent;357 DbusmenuMenuitem *parent;
289 HudStringList *context;358 HudStringList *context;
290 HudItem *item;359 HudDbusmenuItem *item;
360
361 g_assert (!collector->reentrance_check);
291362
292 parent = dbusmenu_menuitem_get_parent (menuitem);363 parent = dbusmenu_menuitem_get_parent (menuitem);
293364
@@ -303,6 +374,13 @@
303374
304 item = hud_dbusmenu_item_new (context, collector->application_id, menuitem);375 item = hud_dbusmenu_item_new (context, collector->application_id, menuitem);
305 g_hash_table_remove (collector->items, menuitem);376 g_hash_table_remove (collector->items, menuitem);
377
378 if (collector->use_count && dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
379 {
380 dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
381 item->is_opened = TRUE;
382 }
383
306 g_hash_table_insert (collector->items, menuitem, item);384 g_hash_table_insert (collector->items, menuitem, item);
307385
308 hud_source_changed (HUD_SOURCE (collector));386 hud_source_changed (HUD_SOURCE (collector));
@@ -313,15 +391,23 @@
313 HudStringList *context,391 HudStringList *context,
314 DbusmenuMenuitem *menuitem)392 DbusmenuMenuitem *menuitem)
315{393{
316 HudItem *item;394 HudDbusmenuItem *item;
317 GList *child;395 GList *child;
318396
319 item = hud_dbusmenu_item_new (context, NULL, menuitem);397 item = hud_dbusmenu_item_new (context, NULL, menuitem);
320 context = hud_item_get_tokens (item);398 context = hud_item_get_tokens (HUD_ITEM (item));
321399
322 g_signal_connect (menuitem, "property-changed", G_CALLBACK (hud_dbusmenu_collector_property_changed), collector);400 g_signal_connect (menuitem, "property-changed", G_CALLBACK (hud_dbusmenu_collector_property_changed), collector);
323 g_signal_connect (menuitem, "child-added", G_CALLBACK (hud_dbusmenu_collector_child_added), collector);401 g_signal_connect (menuitem, "child-added", G_CALLBACK (hud_dbusmenu_collector_child_added), collector);
324 g_signal_connect (menuitem, "child-removed", G_CALLBACK (hud_dbusmenu_collector_child_removed), collector);402 g_signal_connect (menuitem, "child-removed", G_CALLBACK (hud_dbusmenu_collector_child_removed), collector);
403
404 /* If we're actively being queried and we add a new submenu item, open it. */
405 if (collector->use_count && dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
406 {
407 dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
408 item->is_opened = TRUE;
409 }
410
325 g_hash_table_insert (collector->items, menuitem, item);411 g_hash_table_insert (collector->items, menuitem, item);
326412
327 for (child = dbusmenu_menuitem_get_children (menuitem); child; child = child->next)413 for (child = dbusmenu_menuitem_get_children (menuitem); child; child = child->next)
@@ -355,14 +441,21 @@
355{441{
356 if (collector->root)442 if (collector->root)
357 {443 {
444 /* If the collector has the submenus opened, close them before we
445 * remove them all. The use_count being non-zero will cause them
446 * to be reopened as they are added back below (if they will be).
447 */
448 if (collector->use_count > 0)
449 g_hash_table_foreach (collector->items, hud_dbusmenu_collector_close_submenu, NULL);
450
358 hud_dbusmenu_collector_remove_item (collector, collector->root);451 hud_dbusmenu_collector_remove_item (collector, collector->root);
359 collector->root = NULL;452 g_clear_object (&collector->root);
360 }453 }
361454
362 if (root)455 if (root)
363 {456 {
364 hud_dbusmenu_collector_add_item (collector, collector->prefix, root);457 hud_dbusmenu_collector_add_item (collector, collector->prefix, root);
365 collector->root = root;458 collector->root = g_object_ref (root);
366 }459 }
367}460}
368461
@@ -373,6 +466,8 @@
373{466{
374 HudDbusmenuCollector *collector = user_data;467 HudDbusmenuCollector *collector = user_data;
375468
469 g_assert (!collector->reentrance_check);
470
376 hud_dbusmenu_collector_setup_root (collector, root);471 hud_dbusmenu_collector_setup_root (collector, root);
377}472}
378473
@@ -429,6 +524,8 @@
429 g_assert (g_hash_table_size (collector->items) == 0);524 g_assert (g_hash_table_size (collector->items) == 0);
430 g_hash_table_unref (collector->items);525 g_hash_table_unref (collector->items);
431526
527 g_free (collector->application_id);
528
432 hud_string_list_unref (collector->prefix);529 hud_string_list_unref (collector->prefix);
433 g_clear_object (&collector->client);530 g_clear_object (&collector->client);
434531
@@ -445,6 +542,8 @@
445static void542static void
446hud_dbusmenu_collector_iface_init (HudSourceInterface *iface)543hud_dbusmenu_collector_iface_init (HudSourceInterface *iface)
447{544{
545 iface->use = hud_dbusmenu_collector_use;
546 iface->unuse = hud_dbusmenu_collector_unuse;
448 iface->search = hud_dbusmenu_collector_search;547 iface->search = hud_dbusmenu_collector_search;
449}548}
450549
@@ -515,7 +614,6 @@
515 const gchar *desktop_file)614 const gchar *desktop_file)
516{615{
517 HudDbusmenuCollector *collector;616 HudDbusmenuCollector *collector;
518 BamfApplication *application;
519617
520 collector = g_object_new (HUD_TYPE_DBUSMENU_COLLECTOR, NULL);618 collector = g_object_new (HUD_TYPE_DBUSMENU_COLLECTOR, NULL);
521 collector->application_id = g_strdup (desktop_file);619 collector->application_id = g_strdup (desktop_file);
@@ -524,10 +622,6 @@
524 hud_app_menu_registrar_add_observer (hud_app_menu_registrar_get (), collector->xid,622 hud_app_menu_registrar_add_observer (hud_app_menu_registrar_get (), collector->xid,
525 hud_dbusmenu_collector_registrar_observer_func, collector);623 hud_dbusmenu_collector_registrar_observer_func, collector);
526624
527 application = bamf_matcher_get_application_for_window (bamf_matcher_get_default (), window);
528 if (application != NULL)
529 collector->application_id = g_strdup (bamf_application_get_desktop_file (application));
530
531 collector->alive = TRUE;625 collector->alive = TRUE;
532626
533 return collector;627 return collector;
@@ -549,10 +643,5 @@
549{643{
550 hud_string_list_unref (collector->prefix);644 hud_string_list_unref (collector->prefix);
551 collector->prefix = hud_string_list_cons (prefix, NULL);645 collector->prefix = hud_string_list_cons (prefix, NULL);
552646 hud_dbusmenu_collector_setup_root (collector, collector->root);
553 if (collector->root)
554 {
555 hud_dbusmenu_collector_remove_item (collector, collector->root);
556 hud_dbusmenu_collector_add_item (collector, collector->prefix, collector->root);
557 }
558}647}
559648
=== added file 'src/huddebugsource.c'
--- src/huddebugsource.c 1970-01-01 00:00:00 +0000
+++ src/huddebugsource.c 2012-03-17 16:16:19 +0000
@@ -0,0 +1,168 @@
1/*
2 * Copyright © 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Ryan Lortie <desrt@desrt.ca>
17 */
18
19#include "huddebugsource.h"
20
21#include "hudsource.h"
22#include "hudresult.h"
23
24/**
25 * SECTION:huddebugsource
26 * @title: HudDebugSource
27 * @short_description: a source to assist with debugging
28 *
29 * #HudDebugSource is a source for debugging purposes. It is not
30 * enabled by default but you can have it added to the global list of
31 * sources by setting the HUD_DEBUG_SOURCE environment variable.
32 *
33 * Presently it creates a #HudItem corresponding to the current date and
34 * time (and updates it as the time changes).
35 **/
36
37/**
38 * HudDebugSource:
39 *
40 * This is an opaque structure type.
41 **/
42
43struct _HudDebugSource
44{
45 GObject parent_instance;
46
47 HudItem *item;
48 gint use_count;
49 gint timeout;
50};
51
52typedef GObjectClass HudDebugSourceClass;
53
54static void hud_debug_source_iface_init (HudSourceInterface *iface);
55G_DEFINE_TYPE_WITH_CODE (HudDebugSource, hud_debug_source, G_TYPE_OBJECT,
56 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_debug_source_iface_init))
57
58static gboolean
59hud_debug_source_timeout (gpointer user_data)
60{
61 HudDebugSource *source = user_data;
62 HudStringList *tokens;
63 GDateTime *now;
64 gchar *time;
65
66 g_clear_object (&source->item);
67
68 now = g_date_time_new_now_local ();
69 time = g_date_time_format (now, "hud-debug time: %c");
70 tokens = hud_string_list_cons (time, NULL);
71 g_date_time_unref (now);
72 g_free (time);
73
74 source->item = hud_item_new (tokens, NULL, TRUE);
75 hud_string_list_unref (tokens);
76
77 hud_source_changed (HUD_SOURCE (source));
78
79 return TRUE;
80}
81
82static void
83hud_debug_source_use (HudSource *hud_source)
84{
85 HudDebugSource *source = HUD_DEBUG_SOURCE (hud_source);
86
87 if (source->use_count == 0)
88 source->timeout = g_timeout_add (1000, hud_debug_source_timeout, source);
89
90 source->use_count++;
91}
92
93static void
94hud_debug_source_unuse (HudSource *hud_source)
95{
96 HudDebugSource *source = HUD_DEBUG_SOURCE (hud_source);
97
98 source->use_count--;
99
100 if (source->use_count == 0)
101 {
102 g_source_remove (source->timeout);
103 source->timeout = 0;
104 }
105}
106
107static void
108hud_debug_source_search (HudSource *hud_source,
109 GPtrArray *results_array,
110 const gchar *search_string)
111{
112 HudDebugSource *source = HUD_DEBUG_SOURCE (hud_source);
113
114 if (source->item)
115 {
116 HudResult *result;
117
118 result = hud_result_get_if_matched (source->item, search_string, 0);
119 if (result != NULL)
120 g_ptr_array_add (results_array, result);
121 }
122}
123
124static void
125hud_debug_source_finalize (GObject *object)
126{
127 HudDebugSource *source = HUD_DEBUG_SOURCE (object);
128
129 g_clear_object (&source->item);
130
131 if (source->timeout)
132 g_source_remove (source->timeout);
133
134 G_OBJECT_CLASS (hud_debug_source_parent_class)
135 ->finalize (object);
136}
137
138static void
139hud_debug_source_init (HudDebugSource *source)
140{
141}
142
143static void
144hud_debug_source_iface_init (HudSourceInterface *iface)
145{
146 iface->use = hud_debug_source_use;
147 iface->unuse = hud_debug_source_unuse;
148 iface->search = hud_debug_source_search;
149}
150
151static void
152hud_debug_source_class_init (HudDebugSourceClass *class)
153{
154 class->finalize = hud_debug_source_finalize;
155}
156
157/**
158 * hud_debug_source_new:
159 *
160 * Creates a #HudDebugSource.
161 *
162 * Returns: a new empty #HudDebugSource
163 **/
164HudDebugSource *
165hud_debug_source_new (void)
166{
167 return g_object_new (HUD_TYPE_DEBUG_SOURCE, NULL);
168}
0169
=== added file 'src/huddebugsource.h'
--- src/huddebugsource.h 1970-01-01 00:00:00 +0000
+++ src/huddebugsource.h 2012-03-17 16:16:19 +0000
@@ -0,0 +1,36 @@
1/*
2 * Copyright © 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Ryan Lortie <desrt@desrt.ca>
17 */
18
19#ifndef __HUD_DEBUG_SOURCE_H__
20#define __HUD_DEBUG_SOURCE_H__
21
22#include <glib-object.h>
23
24#define HUD_TYPE_DEBUG_SOURCE (hud_debug_source_get_type ())
25#define HUD_DEBUG_SOURCE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
26 HUD_TYPE_DEBUG_SOURCE, HudDebugSource))
27#define HUD_IS_DEBUG_SOURCE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
28 HUD_TYPE_DEBUG_SOURCE))
29
30typedef struct _HudDebugSource HudDebugSource;
31
32GType hud_debug_source_get_type (void);
33
34HudDebugSource * hud_debug_source_new (void);
35
36#endif /* __HUD_DEBUG_SOURCE_H__ */
037
=== modified file 'src/hudindicatorsource.c'
--- src/hudindicatorsource.c 2012-03-12 16:25:31 +0000
+++ src/hudindicatorsource.c 2012-03-17 16:16:19 +0000
@@ -92,7 +92,7 @@
92typedef struct92typedef struct
93{93{
94 const IndicatorInfo *info;94 const IndicatorInfo *info;
95 HudSource *source;95 HudIndicatorSource *source;
96 HudSource *collector;96 HudSource *collector;
97} HudIndicatorSourceIndicator;97} HudIndicatorSourceIndicator;
9898
@@ -102,6 +102,7 @@
102102
103 HudIndicatorSourceIndicator *indicators;103 HudIndicatorSourceIndicator *indicators;
104 gint n_indicators;104 gint n_indicators;
105 gint use_count;
105};106};
106107
107typedef GObjectClass HudIndicatorSourceClass;108typedef GObjectClass HudIndicatorSourceClass;
@@ -111,6 +112,40 @@
111 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_indicator_source_iface_init))112 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_indicator_source_iface_init))
112113
113static void114static void
115hud_indicator_source_use (HudSource *hud_source)
116{
117 HudIndicatorSource *source = HUD_INDICATOR_SOURCE (hud_source);
118 gint i;
119
120 if (source->use_count == 0)
121 {
122 for (i = 0; i < source->n_indicators; i++)
123 if (source->indicators[i].collector)
124 hud_source_use (source->indicators[i].collector);
125 }
126
127 source->use_count++;
128}
129
130static void
131hud_indicator_source_unuse (HudSource *hud_source)
132{
133 HudIndicatorSource *source = HUD_INDICATOR_SOURCE (hud_source);
134 gint i;
135
136 g_return_if_fail (source->use_count > 0);
137
138 source->use_count--;
139
140 if (source->use_count == 0)
141 {
142 for (i = 0; i < source->n_indicators; i++)
143 if (source->indicators[i].collector)
144 hud_source_unuse (source->indicators[i].collector);
145 }
146}
147
148static void
114hud_indicator_source_search (HudSource *hud_source,149hud_indicator_source_search (HudSource *hud_source,
115 GPtrArray *results_array,150 GPtrArray *results_array,
116 const gchar *search_string)151 const gchar *search_string)
@@ -135,7 +170,7 @@
135{170{
136 HudIndicatorSourceIndicator *indicator = user_data;171 HudIndicatorSourceIndicator *indicator = user_data;
137172
138 hud_source_changed (indicator->source);173 hud_source_changed (HUD_SOURCE (indicator->source));
139}174}
140175
141static void176static void
@@ -154,7 +189,11 @@
154 g_signal_connect (collector, "changed", G_CALLBACK (hud_indicator_source_collector_changed), indicator);189 g_signal_connect (collector, "changed", G_CALLBACK (hud_indicator_source_collector_changed), indicator);
155 indicator->collector = HUD_SOURCE (collector);190 indicator->collector = HUD_SOURCE (collector);
156191
157 hud_source_changed (indicator->source);192 /* Set initial use count on new indicator if query is active. */
193 if (indicator->source->use_count)
194 hud_source_use (indicator->collector);
195
196 hud_source_changed (HUD_SOURCE (indicator->source));
158}197}
159198
160static void199static void
@@ -167,10 +206,13 @@
167 if (indicator->collector)206 if (indicator->collector)
168 {207 {
169 g_signal_handlers_disconnect_by_func (indicator->collector, hud_indicator_source_collector_changed, indicator);208 g_signal_handlers_disconnect_by_func (indicator->collector, hud_indicator_source_collector_changed, indicator);
209 /* Drop our use count on dying indicator (if any) */
210 if (indicator->source->use_count)
211 hud_source_unuse (indicator->collector);
170 g_clear_object (&indicator->collector);212 g_clear_object (&indicator->collector);
171 }213 }
172214
173 hud_source_changed (indicator->source);215 hud_source_changed (HUD_SOURCE (indicator->source));
174}216}
175217
176static void218static void
@@ -186,7 +228,7 @@
186 HudIndicatorSourceIndicator *indicator = &source->indicators[i];228 HudIndicatorSourceIndicator *indicator = &source->indicators[i];
187229
188 indicator->info = &indicator_info[i];230 indicator->info = &indicator_info[i];
189 indicator->source = HUD_SOURCE (source);231 indicator->source = source;
190232
191 g_bus_watch_name (G_BUS_TYPE_SESSION, indicator->info->dbus_name, G_BUS_NAME_WATCHER_FLAGS_NONE,233 g_bus_watch_name (G_BUS_TYPE_SESSION, indicator->info->dbus_name, G_BUS_NAME_WATCHER_FLAGS_NONE,
192 hud_indicator_source_name_appeared, hud_indicator_source_name_vanished, indicator, NULL);234 hud_indicator_source_name_appeared, hud_indicator_source_name_vanished, indicator, NULL);
@@ -196,6 +238,8 @@
196static void238static void
197hud_indicator_source_iface_init (HudSourceInterface *iface)239hud_indicator_source_iface_init (HudSourceInterface *iface)
198{240{
241 iface->use = hud_indicator_source_use;
242 iface->unuse = hud_indicator_source_unuse;
199 iface->search = hud_indicator_source_search;243 iface->search = hud_indicator_source_search;
200}244}
201245
202246
=== modified file 'src/huditem.c'
--- src/huditem.c 2012-03-13 13:32:36 +0000
+++ src/huditem.c 2012-03-17 16:16:19 +0000
@@ -69,6 +69,7 @@
69 g_hash_table_remove (hud_item_table, &item->priv->id);69 g_hash_table_remove (hud_item_table, &item->priv->id);
70 hud_string_list_unref (item->priv->tokens);70 hud_string_list_unref (item->priv->tokens);
71 g_free (item->priv->desktop_file);71 g_free (item->priv->desktop_file);
72 g_free (item->priv->usage_tag);
7273
73 G_OBJECT_CLASS (hud_item_parent_class)74 G_OBJECT_CLASS (hud_item_parent_class)
74 ->finalize (object);75 ->finalize (object);
7576
=== modified file 'src/hudmenumodelcollector.c'
--- src/hudmenumodelcollector.c 2012-03-12 16:25:31 +0000
+++ src/hudmenumodelcollector.c 2012-03-17 16:16:19 +0000
@@ -61,9 +61,9 @@
6161
62 gchar *desktop_file;62 gchar *desktop_file;
63 GPtrArray *items;63 GPtrArray *items;
64 gint use_count;
64};65};
6566
66
67typedef struct67typedef struct
68{68{
69 HudItem parent_instance;69 HudItem parent_instance;
@@ -329,6 +329,22 @@
329}329}
330330
331static void331static void
332hud_menu_model_collector_use (HudSource *source)
333{
334 HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
335
336 collector->use_count++;
337}
338
339static void
340hud_menu_model_collector_unuse (HudSource *source)
341{
342 HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
343
344 collector->use_count--;
345}
346
347static void
332hud_menu_model_collector_search (HudSource *source,348hud_menu_model_collector_search (HudSource *source,
333 GPtrArray *results_array,349 GPtrArray *results_array,
334 const gchar *search_string)350 const gchar *search_string)
@@ -381,6 +397,8 @@
381static void397static void
382hud_menu_model_collector_iface_init (HudSourceInterface *iface)398hud_menu_model_collector_iface_init (HudSourceInterface *iface)
383{399{
400 iface->use = hud_menu_model_collector_use;
401 iface->unuse = hud_menu_model_collector_unuse;
384 iface->search = hud_menu_model_collector_search;402 iface->search = hud_menu_model_collector_search;
385}403}
386404
387405
=== modified file 'src/hudquery.c'
--- src/hudquery.c 2012-03-07 21:55:41 +0000
+++ src/hudquery.c 2012-03-17 16:16:19 +0000
@@ -16,6 +16,8 @@
16 * Author: Ryan Lortie <desrt@desrt.ca>16 * Author: Ryan Lortie <desrt@desrt.ca>
17 */17 */
1818
19#define G_LOG_DOMAIN "hudquery"
20
19#include "hudquery.h"21#include "hudquery.h"
2022
21#include "hudresult.h"23#include "hudresult.h"
@@ -138,7 +140,7 @@
138 HudQuery *query = user_data;140 HudQuery *query = user_data;
139141
140 if (!query->refresh_id)142 if (!query->refresh_id)
141 query->refresh_id = g_idle_add (hud_query_dispatch_refresh, g_object_ref (query));143 query->refresh_id = g_idle_add (hud_query_dispatch_refresh, query);
142}144}
143145
144static void146static void
@@ -146,6 +148,13 @@
146{148{
147 HudQuery *query = HUD_QUERY (object);149 HudQuery *query = HUD_QUERY (object);
148150
151 g_debug ("Destroyed query '%s'", query->search_string);
152
153 if (query->refresh_id)
154 g_source_remove (query->refresh_id);
155
156 hud_source_unuse (query->source);
157
149 g_object_unref (query->source);158 g_object_unref (query->source);
150 g_free (query->search_string);159 g_free (query->search_string);
151 g_ptr_array_unref (query->results);160 g_ptr_array_unref (query->results);
@@ -199,12 +208,16 @@
199{208{
200 HudQuery *query;209 HudQuery *query;
201210
211 g_debug ("Created query '%s'", search_string);
212
202 query = g_object_new (HUD_TYPE_QUERY, NULL);213 query = g_object_new (HUD_TYPE_QUERY, NULL);
203 query->source = g_object_ref (source);214 query->source = g_object_ref (source);
204 query->results = g_ptr_array_new_with_free_func (g_object_unref);215 query->results = g_ptr_array_new_with_free_func (g_object_unref);
205 query->search_string = g_strdup (search_string);216 query->search_string = g_strdup (search_string);
206 query->num_results = num_results;217 query->num_results = num_results;
207218
219 hud_source_use (query->source);
220
208 hud_query_refresh (query);221 hud_query_refresh (query);
209222
210 g_signal_connect_object (source, "changed", G_CALLBACK (hud_query_source_changed), query, 0);223 g_signal_connect_object (source, "changed", G_CALLBACK (hud_query_source_changed), query, 0);
211224
=== modified file 'src/hudsource.c'
--- src/hudsource.c 2012-02-29 15:48:43 +0000
+++ src/hudsource.c 2012-03-17 16:16:19 +0000
@@ -85,6 +85,52 @@
85}85}
8686
87/**87/**
88 * hud_source_use:
89 * @source; a #HudSource
90 *
91 * Mark a #HudSource as "in use" (ie: actively being queried).
92 *
93 * The source maintains a use count. You must call hud_source_unuse()
94 * for as many times as you called hud_source_use().
95 *
96 * The source may not emit change signals unless it is marked as being
97 * used (although it is free to ignore this hint and emit them anyway).
98 * Some data in the source may also be out of date. It is therefore
99 * recommended that calls to hud_source_search() be preceeded by a call
100 * to this function.
101 **/
102void
103hud_source_use (HudSource *source)
104{
105 g_return_if_fail (HUD_IS_SOURCE (source));
106
107 g_debug ("use on %s %p", G_OBJECT_TYPE_NAME (source), source);
108
109 HUD_SOURCE_GET_IFACE (source)
110 ->use (source);
111}
112
113/**
114 * hud_source_unuse:
115 * @source; a #HudSource
116 *
117 * Reverses the effect of a previous call to hud_source_use().
118 *
119 * The source maintains a use count. You must call hud_source_unuse()
120 * for as many times as you called hud_source_use().
121 **/
122void
123hud_source_unuse (HudSource *source)
124{
125 g_return_if_fail (HUD_IS_SOURCE (source));
126
127 g_debug ("unuse on %s %p", G_OBJECT_TYPE_NAME (source), source);
128
129 HUD_SOURCE_GET_IFACE (source)
130 ->unuse (source);
131}
132
133/**
88 * hud_source_search:134 * hud_source_search:
89 * @source: a #HudSource135 * @source: a #HudSource
90 * @results_array: (element-type HudResult): array to append results to136 * @results_array: (element-type HudResult): array to append results to
91137
=== modified file 'src/hudsource.h'
--- src/hudsource.h 2012-02-28 18:29:03 +0000
+++ src/hudsource.h 2012-03-17 16:16:19 +0000
@@ -36,6 +36,8 @@
36{36{
37 GTypeInterface g_iface;37 GTypeInterface g_iface;
3838
39 void (* use) (HudSource *source);
40 void (* unuse) (HudSource *source);
39 void (* search) (HudSource *source,41 void (* search) (HudSource *source,
40 GPtrArray *results_array,42 GPtrArray *results_array,
41 const gchar *search_string);43 const gchar *search_string);
@@ -43,6 +45,9 @@
4345
44GType hud_source_get_type (void);46GType hud_source_get_type (void);
4547
48void hud_source_use (HudSource *source);
49void hud_source_unuse (HudSource *source);
50
46void hud_source_search (HudSource *source,51void hud_source_search (HudSource *source,
47 GPtrArray *results_array,52 GPtrArray *results_array,
48 const gchar *search_string);53 const gchar *search_string);
4954
=== modified file 'src/hudsourcelist.c'
--- src/hudsourcelist.c 2012-02-28 18:29:03 +0000
+++ src/hudsourcelist.c 2012-03-17 16:16:19 +0000
@@ -63,6 +63,26 @@
63}63}
6464
65static void65static void
66hud_source_list_use (HudSource *source)
67{
68 HudSourceList *list = HUD_SOURCE_LIST (source);
69 GSList *node;
70
71 for (node = list->list; node; node = node->next)
72 hud_source_use (node->data);
73}
74
75static void
76hud_source_list_unuse (HudSource *source)
77{
78 HudSourceList *list = HUD_SOURCE_LIST (source);
79 GSList *node;
80
81 for (node = list->list; node; node = node->next)
82 hud_source_unuse (node->data);
83}
84
85static void
66hud_source_list_search (HudSource *source,86hud_source_list_search (HudSource *source,
67 GPtrArray *results_array,87 GPtrArray *results_array,
68 const gchar *search_string)88 const gchar *search_string)
@@ -94,6 +114,8 @@
94static void114static void
95hud_source_list_iface_init (HudSourceInterface *iface)115hud_source_list_iface_init (HudSourceInterface *iface)
96{116{
117 iface->use = hud_source_list_use;
118 iface->unuse = hud_source_list_unuse;
97 iface->search = hud_source_list_search;119 iface->search = hud_source_list_search;
98}120}
99121
100122
=== modified file 'src/hudwindowsource.c'
--- src/hudwindowsource.c 2012-03-13 13:39:30 +0000
+++ src/hudwindowsource.c 2012-03-17 16:16:19 +0000
@@ -67,6 +67,8 @@
67 BamfWindow *active_window;67 BamfWindow *active_window;
68 BamfApplication *active_application;68 BamfApplication *active_application;
69 const gchar *active_desktop_file;69 const gchar *active_desktop_file;
70 HudSource *active_collector;
71 gint use_count;
70};72};
7173
72typedef GObjectClass HudWindowSourceClass;74typedef GObjectClass HudWindowSourceClass;
@@ -194,7 +196,6 @@
194 gpointer user_data)196 gpointer user_data)
195{197{
196 HudWindowSource *source = user_data;198 HudWindowSource *source = user_data;
197 HudSource *collector;
198 BamfWindow *window;199 BamfWindow *window;
199 BamfApplication *application;200 BamfApplication *application;
200 const gchar *desktop_file;201 const gchar *desktop_file;
@@ -239,34 +240,65 @@
239240
240 g_debug ("new active window (xid %u)", bamf_window_get_xid (window));241 g_debug ("new active window (xid %u)", bamf_window_get_xid (window));
241242
242 collector = hud_window_source_get_collector (source);243
243 if (collector)244 if (source->active_collector)
244 g_signal_handlers_disconnect_by_func (collector, hud_window_source_collector_changed, source);245 {
245246 g_signal_handlers_disconnect_by_func (source->active_collector, hud_window_source_collector_changed, source);
247 if (source->use_count)
248 hud_source_unuse (source->active_collector);
249 }
250
251 g_clear_object (&source->active_collector);
246 g_clear_object (&source->active_application);252 g_clear_object (&source->active_application);
247 g_clear_object (&source->active_window);253 g_clear_object (&source->active_window);
248 source->active_window = g_object_ref (window);254 source->active_window = g_object_ref (window);
249 source->active_application = g_object_ref (application);255 source->active_application = g_object_ref (application);
250 source->active_desktop_file = desktop_file;256 source->active_desktop_file = desktop_file;
257 source->active_collector = g_object_ref (hud_window_source_get_collector (source));
251258
252 collector = hud_window_source_get_collector (source);259 if (source->use_count)
253 g_signal_connect_object (collector, "changed", G_CALLBACK (hud_window_source_collector_changed), source, 0);260 hud_source_use (source->active_collector);
261 g_signal_connect_object (source->active_collector, "changed",
262 G_CALLBACK (hud_window_source_collector_changed), source, 0);
254263
255 hud_source_changed (HUD_SOURCE (source));264 hud_source_changed (HUD_SOURCE (source));
256}265}
257266
258static void267static void
268hud_window_source_use (HudSource *hud_source)
269{
270 HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);
271
272 if (source->use_count == 0)
273 if (source->active_collector)
274 hud_source_use (source->active_collector);
275
276 source->use_count++;
277}
278
279static void
280hud_window_source_unuse (HudSource *hud_source)
281{
282 HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);
283
284 g_return_if_fail (source->use_count > 0);
285
286 source->use_count--;
287
288 if (source->use_count == 0)
289 if (source->active_collector)
290 hud_source_unuse (source->active_collector);
291}
292
293static void
259hud_window_source_search (HudSource *hud_source,294hud_window_source_search (HudSource *hud_source,
260 GPtrArray *results_array,295 GPtrArray *results_array,
261 const gchar *search_string)296 const gchar *search_string)
262{297{
263 HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);298 HudWindowSource *source = HUD_WINDOW_SOURCE (hud_source);
264 HudSource *collector;299
265300 if (source->active_collector)
266 collector = hud_window_source_get_collector (source);301 hud_source_search (source->active_collector, results_array, search_string);
267
268 if (collector)
269 hud_source_search (collector, results_array, search_string);
270}302}
271303
272static void304static void
@@ -285,15 +317,22 @@
285static void317static void
286hud_window_source_init (HudWindowSource *source)318hud_window_source_init (HudWindowSource *source)
287{319{
320 BamfWindow *window;
321
288 source->matcher = bamf_matcher_get_default ();322 source->matcher = bamf_matcher_get_default ();
289323
290 g_signal_connect_object (source->matcher, "active-window-changed",324 g_signal_connect_object (source->matcher, "active-window-changed",
291 G_CALLBACK (hud_window_source_active_window_changed), source, 0);325 G_CALLBACK (hud_window_source_active_window_changed), source, 0);
326 window = bamf_matcher_get_active_window (source->matcher);
327 if (window != NULL)
328 hud_window_source_active_window_changed (source->matcher, NULL, BAMF_VIEW (window), source);
292}329}
293330
294static void331static void
295hud_window_source_iface_init (HudSourceInterface *iface)332hud_window_source_iface_init (HudSourceInterface *iface)
296{333{
334 iface->use = hud_window_source_use;
335 iface->unuse = hud_window_source_unuse;
297 iface->search = hud_window_source_search;336 iface->search = hud_window_source_search;
298}337}
299338

Subscribers

People subscribed via source and target branches