role: fix name for ATK_ROLE_EDITBAR
[atk.git] / atk / atkutil.c
blob058fc6de52bdd0b3b77d0b924d694f2f55e8e768
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.
20 #include "atkutil.h"
21 #include "atkmarshal.c"
22 #include "config.h"
24 /**
25 * SECTION:atkutil
26 * @Short_description: A set of ATK utility functions for event and toolkit support.
27 * @Title:AtkUtil
29 * A set of ATK utility functions which are used to support event
30 * registration of various types, and obtaining the 'root' accessible
31 * of a process and information about the current ATK implementation
32 * and toolkit version.
35 static void atk_util_class_init (AtkUtilClass *klass);
37 static AtkObject *previous_focus_object = NULL;
39 typedef struct _AtkUtilListenerInfo AtkUtilListenerInfo;
40 struct _AtkUtilListenerInfo
42 gint key;
43 guint signal_id;
44 gulong hook_id;
46 static GHashTable *listener_list = NULL;
48 GType
49 atk_util_get_type (void)
51 static GType type = 0;
53 if (!type)
55 static const GTypeInfo typeInfo =
57 sizeof (AtkUtilClass),
58 (GBaseInitFunc) NULL,
59 (GBaseFinalizeFunc) NULL,
60 (GClassInitFunc) atk_util_class_init,
61 (GClassFinalizeFunc) NULL,
62 NULL,
63 sizeof (AtkUtil),
65 (GInstanceInitFunc) NULL,
66 } ;
67 type = g_type_register_static (G_TYPE_OBJECT, "AtkUtil", &typeInfo, 0) ;
69 return type;
73 * This file supports the addition and removal of multiple focus handlers
74 * as long as they are all called in the same thread.
76 static AtkEventListenerInit focus_tracker_init = (AtkEventListenerInit) NULL;
78 static gboolean init_done = FALSE;
81 * Array of FocusTracker structs
83 static GArray *trackers = NULL;
84 static guint global_index = 0;
86 typedef struct _FocusTracker FocusTracker;
88 struct _FocusTracker {
89 guint index;
90 AtkEventListener func;
93 /**
94 * atk_focus_tracker_init:
95 * @init: Function to be called for focus tracker initialization
97 * Specifies the function to be called for focus tracker initialization.
98 * This function should be called by an implementation of the
99 * ATK interface if any specific work needs to be done to enable
100 * focus tracking.
102 * Deprecated: This method is deprecated since ATK version
103 * 2.9.4. Focus tracking has been dropped as a feature to be
104 * implemented by ATK itself.
107 void
108 atk_focus_tracker_init (AtkEventListenerInit init)
110 if (!focus_tracker_init)
111 focus_tracker_init = init;
115 * atk_add_focus_tracker:
116 * @focus_tracker: Function to be added to the list of functions to be called
117 * when an object receives focus.
119 * Adds the specified function to the list of functions to be called
120 * when an object receives focus.
122 * Deprecated: This method is deprecated since ATK version
123 * 2.9.4. Focus tracking has been dropped as a feature to be
124 * implemented by ATK itself. If you need focus tracking on your
125 * implementation, subscribe to the state-changed:focused signal.
127 * Returns: added focus tracker id, or 0 on failure.
129 guint
130 atk_add_focus_tracker (AtkEventListener focus_tracker)
132 g_return_val_if_fail (focus_tracker, 0);
134 if (!init_done)
136 if (focus_tracker_init)
138 focus_tracker_init ();
140 trackers = g_array_sized_new (FALSE, TRUE, sizeof (FocusTracker), 0);
141 init_done = TRUE;
143 if (init_done)
145 FocusTracker item;
147 item.index = ++global_index;
148 item.func = focus_tracker;
149 trackers = g_array_append_val (trackers, item);
150 return global_index;
152 else
154 return 0;
159 * atk_remove_focus_tracker:
160 * @tracker_id: the id of the focus tracker to remove
162 * Deprecated: This method is deprecated since ATK version
163 * 2.9.4. Focus tracking has been dropped as a feature to be
164 * implemented by ATK itself. If you need focus tracking on your
165 * implementation, subscribe to the state-changed:focused signal.
167 * Removes the specified focus tracker from the list of functions
168 * to be called when any object receives focus.
170 void
171 atk_remove_focus_tracker (guint tracker_id)
173 FocusTracker *item;
174 guint i;
176 if (trackers == NULL)
177 return;
179 if (tracker_id == 0)
180 return;
182 for (i = 0; i < trackers->len; i++)
184 item = &g_array_index (trackers, FocusTracker, i);
185 if (item->index == tracker_id)
187 trackers = g_array_remove_index (trackers, i);
188 break;
194 * atk_focus_tracker_notify:
195 * @object: an #AtkObject
197 * Cause the focus tracker functions which have been specified to be
198 * executed for the object.
200 * Deprecated: This method is deprecated since ATK version
201 * 2.9.4. Focus tracking has been dropped as a feature to be
202 * implemented by ATK itself.
205 void
206 atk_focus_tracker_notify (AtkObject *object)
208 FocusTracker *item;
209 guint i;
211 if (trackers == NULL)
212 return;
214 if (object == previous_focus_object)
215 return;
216 else
218 if (previous_focus_object)
219 g_object_unref (previous_focus_object);
221 previous_focus_object = object;
222 if (object)
224 g_object_ref (object);
226 for (i = 0; i < trackers->len; i++)
228 item = &g_array_index (trackers, FocusTracker, i);
229 g_return_if_fail (item != NULL);
230 item->func (object);
237 static guint
238 add_listener (GSignalEmissionHook listener,
239 const gchar *object_type,
240 const gchar *signal_name,
241 const gchar *detail_string,
242 const gchar *hook_data)
244 GType type;
245 guint signal_id;
246 gint rc = 0;
247 static gint listener_idx = 1;
248 GQuark detail_quark = 0;
250 type = g_type_from_name (object_type);
251 if (type)
253 signal_id = g_signal_lookup (signal_name, type);
254 detail_quark = g_quark_from_string (detail_string);
256 if (signal_id > 0)
258 AtkUtilListenerInfo *listener_info;
260 rc = listener_idx;
262 listener_info = g_new (AtkUtilListenerInfo, 1);
263 listener_info->key = listener_idx;
264 listener_info->hook_id =
265 g_signal_add_emission_hook (signal_id, detail_quark, listener,
266 g_strdup (hook_data),
267 (GDestroyNotify) g_free);
268 listener_info->signal_id = signal_id;
270 g_hash_table_insert(listener_list, &(listener_info->key), listener_info);
271 listener_idx++;
273 else
275 g_debug ("Signal type %s not supported\n", signal_name);
278 else
280 g_warning("Invalid object type %s\n", object_type);
282 return rc;
285 static guint
286 atk_util_real_add_global_event_listener (GSignalEmissionHook listener,
287 const gchar *event_type)
289 guint rc = 0;
290 gchar **split_string;
291 guint length;
293 split_string = g_strsplit (event_type, ":", 0);
294 length = g_strv_length (split_string);
296 if ((length == 3) || (length == 4))
297 rc = add_listener (listener, split_string[1], split_string[2],
298 split_string[3], event_type);
300 g_strfreev (split_string);
302 return rc;
305 static void
306 atk_util_real_remove_global_event_listener (guint remove_listener)
308 if (remove_listener > 0)
310 AtkUtilListenerInfo *listener_info;
311 gint tmp_idx = remove_listener;
313 listener_info = (AtkUtilListenerInfo *)
314 g_hash_table_lookup(listener_list, &tmp_idx);
316 if (listener_info != NULL)
318 /* Hook id of 0 and signal id of 0 are invalid */
319 if (listener_info->hook_id != 0 && listener_info->signal_id != 0)
321 /* Remove the emission hook */
322 g_signal_remove_emission_hook(listener_info->signal_id,
323 listener_info->hook_id);
325 /* Remove the element from the hash */
326 g_hash_table_remove(listener_list, &tmp_idx);
328 else
330 g_warning("Invalid listener hook_id %ld or signal_id %d\n",
331 listener_info->hook_id, listener_info->signal_id);
334 else
336 g_warning("No listener with the specified listener id %d",
337 remove_listener);
340 else
342 g_warning("Invalid listener_id %d", remove_listener);
348 * atk_add_global_event_listener:
349 * @listener: the listener to notify
350 * @event_type: the type of event for which notification is requested
352 * Adds the specified function to the list of functions to be called
353 * when an ATK event of type event_type occurs.
355 * The format of event_type is the following:
356 * "ATK:<atk_type>:<atk_event>:<atk_event_detail>
358 * Where "ATK" works as the namespace, <atk_interface> is the name of
359 * the ATK type (interface or object), <atk_event> is the name of the
360 * signal defined on that interface and <atk_event_detail> is the
361 * gsignal detail of that signal. You can find more info about gsignal
362 * details here:
363 * http://developer.gnome.org/gobject/stable/gobject-Signals.html
365 * The first three parameters are mandatory. The last one is optional.
367 * For example:
368 * ATK:AtkObject:state-change
369 * ATK:AtkText:text-selection-changed
370 * ATK:AtkText:text-insert:system
372 * Toolkit implementor note: ATK provides a default implementation for
373 * this virtual method. ATK implementors are discouraged from
374 * reimplementing this method.
376 * Toolkit implementor note: this method is not intended to be used by
377 * ATK implementors but by ATK consumers.
379 * Returns: added event listener id, or 0 on failure.
381 guint
382 atk_add_global_event_listener (GSignalEmissionHook listener,
383 const gchar *event_type)
385 guint retval;
386 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
388 if (klass->add_global_event_listener)
390 retval = klass->add_global_event_listener (listener, event_type);
392 else
394 retval = 0;
396 g_type_class_unref (klass);
398 return retval;
402 * atk_remove_global_event_listener:
403 * @listener_id: the id of the event listener to remove
405 * @listener_id is the value returned by #atk_add_global_event_listener
406 * when you registered that event listener.
408 * Toolkit implementor note: ATK provides a default implementation for
409 * this virtual method. ATK implementors are discouraged from
410 * reimplementing this method.
412 * Toolkit implementor note: this method is not intended to be used by
413 * ATK implementors but by ATK consumers.
415 * Removes the specified event listener
417 void
418 atk_remove_global_event_listener (guint listener_id)
420 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
422 if (klass && klass->remove_global_event_listener)
423 klass->remove_global_event_listener (listener_id);
427 * atk_add_key_event_listener:
428 * @listener: the listener to notify
429 * @data: a #gpointer that points to a block of data that should be sent to the registered listeners,
430 * along with the event notification, when it occurs.
432 * Adds the specified function to the list of functions to be called
433 * when a key event occurs. The @data element will be passed to the
434 * #AtkKeySnoopFunc (@listener) as the @func_data param, on notification.
436 * Returns: added event listener id, or 0 on failure.
438 guint
439 atk_add_key_event_listener (AtkKeySnoopFunc listener, gpointer data)
441 guint retval;
442 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
443 if (klass && klass->add_key_event_listener)
445 retval = klass->add_key_event_listener (listener, data);
447 else
449 retval = 0;
452 return retval;
456 * atk_remove_key_event_listener:
457 * @listener_id: the id of the event listener to remove
459 * @listener_id is the value returned by #atk_add_key_event_listener
460 * when you registered that event listener.
462 * Removes the specified event listener.
464 void
465 atk_remove_key_event_listener (guint listener_id)
467 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
469 if (klass->remove_key_event_listener)
470 klass->remove_key_event_listener (listener_id);
474 * atk_get_root:
476 * Gets the root accessible container for the current application.
478 * Returns: (transfer none): the root accessible container for the current
479 * application
481 AtkObject*
482 atk_get_root (void)
484 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
485 AtkObject *retval;
486 if (klass->get_root)
488 retval = klass->get_root ();
490 else
492 retval = NULL;
494 g_type_class_unref (klass);
496 return retval;
500 * atk_get_focus_object:
502 * Gets the currently focused object.
504 * Since: 1.6
506 * Returns: (transfer none): the currently focused object for the current
507 * application
509 AtkObject*
510 atk_get_focus_object (void)
512 return previous_focus_object;
516 * atk_get_toolkit_name:
518 * Gets name string for the GUI toolkit implementing ATK for this application.
520 * Returns: name string for the GUI toolkit implementing ATK for this application
522 const gchar*
523 atk_get_toolkit_name (void)
525 const gchar *retval;
526 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
527 if (klass->get_toolkit_name)
529 retval = klass->get_toolkit_name ();
531 else
533 retval = NULL;
535 g_type_class_unref (klass);
537 return retval;
541 * atk_get_toolkit_version:
543 * Gets version string for the GUI toolkit implementing ATK for this application.
545 * Returns: version string for the GUI toolkit implementing ATK for this application
547 const gchar*
548 atk_get_toolkit_version (void)
550 const gchar *retval;
551 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
552 if (klass->get_toolkit_version)
554 retval = klass->get_toolkit_version ();
556 else
558 retval = NULL;
560 g_type_class_unref (klass);
562 return retval;
566 * atk_get_version:
568 * Gets the current version for ATK.
570 * Returns: version string for ATK
572 * Since: 1.20
574 const gchar *
575 atk_get_version (void)
577 return VERSION;
580 static void
581 atk_util_class_init (AtkUtilClass *klass)
583 klass->add_global_event_listener = atk_util_real_add_global_event_listener;
584 klass->remove_global_event_listener = atk_util_real_remove_global_event_listener;
585 klass->get_root = NULL;
586 klass->get_toolkit_name = NULL;
587 klass->get_toolkit_version = NULL;
589 listener_list = g_hash_table_new_full (g_int_hash, g_int_equal, NULL,
590 g_free);