Index: gailtoplevel.c
===================================================================
RCS file: /cvs/gnome/gail/gail/gailtoplevel.c,v
retrieving revision 1.28
diff -u -p -r1.28 gailtoplevel.c
--- gailtoplevel.c	28 Apr 2003 17:42:49 -0000	1.28
+++ gailtoplevel.c	2 Jul 2003 15:58:20 -0000
@@ -21,6 +21,11 @@
 #include <string.h>
 #include <gtk/gtk.h>
 #include "gailtoplevel.h"
+#include "gailwindow.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <gdk/gdkx.h>
 
 static void             gail_toplevel_class_init        (GailToplevelClass      *klass);
 static void             gail_toplevel_object_init       (GailToplevel           *toplevel);
@@ -53,7 +58,11 @@ static void      _gail_toplevel_remove_c
 static gboolean  is_tooltip_window                      (GtkWidget              *widget);
 static gboolean  is_attached_menu_window                (GtkWidget              *widget);
 static gboolean  is_combo_window                        (GtkWidget              *widget);
+static void      initialize_active_window_listener      (gpointer data);
+
 
+static Atom _net_active_window;
+static guint update_handler = 0;
 
 static gpointer parent_class = NULL;
 
@@ -95,8 +104,6 @@ gail_toplevel_new (void)
   g_return_val_if_fail ((object != NULL), NULL);
 
   accessible = ATK_OBJECT (object);
-  accessible->role = ATK_ROLE_APPLICATION;
-  accessible->name = g_get_prgname();
 
   return accessible;
 }
