diff --git a/eek/eek-clutter-key-actor.c b/eek/eek-clutter-key-actor.c index 1679157f..aae45583 100644 --- a/eek/eek-clutter-key-actor.c +++ b/eek/eek-clutter-key-actor.c @@ -59,6 +59,9 @@ struct _EekClutterKeyActorPrivate static struct { /* outline pointer -> ClutterTexture */ GHashTable *outline_textures; + + /* manually maintain the ref-count of outline_textures to set it + to NULL on destroy */ gint outline_textures_ref_count; } texture_cache; @@ -170,16 +173,23 @@ eek_clutter_key_actor_real_released (EekClutterKeyActor *self) } static void -eek_clutter_key_actor_finalize (GObject *object) +eek_clutter_key_actor_dispose (GObject *object) { EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(object); - g_object_unref (priv->key); - if (priv->texture && --texture_cache.outline_textures_ref_count <= 0) { - g_hash_table_unref (texture_cache.outline_textures); - texture_cache.outline_textures = NULL; + if (priv->key) { + g_object_unref (priv->key); + priv->key = NULL; } - G_OBJECT_CLASS (eek_clutter_key_actor_parent_class)->finalize (object); + if (priv->texture) { + /* no need to g_object_unref (priv->texture) */ + priv->texture = NULL; + if (--texture_cache.outline_textures_ref_count == 0) { + g_hash_table_unref (texture_cache.outline_textures); + texture_cache.outline_textures = NULL; + } + } + G_OBJECT_CLASS (eek_clutter_key_actor_parent_class)->dispose (object); } static void @@ -199,7 +209,7 @@ eek_clutter_key_actor_class_init (EekClutterKeyActorClass *klass) actor_class->get_preferred_width = eek_clutter_key_actor_real_get_preferred_width; - gobject_class->finalize = eek_clutter_key_actor_finalize; + gobject_class->dispose = eek_clutter_key_actor_dispose; /* signals */ klass->pressed = eek_clutter_key_actor_real_pressed; @@ -358,10 +368,8 @@ get_texture (EekClutterKeyActor *actor) EekOutline *outline; if (!texture_cache.outline_textures) - texture_cache.outline_textures = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - g_free); + texture_cache.outline_textures = g_hash_table_new (g_direct_hash, + g_direct_equal); outline = eek_key_get_outline (actor->priv->key); texture = g_hash_table_lookup (texture_cache.outline_textures, outline); if (texture == NULL) { diff --git a/eek/eek-clutter-key.c b/eek/eek-clutter-key.c index 4df65d3f..6c9232c7 100644 --- a/eek/eek-clutter-key.c +++ b/eek/eek-clutter-key.c @@ -87,13 +87,15 @@ eek_clutter_key_real_released (EekKey *key) } static void -eek_clutter_key_finalize (GObject *object) +eek_clutter_key_dispose (GObject *object) { EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object); - if (priv->actor) + if (priv->actor) { g_object_unref (priv->actor); - G_OBJECT_CLASS (eek_clutter_key_parent_class)->finalize (object); + priv->actor = NULL; + } + G_OBJECT_CLASS (eek_clutter_key_parent_class)->dispose (object); } static void @@ -108,7 +110,7 @@ eek_clutter_key_class_init (EekClutterKeyClass *klass) element_class->set_name = eek_clutter_key_real_set_name; element_class->set_bounds = eek_clutter_key_real_set_bounds; - gobject_class->finalize = eek_clutter_key_finalize; + gobject_class->dispose = eek_clutter_key_dispose; /* signals */ key_class->pressed = eek_clutter_key_real_pressed; diff --git a/eek/eek-clutter-keyboard.c b/eek/eek-clutter-keyboard.c index 4f9dcae8..beac2138 100644 --- a/eek/eek-clutter-keyboard.c +++ b/eek/eek-clutter-keyboard.c @@ -115,7 +115,7 @@ eek_clutter_keyboard_real_create_section (EekKeyboard *self) } static void -eek_clutter_keyboard_finalize (GObject *object) +eek_clutter_keyboard_dispose (GObject *object) { EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object); @@ -123,11 +123,16 @@ eek_clutter_keyboard_finalize (GObject *object) ClutterActor *stage; stage = clutter_actor_get_stage (priv->actor); - g_signal_handler_disconnect (stage, priv->key_press_event_handler); - g_signal_handler_disconnect (stage, priv->key_release_event_handler); + if (stage) { + g_signal_handler_disconnect (stage, + priv->key_press_event_handler); + g_signal_handler_disconnect (stage, + priv->key_release_event_handler); + } g_object_unref (priv->actor); + priv->actor = NULL; } - G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->finalize (object); + G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object); } static void @@ -143,7 +148,7 @@ eek_clutter_keyboard_class_init (EekClutterKeyboardClass *klass) keyboard_class->create_section = eek_clutter_keyboard_real_create_section; element_class->set_name = eek_clutter_keyboard_real_set_name; element_class->set_bounds = eek_clutter_keyboard_real_set_bounds; - gobject_class->finalize = eek_clutter_keyboard_finalize; + gobject_class->dispose = eek_clutter_keyboard_dispose; } static void diff --git a/eek/eek-clutter-section.c b/eek/eek-clutter-section.c index 031bd81d..c5da851e 100644 --- a/eek/eek-clutter-section.c +++ b/eek/eek-clutter-section.c @@ -132,13 +132,15 @@ eek_clutter_section_real_create_key (EekSection *self, } static void -eek_clutter_section_finalize (GObject *object) +eek_clutter_section_dispose (GObject *object) { EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object); - if (priv->actor) + if (priv->actor) { g_object_unref (priv->actor); - G_OBJECT_CLASS (eek_clutter_section_parent_class)->finalize (object); + priv->actor = NULL; + } + G_OBJECT_CLASS (eek_clutter_section_parent_class)->dispose (object); } static void @@ -154,7 +156,7 @@ eek_clutter_section_class_init (EekClutterSectionClass *klass) section_class->create_key = eek_clutter_section_real_create_key; element_class->set_name = eek_clutter_section_real_set_name; element_class->set_bounds = eek_clutter_section_real_set_bounds; - gobject_class->finalize = eek_clutter_section_finalize; + gobject_class->dispose = eek_clutter_section_dispose; } static void diff --git a/eek/eek-container.c b/eek/eek-container.c index 30dd8900..cf65605e 100644 --- a/eek/eek-container.c +++ b/eek/eek-container.c @@ -102,14 +102,27 @@ eek_container_real_find (EekContainer *self, return NULL; } +static void +eek_container_dispose (GObject *object) +{ + EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(object); + GSList *head; + + for (head = priv->children; head; head = g_slist_next (head)) { + if (head->data) { + g_object_unref (head->data); + head->data = NULL; + } + } + G_OBJECT_CLASS(eek_container_parent_class)->dispose (object); +} + static void eek_container_finalize (GObject *object) { EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(object); GSList *head; - for (head = priv->children; head; head = g_slist_next (head)) - g_object_unref (head->data); g_slist_free (priv->children); G_OBJECT_CLASS(eek_container_parent_class)->finalize (object); } @@ -128,6 +141,7 @@ eek_container_class_init (EekContainerClass *klass) klass->find = eek_container_real_find; gobject_class->finalize = eek_container_finalize; + gobject_class->dispose = eek_container_dispose; signals[CHILD_ADDED] = g_signal_new ("child-added", diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 6eabc720..f1acb47a 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -224,14 +224,15 @@ eek_keyboard_real_find_key_by_keycode (EekKeyboard *self, } static void -eek_keyboard_finalize (GObject *object) +eek_keyboard_dispose (GObject *object) { EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object); - if (priv->layout) + if (priv->layout) { g_object_unref (priv->layout); - - G_OBJECT_CLASS(eek_keyboard_parent_class)->finalize (object); + priv->layout = NULL; + } + G_OBJECT_CLASS(eek_keyboard_parent_class)->dispose (object); } static void @@ -308,7 +309,7 @@ eek_keyboard_class_init (EekKeyboardClass *klass) gobject_class->get_property = eek_keyboard_get_property; gobject_class->set_property = eek_keyboard_set_property; - gobject_class->finalize = eek_keyboard_finalize; + gobject_class->dispose = eek_keyboard_dispose; /** * EekKeyboard:group: diff --git a/eek/eek-xkb-layout.c b/eek/eek-xkb-layout.c index 6a100a17..a3b7e6f3 100644 --- a/eek/eek-xkb-layout.c +++ b/eek/eek-xkb-layout.c @@ -302,10 +302,26 @@ create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard) eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds); } +static void +outline_free (gpointer data) +{ + EekOutline *outline = data; + g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points); + g_boxed_free (EEK_TYPE_OUTLINE, outline); +} + static void eek_xkb_layout_real_apply (EekLayout *layout, EekKeyboard *keyboard) { - g_return_if_fail (EEK_IS_KEYBOARD(keyboard)); + EekXkbLayoutPrivate *priv = EEK_XKB_LAYOUT_GET_PRIVATE (layout); + + g_return_if_fail (priv); + if (priv->outline_hash) + g_hash_table_unref (priv->outline_hash); + priv->outline_hash = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + outline_free); create_keyboard (EEK_XKB_LAYOUT(layout), keyboard); } @@ -472,14 +488,6 @@ eek_xkb_layout_class_init (EekXkbLayoutClass *klass) g_object_class_install_property (gobject_class, PROP_SYMBOLS, pspec); } -static void -outline_free (gpointer data) -{ - EekOutline *outline = data; - g_slice_free1 (sizeof (EekPoint) * outline->num_points, outline->points); - g_boxed_free (EEK_TYPE_OUTLINE, outline); -} - static void eek_xkb_layout_init (EekXkbLayout *self) { @@ -501,10 +509,6 @@ eek_xkb_layout_init (EekXkbLayout *self) XkbGBN_IndicatorMapMask, XkbUseCoreKbd); - priv->outline_hash = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - outline_free); if (priv->xkb == NULL) { g_critical ("XkbGetKeyboard failed to get keyboard from the server!"); return; diff --git a/src/eekboard.c b/src/eekboard.c index e9f7b5d4..0d3001da 100644 --- a/src/eekboard.c +++ b/src/eekboard.c @@ -180,10 +180,9 @@ on_changed (EekLayout *layout, gpointer user_data) actor = clutter_container_find_child_by_name (CLUTTER_CONTAINER(stage), "keyboard"); - /* FIXME: currently keyboard must be finalized before actor. */ - g_object_unref (eek_keyboard); if (actor) clutter_container_remove_actor (CLUTTER_CONTAINER(stage), actor); + g_object_unref (eek_keyboard); eek_keyboard = create_keyboard (stage, layout, width, height); }