/* GAIL - The GNOME Accessibility Implementation Library * Copyright 2001, 2002, 2003 Sun Microsystems Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include #include #include "gailwindow.h" #include "gailtoplevel.h" #include "gail-private-macros.h" enum { ACTIVATE, CREATE, DEACTIVATE, DESTROY, MAXIMIZE, MINIMIZE, MOVE, RESIZE, RESTORE, LAST_SIGNAL }; static void gail_window_class_init (GailWindowClass *klass); static void gail_window_init (GailWindow *accessible); static void gail_window_real_initialize (AtkObject *obj, gpointer data); static void gail_window_finalize (GObject *object); static const gchar* gail_window_get_name (AtkObject *accessible); static AtkObject* gail_window_get_parent (AtkObject *accessible); static gint gail_window_get_index_in_parent (AtkObject *accessible); static gboolean gail_window_real_focus_gtk (GtkWidget *widget, GdkEventFocus *event); static AtkStateSet* gail_window_ref_state_set (AtkObject *accessible); static AtkRelationSet* gail_window_ref_relation_set (AtkObject *accessible); static void gail_window_real_notify_gtk (GObject *obj, GParamSpec *pspec); static gint gail_window_get_mdi_zorder (AtkComponent *component); static gboolean gail_window_state_event_gtk (GtkWidget *widget, GdkEventWindowState *event); /* atkcomponent.h */ static void atk_component_interface_init (AtkComponentIface *iface); static void gail_window_get_extents (AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type); static void gail_window_get_size (AtkComponent *component, gint *width, gint *height); static guint gail_window_signals [LAST_SIGNAL] = { 0, }; G_DEFINE_TYPE_WITH_CODE (GailWindow, gail_window, GAIL_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init)) static void gail_window_class_init (GailWindowClass *klass) { GailWidgetClass *widget_class; GObjectClass *gobject_class = G_OBJECT_CLASS (klass); AtkObjectClass *class = ATK_OBJECT_CLASS (klass); gobject_class->finalize = gail_window_finalize; widget_class = (GailWidgetClass*)klass; widget_class->focus_gtk = gail_window_real_focus_gtk; widget_class->notify_gtk = gail_window_real_notify_gtk; class->get_name = gail_window_get_name; class->get_parent = gail_window_get_parent; class->get_index_in_parent = gail_window_get_index_in_parent; class->ref_relation_set = gail_window_ref_relation_set; class->ref_state_set = gail_window_ref_state_set; class->initialize = gail_window_real_initialize; gail_window_signals [ACTIVATE] = g_signal_new ("activate", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [CREATE] = g_signal_new ("create", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [DEACTIVATE] = g_signal_new ("deactivate", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [DESTROY] = g_signal_new ("destroy", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [MAXIMIZE] = g_signal_new ("maximize", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [MINIMIZE] = g_signal_new ("minimize", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [MOVE] = g_signal_new ("move", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [RESIZE] = g_signal_new ("resize", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gail_window_signals [RESTORE] = g_signal_new ("restore", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, /* default signal handler */ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void gail_window_init (GailWindow *accessible) { } static void gail_window_real_initialize (AtkObject *obj, gpointer data) { GtkWidget *widget = GTK_WIDGET (data); GailWindow *window; /* * A GailWindow can be created for a GtkHandleBox or a GtkWindow */ if (!GTK_IS_WINDOW (widget) && !GTK_IS_HANDLE_BOX (widget)) gail_return_if_fail (FALSE); ATK_OBJECT_CLASS (gail_window_parent_class)->initialize (obj, data); window = GAIL_WINDOW (obj); window->name_change_handler = 0; window->previous_name = g_strdup (gtk_window_get_title (GTK_WINDOW (data))); g_signal_connect (data, "window_state_event", G_CALLBACK (gail_window_state_event_gtk), NULL); g_object_set_data (G_OBJECT (obj), "atk-component-layer", GINT_TO_POINTER (ATK_LAYER_WINDOW)); if (GTK_IS_FILE_CHOOSER_DIALOG (widget)) obj->role = ATK_ROLE_FILE_CHOOSER; else if (GTK_IS_COLOR_SELECTION_DIALOG (widget)) obj->role = ATK_ROLE_COLOR_CHOOSER; else if (GTK_IS_FONT_SELECTION_DIALOG (widget)) obj->role = ATK_ROLE_FONT_CHOOSER; else if (GTK_IS_MESSAGE_DIALOG (widget)) obj->role = ATK_ROLE_ALERT; else if (GTK_IS_DIALOG (widget)) obj->role = ATK_ROLE_DIALOG; else { const gchar *name; name = gtk_widget_get_name (widget); if (!g_strcmp0 (name, "gtk-tooltip")) obj->role = ATK_ROLE_TOOL_TIP; #ifdef GDK_WINDOWING_X11 else if (GTK_IS_PLUG (widget)) obj->role = ATK_ROLE_PANEL; #endif else if (gtk_window_get_window_type (GTK_WINDOW (widget)) == GTK_WINDOW_POPUP) obj->role = ATK_ROLE_WINDOW; else obj->role = ATK_ROLE_FRAME; } /* * Notify that tooltip is showing */ if (obj->role == ATK_ROLE_TOOL_TIP && gtk_widget_get_mapped (widget)) atk_object_notify_state_change (obj, ATK_STATE_SHOWING, 1); } static void gail_window_finalize (GObject *object) { GailWindow* window = GAIL_WINDOW (object); if (window->name_change_handler) { g_source_remove (window->name_change_handler); window->name_change_handler = 0; } if (window->previous_name) { g_free (window->previous_name); window->previous_name = NULL; } G_OBJECT_CLASS (gail_window_parent_class)->finalize (object); } static const gchar* gail_window_get_name (AtkObject *accessible) { const gchar* name; name = ATK_OBJECT_CLASS (gail_window_parent_class)->get_name (accessible); if (name == NULL) { /* * Get the window title if it exists */ GtkWidget* widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (widget == NULL) /* * State is defunct */ return NULL; gail_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); if (GTK_IS_WINDOW (widget)) { GtkWindow *window = GTK_WINDOW (widget); name = gtk_window_get_title (window); if (name == NULL && accessible->role == ATK_ROLE_TOOL_TIP) { GtkWidget *child; child = gtk_bin_get_child (GTK_BIN (window)); /* could be some kind of egg notification bubble thingy? */ /* Handle new GTK+ GNOME 2.20 tooltips */ if (GTK_IS_ALIGNMENT(child)) { child = gtk_bin_get_child (GTK_BIN (child)); if (GTK_IS_BOX(child)) { GList *children; guint count; children = gtk_container_get_children (GTK_CONTAINER (child)); count = g_list_length (children); if (count == 2) { child = (GtkWidget *) g_list_nth_data (children, 1); } g_list_free (children); } } if (!GTK_IS_LABEL (child)) { g_message ("ATK_ROLE_TOOLTIP object found, but doesn't look like a tooltip."); return NULL; } name = gtk_label_get_text (GTK_LABEL (child)); } } } return name; } static AtkObject* gail_window_get_parent (AtkObject *accessible) { AtkObject* parent; parent = ATK_OBJECT_CLASS (gail_window_parent_class)->get_parent (accessible); return parent; } static gint gail_window_get_index_in_parent (AtkObject *accessible) { GtkWidget* widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); AtkObject* atk_obj = atk_get_root (); gint index = -1; if (widget == NULL) /* * State is defunct */ return -1; gail_return_val_if_fail (GTK_IS_WIDGET (widget), -1); index = ATK_OBJECT_CLASS (gail_window_parent_class)->get_index_in_parent (accessible); if (index != -1) return index; if (GTK_IS_WINDOW (widget)) { GtkWindow *window = GTK_WINDOW (widget); if (GAIL_IS_TOPLEVEL (atk_obj)) { GailToplevel* toplevel = GAIL_TOPLEVEL (atk_obj); index = g_list_index (toplevel->window_list, window); } else { int i, sibling_count = atk_object_get_n_accessible_children (atk_obj); for (i = 0; i < sibling_count && index == -1; ++i) { AtkObject *child = atk_object_ref_accessible_child (atk_obj, i); if (accessible == child) index = i; g_object_unref (G_OBJECT (child)); } } } return index; } static gboolean gail_window_real_focus_gtk (GtkWidget *widget, GdkEventFocus *event) { AtkObject* obj; obj = gtk_widget_get_accessible (widget); atk_object_notify_state_change (obj, ATK_STATE_ACTIVE, event->in); return FALSE; } static AtkRelationSet* gail_window_ref_relation_set (AtkObject *obj) { GtkWidget *widget; AtkRelationSet *relation_set; AtkObject *array[1]; AtkRelation* relation; GtkWidget *current_widget; gail_return_val_if_fail (GAIL_IS_WIDGET (obj), NULL); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)); if (widget == NULL) /* * State is defunct */ return NULL; relation_set = ATK_OBJECT_CLASS (gail_window_parent_class)->ref_relation_set (obj); if (atk_object_get_role (obj) == ATK_ROLE_TOOL_TIP) { relation = atk_relation_set_get_relation_by_type (relation_set, ATK_RELATION_POPUP_FOR); if (relation) { atk_relation_set_remove (relation_set, relation); } if (gtk_widget_get_visible(widget) && FALSE /* FIXME gtk_tooltips_get_info_from_tip_window (GTK_WINDOW (widget), NULL, ¤t_widget) */) { array [0] = gtk_widget_get_accessible (current_widget); relation = atk_relation_new (array, 1, ATK_RELATION_POPUP_FOR); atk_relation_set_add (relation_set, relation); g_object_unref (relation); } } return relation_set; } static AtkStateSet* gail_window_ref_state_set (AtkObject *accessible) { AtkStateSet *state_set; GtkWidget *widget; GtkWindow *window; GdkWindow *gdk_window; GdkWindowState state; state_set = ATK_OBJECT_CLASS (gail_window_parent_class)->ref_state_set (accessible); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (widget == NULL) return state_set; window = GTK_WINDOW (widget); if (gtk_window_has_toplevel_focus (window) && gtk_window_is_active (window)) atk_state_set_add_state (state_set, ATK_STATE_ACTIVE); gdk_window = gtk_widget_get_window (widget); if (window) { state = gdk_window_get_state (gdk_window); if (state & GDK_WINDOW_STATE_ICONIFIED) atk_state_set_add_state (state_set, ATK_STATE_ICONIFIED); } if (gtk_window_get_modal (window)) atk_state_set_add_state (state_set, ATK_STATE_MODAL); if (gtk_window_get_resizable (window)) atk_state_set_add_state (state_set, ATK_STATE_RESIZABLE); return state_set; } static gboolean idle_notify_name_change (gpointer data) { GailWindow *window; AtkObject *obj; window = GAIL_WINDOW (data); window->name_change_handler = 0; if (gtk_accessible_get_widget (GTK_ACCESSIBLE (window)) == NULL) return FALSE; obj = ATK_OBJECT (window); if (obj->name == NULL) { /* * The title has changed so notify a change in accessible-name */ g_object_notify (G_OBJECT (obj), "accessible-name"); } g_signal_emit_by_name (obj, "visible_data_changed"); return FALSE; } static void gail_window_real_notify_gtk (GObject *obj, GParamSpec *pspec) { GtkWidget *widget = GTK_WIDGET (obj); AtkObject* atk_obj = gtk_widget_get_accessible (widget); GailWindow *window = GAIL_WINDOW (atk_obj); const gchar *name; gboolean name_changed = FALSE; if (strcmp (pspec->name, "title") == 0) { name = gtk_window_get_title (GTK_WINDOW (widget)); if (name) { if (window->previous_name == NULL || strcmp (name, window->previous_name) != 0) name_changed = TRUE; } else if (window->previous_name != NULL) name_changed = TRUE; if (name_changed) { g_free (window->previous_name); window->previous_name = g_strdup (name); if (window->name_change_handler == 0) window->name_change_handler = gdk_threads_add_idle (idle_notify_name_change, atk_obj); } } else GAIL_WIDGET_CLASS (gail_window_parent_class)->notify_gtk (obj, pspec); } static gboolean gail_window_state_event_gtk (GtkWidget *widget, GdkEventWindowState *event) { AtkObject* obj; obj = gtk_widget_get_accessible (widget); atk_object_notify_state_change (obj, ATK_STATE_ICONIFIED, (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) != 0); return FALSE; } static void atk_component_interface_init (AtkComponentIface *iface) { iface->get_extents = gail_window_get_extents; iface->get_size = gail_window_get_size; iface->get_mdi_zorder = gail_window_get_mdi_zorder; } static void gail_window_get_extents (AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type) { GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); GdkRectangle rect; gint x_toplevel, y_toplevel; if (widget == NULL) /* * State is defunct */ return; gail_return_if_fail (GTK_IS_WINDOW (widget)); if (!gtk_widget_is_toplevel (widget)) { AtkComponentIface *parent_iface; parent_iface = (AtkComponentIface *) g_type_interface_peek_parent (ATK_COMPONENT_GET_IFACE (component)); parent_iface->get_extents (component, x, y, width, height, coord_type); return; } gdk_window_get_frame_extents (gtk_widget_get_window (widget), &rect); *width = rect.width; *height = rect.height; if (!gtk_widget_is_drawable (widget)) { *x = G_MININT; *y = G_MININT; return; } *x = rect.x; *y = rect.y; if (coord_type == ATK_XY_WINDOW) { gdk_window_get_origin (gtk_widget_get_window (widget), &x_toplevel, &y_toplevel); *x -= x_toplevel; *y -= y_toplevel; } } static void gail_window_get_size (AtkComponent *component, gint *width, gint *height) { GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); GdkRectangle rect; if (widget == NULL) /* * State is defunct */ return; gail_return_if_fail (GTK_IS_WINDOW (widget)); if (!gtk_widget_is_toplevel (widget)) { AtkComponentIface *parent_iface; parent_iface = (AtkComponentIface *) g_type_interface_peek_parent (ATK_COMPONENT_GET_IFACE (component)); parent_iface->get_size (component, width, height); return; } gdk_window_get_frame_extents (gtk_widget_get_window (widget), &rect); *width = rect.width; *height = rect.height; } #if defined (GDK_WINDOWING_X11) #include #include #include /* _NET_CLIENT_LIST_STACKING monitoring */ typedef struct { Window *stacked_windows; int stacked_windows_len; GdkWindow *root_window; guint update_handler; int *desktop; guint update_desktop_handler; gboolean *desktop_changed; guint screen_initialized : 1; guint update_stacked_windows : 1; } GailScreenInfo; static GailScreenInfo *gail_screens = NULL; static int num_screens = 0; static Atom _net_client_list_stacking = None; static Atom _net_wm_desktop = None; static gint get_window_desktop (Window window) { Atom ret_type; int format; gulong nitems; gulong bytes_after; guchar *cardinals; int error; int result; int desktop; if (_net_wm_desktop == None) _net_wm_desktop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "_NET_WM_DESKTOP", False); gdk_error_trap_push (); result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), window, _net_wm_desktop, 0, G_MAXLONG, False, XA_CARDINAL, &ret_type, &format, &nitems, &bytes_after, &cardinals); error = gdk_error_trap_pop(); /* nitems < 1 will occur if the property is not set */ if (error != Success || result != Success || nitems < 1) return -1; desktop = *cardinals; XFree (cardinals); if (nitems != 1) return -1; return desktop; } static void free_screen_info (GailScreenInfo *info) { if (info->stacked_windows) XFree (info->stacked_windows); if (info->desktop) g_free (info->desktop); if (info->desktop_changed) g_free (info->desktop_changed); info->stacked_windows = NULL; info->stacked_windows_len = 0; info->desktop = NULL; info->desktop_changed = NULL; } static gboolean get_stacked_windows (GailScreenInfo *info) { Atom ret_type; int format; gulong nitems; gulong bytes_after; guchar *data; int error; int result; int i; int j; int *desktops; gboolean *desktops_changed; if (_net_client_list_stacking == None) _net_client_list_stacking = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "_NET_CLIENT_LIST_STACKING", False); gdk_error_trap_push (); ret_type = None; result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_WINDOW_XID (info->root_window), _net_client_list_stacking, 0, G_MAXLONG, False, XA_WINDOW, &ret_type, &format, &nitems, &bytes_after, &data); error = gdk_error_trap_pop (); /* nitems < 1 will occur if the property is not set */ if (error != Success || result != Success || nitems < 1) { free_screen_info (info); return FALSE; } if (ret_type != XA_WINDOW) { XFree (data); free_screen_info (info); return FALSE; } desktops = g_malloc0 (nitems * sizeof (int)); desktops_changed = g_malloc0 (nitems * sizeof (gboolean)); for (i = 0; i < nitems; i++) { gboolean window_found = FALSE; for (j = 0; j < info->stacked_windows_len; j++) { if (info->stacked_windows [j] == data [i]) { desktops [i] = info->desktop [j]; desktops_changed [i] = info->desktop_changed [j]; window_found = TRUE; break; } } if (!window_found) { desktops [i] = get_window_desktop (data [i]); desktops_changed [i] = FALSE; } } free_screen_info (info); info->stacked_windows = (Window*) data; info->stacked_windows_len = nitems; info->desktop = desktops; info->desktop_changed = desktops_changed; return TRUE; } static gboolean update_screen_info (gpointer data) { int screen_n = GPOINTER_TO_INT (data); gail_screens [screen_n].update_handler = 0; gail_screens [screen_n].update_stacked_windows = FALSE; get_stacked_windows (&gail_screens [screen_n]); return FALSE; } static gboolean update_desktop_info (gpointer data) { int screen_n = GPOINTER_TO_INT (data); GailScreenInfo *info; int i; info = &gail_screens [screen_n]; info->update_desktop_handler = 0; for (i = 0; i < info->stacked_windows_len; i++) { if (info->desktop_changed [i]) { info->desktop [i] = get_window_desktop (info->stacked_windows [i]); info->desktop_changed [i] = FALSE; } } return FALSE; } static GdkFilterReturn filter_func (GdkXEvent *gdkxevent, GdkEvent *event, gpointer data) { XEvent *xevent = gdkxevent; if (xevent->type == PropertyNotify) { if (xevent->xproperty.atom == _net_client_list_stacking) { int screen_n; GdkWindow *window; window = event->any.window; if (window) { screen_n = gdk_screen_get_number (gdk_window_get_screen (window)); gail_screens [screen_n].update_stacked_windows = TRUE; if (!gail_screens [screen_n].update_handler) { gail_screens [screen_n].update_handler = gdk_threads_add_idle (update_screen_info, GINT_TO_POINTER (screen_n)); } } } else if (xevent->xproperty.atom == _net_wm_desktop) { int i; int j; GailScreenInfo *info; for (i = 0; i < num_screens; i++) { info = &gail_screens [i]; for (j = 0; j < info->stacked_windows_len; j++) { if (xevent->xany.window == info->stacked_windows [j]) { info->desktop_changed [j] = TRUE; if (!info->update_desktop_handler) { info->update_desktop_handler = gdk_threads_add_idle (update_desktop_info, GINT_TO_POINTER (i)); } break; } } } } } return GDK_FILTER_CONTINUE; } static void display_closed (GdkDisplay *display, gboolean is_error) { int i; for (i = 0; i < num_screens; i++) { if (gail_screens [i].update_handler) { g_source_remove (gail_screens [i].update_handler); gail_screens [i].update_handler = 0; } if (gail_screens [i].update_desktop_handler) { g_source_remove (gail_screens [i].update_desktop_handler); gail_screens [i].update_desktop_handler = 0; } free_screen_info (&gail_screens [i]); } g_free (gail_screens); gail_screens = NULL; num_screens = 0; } static void init_gail_screens (void) { GdkDisplay *display; display = gdk_display_get_default (); num_screens = gdk_display_get_n_screens (display); gail_screens = g_new0 (GailScreenInfo, num_screens); gdk_window_add_filter (NULL, filter_func, NULL); g_signal_connect (display, "closed", G_CALLBACK (display_closed), NULL); } static void init_gail_screen (GdkScreen *screen, int screen_n) { XWindowAttributes attrs; gail_screens [screen_n].root_window = gdk_screen_get_root_window (screen); get_stacked_windows (&gail_screens [screen_n]); XGetWindowAttributes (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_WINDOW_XID (gail_screens [screen_n].root_window), &attrs); XSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_WINDOW_XID (gail_screens [screen_n].root_window), attrs.your_event_mask | PropertyChangeMask); gail_screens [screen_n].screen_initialized = TRUE; } static GailScreenInfo * get_screen_info (GdkScreen *screen) { int screen_n; gail_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); screen_n = gdk_screen_get_number (screen); if (gail_screens && gail_screens [screen_n].screen_initialized) return &gail_screens [screen_n]; if (!gail_screens) init_gail_screens (); g_assert (gail_screens != NULL); init_gail_screen (screen, screen_n); g_assert (gail_screens [screen_n].screen_initialized); return &gail_screens [screen_n]; } static gint get_window_zorder (GdkWindow *window) { GailScreenInfo *info; Window xid; int i; int zorder; int w_desktop; gail_return_val_if_fail (GDK_IS_WINDOW (window), -1); info = get_screen_info (gdk_window_get_screen (window)); gail_return_val_if_fail (info->stacked_windows != NULL, -1); xid = GDK_WINDOW_XID (window); w_desktop = -1; for (i = 0; i < info->stacked_windows_len; i++) { if (info->stacked_windows [i] == xid) { w_desktop = info->desktop[i]; break; } } if (w_desktop < 0) return w_desktop; zorder = 0; for (i = 0; i < info->stacked_windows_len; i++) { if (info->stacked_windows [i] == xid) { return zorder; } else { if (info->desktop[i] == w_desktop) zorder++; } } return -1; } static gint gail_window_get_mdi_zorder (AtkComponent *component) { GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); if (widget == NULL) /* * State is defunct */ return -1; gail_return_val_if_fail (GTK_IS_WINDOW (widget), -1); return get_window_zorder (gtk_widget_get_window (widget)); } #elif defined (GDK_WINDOWING_WIN32) static gint gail_window_get_mdi_zorder (AtkComponent *component) { GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); if (widget == NULL) /* * State is defunct */ return -1; gail_return_val_if_fail (GTK_IS_WINDOW (widget), -1); return 0; /* Punt, FIXME */ } #else static gint gail_window_get_mdi_zorder (AtkComponent *component) { GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); if (widget == NULL) /* * State is defunct */ return -1; gail_return_val_if_fail (GTK_IS_WINDOW (widget), -1); return 0; /* Punt, FIXME */ } #endif