static void gail_focus_notify (GtkWidget *widget) { AtkObject *atk_obj; gboolean transient; if (widget != _focus_widget) { if (_focus_widget) { void *vp_focus_widget = &_focus_widget; g_object_remove_weak_pointer (G_OBJECT (_focus_widget), vp_focus_widget); } _focus_widget = widget; if (_focus_widget) { void *vp_focus_widget = &_focus_widget; g_object_add_weak_pointer (G_OBJECT (_focus_widget), vp_focus_widget); /* * The UI may not have been updated yet; e.g. in gtkhtml2 * html_view_layout() is called in a idle handler */ if (_focus_widget == focus_before_menu) { void *vp_focus_before_menu = &focus_before_menu; g_object_remove_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu); focus_before_menu = NULL; } } gail_focus_notify_when_idle (_focus_widget); } else { if (_focus_widget) atk_obj = get_accessible_for_widget (_focus_widget, &transient); else atk_obj = NULL; /* * Do not report focus on redundant object */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS; if (atk_obj && (atk_object_get_role(atk_obj) != ATK_ROLE_REDUNDANT_OBJECT)) atk_focus_tracker_notify (atk_obj); G_GNUC_END_IGNORE_DEPRECATIONS; if (atk_obj && transient) g_object_unref (atk_obj); if (subsequent_focus_widget) { GtkWidget *tmp_widget = subsequent_focus_widget; subsequent_focus_widget = NULL; gail_focus_notify_when_idle (tmp_widget); } } }
static gboolean gail_deselect_watcher (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer data) { GObject *object; GtkWidget *widget; GtkWidget *menu_shell; object = g_value_get_object (param_values + 0); g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE); widget = GTK_WIDGET (object); if (!GTK_IS_MENU_ITEM (widget)) return TRUE; if (subsequent_focus_widget == widget) subsequent_focus_widget = NULL; menu_shell = gtk_widget_get_parent (widget); if (GTK_IS_MENU_SHELL (menu_shell)) { GtkWidget *parent_menu_shell; parent_menu_shell = gtk_menu_shell_get_parent_shell (GTK_MENU_SHELL (menu_shell)); if (parent_menu_shell) { GtkWidget *active_menu_item; active_menu_item = gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (parent_menu_shell)); if (active_menu_item) { gail_focus_notify_when_idle (active_menu_item); } } else { if (!GTK_IS_MENU_BAR (menu_shell)) { gail_focus_notify_when_idle (menu_shell); } } } was_deselect = TRUE; return TRUE; }
static gboolean gail_switch_page_watcher (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer data) { GObject *object; GtkWidget *widget; GtkNotebook *notebook; object = g_value_get_object (param_values + 0); g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE); widget = GTK_WIDGET (object); if (!GTK_IS_NOTEBOOK (widget)) return TRUE; notebook = GTK_NOTEBOOK (widget); if (!notebook->focus_tab) return TRUE; gail_focus_notify_when_idle (widget); return TRUE; }
static gboolean gail_deactivate_watcher (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer data) { GObject *object; GtkWidget *widget; GtkMenuShell *shell; GtkWidget *focus = NULL; object = g_value_get_object (param_values + 0); g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE); widget = GTK_WIDGET (object); g_return_val_if_fail (GTK_IS_MENU_SHELL(widget), TRUE); shell = GTK_MENU_SHELL(widget); if (! gtk_menu_shell_get_parent_shell (shell)) focus = focus_before_menu; /* * If we are waiting to report focus on a menubar or a menu item * because of a previous deselect, cancel it. */ if (was_deselect && focus_notify_handler && next_focus_widget && (GTK_IS_MENU_BAR (next_focus_widget) || GTK_IS_MENU_ITEM (next_focus_widget))) { void *vp_next_focus_widget = &next_focus_widget; g_source_remove (focus_notify_handler); g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget); next_focus_widget = NULL; focus_notify_handler = 0; was_deselect = FALSE; } gail_focus_notify_when_idle (focus); return TRUE; }
static void gail_finish_select (GtkWidget *widget) { if (GTK_IS_MENU_ITEM (widget)) { GtkMenuItem* menu_item; GtkWidget *submenu; menu_item = GTK_MENU_ITEM (widget); submenu = gtk_menu_item_get_submenu (menu_item); if (submenu && !gtk_widget_get_mapped (submenu)) { /* * If the submenu is not visble, wait until it is before * reporting focus on the menu item. */ gulong handler_id; handler_id = g_signal_handler_find (submenu, G_SIGNAL_MATCH_FUNC, g_signal_lookup ("map", GTK_TYPE_WINDOW), 0, NULL, (gpointer) gail_map_submenu_cb, NULL); if (!handler_id) g_signal_connect (submenu, "map", G_CALLBACK (gail_map_submenu_cb), NULL); return; } /* * If we are waiting to report focus on a menubar or a menu item * because of a previous deselect, cancel it. */ if (was_deselect && focus_notify_handler && next_focus_widget && (GTK_IS_MENU_BAR (next_focus_widget) || GTK_IS_MENU_ITEM (next_focus_widget))) { void *vp_next_focus_widget = &next_focus_widget; g_source_remove (focus_notify_handler); g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget); next_focus_widget = NULL; focus_notify_handler = 0; was_deselect = FALSE; } } /* * If previously focused widget is not a GtkMenuItem or a GtkMenu, * keep track of it so we can return to it after menubar is deactivated */ if (_focus_widget && !GTK_IS_MENU_ITEM (_focus_widget) && !GTK_IS_MENU (_focus_widget)) { void *vp_focus_before_menu = &focus_before_menu; focus_before_menu = _focus_widget; g_object_add_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu); } gail_focus_notify_when_idle (widget); return; }
static gboolean gail_focus_watcher (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer data) { GObject *object; GtkWidget *widget; GdkEvent *event; object = g_value_get_object (param_values + 0); g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE); event = g_value_get_boxed (param_values + 1); widget = GTK_WIDGET (object); if (event->type == GDK_FOCUS_CHANGE) { if (event->focus_change.in) { if (GTK_IS_WINDOW (widget)) { GtkWidget *focus_widget; GtkWindow *window; GtkWindowType type; window = GTK_WINDOW (widget); focus_widget = gtk_window_get_focus (window); g_object_get (window, "type", &type, NULL); if (focus_widget) { /* * If we already have a potential focus widget set this * windows's focus widget to focus_before_menu so that * it will be reported when menu item is unset. */ if (next_focus_widget) { if (GTK_IS_MENU_ITEM (next_focus_widget) && !focus_before_menu) { void *vp_focus_before_menu = &focus_before_menu; focus_before_menu = focus_widget; g_object_add_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu); } return TRUE; } widget = focus_widget; } else if (type == GTK_WINDOW_POPUP) { if (GTK_IS_BIN (widget)) { GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); if (GTK_IS_WIDGET (child) && gtk_widget_has_grab (child)) { if (GTK_IS_MENU_SHELL (child)) { if (gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (child))) { /* * We have a menu which has a menu item selected * so we do not report focus on the menu. */ return TRUE; } } widget = child; } } else /* popup window has no children; this edge case occurs in some custom code (OOo for instance) */ { return TRUE; } } else /* Widget is a non-popup toplevel with no focus children; don't emit for this case either, as it's useless */ { return TRUE; } } } else { if (next_focus_widget) { GtkWidget *toplevel; toplevel = gtk_widget_get_toplevel (next_focus_widget); if (toplevel == widget) next_focus_widget = NULL; } /* focus out */ widget = NULL; } } else { if (event->type == GDK_MOTION_NOTIFY && gtk_widget_has_focus (widget)) { if (widget == _focus_widget) { return TRUE; } } else { return TRUE; } } #ifdef GDK_WINDOWING_X11 /* * If the focus widget is a GtkSocket without a plug * then ignore the focus notification as the embedded * plug will report a focus notification. */ if (GTK_IS_SOCKET (widget) && gtk_socket_get_plug_window (GTK_SOCKET (widget)) != NULL) return TRUE; #endif /* * The widget may not yet be visible on the screen so we wait until it is. */ gail_focus_notify_when_idle (widget); return TRUE; }