From 6a6a292ffadadf9f5389fe0c8507ef047daffce1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 31 Jan 2011 08:58:18 -0600 Subject: Keep a ref to the client through-out the call to the update --- libdbusmenu-glib/client.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index b196c9f..f59dcf6 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1553,11 +1553,6 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data) DbusmenuClient * client = DBUSMENU_CLIENT(data); DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); - if (priv->layoutcall != NULL) { - g_object_unref(priv->layoutcall); - priv->layoutcall = NULL; - } - GError * error = NULL; GVariant * params = NULL; @@ -1566,7 +1561,7 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data) if (error != NULL) { g_warning("Getting layout failed: %s", error->message); g_error_free(error); - return; + goto out; } guint rev; @@ -1580,7 +1575,7 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data) if (parseable == 0) { g_warning("Unable to parse layout!"); - return; + goto out; } priv->my_revision = rev; @@ -1596,6 +1591,13 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data) update_layout(client); } +out: + if (priv->layoutcall != NULL) { + g_object_unref(priv->layoutcall); + priv->layoutcall = NULL; + } + + g_object_unref(G_OBJECT(client)); return; } @@ -1622,6 +1624,7 @@ update_layout (DbusmenuClient * client) priv->layoutcall = g_cancellable_new(); + g_object_ref(G_OBJECT(client)); g_dbus_proxy_call(priv->menuproxy, "GetLayout", g_variant_new("(i)", 0), /* root */ -- cgit v1.2.3 From db2d419d34f98cf8067bc97cda27b8687ce1be6c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 31 Jan 2011 10:01:59 -0600 Subject: Disconnect realized handler when we don't care about the item anymore. --- libdbusmenu-gtk/menu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c index 9c4f7f8..5231d0f 100644 --- a/libdbusmenu-gtk/menu.c +++ b/libdbusmenu-gtk/menu.c @@ -271,6 +271,10 @@ root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGt #ifdef MASSIVEDEBUGGING g_debug("Root child deleted"); #endif + + /* Remove signal for realized */ + g_signal_handlers_disconnect_by_func(G_OBJECT(child), child_realized, menu); + DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); GtkWidget * item = GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)); if (item != NULL) { -- cgit v1.2.3 From d9b81a0645e15f03c89cae3466a3928d2b75c4ef Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 31 Jan 2011 10:12:20 -0600 Subject: Keeping the root so that we can remove the signal handlers. --- libdbusmenu-gtk/menu.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c index 5231d0f..2a27fe2 100644 --- a/libdbusmenu-gtk/menu.c +++ b/libdbusmenu-gtk/menu.c @@ -46,6 +46,7 @@ enum { /* Private */ struct _DbusmenuGtkMenuPrivate { DbusmenuGtkClient * client; + DbusmenuMenuitem * root; gchar * dbus_object; gchar * dbus_name; @@ -63,6 +64,8 @@ static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * /* Internal */ static void build_client (DbusmenuGtkMenu * self); static void child_realized (DbusmenuMenuitem * child, gpointer userdata); +static void remove_child_signals (gpointer data, gpointer user_data); +static void root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu); /* GObject Stuff */ G_DEFINE_TYPE (DbusmenuGtkMenu, dbusmenu_gtkmenu, GTK_TYPE_MENU); @@ -127,6 +130,12 @@ dbusmenu_gtkmenu_dispose (GObject *object) { DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(object); + /* Remove signals from the root */ + if (priv->root != NULL) { + /* This will clear the root */ + root_changed(priv->client, NULL, DBUSMENU_GTKMENU(object)); + } + if (priv->client != NULL) { g_object_unref(G_OBJECT(priv->client)); priv->client = NULL; @@ -273,7 +282,7 @@ root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGt #endif /* Remove signal for realized */ - g_signal_handlers_disconnect_by_func(G_OBJECT(child), child_realized, menu); + remove_child_signals(child, menu); DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); GtkWidget * item = GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)); @@ -312,15 +321,41 @@ child_realized (DbusmenuMenuitem * child, gpointer userdata) return; } +/* Remove any signals we attached to children -- just realized right now */ +static void +remove_child_signals (gpointer data, gpointer user_data) +{ + g_signal_handlers_disconnect_by_func(G_OBJECT(data), child_realized, user_data); + return; +} + /* When the root menuitem changes we need to resetup things so that we're back in the game. */ static void root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu) { + DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); + + /* Clear out our interest in the old root */ + if (priv->root != NULL) { + GList * children = dbusmenu_menuitem_get_children(priv->root); + g_list_foreach(children, remove_child_signals, menu); + + g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_added, menu); + g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_moved, menu); + g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_delete, menu); + + g_object_unref(priv->root); + priv->root = NULL; + } + if (newroot == NULL) { gtk_widget_hide(GTK_WIDGET(menu)); return; } + priv->root = newroot; + g_object_ref(priv->root); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(root_child_added), menu); g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(root_child_moved), menu); g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(root_child_delete), menu); -- cgit v1.2.3 From 565cc0962042839e4b35f8ae2d01a64864bc665c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 31 Jan 2011 10:48:21 -0600 Subject: Switching the properties callback to use custom structure so that we can reference the client throughout the callback. --- libdbusmenu-glib/client.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index f59dcf6..5e492a3 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -129,6 +129,12 @@ struct _type_handler_t { gchar * type; }; +typedef struct _properties_callback_t properties_callback_t; +struct _properties_callback_t { + DbusmenuClient * client; + GArray * listeners; +}; + #define DBUSMENU_CLIENT_GET_PRIVATE(o) (DBUSMENU_CLIENT(o)->priv) #define DBUSMENU_INTERFACE "com.canonical.dbusmenu" @@ -512,7 +518,8 @@ find_listener (GArray * listeners, guint index, gint id) static void get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data) { - GArray * listeners = (GArray *)user_data; + properties_callback_t * cbdata = (properties_callback_t *)user_data; + GArray * listeners = cbdata->listeners; int i; GError * error = NULL; GVariant * params = NULL; @@ -526,9 +533,8 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data) properties_listener_t * listener = &g_array_index(listeners, properties_listener_t, i); listener->callback(NULL, error, listener->user_data); } - g_array_free(listeners, TRUE); g_error_free(error); - return; + goto out; } /* Callback all the folks we can find */ @@ -575,8 +581,11 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data) g_error_free(localerror); } +out: /* Clean up */ g_array_free(listeners, TRUE); + g_object_unref(cbdata->client); + g_free(user_data); return; } @@ -586,6 +595,7 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data) static gboolean get_properties_idle (gpointer user_data) { + properties_callback_t * cbdata = NULL; DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(user_data); g_return_val_if_fail(priv->menuproxy != NULL, TRUE); @@ -616,6 +626,11 @@ get_properties_idle (gpointer user_data) g_variant_builder_add_value(&builder, variant_props); GVariant * variant_params = g_variant_builder_end(&builder); + cbdata = g_new(properties_callback_t, 1); + cbdata->listeners = priv->delayed_property_listeners; + cbdata->client = DBUSMENU_CLIENT(user_data); + g_object_ref(G_OBJECT(user_data)); + g_dbus_proxy_call(priv->menuproxy, "GetGroupProperties", variant_params, @@ -623,7 +638,7 @@ get_properties_idle (gpointer user_data) -1, /* timeout */ NULL, /* cancellable */ get_properties_callback, - priv->delayed_property_listeners); + cbdata); /* Free properties */ gchar ** dataregion = (gchar **)g_array_free(priv->delayed_property_list, FALSE); -- cgit v1.2.3 -- cgit v1.2.3