[g-a-devel]ATK/GAIL patch for bug #84097



Hi:

Attached is the patch for bug 84097, implementing window stacking
support for ATK/GAIL.

The patch does not yet expose "desktop" information, that is, stacking
information is available for toplevels but is not segregated by the
WM_DESKTOP property.  Support for multiple 'virtual desktops' should
probably be the subject of another bug and patch; however the attached
patch (from Mark McLoughlin) should solve the problem in #84097.

The patch monitors _NET_CLIENT_LIST_STACKING in order to return current
values for the Z order of toplevel windows.  It also reports that
toplevels are contained in ATK_LAYER_WINDOW, whereas toplevel windows
were previously (incorrectly) reported in ATK_LAYER_WIDGET.

regards,

Bill

----------
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gail/ChangeLog,v
retrieving revision 1.491
diff -u -p -r1.491 ChangeLog
--- ChangeLog	5 Sep 2002 13:29:23 -0000	1.491
+++ ChangeLog	6 Sep 2002 05:44:44 -0000
@@ -1,3 +1,16 @@
+2002-09-06  Mark McLoughlin  <mark skynet ie>
+
+	* gail/gailwindow.c: (gail_window_class_init): fix warnings.
+	(gail_window_real_initialize): set layer as ATK_LAYER_WINDOW.
+	(atk_component_interface_init): set get_mdi_zorder.
+	(get_stacked_windows), (update_screen_info),
+	(root_window_event_filter), (display_closed),
+	(init_gail_screens), (init_gail_screen),
+	(get_screen_info), (get_window_zorder),
+	(gail_window_get_mdi_zorder): impl code to obtain the z-order
+	directly from _NET_CLIENT_LIST_STACKING root window property
+	and to monitor for changes on that property.
+
 2002-09-05  Padraig O'Briain  <padraig obriain sun com>

 	* docs/reference/libgail-util/gail-libgail-util-sections.txt:
Index: gail/gailwindow.c
===================================================================
RCS file: /cvs/gnome/gail/gail/gailwindow.c,v
retrieving revision 1.36
diff -u -p -r1.36 gailwindow.c
--- gail/gailwindow.c	15 Jul 2002 11:56:44 -0000	1.36
+++ gail/gailwindow.c	6 Sep 2002 05:44:46 -0000
@@ -49,6 +49,7 @@ static gboolean              gail_window
 static AtkStateSet*          gail_window_ref_state_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);
