2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.,
6 * Copyright 2001, 2002, 2003 Ximian, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
28 #include <libbonobo.h>
29 #include <orbit/orbit.h>
31 #include <atk/atkobject.h>
32 #include <atk/atknoopobject.h>
33 #include <libspi/Accessibility.h>
34 #include <libspi/spi-private.h>
35 #include "accessible.h"
36 #include "application.h"
38 #include <bonobo-activation/bonobo-activation-register.h>
40 #undef SPI_BRIDGE_DEBUG
42 #define DBG(a,b) if(_dbg>=(a))b
45 static CORBA_Environment ev;
46 static Accessibility_Registry registry = CORBA_OBJECT_NIL;
47 static Accessibility_DeviceEventController device_event_controller = CORBA_OBJECT_NIL;
48 static SpiApplication *this_app = NULL;
49 static gboolean registry_died = FALSE;
50 static gboolean atk_listeners_registered = FALSE;
51 static gint toplevels = 0;
53 static guint atk_signal_text_changed;
54 static guint atk_signal_children_changed;
55 static guint atk_signal_active_descendant_changed;
56 static guint atk_signal_text_selection_changed;
59 static guint atk_signal_row_reordered;
60 static guint atk_signal_row_inserted;
61 static guint atk_signal_row_deleted;
62 static guint atk_signal_column_reordered;
63 static guint atk_signal_column_inserted;
64 static guint atk_signal_column_deleted;
67 static guint atk_signal_link_selected;
69 static Accessibility_Registry spi_atk_bridge_get_registry (void);
70 static void spi_atk_bridge_do_registration (void);
71 static void spi_atk_bridge_toplevel_added (AtkObject *object,
74 static void spi_atk_bridge_toplevel_removed (AtkObject *object,
78 static void spi_atk_bridge_exit_func (void);
79 static void spi_atk_register_event_listeners (void);
80 static void spi_atk_bridge_focus_tracker (AtkObject *object);
81 static void spi_atk_bridge_register_application (Accessibility_Registry registry);
82 static gboolean spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint,
84 const GValue *param_values,
87 spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint,
89 const GValue *param_values,
92 spi_atk_bridge_state_event_listener (GSignalInvocationHint *signal_hint,
94 const GValue *param_values,
96 static gboolean spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint,
98 const GValue *param_values,
100 static gint spi_atk_bridge_key_listener (AtkKeyEventStruct *event,
102 static void spi_atk_tidy_windows (void);
103 static void deregister_application (BonoboObject *app);
104 static void reinit_register_vars (void);
106 /* For automatic libgnome init */
107 extern void gnome_accessibility_module_init (void);
108 extern void gnome_accessibility_module_shutdown (void);
110 static int atk_bridge_initialized = FALSE;
111 static guint atk_bridge_focus_tracker_id = 0;
112 static guint atk_bridge_key_event_listener_id = 0;
113 static GArray *listener_ids = NULL;
116 * These exported symbols are hooked by gnome-program
117 * to provide automatic module initialization and shutdown.
119 extern void gnome_accessibility_module_init (void);
120 extern void gnome_accessibility_module_shutdown (void);
123 spi_atk_bridge_init_event_type_consts ()
125 static gboolean done = FALSE;
130 atk_signal_children_changed = g_signal_lookup ("children_changed",
132 atk_signal_text_changed = g_signal_lookup ("text_changed",
134 atk_signal_active_descendant_changed =
135 g_signal_lookup ("active_descendant_changed",
137 atk_signal_link_selected = g_signal_lookup ("link_selected",
139 atk_signal_text_selection_changed = g_signal_lookup ("text_selection_changed",
145 atk_bridge_init (gint *argc, gchar **argv[])
147 const char *debug_env_string = g_getenv ("AT_SPI_DEBUG");
149 if (atk_bridge_initialized)
153 atk_bridge_initialized = TRUE;
155 if (debug_env_string)
156 _dbg = (int) g_ascii_strtod (debug_env_string, NULL);
158 if (!bonobo_init (argc, argv ? *argv : NULL))
160 g_error ("Could not initialize Bonobo");
163 /* Create the accessible application server object */
164 this_app = spi_application_new (atk_get_root ());
166 * We only want to enable the bridge for top level
167 * applications, we detect bonobo components by seeing
168 * if they were activated with the intention of extracting
169 * an impl. by IID - very solid.
171 if (bonobo_activation_iid_get ())
173 DBG (1, g_message ("Found Bonobo component\n"));
174 g_signal_connect (atk_get_root (),
175 "children-changed::add",
176 (GCallback) spi_atk_bridge_toplevel_added,
178 g_signal_connect (atk_get_root (),
179 "children-changed::remove",
180 (GCallback) spi_atk_bridge_toplevel_removed,
185 spi_atk_bridge_do_registration ();
187 spi_atk_register_event_listeners ();
188 spi_atk_bridge_init_event_type_consts ();
195 spi_atk_bridge_do_registration (void)
197 CORBA_Environment ev;
199 CORBA_exception_init(&ev);
201 if (spi_atk_bridge_get_registry () == CORBA_OBJECT_NIL)
203 g_error ("Could not locate registry");
208 /* Create the accessible application server object */
209 if (this_app == NULL)
210 this_app = spi_application_new (atk_get_root ());
212 DBG (1, g_message ("About to register application\n"));
214 spi_atk_bridge_register_application (spi_atk_bridge_get_registry ());
216 g_atexit (spi_atk_bridge_exit_func);
218 DBG (1, g_message ("Application registered & listening\n"));
223 spi_atk_bridge_toplevel_added (AtkObject *object,
229 spi_atk_bridge_do_registration ();
235 spi_atk_bridge_toplevel_removed (AtkObject *object,
239 BonoboObject *app = (BonoboObject *) this_app;
244 deregister_application (app);
245 reinit_register_vars ();
249 g_warning ("More toplevels removed than added\n");
255 spi_atk_bridge_register_application (Accessibility_Registry registry)
257 Accessibility_Registry_registerApplication (spi_atk_bridge_get_registry (),
258 BONOBO_OBJREF (this_app),
262 static Accessibility_Registry
263 spi_atk_bridge_get_registry (void)
265 CORBA_Environment ev;
267 if (registry_died || (registry == CORBA_OBJECT_NIL)) {
268 CORBA_exception_init (&ev);
270 DBG (1, g_warning ("registry died! restarting..."));
271 registry = bonobo_activation_activate_from_id (
272 "OAFIID:Accessibility_Registry:1.0", 0, NULL, &ev);
274 if (ev._major != CORBA_NO_EXCEPTION)
276 g_error ("Accessibility app error: exception during "
277 "registry activation from id: %s\n",
278 CORBA_exception_id (&ev));
279 CORBA_exception_free (&ev);
282 if (registry_died && registry) {
283 registry_died = FALSE;
284 spi_atk_bridge_register_application (registry);
290 static Accessibility_DeviceEventController
291 spi_atk_bridget_get_dec (void)
293 CORBA_Environment ev;
295 if (device_event_controller != CORBA_OBJECT_NIL)
297 if (ORBit_small_get_connection_status (device_event_controller)
298 == ORBIT_CONNECTION_CONNECTED)
299 return device_event_controller;
302 CORBA_exception_init (&ev);
304 device_event_controller =
305 Accessibility_Registry_getDeviceEventController (
306 spi_atk_bridge_get_registry (), &ev);
310 g_warning (_("failure: no device event controller found.\n"));
311 registry_died = TRUE;
312 device_event_controller = CORBA_OBJECT_NIL;
315 return device_event_controller;
319 gtk_module_init (gint *argc, gchar **argv[])
321 return atk_bridge_init (argc, argv);
325 add_signal_listener (const char *signal_name)
329 id = atk_add_global_event_listener (
330 spi_atk_bridge_signal_listener, signal_name);
332 g_array_append_val (listener_ids, id);
336 spi_atk_register_event_listeners (void)
339 * kludge to make sure the Atk interface types are registered, otherwise
340 * the AtkText signal handlers below won't get registered
343 GObject *ao = g_object_new (ATK_TYPE_OBJECT, NULL);
344 AtkObject *bo = atk_no_op_object_new (ao);
347 if (atk_listeners_registered) return;
349 atk_listeners_registered = TRUE;
351 /* Register for focus event notifications, and register app with central registry */
353 listener_ids = g_array_sized_new (FALSE, TRUE, sizeof (guint), 16);
355 atk_bridge_focus_tracker_id = atk_add_focus_tracker (spi_atk_bridge_focus_tracker);
357 id = atk_add_global_event_listener (spi_atk_bridge_property_event_listener,
358 "Gtk:AtkObject:property-change");
359 g_array_append_val (listener_ids, id);
360 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
362 g_array_append_val (listener_ids, id);
363 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
365 g_array_append_val (listener_ids, id);
366 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
368 g_array_append_val (listener_ids, id);
369 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
371 g_array_append_val (listener_ids, id);
372 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
374 g_array_append_val (listener_ids, id);
375 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
377 g_array_append_val (listener_ids, id);
378 id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener,
379 "window:deactivate");
380 g_array_append_val (listener_ids, id);
381 id = atk_add_global_event_listener (spi_atk_bridge_state_event_listener,
382 "Gtk:AtkObject:state-change");
383 g_array_append_val (listener_ids, id);
385 add_signal_listener ("Gtk:AtkObject:children-changed");
386 add_signal_listener ("Gtk:AtkObject:visible-data-changed");
387 add_signal_listener ("Gtk:AtkObject:active-descendant-changed");
388 add_signal_listener ("Gtk:AtkSelection:selection-changed");
389 add_signal_listener ("Gtk:AtkText:text-selection-changed");
390 add_signal_listener ("Gtk:AtkText:text-changed");
391 add_signal_listener ("Gtk:AtkText:text-caret-moved");
392 add_signal_listener ("Gtk:AtkTable:row-inserted");
393 add_signal_listener ("Gtk:AtkTable:row-reordered");
394 add_signal_listener ("Gtk:AtkTable:row-deleted");
395 add_signal_listener ("Gtk:AtkTable:column-inserted");
396 add_signal_listener ("Gtk:AtkTable:column-reordered");
397 add_signal_listener ("Gtk:AtkTable:column-deleted");
398 add_signal_listener ("Gtk:AtkTable:model-changed");
399 add_signal_listener ("Gtk:AtkHypertext:link-selected");
401 * May add the following listeners to implement preemptive key listening for GTK+
403 * atk_add_global_event_listener (spi_atk_bridge_widgetkey_listener, "Gtk:GtkWidget:key-press-event");
404 * atk_add_global_event_listener (spi_atk_bridge_widgetkey_listener, "Gtk:GtkWidget:key-release-event");
406 atk_bridge_key_event_listener_id = atk_add_key_event_listener (
407 spi_atk_bridge_key_listener, NULL);
409 g_object_unref (G_OBJECT (bo));
414 deregister_application (BonoboObject *app)
416 Accessibility_Registry registry = spi_atk_bridge_get_registry ();
417 Accessibility_Registry_deregisterApplication (registry, BONOBO_OBJREF (app), &ev);
419 device_event_controller = bonobo_object_release_unref (device_event_controller, &ev);
420 registry = bonobo_object_release_unref (registry, &ev);
422 app = bonobo_object_unref (app);
426 spi_atk_bridge_exit_func (void)
428 BonoboObject *app = (BonoboObject *) this_app;
430 DBG (1, g_message ("exiting bridge\n"));
439 * Check whether we still have windows which have not been deleted.
441 spi_atk_tidy_windows ();
443 * FIXME: this may be incorrect for apps that do their own bonobo
444 * shutdown, until we can explicitly shutdown to get the ordering
447 if (!bonobo_is_initialized ())
449 DBG (1, g_warning ("Re-initializing bonobo\n"));
450 g_assert (bonobo_init (0, NULL));
451 g_assert (bonobo_activate ());
454 deregister_application (app);
456 DBG (1, g_message ("bridge exit func complete.\n"));
458 if (g_getenv ("AT_BRIDGE_SHUTDOWN"))
460 g_assert (!bonobo_debug_shutdown ());
465 gnome_accessibility_module_init (void)
467 atk_bridge_init (NULL, NULL);
469 g_print("Atk Accessibilty bridge initialized\n");
473 gnome_accessibility_module_shutdown (void)
475 BonoboObject *app = (BonoboObject *) this_app;
477 GArray *ids = listener_ids;
479 if (!atk_bridge_initialized)
483 atk_bridge_initialized = FALSE;
486 g_print("Atk Accessibilty bridge shutdown\n");
489 atk_remove_focus_tracker (atk_bridge_focus_tracker_id);
491 for (i = 0; ids && i < ids->len; i++)
493 atk_remove_global_event_listener (g_array_index (ids, guint, i));
496 atk_remove_key_event_listener (atk_bridge_key_event_listener_id);
498 deregister_application (app);
502 spi_atk_bridge_focus_tracker (AtkObject *object)
504 SpiAccessible *source;
505 Accessibility_Event e;
507 source = spi_accessible_new (object);
510 e.source = BONOBO_OBJREF (source);
513 spi_init_any_nil (&e.any_data);
515 CORBA_exception_init (&ev);
516 Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev);
518 registry_died = TRUE;
520 bonobo_object_unref (source);
522 CORBA_exception_free (&ev);
526 spi_atk_emit_eventv (const GObject *gobject,
530 const char *format, ...)
533 Accessibility_Event e;
534 SpiAccessible *source;
536 #ifdef SPI_BRIDGE_DEBUG
540 va_start (args, format);
542 if (ATK_IS_IMPLEMENTOR (gobject))
544 aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject));
545 source = spi_accessible_new (aobject);
546 g_object_unref (G_OBJECT (aobject));
548 else if (ATK_IS_OBJECT (gobject))
550 aobject = ATK_OBJECT (gobject);
551 source = spi_accessible_new (aobject);
557 DBG (0, g_warning ("received property-change event from non-AtkImplementor"));
562 e.type = g_strdup_vprintf (format, args);
563 e.source = BONOBO_OBJREF (source);
566 if (any) e.any_data = *any;
567 else spi_init_any_nil (&e.any_data);
569 #ifdef SPI_BRIDGE_DEBUG
570 s = Accessibility_Accessible__get_name (BONOBO_OBJREF (source), &ev);
571 g_warning ("Emitting event '%s' (%lu, %lu) on %s",
572 e.type, e.detail1, e.detail2, s);
575 CORBA_exception_init (&ev);
576 Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (),
578 #ifdef SPI_BRIDGE_DEBUG
579 if (ev._major != CORBA_NO_EXCEPTION)
580 g_warning ("error emitting event %s, (%d) %s",
583 CORBA_exception_id(&ev));
585 if (BONOBO_EX (&ev)) registry_died = TRUE;
586 Accessibility_Accessible_unref (e.source, &ev);
588 CORBA_exception_free (&ev);
598 spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint,
599 guint n_param_values,
600 const GValue *param_values,
603 AtkPropertyValues *values;
605 const gchar *prop_name;
607 const gchar *sp = NULL;
609 SpiAccessible *s_ao = NULL;
613 #ifdef SPI_BRIDGE_DEBUG
614 GSignalQuery signal_query;
618 g_signal_query (signal_hint->signal_id, &signal_query);
619 name = signal_query.signal_name;
621 s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0)));
622 s = atk_object_get_name (ATK_OBJECT (g_value_get_object (param_values + 0)));
623 values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1);
624 DBG (2, g_message ("Received (property) signal %s:%s:%s from object %s (gail %s)\n",
625 g_type_name (signal_query.itype), name, values->property_name, s, s2));
629 gobject = g_value_get_object (param_values + 0);
630 values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1);
632 prop_name = values->property_name;
633 if (strcmp (prop_name, "accessible-name") == 0)
635 sp = atk_object_get_name (ATK_OBJECT (gobject));
636 spi_init_any_string (&any, (gchar **)&sp);
638 else if (strcmp (prop_name, "accessible-description") == 0)
640 sp = atk_object_get_description (ATK_OBJECT (gobject));
641 spi_init_any_string (&any, (gchar **)&sp);
643 else if (strcmp (prop_name, "accessible-parent") == 0)
645 ao = atk_object_get_parent (ATK_OBJECT (gobject));
648 s_ao = spi_accessible_new (ao);
649 c_obj = BONOBO_OBJREF (s_ao);
650 spi_init_any_object (&any, &c_obj);
654 spi_init_any_nil (&any);
657 else if (strcmp (prop_name, "accessible-table-summary") == 0)
659 ao = atk_table_get_summary (ATK_TABLE (gobject));
662 s_ao = spi_accessible_new (ao);
663 c_obj = BONOBO_OBJREF (s_ao);
664 spi_init_any_object (&any, &c_obj);
668 spi_init_any_nil (&any);
671 else if (strcmp (prop_name, "accessible-table-column-header") == 0)
673 i = g_value_get_int (&(values->new_value));
674 ao = atk_table_get_column_header (ATK_TABLE (gobject), i);
677 s_ao = spi_accessible_new (ao);
678 c_obj = BONOBO_OBJREF (s_ao);
679 spi_init_any_object (&any, &c_obj);
683 spi_init_any_nil (&any);
686 else if (strcmp (prop_name, "accessible-table-row-header") == 0)
688 i = g_value_get_int (&(values->new_value));
689 ao = atk_table_get_row_header (ATK_TABLE (gobject), i);
692 s_ao = spi_accessible_new (ao);
693 c_obj = BONOBO_OBJREF (s_ao);
694 spi_init_any_object (&any, &c_obj);
698 spi_init_any_nil (&any);
701 else if (strcmp (prop_name, "accessible-table-row-description") == 0)
703 i = g_value_get_int (&(values->new_value));
704 sp = atk_table_get_row_description (ATK_TABLE (gobject), i);
705 spi_init_any_string (&any, (gchar **)&sp);
707 else if (strcmp (prop_name, "accessible-table-column-description") == 0)
709 i = g_value_get_int (&(values->new_value));
710 sp = atk_table_get_column_description (ATK_TABLE (gobject), i);
711 spi_init_any_string (&any, (gchar **)&sp);
713 else if (strcmp (prop_name, "accessible-table-caption-object") == 0)
715 ao = atk_table_get_caption (ATK_TABLE (gobject));
716 sp = atk_object_get_name (ao);
717 spi_init_any_string (&any, (gchar **)&sp);
721 spi_init_any_nil (&any);
724 spi_atk_emit_eventv (gobject, 0, 0, &any,
725 "object:property-change:%s", prop_name);
732 spi_atk_bridge_state_event_listener (GSignalInvocationHint *signal_hint,
733 guint n_param_values,
734 const GValue *param_values,
738 gchar *property_name;
740 unsigned long detail1;
741 #ifdef SPI_BRIDGE_DEBUG
742 GSignalQuery signal_query;
745 g_signal_query (signal_hint->signal_id, &signal_query);
746 name = signal_query.signal_name;
747 fprintf (stderr, "Received (state) signal %s:%s\n",
748 g_type_name (signal_query.itype), name);
751 gobject = g_value_get_object (param_values + 0);
752 property_name = g_strdup (g_value_get_string (param_values + 1));
753 detail1 = (g_value_get_boolean (param_values + 2))
755 type = g_strdup_printf ("object:state-changed:%s", property_name);
756 spi_atk_emit_eventv (gobject,
761 g_free (property_name);
767 spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke,
768 AtkKeyEventStruct *event)
773 g_print ("event %c (%d)\n", (int) event->keyval, (int) event->keycode);
779 g_print (_("WARNING: NULL key event reported."));
782 keystroke->id = (CORBA_long) event->keyval;
783 keystroke->hw_code = (CORBA_short) event->keycode;
784 keystroke->timestamp = (CORBA_unsigned_long) event->timestamp;
785 keystroke->modifiers = (CORBA_unsigned_short) (event->state & 0xFFFF);
790 keystroke->event_string = CORBA_string_dup (event->string);
791 c = g_utf8_get_char_validated (event->string, -1);
792 if (c > 0 && g_unichar_isprint (c))
793 keystroke->is_text = CORBA_TRUE;
795 keystroke->is_text = CORBA_FALSE;
799 keystroke->event_string = CORBA_string_dup ("");
800 keystroke->is_text = CORBA_FALSE;
804 case (ATK_KEY_EVENT_PRESS):
805 keystroke->type = Accessibility_KEY_PRESSED_EVENT;
807 case (ATK_KEY_EVENT_RELEASE):
808 keystroke->type = Accessibility_KEY_RELEASED_EVENT;
815 g_print ("key_event type %d; val=%d code=%d modifiers=%x name=%s is_text=%d, time=%lx\n",
816 (int) keystroke->type, (int) keystroke->id, (int) keystroke->hw_code,
817 (int) keystroke->modifiers,
818 keystroke->event_string, (int) keystroke->is_text, (unsigned long) keystroke->timestamp);
823 spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data)
825 CORBA_boolean result;
826 Accessibility_DeviceEvent key_event;
828 CORBA_exception_init (&ev);
830 spi_init_keystroke_from_atk_key_event (&key_event, event);
832 result = Accessibility_DeviceEventController_notifyListenersSync (
833 spi_atk_bridget_get_dec (), &key_event, &ev);
835 CORBA_exception_free (&ev);
841 spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint,
842 guint n_param_values,
843 const GValue *param_values,
847 GSignalQuery signal_query;
855 gint detail1 = 0, detail2 = 0;
856 SpiAccessible *s_ao = NULL;
857 #ifdef SPI_BRIDGE_DEBUG
861 g_signal_query (signal_hint->signal_id, &signal_query);
863 name = signal_query.signal_name;
864 if (signal_hint->detail)
865 detail = g_quark_to_string (signal_hint->detail);
869 #ifdef SPI_BRIDGE_DEBUG
870 s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0)));
871 s = atk_object_get_name (ATK_OBJECT (g_value_get_object (param_values + 0)));
872 fprintf (stderr, "Received signal %s:%s detail: %s from object %s (gail %s)\n",
873 g_type_name (signal_query.itype), name,
874 detail ? detail : "<NULL>", s ? s : "<NULL>" , s2);
877 gobject = g_value_get_object (param_values + 0);
879 if (signal_query.signal_id == atk_signal_active_descendant_changed)
881 gpointer child = g_value_get_pointer (param_values + 1);
883 g_return_val_if_fail (ATK_IS_OBJECT (child), TRUE);
885 ao = ATK_OBJECT (child);
887 detail1 = atk_object_get_index_in_parent (ao);
888 s_ao = spi_accessible_new (ao);
889 c_obj = BONOBO_OBJREF (s_ao);
890 spi_init_any_object (&any, &c_obj);
892 else if (signal_query.signal_id == atk_signal_link_selected)
894 if (G_VALUE_TYPE (param_values + 1) == G_TYPE_INT)
895 detail1 = g_value_get_int (param_values + 1);
896 spi_init_any_nil (&any);
898 else if ((signal_query.signal_id == atk_signal_children_changed) && gobject)
900 ao = atk_object_ref_accessible_child (ATK_OBJECT (gobject),
904 s_ao = spi_accessible_new (ao);
905 c_obj = BONOBO_OBJREF (s_ao);
906 spi_init_any_object (&any, &c_obj);
911 spi_init_any_nil (&any);
916 if (n_param_values >= 2)
918 if (G_VALUE_TYPE (param_values + 1) == G_TYPE_INT)
919 detail1 = g_value_get_int (param_values + 1);
920 if (n_param_values >= 3)
922 if (G_VALUE_TYPE (param_values + 2) == G_TYPE_INT)
923 detail2 = g_value_get_int (param_values + 2);
927 if (signal_query.signal_id == atk_signal_text_changed)
929 sp = atk_text_get_text (ATK_TEXT (gobject),
932 spi_init_any_string (&any, &sp);
934 else if (signal_query.signal_id == atk_signal_text_selection_changed)
936 text = ATK_TEXT (gobject);
938 /* Return NULL as the selected string */
939 spi_init_any_nil (&any);
943 spi_init_any_nil (&any);
948 spi_atk_emit_eventv (gobject, detail1, detail2, &any,
949 "object:%s:%s", name, detail);
951 spi_atk_emit_eventv (gobject, detail1, detail2, &any,
961 spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint,
962 guint n_param_values,
963 const GValue *param_values,
967 GSignalQuery signal_query;
969 const gchar *name, *s;
970 #ifdef SPI_BRIDGE_DEBUG
974 g_signal_query (signal_hint->signal_id, &signal_query);
976 name = signal_query.signal_name;
978 #ifdef SPI_BRIDGE_DEBUG
979 s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0)));
980 s = atk_object_get_name (ATK_OBJECT (g_value_get_object (param_values + 0)));
981 fprintf (stderr, "Received signal %s:%s from object %s (gail %s)\n",
982 g_type_name (signal_query.itype), name, s ? s : "<NULL>" , s2);
985 gobject = g_value_get_object (param_values + 0);
987 s = atk_object_get_name (ATK_OBJECT (gobject));
988 spi_init_any_string (&any, (char **) &s);
990 spi_atk_emit_eventv (gobject, 0, 0, &any,
996 spi_atk_tidy_windows (void)
1002 root = atk_get_root ();
1003 n_children = atk_object_get_n_accessible_children (root);
1004 for (i = 0; i < n_children; i++)
1007 AtkStateSet *stateset;
1011 child = atk_object_ref_accessible_child (root, i);
1012 stateset = atk_object_ref_state_set (child);
1014 name = atk_object_get_name (child);
1015 spi_init_any_string (&any, (char**) &name);
1016 if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE))
1018 spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:deactivate");
1022 spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:destroy");
1023 g_object_unref (child);
1028 reinit_register_vars (void)
1030 registry = CORBA_OBJECT_NIL;
1031 device_event_controller = CORBA_OBJECT_NIL;