diff options
| author | Stephen M. Webb <stephen.webb@canonical.com> | 2013-09-25 22:09:02 -0400 |
|---|---|---|
| committer | Stephen M. Webb <stephen.webb@canonical.com> | 2013-09-25 22:09:02 -0400 |
| commit | 590ff9e3ef5beba9d1cc699e5937eaf0a43b47ea (patch) | |
| tree | fbcb2a5853634b0d703b219c13495eb21e7092d4 | |
| parent | 37ecfeae7bb6fccfc602669c77fa7e95f7351ccb (diff) | |
broke some circular refs during shutdown to reduce memory leaks reported by valgrind (lp: #1231222)bregma_fix-indicator-leaks
Fixes LP: #1231222 (bzr r3533)
| -rw-r--r-- | services/panel-indicator-accessible.c | 6 | ||||
| -rw-r--r-- | services/panel-indicator-accessible.h | 1 | ||||
| -rw-r--r-- | services/panel-root-accessible.c | 29 | ||||
| -rw-r--r-- | services/panel-service.c | 17 |
4 files changed, 34 insertions, 19 deletions
diff --git a/services/panel-indicator-accessible.c b/services/panel-indicator-accessible.c index dde94561c..ee1419eb5 100644 --- a/services/panel-indicator-accessible.c +++ b/services/panel-indicator-accessible.c @@ -384,3 +384,9 @@ panel_indicator_accessible_ref_state_set (AtkObject *accessible) return state_set; } + +IndicatorObject * +panel_indicator_accessible_get_indicator (PanelIndicatorAccessible *pia) +{ + return pia->priv->indicator; +} diff --git a/services/panel-indicator-accessible.h b/services/panel-indicator-accessible.h index 685387d49..73c2ec0ca 100644 --- a/services/panel-indicator-accessible.h +++ b/services/panel-indicator-accessible.h @@ -49,6 +49,7 @@ struct _PanelIndicatorAccessibleClass GType panel_indicator_accessible_get_type (void); AtkObject *panel_indicator_accessible_new (IndicatorObject *indicator); +IndicatorObject *panel_indicator_accessible_get_indicator (PanelIndicatorAccessible *pia); G_END_DECLS diff --git a/services/panel-root-accessible.c b/services/panel-root-accessible.c index 6881941d1..cd5b2f4af 100644 --- a/services/panel-root-accessible.c +++ b/services/panel-root-accessible.c @@ -89,23 +89,26 @@ panel_root_accessible_new (void) } static void -on_indicator_removed (gpointer *data, GObject *removed_indicator) +on_indicator_removed_cb (PanelService *panel_service, IndicatorObject *indicator, AtkObject *child) { - PanelRootAccessible *root = data[0]; - AtkObject *child = data[1]; + AtkObject *parent; + PanelRootAccessible *root; + if (indicator != panel_indicator_accessible_get_indicator (PANEL_INDICATOR_ACCESSIBLE (child))) + return; + + parent = atk_object_get_parent (child); + root = PANEL_ROOT_ACCESSIBLE (parent); g_return_if_fail (PANEL_IS_ROOT_ACCESSIBLE (root)); - g_return_if_fail (ATK_IS_OBJECT (child)); gint index = g_slist_index (root->priv->a11y_children, child); if (index >= 0) { root->priv->a11y_children = g_slist_remove (root->priv->a11y_children, child); g_signal_emit_by_name (root, "children-changed::remove", index, child); + g_signal_handlers_disconnect_by_func (panel_service, on_indicator_removed_cb, child); g_object_unref (child); } - - g_free (data); } /* Implementation of AtkObject methods */ @@ -133,17 +136,9 @@ panel_root_accessible_initialize (AtkObject *accessible, gpointer data) indicator = panel_service_get_indicator_nth (root->priv->service, i); if (INDICATOR_IS_OBJECT (indicator)) { - AtkObject *child; - gpointer *weak_data; - - child = panel_indicator_accessible_new (indicator); - /* FIXME: use proper signals once we support dynamic adding/removing - * of indicators */ - weak_data = g_new0 (gpointer, 2); - weak_data[0] = root; - weak_data[1] = child; - g_object_weak_ref (G_OBJECT (indicator), - (GWeakNotify) on_indicator_removed, weak_data); + AtkObject *child = panel_indicator_accessible_new (indicator); + + g_signal_connect (root->priv->service, "indicator-removed", G_CALLBACK (on_indicator_removed_cb), child); atk_object_set_parent (child, accessible); root->priv->a11y_children = g_slist_append (root->priv->a11y_children, child); diff --git a/services/panel-service.c b/services/panel-service.c index 4d85ab407..7774bf862 100644 --- a/services/panel-service.c +++ b/services/panel-service.c @@ -92,6 +92,7 @@ enum ENTRY_ACTIVATE_REQUEST, ENTRY_SHOW_NOW_CHANGED, GEOMETRIES_CHANGED, + INDICATOR_REMOVED, INDICATORS_CLEARED, LAST_SIGNAL @@ -270,6 +271,14 @@ panel_service_class_init (PanelServiceClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN); + _service_signals[INDICATOR_REMOVED] = + g_signal_new ("indicator-removed", + G_OBJECT_CLASS_TYPE (obj_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + _service_signals[INDICATORS_CLEARED] = g_signal_new ("indicators-cleared", G_OBJECT_CLASS_TYPE (obj_class), @@ -688,11 +697,16 @@ panel_service_actually_remove_indicator (PanelService *self, IndicatorObject *in self->priv->indicators = g_slist_remove (self->priv->indicators, indicator); + indicator_object_set_visible (indicator, FALSE); + + g_signal_emit (self, _service_signals[INDICATOR_REMOVED], 0, indicator); + if (g_object_is_floating (G_OBJECT (indicator))) { g_object_ref_sink (G_OBJECT (indicator)); } + g_debug ("%s unreffing indicator \"%s\" (refcount is %u)", G_STRFUNC, (gchar *)g_object_get_data (G_OBJECT (indicator), "id"), G_OBJECT(indicator)->ref_count); g_object_unref (G_OBJECT (indicator)); } @@ -817,7 +831,6 @@ panel_service_add_indicator (PanelService *self, IndicatorObject *indicator) g_return_if_fail (PANEL_IS_SERVICE (self)); g_return_if_fail (INDICATOR_IS_OBJECT (indicator)); - g_object_ref (indicator); load_indicator (self, indicator, NULL); } @@ -1116,6 +1129,7 @@ load_indicator (PanelService *self, IndicatorObject *object, const gchar *_name) } g_list_free (entries); + g_debug ("%s loaded indicator \"%s\"", G_STRFUNC, name); g_free (name); } @@ -1142,7 +1156,6 @@ load_indicators (PanelService *self) continue; path = g_build_filename (INDICATORDIR, name, NULL); - g_debug ("Loading: %s", path); object = indicator_object_new_from_file (path); if (object == NULL) |
