gtk2/gtk/a11y/gailwindow.c
Benjamin Otte 52c0933bc0 a11y: Use simple code for window name change tracking
Remove idle handler and omit checking if the name really was changed.
ATs will either have to live with the name not really changoing or we
should check in GtkWindow.
2011-07-05 16:08:55 -04:00

941 lines
27 KiB
C

/* 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 <string.h>
#include <gtk/gtkx.h>
#include "gailwindow.h"
#include "gailtoplevel.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 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;
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
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);
/*
* A GailWindow can be created for a GtkHandleBox or a GtkWindow
*/
if (!GTK_IS_WINDOW (widget) && !GTK_IS_HANDLE_BOX (widget))
return;
ATK_OBJECT_CLASS (gail_window_parent_class)->initialize (obj, 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 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)
return 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)
return -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;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
if (widget == NULL)
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, &current_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 void
gail_window_real_notify_gtk (GObject *obj,
GParamSpec *pspec)
{
GtkWidget *widget = GTK_WIDGET (obj);
AtkObject* atk_obj = gtk_widget_get_accessible (widget);
if (strcmp (pspec->name, "title") == 0)
{
g_object_notify (G_OBJECT (atk_obj), "accessible-name");
g_signal_emit_by_name (atk_obj, "visible_data_changed");
}
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)
return;
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)
return;
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 <X11/Xlib.h>
#include <X11/Xatom.h>
#include <gdk/x11/gdkx.h>
/* _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)
{
gint screen_n;
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;
info = get_screen_info (gdk_window_get_screen (window));
if (info->stacked_windows == NULL)
return -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)
return -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)
return -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)
return -1;
return 0; /* Punt, FIXME */
}
#endif