X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-bridge%2Fbridge.c;h=1d3c73250845cf340e1e896a9c612c6fc44d66d3;hb=8228cc05105506c3bcfb5a88ff38165c55c89ecc;hp=e5266a09c7012c519e2b069fe3636b6e278b1c38;hpb=5e9de4f03f0c4406e3479d50a012901e87642210;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index e5266a0..1d3c732 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -48,7 +48,7 @@ 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; +static gint toplevels = 0; static guint atk_signal_text_changed; static guint atk_signal_children_changed; @@ -71,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, @@ -96,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); @@ -116,6 +123,11 @@ extern void gnome_accessibility_module_shutdown (void); static void spi_atk_bridge_init_event_type_consts () { + 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", @@ -127,6 +139,7 @@ spi_atk_bridge_init_event_type_consts () ATK_TYPE_HYPERTEXT); atk_signal_text_selection_changed = g_signal_lookup ("text_selection_changed", ATK_TYPE_TEXT); + done = TRUE; } static int @@ -157,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; } @@ -206,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 @@ -224,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...")); @@ -371,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 (); @@ -396,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. @@ -947,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; +} +