summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Piñeiro <apinheiro@igalia.com>2012-06-22 21:26:53 +0200
committerAlejandro Piñeiro <apinheiro@igalia.com>2012-06-22 21:32:40 +0200
commit617065d6dbfe6be113c69a15a4fbf7086c4f920e (patch)
tree7e25e33553949fa56fd9d77e1822801787dae348
parentae9d2a8e9a2135b4ea0d07932c65c087f4ac90eb (diff)
downloadatk-617065d6dbfe6be113c69a15a4fbf7086c4f920e.tar.gz
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.
-rwxr-xr-xatk/atkutil.c144
1 files 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);
+}