Merge lp:~charlesk/libdbusmenu/lp-977803 into lp:libdbusmenu/0.6

Proposed by Charles Kerr
Status: Merged
Approved by: Ted Gould
Approved revision: 409
Merged at revision: 408
Proposed branch: lp:~charlesk/libdbusmenu/lp-977803
Merge into: lp:libdbusmenu/0.6
Diff against target: 356 lines (+114/-93)
1 file modified
libdbusmenu-gtk/parser.c (+114/-93)
To merge this branch: bzr merge lp:~charlesk/libdbusmenu/lp-977803
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+101401@code.launchpad.net

Description of the change

I'm still suspicious about parser.c's signal handling, but this morning's bug #977803 shows that my disconnect-smoke-tests from yesterday have too many noisy false positives.

This commit remembers the handler_id of each signal that we connect to so that we can give more useful warnings at disconnect time.

To post a comment you must log in.
lp:~charlesk/libdbusmenu/lp-977803 updated
409. By Charles Kerr

switch the smoke test to a g_debug statement

Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libdbusmenu-gtk/parser.c'
--- libdbusmenu-gtk/parser.c 2012-04-09 16:16:07 +0000
+++ libdbusmenu-gtk/parser.c 2012-04-10 16:09:19 +0000
@@ -39,11 +39,27 @@
39typedef struct _ParserData39typedef struct _ParserData
40{40{
41 GtkWidget *label;41 GtkWidget *label;
42 gulong label_notify_handler_id;
43
42 GtkAction *action;44 GtkAction *action;
43 GtkWidget *widget;45 gulong action_notify_handler_id;
46
44 GtkWidget *shell;47 GtkWidget *shell;
48 gulong item_inserted_handler_id;
49 gulong item_removed_handler_id;
50
45 GtkWidget *image;51 GtkWidget *image;
52 gulong image_notify_handler_id;
53
46 AtkObject *accessible;54 AtkObject *accessible;
55 gulong a11y_handler_id;
56
57 GtkWidget *widget;
58 gulong widget_notify_handler_id;
59 gulong widget_add_handler_id;
60 gulong widget_accel_handler_id;
61 gulong widget_toggle_handler_id;
62 gulong widget_visible_handler_id;
4763
48} ParserData;64} ParserData;
4965
@@ -160,6 +176,41 @@
160****176****
161***/177***/
162178
179static void
180dbusmenu_gtk_clear_signal_handler (gpointer instance, gulong *handler_id)
181{
182 if (handler_id && *handler_id) {
183 /* complain if we thought we were connected but aren't */
184 if (!g_signal_handler_is_connected (instance, *handler_id)) {
185 g_debug ("%s tried to disconnect signal handler %lu from disconnected %p", G_STRLOC, *handler_id, instance);
186 } else {
187 g_signal_handler_disconnect (instance, *handler_id);
188 *handler_id = 0;
189 }
190 }
191}
192
193/* get the ParserData associated with the specified DbusmenuMenuitem */
194static ParserData*
195parser_data_get_from_menuitem (DbusmenuMenuitem * item)
196{
197 return (ParserData *) g_object_get_data(G_OBJECT(item), PARSER_DATA);
198}
199
200/* get the ParserData associated with the specified widget */
201static ParserData*
202parser_data_get_from_widget (GtkWidget * widget)
203{
204 DbusmenuMenuitem * item = dbusmenu_gtk_parse_get_cached_item (widget);
205 if (item != NULL)
206 return parser_data_get_from_menuitem (item);
207 return NULL;
208}
209
210/***
211****
212***/
213
163/**214/**
164 * dbusmenu_gtk_parse_menu_structure:215 * dbusmenu_gtk_parse_menu_structure:
165 * @widget: A #GtkMenuItem or #GtkMenuShell to turn into a #DbusmenuMenuitem216 * @widget: A #GtkMenuItem or #GtkMenuShell to turn into a #DbusmenuMenuitem
@@ -222,64 +273,47 @@
222 g_return_if_fail (pdata != NULL);273 g_return_if_fail (pdata != NULL);
223274
224 if (pdata->label != NULL) {275 if (pdata->label != NULL) {
225 gint i = 0;276 GObject * o = G_OBJECT(pdata->label);
226 i += g_signal_handlers_disconnect_matched(pdata->label, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,277 dbusmenu_gtk_clear_signal_handler (o, &pdata->label_notify_handler_id);
227 0, 0, NULL, G_CALLBACK(label_notify_cb), NULL);278 g_object_remove_weak_pointer(o, (gpointer*)&pdata->label);
228 g_warn_if_fail (i != 1);
229 g_object_remove_weak_pointer(G_OBJECT(pdata->label), (gpointer*)&pdata->label);
230 }279 }
231280
232 if (pdata->action != NULL) {281 if (pdata->action != NULL) {
233 gint i = 0;282 GObject * o = G_OBJECT(pdata->action);
234 i += g_signal_handlers_disconnect_matched(pdata->action, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,283 dbusmenu_gtk_clear_signal_handler (o, &pdata->action_notify_handler_id);
235 0, 0, NULL, G_CALLBACK(action_notify_cb), NULL);284 g_object_remove_weak_pointer(o, (gpointer*)&pdata->action);
236 g_warn_if_fail (i != 1);
237 g_object_remove_weak_pointer(G_OBJECT(pdata->action), (gpointer*)&pdata->action);
238 }285 }
239286
240 if (pdata->widget != NULL) {287 if (pdata->widget != NULL) {
241 GObject * o = G_OBJECT(pdata->widget);288 GObject * o = G_OBJECT(pdata->widget);
242 gint i = 0;289 dbusmenu_gtk_clear_signal_handler (o, &pdata->widget_notify_handler_id);
243 i += g_signal_handlers_disconnect_matched(o, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,290 dbusmenu_gtk_clear_signal_handler (o, &pdata->widget_add_handler_id);
244 0, 0, NULL, G_CALLBACK(widget_notify_cb), NULL);291 dbusmenu_gtk_clear_signal_handler (o, &pdata->widget_accel_handler_id);
245 i += g_signal_handlers_disconnect_matched(o, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,292 dbusmenu_gtk_clear_signal_handler (o, &pdata->widget_toggle_handler_id);
246 0, 0, NULL, G_CALLBACK(widget_add_cb), NULL);293 dbusmenu_gtk_clear_signal_handler (o, &pdata->widget_visible_handler_id);
247 i += g_signal_handlers_disconnect_matched(o, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
248 0, 0, NULL, G_CALLBACK(accel_changed), NULL);
249 i += g_signal_handlers_disconnect_matched(o, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
250 0, 0, NULL, G_CALLBACK(checkbox_toggled), NULL);
251 i += g_signal_handlers_disconnect_matched(o, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
252 0, 0, NULL, G_CALLBACK(menuitem_notify_cb), NULL);
253 g_warn_if_fail (i != 5);
254 g_object_remove_weak_pointer(o, (gpointer*)&pdata->widget);294 g_object_remove_weak_pointer(o, (gpointer*)&pdata->widget);
295
255 /* since the DbusmenuMenuitem is being destroyed, uncache it from the GtkWidget */296 /* since the DbusmenuMenuitem is being destroyed, uncache it from the GtkWidget */
256 g_object_steal_data(o, CACHED_MENUITEM);297 g_object_steal_data(o, CACHED_MENUITEM);
257 }298 }
258299
259 if (pdata->shell != NULL) {300 if (pdata->shell != NULL) {
260 gint i = 0;301 GObject * o = G_OBJECT(pdata->shell);
261 i += g_signal_handlers_disconnect_matched(pdata->shell, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,302 dbusmenu_gtk_clear_signal_handler (o, &pdata->item_inserted_handler_id);
262 0, 0, NULL, G_CALLBACK(item_inserted_cb), NULL);303 dbusmenu_gtk_clear_signal_handler (o, &pdata->item_removed_handler_id);
263 i += g_signal_handlers_disconnect_matched(pdata->shell, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,304 g_object_remove_weak_pointer(o, (gpointer*)&pdata->shell);
264 0, 0, NULL, G_CALLBACK(item_removed_cb), NULL);
265 g_warn_if_fail (i != 2);
266 g_object_remove_weak_pointer(G_OBJECT(pdata->shell), (gpointer*)&pdata->shell);
267 }305 }
268306
269 if (pdata->image != NULL) {307 if (pdata->image != NULL) {
270 gint i = 0;308 GObject * o = G_OBJECT(pdata->image);
271 i += g_signal_handlers_disconnect_matched(pdata->image, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,309 dbusmenu_gtk_clear_signal_handler (o, &pdata->image_notify_handler_id);
272 0, 0, NULL, G_CALLBACK(image_notify_cb), NULL);310 g_object_remove_weak_pointer(o, (gpointer*)&pdata->image);
273 g_warn_if_fail (i != 1);
274 g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image);
275 }311 }
276312
277 if (pdata->accessible != NULL) {313 if (pdata->accessible != NULL) {
278 gint i = 0;314 GObject * o = G_OBJECT(pdata->accessible);
279 i += g_signal_handlers_disconnect_matched(pdata->accessible, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,315 dbusmenu_gtk_clear_signal_handler (o, &pdata->a11y_handler_id);
280 0, 0, NULL, G_CALLBACK(a11y_name_notify_cb), NULL);316 g_object_remove_weak_pointer(o, (gpointer*)&pdata->accessible);
281 g_warn_if_fail (i != 1);
282 g_object_remove_weak_pointer(G_OBJECT(pdata->accessible), (gpointer*)&pdata->accessible);
283 }317 }
284318
285 g_free(pdata);319 g_free(pdata);
@@ -347,10 +381,10 @@
347 g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));381 g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
348 g_return_if_fail(GTK_IS_MENU_SHELL(menu));382 g_return_if_fail(GTK_IS_MENU_SHELL(menu));
349383
350 ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(mi), PARSER_DATA);384 ParserData *pdata = parser_data_get_from_menuitem (mi);
351385
352 pdata->shell = menu;386 pdata->shell = menu;
353 g_signal_connect (G_OBJECT (menu),387 pdata->item_inserted_handler_id = g_signal_connect (G_OBJECT (menu),
354#ifdef HAVE_GTK3388#ifdef HAVE_GTK3
355 "insert",389 "insert",
356#else390#else
@@ -358,10 +392,10 @@
358#endif392#endif
359 G_CALLBACK (item_inserted_cb),393 G_CALLBACK (item_inserted_cb),
360 mi);394 mi);
361 g_signal_connect (G_OBJECT (menu),395 pdata->item_removed_handler_id = g_signal_connect (G_OBJECT (menu),
362 "remove",396 "remove",
363 G_CALLBACK (item_removed_cb),397 G_CALLBACK (item_removed_cb),
364 mi);398 mi);
365 g_object_add_weak_pointer(G_OBJECT (menu), (gpointer*)&pdata->shell);399 g_object_add_weak_pointer(G_OBJECT (menu), (gpointer*)&pdata->shell);
366400
367 /* Some apps (notably Eclipse RCP apps) don't fill contents of submenus401 /* Some apps (notably Eclipse RCP apps) don't fill contents of submenus
@@ -447,17 +481,18 @@
447 thisitem = construct_dbusmenu_for_widget (widget);481 thisitem = construct_dbusmenu_for_widget (widget);
448482
449 if (!gtk_widget_get_visible (widget)) {483 if (!gtk_widget_get_visible (widget)) {
450 g_signal_connect (G_OBJECT (widget),484 ParserData *pdata = parser_data_get_from_menuitem (thisitem);
451 "notify::visible",485 pdata->widget_visible_handler_id = g_signal_connect (G_OBJECT (widget),
452 G_CALLBACK (menuitem_notify_cb),486 "notify::visible",
453 recurse->toplevel);487 G_CALLBACK (menuitem_notify_cb),
454 }488 recurse->toplevel);
489 }
455490
456 if (GTK_IS_TEAROFF_MENU_ITEM (widget)) {491 if (GTK_IS_TEAROFF_MENU_ITEM (widget)) {
457 dbusmenu_menuitem_property_set_bool (thisitem,492 dbusmenu_menuitem_property_set_bool (thisitem,
458 DBUSMENU_MENUITEM_PROP_VISIBLE,493 DBUSMENU_MENUITEM_PROP_VISIBLE,
459 FALSE);494 FALSE);
460 }495 }
461 }496 }
462497
463 /* Check to see if we're in our parents list of children, if we have498 /* Check to see if we're in our parents list of children, if we have
@@ -584,10 +619,8 @@
584 }619 }
585 else620 else
586 {621 {
587 g_signal_connect (widget,622 pdata->widget_accel_handler_id = g_signal_connect (widget, "accel-closures-changed",
588 "accel-closures-changed",623 G_CALLBACK (accel_changed), mi);
589 G_CALLBACK (accel_changed),
590 mi);
591624
592 if (GTK_IS_CHECK_MENU_ITEM (widget))625 if (GTK_IS_CHECK_MENU_ITEM (widget))
593 {626 {
@@ -599,10 +632,7 @@
599 DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,632 DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
600 gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);633 gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
601634
602 g_signal_connect (widget,635 pdata->widget_toggle_handler_id = g_signal_connect (widget, "activate", G_CALLBACK (checkbox_toggled), mi);
603 "activate",
604 G_CALLBACK (checkbox_toggled),
605 mi);
606 }636 }
607637
608 if (GTK_IS_IMAGE_MENU_ITEM (widget))638 if (GTK_IS_IMAGE_MENU_ITEM (widget))
@@ -626,10 +656,7 @@
626 g_free (text);656 g_free (text);
627657
628 pdata->label = label;658 pdata->label = label;
629 g_signal_connect (G_OBJECT (label),659 pdata->label_notify_handler_id = g_signal_connect (G_OBJECT (label), "notify", G_CALLBACK(label_notify_cb), mi);
630 "notify",
631 G_CALLBACK (label_notify_cb),
632 mi);
633 g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);660 g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);
634661
635 AtkObject *accessible = gtk_widget_get_accessible (widget);662 AtkObject *accessible = gtk_widget_get_accessible (widget);
@@ -646,10 +673,10 @@
646 // An application may set an alternate accessible name in the future,673 // An application may set an alternate accessible name in the future,
647 // so we had better watch out for it.674 // so we had better watch out for it.
648 pdata->accessible = accessible;675 pdata->accessible = accessible;
649 g_signal_connect (G_OBJECT (accessible),676 pdata->a11y_handler_id = g_signal_connect (G_OBJECT (accessible),
650 "notify::accessible-name",677 "notify::accessible-name",
651 G_CALLBACK (a11y_name_notify_cb),678 G_CALLBACK (a11y_name_notify_cb),
652 mi);679 mi);
653 g_object_add_weak_pointer(G_OBJECT (accessible), (gpointer*)&pdata->accessible);680 g_object_add_weak_pointer(G_OBJECT (accessible), (gpointer*)&pdata->accessible);
654 }681 }
655682
@@ -667,10 +694,9 @@
667 sensitive = gtk_action_is_sensitive (action);694 sensitive = gtk_action_is_sensitive (action);
668695
669 pdata->action = action;696 pdata->action = action;
670 g_signal_connect_object (action, "notify",697 pdata->action_notify_handler_id = g_signal_connect_object (action, "notify",
671 G_CALLBACK (action_notify_cb),698 G_CALLBACK (action_notify_cb), mi,
672 mi,699 G_CONNECT_AFTER);
673 G_CONNECT_AFTER);
674 g_object_add_weak_pointer(G_OBJECT (action), (gpointer*)&pdata->action);700 g_object_add_weak_pointer(G_OBJECT (action), (gpointer*)&pdata->action);
675 }701 }
676 }702 }
@@ -714,15 +740,11 @@
714 DBUSMENU_MENUITEM_PROP_ENABLED,740 DBUSMENU_MENUITEM_PROP_ENABLED,
715 sensitive);741 sensitive);
716742
717 g_signal_connect (widget,743 pdata->widget_notify_handler_id = g_signal_connect (widget, "notify",
718 "notify",744 G_CALLBACK (widget_notify_cb), mi);
719 G_CALLBACK (widget_notify_cb),
720 mi);
721745
722 g_signal_connect (widget,746 pdata->widget_add_handler_id = g_signal_connect (widget, "add",
723 "add",747 G_CALLBACK (widget_add_cb), mi);
724 G_CALLBACK (widget_add_cb),
725 mi);
726748
727 return mi;749 return mi;
728 }750 }
@@ -742,16 +764,15 @@
742 if (pspec->name == interned_str_visible)764 if (pspec->name == interned_str_visible)
743 {765 {
744 GtkWidget * new_toplevel = gtk_widget_get_toplevel (widget);766 GtkWidget * new_toplevel = gtk_widget_get_toplevel (widget);
745 GtkWidget * old_toplevel = GTK_WIDGET(data);767 GtkWidget * old_toplevel = GTK_WIDGET(data);
746768
747 if (new_toplevel == old_toplevel) {769 if (new_toplevel == old_toplevel) {
748 /* TODO: Figure this out -> rebuild (context->bridge, window); */770 /* TODO: Figure this out -> rebuild (context->bridge, window); */
749 }771 }
750772
751 /* We only care about this once, so let's disconnect now. */773 /* We only care about this once, so let's disconnect now. */
752 g_signal_handlers_disconnect_by_func (widget,774 ParserData * pdata = parser_data_get_from_widget (widget);
753 G_CALLBACK (menuitem_notify_cb),775 dbusmenu_gtk_clear_signal_handler (widget, &pdata->widget_visible_handler_id);
754 data);
755 }776 }
756}777}
757778
@@ -785,17 +806,18 @@
785 if (image != GTK_IMAGE(pdata->image)) {806 if (image != GTK_IMAGE(pdata->image)) {
786807
787 if (pdata->image != NULL) {808 if (pdata->image != NULL) {
788 g_signal_handlers_disconnect_by_func(pdata->image, G_CALLBACK(image_notify_cb), menuitem);809 GObject * o = G_OBJECT(pdata->image);
789 g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image);810 dbusmenu_gtk_clear_signal_handler (o, &pdata->image_notify_handler_id);
811 g_object_remove_weak_pointer(o, (gpointer*)&pdata->image);
790 }812 }
791813
792 pdata->image = GTK_WIDGET(image);814 pdata->image = GTK_WIDGET(image);
793815
794 if (pdata->image != NULL) {816 if (pdata->image != NULL) {
795 g_signal_connect (G_OBJECT (pdata->image),817 pdata->image_notify_handler_id = g_signal_connect (G_OBJECT (pdata->image),
796 "notify",818 "notify",
797 G_CALLBACK (image_notify_cb),819 G_CALLBACK (image_notify_cb),
798 menuitem);820 menuitem);
799 g_object_add_weak_pointer(G_OBJECT (pdata->image), (gpointer*)&pdata->image);821 g_object_add_weak_pointer(G_OBJECT (pdata->image), (gpointer*)&pdata->image);
800 }822 }
801 }823 }
@@ -1205,9 +1227,8 @@
1205 */1227 */
1206 if (GTK_WIDGET (g_value_get_object (&prop_value)) == NULL) 1228 if (GTK_WIDGET (g_value_get_object (&prop_value)) == NULL)
1207 {1229 {
1208 g_signal_handlers_disconnect_by_func (widget,1230 ParserData *pdata = parser_data_get_from_menuitem (child);
1209 G_CALLBACK (widget_notify_cb),1231 dbusmenu_gtk_clear_signal_handler (widget, &pdata->widget_notify_handler_id);
1210 child);
12111232
1212 DbusmenuMenuitem *parent = dbusmenu_menuitem_get_parent (child);1233 DbusmenuMenuitem *parent = dbusmenu_menuitem_get_parent (child);
12131234

Subscribers

People subscribed via source and target branches

to all changes: