summaryrefslogtreecommitdiff
diff options
authorStephen M. Webb <stephen.webb@canonical.com>2013-09-25 22:09:02 -0400
committerStephen M. Webb <stephen.webb@canonical.com>2013-09-25 22:09:02 -0400
commit590ff9e3ef5beba9d1cc699e5937eaf0a43b47ea (patch)
treefbcb2a5853634b0d703b219c13495eb21e7092d4
parent37ecfeae7bb6fccfc602669c77fa7e95f7351ccb (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.c6
-rw-r--r--services/panel-indicator-accessible.h1
-rw-r--r--services/panel-root-accessible.c29
-rw-r--r--services/panel-service.c17
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)