From 617065d6dbfe6be113c69a15a4fbf7086c4f920e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alejandro=20Pi=C3=B1eiro?= Date: Fri, 22 Jun 2012 21:26:53 +0200 Subject: [PATCH] Default implementation for atk_util_[add/remove]_global_event_listener Implementing means that toolkits are not longer required to implement those virtual methods, and is a first step to a multi-toolkit environment. --- atk/atkutil.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 134 insertions(+), 10 deletions(-) diff --git a/atk/atkutil.c b/atk/atkutil.c index 9a06723..fc0f3c4 100755 --- a/atk/atkutil.c +++ b/atk/atkutil.c @@ -25,6 +25,15 @@ static void atk_util_class_init (AtkUtilClass *klass); static AtkObject *previous_focus_object = NULL; +typedef struct _AtkUtilListenerInfo AtkUtilListenerInfo; +struct _AtkUtilListenerInfo +{ + gint key; + guint signal_id; + gulong hook_id; +}; +static GHashTable *listener_list = NULL; + GType atk_util_get_type (void) { @@ -49,16 +58,6 @@ atk_util_get_type (void) return type; } -static void -atk_util_class_init (AtkUtilClass *klass) -{ - klass->add_global_event_listener = NULL; - klass->remove_global_event_listener = NULL; - klass->get_root = NULL; - klass->get_toolkit_name = NULL; - klass->get_toolkit_version = NULL; -} - /* * This file supports the addition and removal of multiple focus handlers * as long as they are all called in the same thread. @@ -204,6 +203,109 @@ atk_focus_tracker_notify (AtkObject *object) } } +static guint +add_listener (GSignalEmissionHook listener, + const gchar *object_type, + const gchar *signal_name, + const gchar *hook_data) +{ + GType type; + guint signal_id; + gint rc = 0; + static gint listener_idx = 1; + + type = g_type_from_name (object_type); + if (type) + { + signal_id = g_signal_lookup (signal_name, type); + if (signal_id > 0) + { + AtkUtilListenerInfo *listener_info; + + rc = listener_idx; + + listener_info = g_new (AtkUtilListenerInfo, 1); + listener_info->key = listener_idx; + listener_info->hook_id = + g_signal_add_emission_hook (signal_id, 0, listener, + g_strdup (hook_data), + (GDestroyNotify) g_free); + listener_info->signal_id = signal_id; + + g_hash_table_insert(listener_list, &(listener_info->key), listener_info); + listener_idx++; + } + else + { + g_debug ("Signal type %s not supported\n", signal_name); + } + } + else + { + g_warning("Invalid object type %s\n", object_type); + } + return rc; +} + +static guint +atk_util_real_add_global_event_listener (GSignalEmissionHook listener, + const gchar *event_type) +{ + guint rc = 0; + gchar **split_string; + + split_string = g_strsplit (event_type, ":", 3); + + if (g_strv_length (split_string) == 3) + rc = add_listener (listener, split_string[1], split_string[2], event_type); + + g_strfreev (split_string); + + return rc; +} + +static void +atk_util_real_remove_global_event_listener (guint remove_listener) +{ + if (remove_listener > 0) + { + AtkUtilListenerInfo *listener_info; + gint tmp_idx = remove_listener; + + listener_info = (AtkUtilListenerInfo *) + g_hash_table_lookup(listener_list, &tmp_idx); + + if (listener_info != NULL) + { + /* Hook id of 0 and signal id of 0 are invalid */ + if (listener_info->hook_id != 0 && listener_info->signal_id != 0) + { + /* Remove the emission hook */ + g_signal_remove_emission_hook(listener_info->signal_id, + listener_info->hook_id); + + /* Remove the element from the hash */ + g_hash_table_remove(listener_list, &tmp_idx); + } + else + { + g_warning("Invalid listener hook_id %ld or signal_id %d\n", + listener_info->hook_id, listener_info->signal_id); + } + } + else + { + g_warning("No listener with the specified listener id %d", + remove_listener); + } + } + else + { + g_warning("Invalid listener_id %d", remove_listener); + } +} + + /** * atk_add_global_event_listener: * @listener: the listener to notify @@ -223,6 +325,11 @@ atk_focus_tracker_notify (AtkObject *object) * ATK:AtkObject:state-change * ATK:AtkText:text-selection-changed * + * Toolkit implementor note: Atk provides a default implementation for + * this virtual method, and that implementation should be enough for + * most of the cases. You should have a really good reason to + * reimplement this method. + * * Returns: added event listener id, or 0 on failure. **/ guint @@ -252,6 +359,11 @@ atk_add_global_event_listener (GSignalEmissionHook listener, * @listener_id is the value returned by #atk_add_global_event_listener * when you registered that event listener. * + * Toolkit implementor note: Atk provides a default implementation for + * this virtual method, and that implementation should be enough for + * most of the cases. You should have a really good reason to + * reimplement this method. + * * Removes the specified event listener **/ void @@ -417,3 +529,15 @@ atk_get_version (void) return VERSION; } +static void +atk_util_class_init (AtkUtilClass *klass) +{ + klass->add_global_event_listener = atk_util_real_add_global_event_listener; + klass->remove_global_event_listener = atk_util_real_remove_global_event_listener; + klass->get_root = NULL; + klass->get_toolkit_name = NULL; + klass->get_toolkit_version = NULL; + + listener_list = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, + g_free); +} -- 2.7.4