Merge lp:~achiang/appmenu-gtk/memleaks-787736-780602 into lp:appmenu-gtk/0.4

Proposed by Alex Chiang
Status: Merged
Approved by: Charles Kerr
Approved revision: 154
Merged at revision: 153
Proposed branch: lp:~achiang/appmenu-gtk/memleaks-787736-780602
Merge into: lp:appmenu-gtk/0.4
Diff against target: 211 lines (+83/-78)
1 file modified
src/bridge.c (+83/-78)
To merge this branch: bzr merge lp:~achiang/appmenu-gtk/memleaks-787736-780602
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
Review via email: mp+136550@code.launchpad.net

Description of the change

Cherrypick r158 from trunk to help fix nm-applet in Precise.

To post a comment you must log in.
Revision history for this message
Charles Kerr (charlesk) wrote :

Alex, you'll need to pull in r160 as well

154. By Alex Chiang

Backport r160 from trunk to eliminate noisy debug statements

Revision history for this message
Charles Kerr (charlesk) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/bridge.c'
--- src/bridge.c 2012-04-02 19:12:37 +0000
+++ src/bridge.c 2012-11-28 18:08:20 +0000
@@ -85,21 +85,13 @@
8585
86 GDBusProxy *appmenuproxy;86 GDBusProxy *appmenuproxy;
87 gboolean online;87 gboolean online;
88
89 GSList *rebuild_list;
90 guint rebuild_timer_id;
88};91};
8992
90typedef struct _RecurseContext
91{
92 AppMenuBridge *bridge;
93 AppWindowContext *context;
94
95 gint count;
96 gboolean previous;
97 DbusmenuMenuitem *stack[30];
98} RecurseContext;
99
100G_DEFINE_DYNAMIC_TYPE(AppMenuBridge, app_menu_bridge, UBUNTU_TYPE_MENU_PROXY)93G_DEFINE_DYNAMIC_TYPE(AppMenuBridge, app_menu_bridge, UBUNTU_TYPE_MENU_PROXY)
10194
102static GHashTable *rebuild_ids = NULL;
103static GDBusNodeInfo * registrar_node_info = NULL;95static GDBusNodeInfo * registrar_node_info = NULL;
104static GDBusInterfaceInfo * registrar_interface_info = NULL;96static GDBusInterfaceInfo * registrar_interface_info = NULL;
10597
@@ -213,28 +205,58 @@
213 g_free (context);205 g_free (context);
214}206}
215207
208
209/* a widget that was queued for rebuild has been destroyed,
210 so remove it from our queue */
211static void
212rebuild_list_widget_destroyed (gpointer gbridge, GObject * dead_object)
213{
214 AppMenuBridge * bridge = APP_MENU_BRIDGE (gbridge);
215 AppMenuBridgePrivate * p = bridge->priv;
216
217 p->rebuild_list = g_slist_remove (p->rebuild_list, dead_object);
218}
219
220static void
221rebuild_list_clear (AppMenuBridge * bridge)
222{
223 GSList * l;
224 AppMenuBridgePrivate * p = bridge->priv;
225
226 /* unref the widgets and blow away the list */
227 for (l=p->rebuild_list; l!=NULL; l=l->next)
228 g_object_weak_unref (l->data, rebuild_list_widget_destroyed, bridge);
229 g_slist_free (p->rebuild_list);
230 p->rebuild_list = NULL;
231
232 /* remove the rebuild timer */
233 if (p->rebuild_timer_id > 0)
234 {
235 g_source_remove (p->rebuild_timer_id);
236 p->rebuild_timer_id = 0;
237 }
238}
239
216static void240static void
217app_menu_bridge_dispose (GObject *object)241app_menu_bridge_dispose (GObject *object)
218{242{
219 AppMenuBridge *bridge = APP_MENU_BRIDGE (object);243 AppMenuBridge *bridge = APP_MENU_BRIDGE (object);
220244 AppMenuBridgePrivate * p = bridge->priv;
221 g_list_foreach (bridge->priv->windows, (GFunc)context_dispose, NULL);245
222246 rebuild_list_clear (bridge);
223 if (bridge->priv->appmenuproxy)247 g_list_foreach (p->windows, (GFunc)context_dispose, NULL);
224 {248 g_clear_object (&p->appmenuproxy);
225 g_object_unref (bridge->priv->appmenuproxy);
226 bridge->priv->appmenuproxy = NULL;
227 }
228}249}
229250
230static void251static void
231app_menu_bridge_finalize (GObject *object)252app_menu_bridge_finalize (GObject *object)
232{253{
233 AppMenuBridge *bridge = APP_MENU_BRIDGE (object);254 AppMenuBridge *bridge = APP_MENU_BRIDGE (object);
255 AppMenuBridgePrivate * p = bridge->priv;
234256
235 g_list_foreach (bridge->priv->windows, (GFunc)context_free, NULL);257 g_list_foreach (p->windows, (GFunc)context_free, NULL);
236 g_list_free (bridge->priv->windows);258 g_list_free (p->windows);
237 bridge->priv->windows = NULL;259 p->windows = NULL;
238260
239 G_OBJECT_CLASS (app_menu_bridge_parent_class)->finalize (object);261 G_OBJECT_CLASS (app_menu_bridge_parent_class)->finalize (object);
240}262}
@@ -505,63 +527,51 @@
505 return;527 return;
506}528}
507529
508typedef struct _RebuildData {
509 AppMenuBridge *bridge;
510 GtkWidget *widget;
511} RebuildData;
512
513static gboolean530static gboolean
514do_rebuild (RebuildData *data)531rebuild_timer_func (gpointer gbridge)
515{532{
516 if (data->widget != NULL && gtk_widget_is_toplevel (data->widget))533 GSList * l;
517 {534 AppMenuBridge *bridge = APP_MENU_BRIDGE (gbridge);
518 rebuild_window_items (data->bridge,535 AppMenuBridgePrivate * p = bridge->priv;
519 data->widget);536
520 }537 /* call rebuild_window_items() for each toplevel in our list */
521538 for (l=p->rebuild_list; l!=NULL; l=l->next)
522 if (data->widget != NULL)539 {
523 {540 GtkWidget * w = GTK_WIDGET(l->data);
524 g_object_remove_weak_pointer (G_OBJECT (data->widget), (gpointer*)&data->widget);541
525 g_hash_table_remove (rebuild_ids, data->widget);542 if (gtk_widget_is_toplevel(w))
526 }543 rebuild_window_items (bridge, w);
527544 }
528 g_free (data);545
529546 /* cleanup */
530 return FALSE;547 rebuild_list_clear (bridge);
548 return G_SOURCE_REMOVE;
531}549}
532550
551/* widgets tend to get a lot of changes all at once...
552 + inserting a 100 msec delay here lets us batch up those changes */
533static void553static void
534rebuild (AppMenuBridge *bridge,554rebuild (AppMenuBridge * bridge, GtkWidget * toplevel)
535 GtkWidget *toplevel)
536{555{
537 guint id = 0;556 AppMenuBridgePrivate * p = bridge->priv;
538557
539 if (rebuild_ids != NULL)558 g_return_if_fail (toplevel != NULL);
540 {559
541 id = GPOINTER_TO_UINT (g_hash_table_lookup (rebuild_ids, toplevel));560 /* ensure there's a rebuild timer ticking */
542561 if (p->rebuild_timer_id == 0)
543 if (id > 0)562 {
544 {563 p->rebuild_timer_id = gdk_threads_add_timeout (100,
545 g_source_remove (id);564 rebuild_timer_func,
546 g_hash_table_remove (rebuild_ids, toplevel);565 bridge);
547 id = 0;566 }
548 }567
549 }568 /* ensure this widget is in our rebuild list */
550569 if (g_slist_find (p->rebuild_list, toplevel) == NULL)
551 RebuildData *data = g_new0 (RebuildData, 1);570 {
552 data->bridge = bridge;571 GObject * o = G_OBJECT(toplevel);
553 data->widget = toplevel;572 p->rebuild_list = g_slist_prepend (p->rebuild_list, o);
554573 g_object_weak_ref (o, rebuild_list_widget_destroyed, bridge);
555 id = gdk_threads_add_timeout (100, (GSourceFunc)do_rebuild, data);574 }
556
557 g_object_add_weak_pointer (G_OBJECT (data->widget), (gpointer*)&data->widget);
558
559 if (rebuild_ids == NULL)
560 {
561 rebuild_ids = g_hash_table_new (g_direct_hash, g_direct_equal);
562 }
563
564 g_hash_table_insert (rebuild_ids, toplevel, GUINT_TO_POINTER (id));
565}575}
566576
567static DbusmenuMenuitem * find_menu_bar (GtkWidget * widget);577static DbusmenuMenuitem * find_menu_bar (GtkWidget * widget);
@@ -985,9 +995,4 @@
985G_MODULE_EXPORT void995G_MODULE_EXPORT void
986menu_proxy_module_unload (UbuntuMenuProxyModule *module)996menu_proxy_module_unload (UbuntuMenuProxyModule *module)
987{997{
988 if (rebuild_ids)
989 {
990 g_hash_table_destroy (rebuild_ids);
991 rebuild_ids = NULL;
992 }
993}998}

Subscribers

People subscribed via source and target branches