X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-bridge%2Fbridge.c;h=1d3c73250845cf340e1e896a9c612c6fc44d66d3;hb=8228cc05105506c3bcfb5a88ff38165c55c89ecc;hp=b1666da30e944e60da9fde7edc62bb2383143af3;hpb=0210eb491dc2d3e704e3fad467c5398c5b822d5f;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index b1666da..1d3c732 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -21,6 +21,7 @@ * Boston, MA 02111-1307, USA. */ +#include #include #include #include @@ -47,25 +48,14 @@ static Accessibility_DeviceEventController device_event_controller = CORBA_OBJEC static SpiApplication *this_app = NULL; static gboolean registry_died = FALSE; static gboolean atk_listeners_registered = FALSE; -static guint toplevel_handler; - -/* NOT YET USED - static GQuark atk_quark_property_changed_name; - static GQuark atk_quark_property_changed_description; - static GQuark atk_quark_property_changed_parent; - static GQuark atk_quark_property_changed_role; - static GQuark atk_quark_property_changed_table_caption; - static GQuark atk_quark_property_changed_table_column_description; - static GQuark atk_quark_property_changed_table_row_description; - static guint atk_signal_property_changed; -*/ +static gint toplevels = 0; static guint atk_signal_text_changed; -static guint atk_signal_child_changed; +static guint atk_signal_children_changed; static guint atk_signal_active_descendant_changed; +static guint atk_signal_text_selection_changed; /* NOT YET USED - static guint atk_signal_text_selection_changed; static guint atk_signal_row_reordered; static guint atk_signal_row_inserted; static guint atk_signal_row_deleted; @@ -81,9 +71,13 @@ static void spi_atk_bridge_do_registration (void); static void spi_atk_bridge_toplevel_added (AtkObject *object, guint index, AtkObject *child); +static void spi_atk_bridge_toplevel_removed (AtkObject *object, + guint index, + AtkObject *child); static void spi_atk_bridge_exit_func (void); static void spi_atk_register_event_listeners (void); +static void spi_atk_deregister_event_listeners (void); static void spi_atk_bridge_focus_tracker (AtkObject *object); static void spi_atk_bridge_register_application (Accessibility_Registry registry); static gboolean spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, @@ -106,6 +100,9 @@ static gboolean spi_atk_bridge_signal_listener (GSignalInvocationHint *s gpointer data); static gint spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data); +static void spi_atk_tidy_windows (void); +static void deregister_application (BonoboObject *app); +static void reinit_register_vars (void); /* For automatic libgnome init */ extern void gnome_accessibility_module_init (void); @@ -126,7 +123,12 @@ extern void gnome_accessibility_module_shutdown (void); static void spi_atk_bridge_init_event_type_consts () { - atk_signal_child_changed = g_signal_lookup ("child_changed", + static gboolean done = FALSE; + + if (done) + return; + + atk_signal_children_changed = g_signal_lookup ("children_changed", ATK_TYPE_OBJECT); atk_signal_text_changed = g_signal_lookup ("text_changed", ATK_TYPE_TEXT); @@ -135,6 +137,9 @@ spi_atk_bridge_init_event_type_consts () ATK_TYPE_OBJECT); atk_signal_link_selected = g_signal_lookup ("link_selected", ATK_TYPE_HYPERTEXT); + atk_signal_text_selection_changed = g_signal_lookup ("text_selection_changed", + ATK_TYPE_TEXT); + done = TRUE; } static int @@ -165,18 +170,21 @@ atk_bridge_init (gint *argc, gchar **argv[]) if (bonobo_activation_iid_get ()) { DBG (1, g_message ("Found Bonobo component\n")); - toplevel_handler = g_signal_connect (atk_get_root (), - "children-changed::add", - (GCallback) spi_atk_bridge_toplevel_added, - NULL); + g_signal_connect (atk_get_root (), + "children-changed::add", + (GCallback) spi_atk_bridge_toplevel_added, + NULL); + g_signal_connect (atk_get_root (), + "children-changed::remove", + (GCallback) spi_atk_bridge_toplevel_removed, + NULL); } else { spi_atk_bridge_do_registration (); + spi_atk_bridge_init_event_type_consts (); } - spi_atk_bridge_init_event_type_consts (); - return 0; } @@ -214,8 +222,33 @@ spi_atk_bridge_toplevel_added (AtkObject *object, guint index, AtkObject *child) { - g_signal_handler_disconnect (object, toplevel_handler); - spi_atk_bridge_do_registration (); + if (toplevels == 0) + { + spi_atk_bridge_do_registration (); + spi_atk_bridge_init_event_type_consts (); + } + toplevels++; +} + +static void +spi_atk_bridge_toplevel_removed (AtkObject *object, + guint index, + AtkObject *child) +{ + BonoboObject *app = (BonoboObject *) this_app; + + toplevels--; + if (toplevels == 0) + { + deregister_application (app); + spi_atk_deregister_event_listeners (); + reinit_register_vars (); + } + if (toplevels < 0) + { + g_warning ("More toplevels removed than added\n"); + toplevels = 0; + } } static void @@ -232,7 +265,7 @@ spi_atk_bridge_get_registry (void) { CORBA_Environment ev; - if (registry_died || (registry == NULL)) { + if (registry_died || (registry == CORBA_OBJECT_NIL)) { CORBA_exception_init (&ev); if (registry_died) DBG (1, g_warning ("registry died! restarting...")); @@ -379,6 +412,32 @@ spi_atk_register_event_listeners (void) } static void +spi_atk_deregister_event_listeners (void) +{ + gint i; + guint id; + + if (!atk_listeners_registered) + return; + + atk_listeners_registered = FALSE; + + for (i = 0; i < listener_ids->len; i++) + { + id = g_array_index (listener_ids, guint, i); + atk_remove_global_event_listener (id); + } + g_array_free (listener_ids, TRUE); + listener_ids = NULL; + + atk_remove_focus_tracker (atk_bridge_focus_tracker_id); + atk_bridge_focus_tracker_id = 0; + + atk_remove_key_event_listener (atk_bridge_key_event_listener_id); + atk_bridge_key_event_listener_id = 0; +} + +static void deregister_application (BonoboObject *app) { Accessibility_Registry registry = spi_atk_bridge_get_registry (); @@ -404,6 +463,10 @@ spi_atk_bridge_exit_func (void) this_app = NULL; /* + * Check whether we still have windows which have not been deleted. + */ + spi_atk_tidy_windows (); + /* * FIXME: this may be incorrect for apps that do their own bonobo * shutdown, until we can explicitly shutdown to get the ordering * right. @@ -566,6 +629,13 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, { AtkPropertyValues *values; GObject *gobject; + const gchar *prop_name; + CORBA_any any; + const gchar *sp = NULL; + AtkObject *ao; + SpiAccessible *s_ao = NULL; + CORBA_Object c_obj; + gint i; #ifdef SPI_BRIDGE_DEBUG GSignalQuery signal_query; @@ -586,8 +656,101 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, gobject = g_value_get_object (param_values + 0); values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1); - spi_atk_emit_eventv (gobject, 0, 0, NULL, - "object:property-change:%s", values->property_name); + prop_name = values->property_name; + if (strcmp (prop_name, "accessible-name") == 0) + { + sp = atk_object_get_name (ATK_OBJECT (gobject)); + spi_init_any_string (&any, (gchar **)&sp); + } + else if (strcmp (prop_name, "accessible-description") == 0) + { + sp = atk_object_get_description (ATK_OBJECT (gobject)); + spi_init_any_string (&any, (gchar **)&sp); + } + else if (strcmp (prop_name, "accessible-parent") == 0) + { + ao = atk_object_get_parent (ATK_OBJECT (gobject)); + if (ao) + { + s_ao = spi_accessible_new (ao); + c_obj = BONOBO_OBJREF (s_ao); + spi_init_any_object (&any, &c_obj); + } + else + { + spi_init_any_nil (&any); + } + } + else if (strcmp (prop_name, "accessible-table-summary") == 0) + { + ao = atk_table_get_summary (ATK_TABLE (gobject)); + if (ao) + { + s_ao = spi_accessible_new (ao); + c_obj = BONOBO_OBJREF (s_ao); + spi_init_any_object (&any, &c_obj); + } + else + { + spi_init_any_nil (&any); + } + } + else if (strcmp (prop_name, "accessible-table-column-header") == 0) + { + i = g_value_get_int (&(values->new_value)); + ao = atk_table_get_column_header (ATK_TABLE (gobject), i); + if (ao) + { + s_ao = spi_accessible_new (ao); + c_obj = BONOBO_OBJREF (s_ao); + spi_init_any_object (&any, &c_obj); + } + else + { + spi_init_any_nil (&any); + } + } + else if (strcmp (prop_name, "accessible-table-row-header") == 0) + { + i = g_value_get_int (&(values->new_value)); + ao = atk_table_get_row_header (ATK_TABLE (gobject), i); + if (ao) + { + s_ao = spi_accessible_new (ao); + c_obj = BONOBO_OBJREF (s_ao); + spi_init_any_object (&any, &c_obj); + } + else + { + spi_init_any_nil (&any); + } + } + else if (strcmp (prop_name, "accessible-table-row-description") == 0) + { + i = g_value_get_int (&(values->new_value)); + sp = atk_table_get_row_description (ATK_TABLE (gobject), i); + spi_init_any_string (&any, (gchar **)&sp); + } + else if (strcmp (prop_name, "accessible-table-column-description") == 0) + { + i = g_value_get_int (&(values->new_value)); + sp = atk_table_get_column_description (ATK_TABLE (gobject), i); + spi_init_any_string (&any, (gchar **)&sp); + } + else if (strcmp (prop_name, "accessible-table-caption-object") == 0) + { + ao = atk_table_get_caption (ATK_TABLE (gobject)); + sp = atk_object_get_name (ao); + spi_init_any_string (&any, (gchar **)&sp); + } + else + { + spi_init_any_nil (&any); + } + + spi_atk_emit_eventv (gobject, 0, 0, &any, + "object:property-change:%s", prop_name); + return TRUE; } @@ -649,8 +812,14 @@ spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke, keystroke->modifiers = (CORBA_unsigned_short) (event->state & 0xFFFF); if (event->string) { + gunichar c; + keystroke->event_string = CORBA_string_dup (event->string); - keystroke->is_text = CORBA_TRUE; + c = g_utf8_get_char_validated (event->string, -1); + if (c > 0 && g_unichar_isprint (c)) + keystroke->is_text = CORBA_TRUE; + else + keystroke->is_text = CORBA_FALSE; } else { @@ -709,6 +878,7 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, CORBA_Object c_obj; char *sp = NULL; AtkObject *ao; + AtkText *text; gint detail1 = 0, detail2 = 0; SpiAccessible *s_ao = NULL; #ifdef SPI_BRIDGE_DEBUG @@ -752,12 +922,34 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, detail1 = g_value_get_int (param_values + 1); spi_init_any_nil (&any); } + else if ((signal_query.signal_id == atk_signal_children_changed) && gobject) + { + ao = atk_object_ref_accessible_child (ATK_OBJECT (gobject), + detail1); + if (ao) + { + s_ao = spi_accessible_new (ao); + c_obj = BONOBO_OBJREF (s_ao); + spi_init_any_object (&any, &c_obj); + g_object_unref (ao); + } + else + { + spi_init_any_nil (&any); + } + } else { - if (G_VALUE_TYPE (param_values + 1) == G_TYPE_INT) - detail1 = g_value_get_int (param_values + 1); - if (G_VALUE_TYPE (param_values + 2) == G_TYPE_INT) - detail2 = g_value_get_int (param_values + 2); + if (n_param_values >= 2) + { + if (G_VALUE_TYPE (param_values + 1) == G_TYPE_INT) + detail1 = g_value_get_int (param_values + 1); + if (n_param_values >= 3) + { + if (G_VALUE_TYPE (param_values + 2) == G_TYPE_INT) + detail2 = g_value_get_int (param_values + 2); + } + } if (signal_query.signal_id == atk_signal_text_changed) { @@ -766,21 +958,12 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, detail1+detail2); spi_init_any_string (&any, &sp); } - else if ((signal_query.signal_id == atk_signal_child_changed) && gobject) + else if (signal_query.signal_id == atk_signal_text_selection_changed) { - ao = atk_object_ref_accessible_child (ATK_OBJECT (gobject), - detail1); - if (ao) - { - s_ao = spi_accessible_new (ao); - c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); - g_object_unref (ao); - } - else - { - spi_init_any_nil (&any); - } + text = ATK_TEXT (gobject); + + /* Return NULL as the selected string */ + spi_init_any_nil (&any); } else { @@ -835,3 +1018,44 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, "window:%s", name); return TRUE; } + +static void +spi_atk_tidy_windows (void) +{ + AtkObject *root; + gint n_children; + gint i; + + root = atk_get_root (); + n_children = atk_object_get_n_accessible_children (root); + for (i = 0; i < n_children; i++) + { + AtkObject *child; + AtkStateSet *stateset; + CORBA_any any; + const gchar *name; + + child = atk_object_ref_accessible_child (root, i); + stateset = atk_object_ref_state_set (child); + + name = atk_object_get_name (child); + spi_init_any_string (&any, (char**) &name); + if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE)) + { + spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:deactivate"); + } + g_free (stateset); + + spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:destroy"); + g_object_unref (child); + } +} + +static void +reinit_register_vars (void) +{ + registry = CORBA_OBJECT_NIL; + device_event_controller = CORBA_OBJECT_NIL; + this_app = NULL; +} +