@@ -118,6 +125,7 @@ gail_toplevel_class_init (GailToplevelCl
 static void
 gail_toplevel_object_init (GailToplevel *toplevel)
 {
+  AtkObject *obj;
   GtkWindow *window;
   GtkWidget *widget;
   GList *l;
@@ -160,6 +168,12 @@ gail_toplevel_object_init (GailToplevel 
   signal_id  = g_signal_lookup ("hide", GTK_TYPE_WINDOW);
   g_signal_add_emission_hook (signal_id, 0,
     gail_toplevel_hide_event_watcher, toplevel, (GDestroyNotify) NULL);
+
+  toplevel->active_window = NULL;
+  initialize_active_window_listener (toplevel);
+  obj = ATK_OBJECT (toplevel);
+  obj->role = ATK_ROLE_APPLICATION;
+  obj->name = g_get_prgname();
 }
 
 static void
@@ -253,6 +267,7 @@ gail_toplevel_show_event_watcher (GSigna
   */
   child = gtk_widget_get_accessible (widget);
   atk_object_set_parent (child, atk_obj);
+  g_signal_emit (child, g_signal_lookup ("create", GAIL_TYPE_WINDOW), 0);
   g_signal_emit_by_name (atk_obj, "children-changed::add",
                          n_children - 1, 
                          child, NULL);
@@ -314,6 +329,7 @@ _gail_toplevel_remove_child (GailTopleve
               toplevel->window_list = g_list_remove (toplevel->window_list,
                                                      l->data);
               child = gtk_widget_get_accessible (GTK_WIDGET (window));
+              g_signal_emit (child, g_signal_lookup ("destroy", GAIL_TYPE_WINDOW), 0);
               g_signal_emit_by_name (atk_obj, "children-changed::remove",
                                      window_count, 
                                      child, NULL);
@@ -387,4 +403,119 @@ is_combo_window (GtkWidget *widget)
     return TRUE;
 
   return  FALSE;
+}
+
+static gboolean
+update_idle (gpointer data)
+{
+  Atom ret_type;
+  int format;
+  gulong nitems;
+  gulong bytes_after;
+  Window *window;
+  int error;
+  int result;
+  GailToplevel *toplevel;
+  GList *l;
+  gboolean found;
+  GtkWidget *widget;
+  GdkWindow *gdk_window;
+  Window xid;
+  AtkObject *obj;
+  
+  update_handler = 0;
+
+  gdk_error_trap_push();                               
+  ret_type = None;
+  result = XGetWindowProperty (gdk_display,
+                               RootWindow (gdk_display, 0),
+                               _net_active_window,
+                               0, G_MAXLONG,
+                               False, XA_WINDOW, &ret_type, &format, &nitems,
+                               &bytes_after, (guchar **)&window);
+  error = gdk_error_trap_pop();                               
+  if (error != Success ||
+      result != Success)
+    return FALSE;
+
+  if (ret_type != XA_WINDOW)
+    {
+      XFree (window);
+      return FALSE;
+    }
+  g_return_val_if_fail (GAIL_IS_TOPLEVEL (data), FALSE);
+  toplevel = GAIL_TOPLEVEL (data);
+  l = toplevel->window_list;
+
+  found = FALSE;
+  widget = NULL;
+  while (l)
+    {
+      widget = GTK_WIDGET (l->data);
+      gdk_window = widget->window;
+
+      xid = GDK_WINDOW_XID (gdk_window);
+      if (xid == *window)
+        {
+          found = TRUE;
+          break;
+        }
+      l = l->next;
+    }
+
+  XFree (window);
+  if (toplevel->active_window)
+    {
+      obj = gtk_widget_get_accessible (toplevel->active_window);
+      g_signal_emit (obj, g_signal_lookup ("deactivate", GAIL_TYPE_WINDOW), 0);
+      toplevel->active_window = NULL;
+    }
+
+  if (found)
+    {
+      toplevel->active_window = widget; 
+      obj = gtk_widget_get_accessible (toplevel->active_window);
+      g_signal_emit (obj, g_signal_lookup ("activate", GAIL_TYPE_WINDOW), 0);
+    }
+  return FALSE;
+}
+
+static GdkFilterReturn
+filter_func (GdkXEvent *gdkxevent,
+             GdkEvent  *event,
+             gpointer data)
+{
+  XEvent *xevent = gdkxevent;
+
+  if (xevent->type == PropertyNotify)
+    {
+      if (xevent->xproperty.atom == _net_active_window)
+        {
+          if (update_handler == 0)
+            update_handler = g_idle_add (update_idle, data);
+        }
+    }
+
+  return GDK_FILTER_CONTINUE;
+}
+
+static void
+initialize_active_window_listener (gpointer data)
+{
+  static gboolean initialized = FALSE;
+  Window window;
+  XWindowAttributes attrs;
+
+  if (!initialized)
+    {
+
+      gdk_window_add_filter (NULL, filter_func, data);
+      _net_active_window = XInternAtom (gdk_display, "_NET_ACTIVE_WINDOW", False);
+      window = RootWindow (gdk_display, 0);
+      XGetWindowAttributes (gdk_display, window, &attrs);
+      XSelectInput (gdk_display, window,
+                    attrs.your_event_mask | PropertyChangeMask);
+      
+      initialized = TRUE;
+    }
 }
Index: gailtoplevel.h
===================================================================
RCS file: /cvs/gnome/gail/gail/gailtoplevel.h,v
retrieving revision 1.1
diff -u -p -r1.1 gailtoplevel.h
--- gailtoplevel.h	26 Jul 2001 15:07:51 -0000	1.1
+++ gailtoplevel.h	2 Jul 2003 15:58:20 -0000
@@ -40,6 +40,7 @@ struct _GailToplevel
 {
   AtkObject parent;
   GList *window_list;
+  GtkWidget *active_window;
 };
 
 GType gail_toplevel_get_type (void);
Index: gailutil.c
===================================================================
RCS file: /cvs/gnome/gail/gail/gailutil.c,v
retrieving revision 1.31
diff -u -p -r1.31 gailutil.c
--- gailutil.c	14 May 2003 09:43:10 -0000	1.31
+++ gailutil.c	2 Jul 2003 15:58:20 -0000
@@ -50,25 +50,17 @@ static gboolean         state_event_watc
                                                                  guint                  n_param_values,
                                                                  const GValue           *param_values,
                                                                  gpointer               data);
-static void             window_added                             (AtkObject             *atk_obj,
-                                                                  guint                 index,
-                                                                  AtkObject             *child);
-static void             window_removed                           (AtkObject             *atk_obj,
-                                                                  guint                 index,
-                                                                  AtkObject             *child);
-static gboolean        window_focus                              (GtkWidget             *widget,
-                                                                  GdkEventFocus         *event);
 static gboolean         configure_event_watcher                 (GSignalInvocationHint  *hint,
                                                                  guint                  n_param_values,
                                                                  const GValue           *param_values,
                                                                  gpointer               data);
                                                                   
 
-static AtkObject* root = NULL;
 static GHashTable *listener_list = NULL;
 static gint listener_idx = 1;
 static GHashTable *key_listener_list = NULL;
 static guint key_snooper_id = 0;
+static gboolean active_window_listener_inited = FALSE;
 
 typedef struct _GailUtilListenerInfo GailUtilListenerInfo;
 typedef struct _GailKeyEventInfo GailKeyEventInfo;
@@ -315,6 +307,8 @@ gail_util_remove_key_event_listener (gui
 static AtkObject*
 gail_util_get_root (void)
 {
+  static AtkObject* root = NULL;
+
   if (!root)
     root = gail_toplevel_new();
 
@@ -389,8 +383,6 @@ add_listener (GSignalEmissionHook listen
 static void
 do_window_event_initialization (void)
 {
-  AtkObject *root;
-
   /*
    * Ensure that GailWindowClass exists.
    */
@@ -399,12 +391,6 @@ do_window_event_initialization (void)
                               0, state_event_watcher, NULL, (GDestroyNotify) NULL);
   g_signal_add_emission_hook (g_signal_lookup ("configure-event", GTK_TYPE_WIDGET),
                               0, configure_event_watcher, NULL, (GDestroyNotify) NULL);
-
-  root = atk_get_root ();
-  g_signal_connect (root, "children-changed::add",
-                    (GCallback) window_added, NULL);
-  g_signal_connect (root, "children-changed::remove",
-                    (GCallback) window_removed, NULL);
 }
 
 static gboolean
@@ -471,10 +457,6 @@ window_added (AtkObject *atk_obj,
   widget = GTK_ACCESSIBLE (child)->widget;
   g_return_if_fail (widget);
 
-  g_signal_connect (widget, "focus-in-event",  
-                    (GCallback) window_focus, NULL);
-  g_signal_connect (widget, "focus-out-event",  
-                    (GCallback) window_focus, NULL);
   g_signal_emit (child, g_signal_lookup ("create", GAIL_TYPE_WINDOW), 0); 
 }
 
@@ -491,24 +473,7 @@ window_removed (AtkObject *atk_obj,
   widget = GTK_ACCESSIBLE (child)->widget;
   g_return_if_fail (widget);
 
-  g_signal_handlers_disconnect_by_func (widget, (GCallback) window_focus, NULL);
   g_signal_emit (child, g_signal_lookup ("destroy", GAIL_TYPE_WINDOW), 0); 
-}
-
-static gboolean
-window_focus (GtkWidget     *widget,
-              GdkEventFocus *event)
-{
-  gchar *signal_name;
-  AtkObject *atk_obj;
-
-  g_return_val_if_fail (GTK_WIDGET (widget), FALSE);
-
-  atk_obj = gtk_widget_get_accessible (widget);
-  signal_name =  (event->in) ? "activate" : "deactivate";
-  g_signal_emit (atk_obj, g_signal_lookup (signal_name, GAIL_TYPE_WINDOW), 0); 
-
-  return FALSE;
 }
 
 static gboolean 
