gobject-introspection: fix virtual annotations and missing type descriptions
[atk.git] / atk / atkutil.c
blobbe9b9833718b26fd1b0dda386c4cbad9e263b5f2
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 "config.h"
22 #include "atkutil.h"
23 #include "atkmarshal.h"
25 /**
26 * SECTION:atkutil
27 * @Short_description: A set of ATK utility functions for event and toolkit support.
28 * @Title:AtkUtil
30 * A set of ATK utility functions which are used to support event
31 * registration of various types, and obtaining the 'root' accessible
32 * of a process and information about the current ATK implementation
33 * and toolkit version.
36 static void atk_util_class_init (AtkUtilClass *klass);
38 static AtkObject *previous_focus_object = NULL;
40 typedef struct _AtkUtilListenerInfo AtkUtilListenerInfo;
41 struct _AtkUtilListenerInfo
43 gint key;
44 guint signal_id;
45 gulong hook_id;
47 static GHashTable *listener_list = NULL;
49 GType
50 atk_util_get_type (void)
52 static GType type = 0;
54 if (!type)
56 static const GTypeInfo typeInfo =
58 sizeof (AtkUtilClass),
59 (GBaseInitFunc) NULL,
60 (GBaseFinalizeFunc) NULL,
61 (GClassInitFunc) atk_util_class_init,
62 (GClassFinalizeFunc) NULL,
63 NULL,
64 sizeof (AtkUtil),
66 (GInstanceInitFunc) NULL,
67 } ;
68 type = g_type_register_static (G_TYPE_OBJECT, "AtkUtil", &typeInfo, 0) ;
70 return type;
74 * This file supports the addition and removal of multiple focus handlers
75 * as long as they are all called in the same thread.
77 static AtkEventListenerInit focus_tracker_init = (AtkEventListenerInit) NULL;
79 static gboolean init_done = FALSE;
82 * Array of FocusTracker structs
84 static GArray *trackers = NULL;
85 static guint global_index = 0;
87 typedef struct _FocusTracker FocusTracker;
89 struct _FocusTracker {
90 guint index;
91 AtkEventListener func;
94 /**
95 * atk_focus_tracker_init: (skip)
96 * @init: Function to be called for focus tracker initialization
98 * Specifies the function to be called for focus tracker initialization.
99 * This function should be called by an implementation of the
100 * ATK interface if any specific work needs to be done to enable
101 * focus tracking.
103 * Deprecated: 2.9.4: Focus tracking has been dropped as a feature
104 * to be 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: (skip)
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: 2.9.4: Focus tracking has been dropped as a feature
123 * to be implemented by ATK itself. If you need focus tracking on your
124 * implementation, subscribe to the #AtkObject::state-change "focused" signal.
126 * Returns: added focus tracker id, or 0 on failure.
128 guint
129 atk_add_focus_tracker (AtkEventListener focus_tracker)
131 g_return_val_if_fail (focus_tracker, 0);
133 if (!init_done)
135 if (focus_tracker_init)
137 focus_tracker_init ();
139 trackers = g_array_sized_new (FALSE, TRUE, sizeof (FocusTracker), 0);
140 init_done = TRUE;
142 if (init_done)
144 FocusTracker item;
146 item.index = ++global_index;
147 item.func = focus_tracker;
148 trackers = g_array_append_val (trackers, item);
149 return global_index;
151 else
153 return 0;
158 * atk_remove_focus_tracker:
159 * @tracker_id: the id of the focus tracker to remove
161 * Deprecated: 2.9.4: Focus tracking has been dropped as a feature
162 * to be implemented by ATK itself. If you need focus tracking on your
163 * implementation, subscribe to the #AtkObject::state-change "focused" signal.
165 * Removes the specified focus tracker from the list of functions
166 * to be called when any object receives focus.
168 void
169 atk_remove_focus_tracker (guint tracker_id)
171 FocusTracker *item;
172 guint i;
174 if (trackers == NULL)
175 return;
177 if (tracker_id == 0)
178 return;
180 for (i = 0; i < trackers->len; i++)
182 item = &g_array_index (trackers, FocusTracker, i);
183 if (item->index == tracker_id)
185 trackers = g_array_remove_index (trackers, i);
186 break;
192 * atk_focus_tracker_notify:
193 * @object: an #AtkObject
195 * Cause the focus tracker functions which have been specified to be
196 * executed for the object.
198 * Deprecated: 2.9.4: Focus tracking has been dropped as a feature
199 * to be implemented by ATK itself. As #AtkObject::focus-event was
200 * deprecated in favor of a #AtkObject::state-change signal, in order
201 * to notify a focus change on your implementation, you can use
202 * atk_object_notify_state_change() instead.
204 void
205 atk_focus_tracker_notify (AtkObject *object)
207 FocusTracker *item;
208 guint i;
210 if (trackers == NULL)
211 return;
213 if (object == previous_focus_object)
214 return;
215 else
217 if (previous_focus_object)
218 g_object_unref (previous_focus_object);
220 previous_focus_object = object;
221 if (object)
223 g_object_ref (object);
225 for (i = 0; i < trackers->len; i++)
227 item = &g_array_index (trackers, FocusTracker, i);
228 g_return_if_fail (item != NULL);
229 item->func (object);
236 static guint
237 add_listener (GSignalEmissionHook listener,
238 const gchar *object_type,
239 const gchar *signal_name,
240 const gchar *detail_string,
241 const gchar *hook_data)
243 GType type;
244 guint signal_id;
245 gint rc = 0;
246 static gint listener_idx = 1;
247 GQuark detail_quark = 0;
249 type = g_type_from_name (object_type);
250 if (type)
252 signal_id = g_signal_lookup (signal_name, type);
253 detail_quark = g_quark_from_string (detail_string);
255 if (signal_id > 0)
257 AtkUtilListenerInfo *listener_info;
259 rc = listener_idx;
261 listener_info = g_new (AtkUtilListenerInfo, 1);
262 listener_info->key = listener_idx;
263 listener_info->hook_id =
264 g_signal_add_emission_hook (signal_id, detail_quark, listener,
265 g_strdup (hook_data),
266 (GDestroyNotify) g_free);
267 listener_info->signal_id = signal_id;
269 g_hash_table_insert(listener_list, &(listener_info->key), listener_info);
270 listener_idx++;
272 else
274 g_debug ("Signal type %s not supported\n", signal_name);
277 else
279 g_warning("Invalid object type %s\n", object_type);
281 return rc;
284 static guint
285 atk_util_real_add_global_event_listener (GSignalEmissionHook listener,
286 const gchar *event_type)
288 guint rc = 0;
289 gchar **split_string;
290 guint length;
292 split_string = g_strsplit (event_type, ":", 0);
293 length = g_strv_length (split_string);
295 if ((length == 3) || (length == 4))
296 rc = add_listener (listener, split_string[1], split_string[2],
297 split_string[3], event_type);
299 g_strfreev (split_string);
301 return rc;
304 static void
305 atk_util_real_remove_global_event_listener (guint remove_listener)
307 if (remove_listener > 0)
309 AtkUtilListenerInfo *listener_info;
310 gint tmp_idx = remove_listener;
312 listener_info = (AtkUtilListenerInfo *)
313 g_hash_table_lookup(listener_list, &tmp_idx);
315 if (listener_info != NULL)
317 /* Hook id of 0 and signal id of 0 are invalid */
318 if (listener_info->hook_id != 0 && listener_info->signal_id != 0)
320 /* Remove the emission hook */
321 g_signal_remove_emission_hook(listener_info->signal_id,
322 listener_info->hook_id);
324 /* Remove the element from the hash */
325 g_hash_table_remove(listener_list, &tmp_idx);
327 else
329 g_warning("Invalid listener hook_id %ld or signal_id %d\n",
330 listener_info->hook_id, listener_info->signal_id);
333 else
335 g_warning("No listener with the specified listener id %d",
336 remove_listener);
339 else
341 g_warning("Invalid listener_id %d", remove_listener);
347 * atk_add_global_event_listener: (skip)
348 * @listener: the listener to notify
349 * @event_type: the type of event for which notification is requested
351 * Adds the specified function to the list of functions to be called
352 * when an ATK event of type event_type occurs.
354 * The format of event_type is the following:
355 * "ATK:&lt;atk_type&gt;:&lt;atk_event&gt;:&lt;atk_event_detail&gt;
357 * Where "ATK" works as the namespace, &lt;atk_interface&gt; is the name of
358 * the ATK type (interface or object), &lt;atk_event&gt; is the name of the
359 * signal defined on that interface and &lt;atk_event_detail&gt; is the
360 * gsignal detail of that signal. You can find more info about gsignal
361 * details here:
362 * http://developer.gnome.org/gobject/stable/gobject-Signals.html
364 * The first three parameters are mandatory. The last one is optional.
366 * For example:
367 * ATK:AtkObject:state-change
368 * ATK:AtkText:text-selection-changed
369 * ATK:AtkText:text-insert:system
371 * Toolkit implementor note: ATK provides a default implementation for
372 * this virtual method. ATK implementors are discouraged from
373 * reimplementing this method.
375 * Toolkit implementor note: this method is not intended to be used by
376 * ATK implementors but by ATK consumers.
378 * ATK consumers note: as this method adds a listener for a given ATK
379 * type, that type should be already registered on the GType system
380 * before calling this method. A simple way to do that is creating an
381 * instance of #AtkNoOpObject. This class implements all ATK
382 * interfaces, so creating the instance will register all ATK types as
383 * a collateral effect.
385 * Returns: added event listener id, or 0 on failure.
387 guint
388 atk_add_global_event_listener (GSignalEmissionHook listener,
389 const gchar *event_type)
391 guint retval;
392 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
394 if (klass->add_global_event_listener)
396 retval = klass->add_global_event_listener (listener, event_type);
398 else
400 retval = 0;
402 g_type_class_unref (klass);
404 return retval;
408 * atk_remove_global_event_listener:
409 * @listener_id: the id of the event listener to remove
411 * @listener_id is the value returned by #atk_add_global_event_listener
412 * when you registered that event listener.
414 * Toolkit implementor note: ATK provides a default implementation for
415 * this virtual method. ATK implementors are discouraged from
416 * reimplementing this method.
418 * Toolkit implementor note: this method is not intended to be used by
419 * ATK implementors but by ATK consumers.
421 * Removes the specified event listener
423 void
424 atk_remove_global_event_listener (guint listener_id)
426 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
428 if (klass && klass->remove_global_event_listener)
429 klass->remove_global_event_listener (listener_id);
433 * atk_add_key_event_listener: (skip)
434 * @listener: the listener to notify
435 * @data: a #gpointer that points to a block of data that should be sent to the registered listeners,
436 * along with the event notification, when it occurs.
438 * Adds the specified function to the list of functions to be called
439 * when a key event occurs. The @data element will be passed to the
440 * #AtkKeySnoopFunc (@listener) as the @func_data param, on notification.
442 * Returns: added event listener id, or 0 on failure.
444 guint
445 atk_add_key_event_listener (AtkKeySnoopFunc listener, gpointer data)
447 guint retval;
448 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
449 if (klass && klass->add_key_event_listener)
451 retval = klass->add_key_event_listener (listener, data);
453 else
455 retval = 0;
458 return retval;
462 * atk_remove_key_event_listener:
463 * @listener_id: the id of the event listener to remove
465 * @listener_id is the value returned by #atk_add_key_event_listener
466 * when you registered that event listener.
468 * Removes the specified event listener.
470 void
471 atk_remove_key_event_listener (guint listener_id)
473 AtkUtilClass *klass = g_type_class_peek (ATK_TYPE_UTIL);
475 if (klass->remove_key_event_listener)
476 klass->remove_key_event_listener (listener_id);
480 * atk_get_root:
482 * Gets the root accessible container for the current application.
484 * Returns: (transfer none): the root accessible container for the current
485 * application
487 AtkObject*
488 atk_get_root (void)
490 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
491 AtkObject *retval;
492 if (klass->get_root)
494 retval = klass->get_root ();
496 else
498 retval = NULL;
500 g_type_class_unref (klass);
502 return retval;
506 * atk_get_focus_object:
508 * Gets the currently focused object.
510 * Since: 1.6
512 * Returns: (transfer none): the currently focused object for the current
513 * application
515 AtkObject*
516 atk_get_focus_object (void)
518 return previous_focus_object;
522 * atk_get_toolkit_name:
524 * Gets name string for the GUI toolkit implementing ATK for this application.
526 * Returns: name string for the GUI toolkit implementing ATK for this application
528 const gchar*
529 atk_get_toolkit_name (void)
531 const gchar *retval;
532 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
533 if (klass->get_toolkit_name)
535 retval = klass->get_toolkit_name ();
537 else
539 retval = NULL;
541 g_type_class_unref (klass);
543 return retval;
547 * atk_get_toolkit_version:
549 * Gets version string for the GUI toolkit implementing ATK for this application.
551 * Returns: version string for the GUI toolkit implementing ATK for this application
553 const gchar*
554 atk_get_toolkit_version (void)
556 const gchar *retval;
557 AtkUtilClass *klass = g_type_class_ref (ATK_TYPE_UTIL);
558 if (klass->get_toolkit_version)
560 retval = klass->get_toolkit_version ();
562 else
564 retval = NULL;
566 g_type_class_unref (klass);
568 return retval;
572 * atk_get_version:
574 * Gets the current version for ATK.
576 * Returns: version string for ATK
578 * Since: 1.20
580 const gchar *
581 atk_get_version (void)
583 return VERSION;
586 static void
587 atk_util_class_init (AtkUtilClass *klass)
589 klass->add_global_event_listener = atk_util_real_add_global_event_listener;
590 klass->remove_global_event_listener = atk_util_real_remove_global_event_listener;
591 klass->get_root = NULL;
592 klass->get_toolkit_name = NULL;
593 klass->get_toolkit_version = NULL;
595 listener_list = g_hash_table_new_full (g_int_hash, g_int_equal, NULL,
596 g_free);