X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk%2Fatkutil.c;h=dd505d93957b2029efb774765495513fb8528f15;hb=864e0d3e34f282bcc64f3076ee3bd2e1788e91ba;hp=e9317f573f177749261f4257105772a6fd6e02ad;hpb=dba66b4bec94a908cd35a5537209db255fa5fa33;p=platform%2Fupstream%2Fatk.git diff --git a/atk/atkutil.c b/atk/atkutil.c index e9317f5..dd505d9 100755 --- a/atk/atkutil.c +++ b/atk/atkutil.c @@ -18,12 +18,62 @@ */ #include "atkutil.h" +#include "atkmarshal.c" +#include "config.h" + +/** + * SECTION:atkutil + * @Short_description: A set of ATK utility functions for event and toolkit support. + * @Title:AtkUtil + * + * A set of ATK utility functions which are used to support event + * registration of various types, and obtaining the 'root' accessible + * of a process and information about the current ATK implementation + * and toolkit version. + */ + +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) +{ + static GType type = 0; + + if (!type) + { + static const GTypeInfo typeInfo = + { + sizeof (AtkUtilClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) atk_util_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (AtkUtil), + 0, + (GInstanceInitFunc) NULL, + } ; + type = g_type_register_static (G_TYPE_OBJECT, "AtkUtil", &typeInfo, 0) ; + } + return type; +} /* * This file supports the addition and removal of multiple focus handlers * as long as they are all called in the same thread. */ -static AtkFocusTrackerInit focus_tracker_init = NULL; +static AtkEventListenerInit focus_tracker_init = (AtkEventListenerInit) NULL; static gboolean init_done = FALSE; @@ -31,29 +81,59 @@ static gboolean init_done = FALSE; * Array of FocusTracker structs */ static GArray *trackers = NULL; -static guint index = 0; +static guint global_index = 0; + +typedef struct _FocusTracker FocusTracker; struct _FocusTracker { guint index; - AtkFocusTracker func; + AtkEventListener func; }; -typedef struct _FocusTracker FocusTracker; - + +/** + * atk_focus_tracker_init: + * @init: Function to be called for focus tracker initialization + * + * Specifies the function to be called for focus tracker initialization. + * This function should be called by an implementation of the + * ATK interface if any specific work needs to be done to enable + * focus tracking. + * + * Deprecated: This method is deprecated since ATK version + * 2.9.4. Focus tracking has been dropped as a feature to be + * implemented by ATK itself. + * + **/ void -atk_focus_tracker_init (AtkFocusTrackerInit init) +atk_focus_tracker_init (AtkEventListenerInit init) { - if (focus_tracker_init == NULL) + if (!focus_tracker_init) focus_tracker_init = init; } +/** + * atk_add_focus_tracker: + * @focus_tracker: Function to be added to the list of functions to be called + * when an object receives focus. + * + * Adds the specified function to the list of functions to be called + * when an object receives focus. + * + * Deprecated: This method is deprecated since ATK version + * 2.9.4. Focus tracking has been dropped as a feature to be + * implemented by ATK itself. If you need focus tracking on your + * implementation, subscribe to the state-changed:focused signal. + * + * Returns: added focus tracker id, or 0 on failure. + **/ guint -atk_add_focus_tracker (AtkFocusTracker focus_tracker) +atk_add_focus_tracker (AtkEventListener focus_tracker) { - g_return_val_if_fail ((focus_tracker != NULL), 0); + g_return_val_if_fail (focus_tracker, 0); if (!init_done) { - if (focus_tracker_init != NULL) + if (focus_tracker_init) { focus_tracker_init (); } @@ -64,10 +144,10 @@ atk_add_focus_tracker (AtkFocusTracker focus_tracker) { FocusTracker item; - item.index = ++index; + item.index = ++global_index; item.func = focus_tracker; - trackers = g_array_append_val (trackers, item); - return index; + trackers = g_array_append_val (trackers, item); + return global_index; } else { @@ -75,6 +155,18 @@ atk_add_focus_tracker (AtkFocusTracker focus_tracker) } } +/** + * atk_remove_focus_tracker: + * @tracker_id: the id of the focus tracker to remove + * + * Deprecated: This method is deprecated since ATK version + * 2.9.4. Focus tracking has been dropped as a feature to be + * implemented by ATK itself. If you need focus tracking on your + * implementation, subscribe to the state-changed:focused signal. + * + * Removes the specified focus tracker from the list of functions + * to be called when any object receives focus. + **/ void atk_remove_focus_tracker (guint tracker_id) { @@ -98,6 +190,18 @@ atk_remove_focus_tracker (guint tracker_id) } } +/** + * atk_focus_tracker_notify: + * @object: an #AtkObject + * + * Cause the focus tracker functions which have been specified to be + * executed for the object. + * + * Deprecated: This method is deprecated since ATK version + * 2.9.4. Focus tracking has been dropped as a feature to be + * implemented by ATK itself. + * + **/ void atk_focus_tracker_notify (AtkObject *object) { @@ -107,10 +211,377 @@ atk_focus_tracker_notify (AtkObject *object) if (trackers == NULL) return; - for (i = 0; i < trackers->len; i++) - { - item = &g_array_index (trackers, FocusTracker, i); - g_return_if_fail (item != NULL); - item->func (object); - } + if (object == previous_focus_object) + return; + else + { + if (previous_focus_object) + g_object_unref (previous_focus_object); + + previous_focus_object = object; + if (object) + { + g_object_ref (object); + + for (i = 0; i < trackers->len; i++) + { + item = &g_array_index (trackers, FocusTracker, i); + g_return_if_fail (item != NULL); + item->func (object); + } + } + + } +} + +static guint +add_listener (GSignalEmissionHook listener, + const gchar *object_type, + const gchar *signal_name, + const gchar *detail_string, + const gchar *hook_data) +{ + GType type; + guint signal_id; + gint rc = 0; + static gint listener_idx = 1; + GQuark detail_quark = 0; + + type = g_type_from_name (object_type); + if (type) + { + signal_id = g_signal_lookup (signal_name, type); + detail_quark = g_quark_from_string (detail_string); + + 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, detail_quark, 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; + guint length; + + split_string = g_strsplit (event_type, ":", 0); + length = g_strv_length (split_string); + + if ((length == 3) || (length == 4)) + rc = add_listener (listener, split_string[1], split_string[2], + split_string[3], 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 + * @event_type: the type of event for which notification is requested + * + * Adds the specified function to the list of functions to be called + * when an ATK event of type event_type occurs. + * + * The format of event_type is the following: + * "ATK::: + * + * Where "ATK" works as the namespace, is the name of + * the ATK type (interface or object), is the name of the + * signal defined on that interface and is the + * gsignal detail of that signal. You can find more info about gsignal + * details here: + * http://developer.gnome.org/gobject/stable/gobject-Signals.html + * + * The first three parameters are mandatory. The last one is optional. + * + * For example: + * ATK:AtkObject:state-change + * ATK:AtkText:text-selection-changed + * ATK:AtkText:text-insert:system + * + * 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 +atk_add_global_event_listener (GSignalEmissionHook listener, + const gchar *event_type) +{ + guint retval; + AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL); + + if (klass->add_global_event_listener) + { + retval = klass->add_global_event_listener (listener, event_type); + } + else + { + retval = 0; + } + g_type_class_unref (klass); + + return retval; +} + +/** + * atk_remove_global_event_listener: + * @listener_id: the id of the event listener to remove + * + * @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 +atk_remove_global_event_listener (guint listener_id) +{ + AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL); + + if (klass && klass->remove_global_event_listener) + klass->remove_global_event_listener (listener_id); +} + +/** + * atk_add_key_event_listener: + * @listener: the listener to notify + * @data: a #gpointer that points to a block of data that should be sent to the registered listeners, + * along with the event notification, when it occurs. + * + * Adds the specified function to the list of functions to be called + * when a key event occurs. The @data element will be passed to the + * #AtkKeySnoopFunc (@listener) as the @func_data param, on notification. + * + * Returns: added event listener id, or 0 on failure. + **/ +guint +atk_add_key_event_listener (AtkKeySnoopFunc listener, gpointer data) +{ + guint retval; + AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL); + if (klass && klass->add_key_event_listener) + { + retval = klass->add_key_event_listener (listener, data); + } + else + { + retval = 0; + } + + return retval; +} + +/** + * atk_remove_key_event_listener: + * @listener_id: the id of the event listener to remove + * + * @listener_id is the value returned by #atk_add_key_event_listener + * when you registered that event listener. + * + * Removes the specified event listener. + **/ +void +atk_remove_key_event_listener (guint listener_id) +{ + AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL); + + if (klass->remove_key_event_listener) + klass->remove_key_event_listener (listener_id); +} + +/** + * atk_get_root: + * + * Gets the root accessible container for the current application. + * + * Returns: (transfer none): the root accessible container for the current + * application + **/ +AtkObject* +atk_get_root (void) +{ + AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL); + AtkObject *retval; + if (klass->get_root) + { + retval = klass->get_root (); + } + else + { + retval = NULL; + } + g_type_class_unref (klass); + + return retval; +} + +/** + * atk_get_focus_object: + * + * Gets the currently focused object. + * + * Since: 1.6 + * + * Returns: (transfer none): the currently focused object for the current + * application + **/ +AtkObject* +atk_get_focus_object (void) +{ + return previous_focus_object; +} + +/** + * atk_get_toolkit_name: + * + * Gets name string for the GUI toolkit implementing ATK for this application. + * + * Returns: name string for the GUI toolkit implementing ATK for this application + **/ +const gchar* +atk_get_toolkit_name (void) +{ + const gchar *retval; + AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL); + if (klass->get_toolkit_name) + { + retval = klass->get_toolkit_name (); + } + else + { + retval = NULL; + } + g_type_class_unref (klass); + + return retval; +} + +/** + * atk_get_toolkit_version: + * + * Gets version string for the GUI toolkit implementing ATK for this application. + * + * Returns: version string for the GUI toolkit implementing ATK for this application + **/ +const gchar* +atk_get_toolkit_version (void) +{ + const gchar *retval; + AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL); + if (klass->get_toolkit_version) + { + retval = klass->get_toolkit_version (); + } + else + { + retval = NULL; + } + g_type_class_unref (klass); + + return retval; +} + +/** + * atk_get_version: + * + * Gets the current version for ATK. + * + * Returns: version string for ATK + * + * Since: 1.20 + */ +const gchar * +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); }