@@ -129,7 +130,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("activate",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -137,7 +138,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("create",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -145,7 +146,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("deactivate",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -153,7 +154,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("destroy",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -161,7 +162,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("maximize",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -169,7 +170,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("minimize",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -177,7 +178,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("resize",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -185,7 +186,7 @@ gail_window_class_init (GailWindowClass
     g_signal_new ("restore",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
-                  NULL, /* default signal handler */
+                  0, /* default signal handler */
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
@@ -239,6 +240,8 @@ gail_window_real_initialize (AtkObject *
                     "window_state_event",
                     G_CALLBACK (gail_window_state_event_gtk),
                     NULL);
+
+  obj->layer = ATK_LAYER_WINDOW;
 }

 static G_CONST_RETURN gchar*
@@ -407,6 +410,7 @@ atk_component_interface_init (AtkCompone

   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
@@ -488,3 +492,243 @@ gail_window_get_size (AtkComponent *comp
   *height = rect.height;
 }

+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <gdk/gdkx.h>
+
+/* _NET_CLIENT_LIST_STACKING monitoring */
+
+typedef struct {
+  Window     *stacked_windows;
+  int         stacked_windows_len;
+  GdkWindow  *root_window;
+  guint       update_handler;
+
+  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 gboolean
+get_stacked_windows (GailScreenInfo *info)
+{
+  Atom    ret_type;
+  int     format;
+  gulong  nitems;
+  gulong  bytes_after;
+  Window *data;
+  int     error;
+  int     result;
+
+  if (_net_client_list_stacking == None)
+    _net_client_list_stacking =
+		XInternAtom (gdk_display, "_NET_CLIENT_LIST_STACKING", False);
+
+  if (info->stacked_windows)
+    XFree (info->stacked_windows);
+
+  info->stacked_windows = NULL;
+  info->stacked_windows_len = 0;
+
+  gdk_error_trap_push ();
+  ret_type = None;
+  result = XGetWindowProperty (gdk_display,
+                               GDK_WINDOW_XWINDOW (info->root_window),
+                               _net_client_list_stacking,
+                               0, G_MAXLONG,
+                               False, XA_WINDOW, &ret_type, &format, &nitems,
+                               &bytes_after, (guchar **)&data);
+  error = gdk_error_trap_pop ();
+  if (error != Success || result != Success)
+    return FALSE;
+
+  if (ret_type != XA_WINDOW)
+    {
+      XFree (data);
+      return FALSE;
+    }
+
+  info->stacked_windows = data;
+  info->stacked_windows_len = nitems;
+
+  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 GdkFilterReturn
+root_window_event_filter (GdkXEvent *gdkxevent,
+			  GdkEvent  *event,
+			  gpointer   data)
+{
+  XEvent *xevent = gdkxevent;
+  int     screen_n;
+
+  if (xevent->type != PropertyNotify ||
+     xevent->xproperty.atom != _net_client_list_stacking)
+    return GDK_FILTER_CONTINUE;
+
+  screen_n = gdk_screen_get_number (
+		gdk_drawable_get_screen (GDK_DRAWABLE (event->any.window)));
+
+  gail_screens [screen_n].update_stacked_windows = TRUE;
+  if (!gail_screens [screen_n].update_handler)
+    {
+      gail_screens [screen_n].update_handler = g_idle_add (update_screen_info,
+							   GINT_TO_POINTER (screen_n));
+    }
+
+  return GDK_FILTER_CONTINUE;
+}
+
+static void
+display_closed (GdkDisplay *display,
+		gboolean    is_error)
+{
+  int i;
+
+  for (i = 0; i < num_screens; i++)
+    {
+      gdk_window_remove_filter (gail_screens [i].root_window,
+				root_window_event_filter, NULL);
+
+      if (gail_screens [i].update_handler)
+	{
+	  g_source_remove (gail_screens [i].update_handler);
+	  gail_screens [i].update_handler = 0;
+	}
+
+      if (gail_screens [i].stacked_windows)
+	{
+	  XFree (gail_screens [i].stacked_windows);
+	  gail_screens [i].stacked_windows = NULL;
+	  gail_screens [i].stacked_windows_len = 0;
+	}
+    }
+
+  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);
+
+  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]);
+
+  /* Probably not neccessary */
+  XGetWindowAttributes (gdk_display,
+			GDK_WINDOW_XWINDOW (gail_screens [screen_n].root_window),
+			&attrs);
+
+  XSelectInput (gdk_display,
+		GDK_WINDOW_XWINDOW (gail_screens [screen_n].root_window),
+                attrs.your_event_mask | PropertyChangeMask);
+
+  gdk_window_add_filter (gail_screens [screen_n].root_window,
+			 root_window_event_filter, NULL);
+
+  gail_screens [screen_n].screen_initialized = TRUE;
+}
+
+static GailScreenInfo *
+get_screen_info (GdkScreen *screen)
+{
+  int screen_n;
+
+  g_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;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), -1);
+
+  info = get_screen_info (
+		gdk_drawable_get_screen (GDK_DRAWABLE (window)));
+
+  g_return_val_if_fail (info->stacked_windows != NULL, -1);
+
+  xid = GDK_WINDOW_XID (window);
+
+  for (i = 0; i < info->stacked_windows_len; i++)
+    {
+      g_print ("%d: Comparing %ld %ld\n", i, info->stacked_windows [i], xid);
+      if (info->stacked_windows [i] == xid)
+        {
+          g_print ("%d: Matched %ld %ld\n", i, info->stacked_windows [i], xid);
+          return i;
+        }
+     }
+
+  return -1;
+}
+
+static gint
+gail_window_get_mdi_zorder (AtkComponent *component)
+{
+  GtkWidget *widget = GTK_ACCESSIBLE (component)->widget;
+
+  if (widget == NULL)
+    /*
+     * State is defunct
+     */
+    return -1;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (widget), -1);
+
+  return get_window_zorder (widget->window);
+}




Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/atk/ChangeLog,v
retrieving revision 1.205
diff -u -p -r1.205 ChangeLog
--- ChangeLog	5 Sep 2002 13:51:08 -0000	1.205
+++ ChangeLog	6 Sep 2002 05:44:53 -0000
@@ -1,3 +1,9 @@
+2002-09-06  Mark McLoughlin  <mark skynet ie>
+
+	* atk/atkobject.h: add ATK_LAYER_WINDOW.
+
+	* atk/atkcomponent.c: upd docs.
+
 2002-09-05  Padraig O'Briain  <padraig obriain sun com>

 	* docs/atk-sections.txt docs/tmpl/atkaction.sgml
Index: atk/atkcomponent.c
===================================================================
RCS file: /cvs/gnome/atk/atk/atkcomponent.c,v
retrieving revision 1.19
diff -u -p -r1.19 atkcomponent.c
--- atk/atkcomponent.c	15 Feb 2002 11:26:25 -0000	1.19
+++ atk/atkcomponent.c	6 Sep 2002 05:44:54 -0000
@@ -344,7 +344,7 @@ atk_component_get_layer (AtkComponent *c
  * @component: an #AtkComponent
  *
  * Gets the zorder of the component. The value G_MININT will be returned
- * if the layer of the component is not ATK_LAYER_MDI.
+ * if the layer of the component is not ATK_LAYER_MDI or ATK_LAYER_WINDOW.
  *
  * Returns: a gint which is the zorder of the component, i.e. the depth at
  * which the component is shown in relation to other components in the same
Index: atk/atkobject.h
===================================================================
RCS file: /cvs/gnome/atk/atk/atkobject.h,v
retrieving revision 1.31
diff -u -p -r1.31 atkobject.h
--- atk/atkobject.h	13 Feb 2002 14:15:05 -0000	1.31
+++ atk/atkobject.h	6 Sep 2002 05:44:55 -0000
@@ -197,6 +197,7 @@ AtkRole                  atk_role_regist
  * ATK_LAYER_MDI: This layer is used for layered components
  * ATK_LAYER_POPUP: This layer is used for popup components, such as menus
  * ATK_LAYER_OVERLAY: This layer is reserved for future use.
+ * ATK_LAYER_WINDOW: This layer is used for toplevel windows.
  *
  * Describes the layer of a component
  **/
@@ -208,7 +209,8 @@ typedef enum
   ATK_LAYER_WIDGET,
   ATK_LAYER_MDI,
   ATK_LAYER_POPUP,
-  ATK_LAYER_OVERLAY
+  ATK_LAYER_OVERLAY,
+  ATK_LAYER_WINDOW
 } AtkLayer;

 #define ATK_TYPE_OBJECT                           (atk_object_get_type ())




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]