1 /* ATK - Accessibility Toolkit
2 * Copyright 2001 Sun Microsystems Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include "atkmarshal.c"
24 static void atk_util_class_init (AtkUtilClass *klass);
26 static AtkObject *previous_focus_object = NULL;
28 typedef struct _AtkUtilListenerInfo AtkUtilListenerInfo;
29 struct _AtkUtilListenerInfo
35 static GHashTable *listener_list = NULL;
38 atk_util_get_type (void)
40 static GType type = 0;
44 static const GTypeInfo typeInfo =
46 sizeof (AtkUtilClass),
48 (GBaseFinalizeFunc) NULL,
49 (GClassInitFunc) atk_util_class_init,
50 (GClassFinalizeFunc) NULL,
54 (GInstanceInitFunc) NULL,
56 type = g_type_register_static (G_TYPE_OBJECT, "AtkUtil", &typeInfo, 0) ;
62 * This file supports the addition and removal of multiple focus handlers
63 * as long as they are all called in the same thread.
65 static AtkEventListenerInit focus_tracker_init = (AtkEventListenerInit) NULL;
67 static gboolean init_done = FALSE;
70 * Array of FocusTracker structs
72 static GArray *trackers = NULL;
73 static guint global_index = 0;
75 typedef struct _FocusTracker FocusTracker;
77 struct _FocusTracker {
79 AtkEventListener func;
83 * atk_focus_tracker_init:
84 * @init: Function to be called for focus tracker initialization
86 * Specifies the function to be called for focus tracker initialization.
87 * This function should be called by an implementation of the
88 * ATK interface if any specific work needs to be done to enable
91 * Deprecated: This method is deprecated since ATK version
92 * 2.9.4. Focus tracking has been dropped as a feature to be
93 * implemented by ATK itself.
97 atk_focus_tracker_init (AtkEventListenerInit init)
99 if (!focus_tracker_init)
100 focus_tracker_init = init;
104 * atk_add_focus_tracker:
105 * @focus_tracker: Function to be added to the list of functions to be called
106 * when an object receives focus.
108 * Adds the specified function to the list of functions to be called
109 * when an object receives focus.
111 * Deprecated: This method is deprecated since ATK version
112 * 2.9.4. Focus tracking has been dropped as a feature to be
113 * implemented by ATK itself. If you need focus tracking on your
114 * implementation, subscribe to the state-changed:focused signal.
116 * Returns: added focus tracker id, or 0 on failure.
119 atk_add_focus_tracker (AtkEventListener focus_tracker)
121 g_return_val_if_fail (focus_tracker, 0);
125 if (focus_tracker_init)
127 focus_tracker_init ();
129 trackers = g_array_sized_new (FALSE, TRUE, sizeof (FocusTracker), 0);
136 item.index = ++global_index;
137 item.func = focus_tracker;
138 trackers = g_array_append_val (trackers, item);
148 * atk_remove_focus_tracker:
149 * @tracker_id: the id of the focus tracker to remove
151 * Deprecated: This method is deprecated since ATK version
152 * 2.9.4. Focus tracking has been dropped as a feature to be
153 * implemented by ATK itself. If you need focus tracking on your
154 * implementation, subscribe to the state-changed:focused signal.
156 * Removes the specified focus tracker from the list of functions
157 * to be called when any object receives focus.
160 atk_remove_focus_tracker (guint tracker_id)
165 if (trackers == NULL)
171 for (i = 0; i < trackers->len; i++)
173 item = &g_array_index (trackers, FocusTracker, i);
174 if (item->index == tracker_id)
176 trackers = g_array_remove_index (trackers, i);
183 * atk_focus_tracker_notify:
184 * @object: an #AtkObject
186 * Cause the focus tracker functions which have been specified to be
187 * executed for the object.
189 * Deprecated: This method is deprecated since ATK version
190 * 2.9.4. Focus tracking has been dropped as a feature to be
191 * implemented by ATK itself.
195 atk_focus_tracker_notify (AtkObject *object)
200 if (trackers == NULL)
203 if (object == previous_focus_object)
207 if (previous_focus_object)
208 g_object_unref (previous_focus_object);
210 previous_focus_object = object;
213 g_object_ref (object);
215 for (i = 0; i < trackers->len; i++)
217 item = &g_array_index (trackers, FocusTracker, i);
218 g_return_if_fail (item != NULL);
227 add_listener (GSignalEmissionHook listener,
228 const gchar *object_type,
229 const gchar *signal_name,
230 const gchar *detail_string,
231 const gchar *hook_data)
236 static gint listener_idx = 1;
237 GQuark detail_quark = 0;
239 type = g_type_from_name (object_type);
242 signal_id = g_signal_lookup (signal_name, type);
243 detail_quark = g_quark_from_string (detail_string);
247 AtkUtilListenerInfo *listener_info;
251 listener_info = g_new (AtkUtilListenerInfo, 1);
252 listener_info->key = listener_idx;
253 listener_info->hook_id =
254 g_signal_add_emission_hook (signal_id, detail_quark, listener,
255 g_strdup (hook_data),
256 (GDestroyNotify) g_free);
257 listener_info->signal_id = signal_id;
259 g_hash_table_insert(listener_list, &(listener_info->key), listener_info);
264 g_debug ("Signal type %s not supported\n", signal_name);
269 g_warning("Invalid object type %s\n", object_type);
275 atk_util_real_add_global_event_listener (GSignalEmissionHook listener,
276 const gchar *event_type)
279 gchar **split_string;
282 split_string = g_strsplit (event_type, ":", 0);
283 length = g_strv_length (split_string);
285 if ((length == 3) || (length == 4))
286 rc = add_listener (listener, split_string[1], split_string[2],
287 split_string[3], event_type);
289 g_strfreev (split_string);
295 atk_util_real_remove_global_event_listener (guint remove_listener)
297 if (remove_listener > 0)
299 AtkUtilListenerInfo *listener_info;
300 gint tmp_idx = remove_listener;
302 listener_info = (AtkUtilListenerInfo *)
303 g_hash_table_lookup(listener_list, &tmp_idx);
305 if (listener_info != NULL)
307 /* Hook id of 0 and signal id of 0 are invalid */
308 if (listener_info->hook_id != 0 && listener_info->signal_id != 0)
310 /* Remove the emission hook */
311 g_signal_remove_emission_hook(listener_info->signal_id,
312 listener_info->hook_id);
314 /* Remove the element from the hash */
315 g_hash_table_remove(listener_list, &tmp_idx);
319 g_warning("Invalid listener hook_id %ld or signal_id %d\n",
320 listener_info->hook_id, listener_info->signal_id);
325 g_warning("No listener with the specified listener id %d",
331 g_warning("Invalid listener_id %d", remove_listener);
337 * atk_add_global_event_listener:
338 * @listener: the listener to notify
339 * @event_type: the type of event for which notification is requested
341 * Adds the specified function to the list of functions to be called
342 * when an ATK event of type event_type occurs.
344 * The format of event_type is the following:
345 * "ATK:<atk_type>:<atk_event>:<atk_event_detail>
347 * Where "ATK" works as the namespace, <atk_interface> is the name of
348 * the ATK type (interface or object), <atk_event> is the name of the
349 * signal defined on that interface and <atk_event_detail> is the
350 * gsignal detail of that signal. You can find more info about gsignal
352 * http://developer.gnome.org/gobject/stable/gobject-Signals.html
354 * The first three parameters are mandatory. The last one is optional.
357 * ATK:AtkObject:state-change
358 * ATK:AtkText:text-selection-changed
359 * ATK:AtkText:text-insert:system
361 * Toolkit implementor note: Atk provides a default implementation for
362 * this virtual method, and that implementation should be enough for
363 * most of the cases. You should have a really good reason to
364 * reimplement this method.
366 * Returns: added event listener id, or 0 on failure.
369 atk_add_global_event_listener (GSignalEmissionHook listener,
370 const gchar *event_type)
373 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
375 if (klass->add_global_event_listener)
377 retval = klass->add_global_event_listener (listener, event_type);
383 g_type_class_unref (klass);
389 * atk_remove_global_event_listener:
390 * @listener_id: the id of the event listener to remove
392 * @listener_id is the value returned by #atk_add_global_event_listener
393 * when you registered that event listener.
395 * Toolkit implementor note: Atk provides a default implementation for
396 * this virtual method, and that implementation should be enough for
397 * most of the cases. You should have a really good reason to
398 * reimplement this method.
400 * Removes the specified event listener
403 atk_remove_global_event_listener (guint listener_id)
405 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
407 if (klass && klass->remove_global_event_listener)
408 klass->remove_global_event_listener (listener_id);
412 * atk_add_key_event_listener:
413 * @listener: the listener to notify
414 * @data: a #gpointer that points to a block of data that should be sent to the registered listeners,
415 * along with the event notification, when it occurs.
417 * Adds the specified function to the list of functions to be called
418 * when a key event occurs. The @data element will be passed to the
419 * #AtkKeySnoopFunc (@listener) as the @func_data param, on notification.
421 * Returns: added event listener id, or 0 on failure.
424 atk_add_key_event_listener (AtkKeySnoopFunc listener, gpointer data)
427 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
428 if (klass && klass->add_key_event_listener)
430 retval = klass->add_key_event_listener (listener, data);
441 * atk_remove_key_event_listener:
442 * @listener_id: the id of the event listener to remove
444 * @listener_id is the value returned by #atk_add_key_event_listener
445 * when you registered that event listener.
447 * Removes the specified event listener.
450 atk_remove_key_event_listener (guint listener_id)
452 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
454 if (klass->remove_key_event_listener)
455 klass->remove_key_event_listener (listener_id);
461 * Gets the root accessible container for the current application.
463 * Returns: (transfer none): the root accessible container for the current
469 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
473 retval = klass->get_root ();
479 g_type_class_unref (klass);
485 * atk_get_focus_object:
487 * Gets the currently focused object.
491 * Returns: (transfer none): the currently focused object for the current
495 atk_get_focus_object (void)
497 return previous_focus_object;
501 * atk_get_toolkit_name:
503 * Gets name string for the GUI toolkit implementing ATK for this application.
505 * Returns: name string for the GUI toolkit implementing ATK for this application
508 atk_get_toolkit_name (void)
511 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
512 if (klass->get_toolkit_name)
514 retval = klass->get_toolkit_name ();
520 g_type_class_unref (klass);
526 * atk_get_toolkit_version:
528 * Gets version string for the GUI toolkit implementing ATK for this application.
530 * Returns: version string for the GUI toolkit implementing ATK for this application
533 atk_get_toolkit_version (void)
536 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
537 if (klass->get_toolkit_version)
539 retval = klass->get_toolkit_version ();
545 g_type_class_unref (klass);
553 * Gets the current version for ATK.
555 * Returns: version string for ATK
560 atk_get_version (void)
566 atk_util_class_init (AtkUtilClass *klass)
568 klass->add_global_event_listener = atk_util_real_add_global_event_listener;
569 klass->remove_global_event_listener = atk_util_real_remove_global_event_listener;
570 klass->get_root = NULL;
571 klass->get_toolkit_name = NULL;
572 klass->get_toolkit_version = NULL;
574 listener_list = g_hash_table_new_full (g_int_hash, g_int_equal, NULL,