Gnome pager stacking order patch



(gnome-hackers list cc'd for the benefit of those not yet transitioned
to gnome-hackers)

The following patch:

* Makes the gnome pager display windows in the correct stacking order.

* Makes geometry of pager displayed windows a bit more accurate by
accounting for WM decorations.

* Adds the FSF to the copyright line since the change is not entirely
trivial (~300 line patch) and I've assigned my GNOME changes to the FSF.
I haven't added myself to the authors line though.

* Should even work with Enlightenment virtual root windows, although I
have not tested this (someone please test). I _have_ tested it with
gnome-compliant window managers that don't use virtual roots.

I consider this a bugfix although a non-critical one. I would like to
check it in before tomorrow's tarballs get made and will do so sometime
tomorrow unless there are major objections.



cvs server: Diffing applets/gnome-pager
Index: applets/gnome-pager/gnomepager.h
===================================================================
RCS file: /cvs/gnome/gnome-core/applets/gnome-pager/gnomepager.h,v
retrieving revision 1.7
diff -u -r1.7 gnomepager.h
--- gnomepager.h        1999/02/08 02:37:44     1.7
+++ gnomepager.h        1999/02/11 01:31:50
@@ -23,6 +23,8 @@
   gchar              *name;
   gint                x, y, w, h;
   Window              win;
+  Window              frame; /* Window manager's frame window */
+  Window              root;  /* Root or pseudo-root */
   gchar               iconified;
   gchar               shaded;
   gchar               focused;
@@ -30,6 +32,8 @@
   gint                desktop;
   GdkWindow          *gdkwin;
   GtkWidget          *dummy;
+  GdkWindow          *frame_gdkwin;
+  GtkWidget          *frame_dummy;
 }
 Task;
 
@@ -107,6 +111,12 @@
 void desktop_set_area(int ax, int ay);
 void create_popbox(void);
 void showpop_cb(GtkWidget *widget, gpointer data);
+
+void get_window_root_and_frame_id(Window w, Window *ret_frame, 
+                                     Window *ret_root);
+GList *get_task_stacking(GList *p, gint desk);
+
+
 
 #include "icon1.xpm"
 #include "icon2.xpm"
Index: applets/gnome-pager/gnomepager_applet.c
===================================================================
RCS file: /cvs/gnome/gnome-core/applets/gnome-pager/gnomepager_applet.c,v
retrieving revision 1.37
diff -u -r1.37 gnomepager_applet.c
--- gnomepager_applet.c 1999/02/08 02:37:45     1.37
+++ gnomepager_applet.c 1999/02/11 01:31:50
@@ -103,7 +103,7 @@
     {"The Rasterman", NULL};
   
   about = gnome_about_new
-    (_("Desktop Pager Applet"), "0.1", _("Copyright (C)1998 Red Hat Software"),
+    (_("Desktop Pager Applet"), "0.1", _("Copyright (C)1998,1999 Red Hat Software, Free Software Foundation"),
      authors,
      _("Pager for a GNOME compliant Window Manager"),
      NULL);
@@ -781,7 +781,7 @@
 {
   gint i, tdesk;
   gchar tsticky;
-  
+
   tsticky = t->sticky;
   tdesk = t->desktop;
   task_get_info(t);
@@ -969,7 +969,8 @@
       while (ptr)
        {
          t = (Task *)(ptr->data);
-         if (t->win == xevent->xconfigure.window)
+         if (t->win == xevent->xconfigure.window ||
+             t->frame == xevent->xconfigure.window)
            {
              cb_task_change(NULL, (GdkEventProperty *)event, t);
              return GDK_FILTER_CONTINUE;
@@ -1002,7 +1003,7 @@
 task_get_info(Task *t)
 {
   GnomeWinState       *win_state;
-  Window               w2, ret, root, *wl;
+  Window               ret;
   gchar               *name;
   gint                 size;
   guint                w, h, d;
@@ -1070,28 +1071,14 @@
     }
   
   /* geometry!!!!!!!!!!! */
-  XGetGeometry(GDK_DISPLAY(), t->win, &ret, &size, &size, &w, &h, &d, &d);
+  get_window_root_and_frame_id(t->win, &t->frame, &t->root);
+
+  XGetGeometry(GDK_DISPLAY(), t->frame, &ret, &size, &size, &w, &h, &d, &d);
   t->w = (gint)w;
   t->h = (gint)h;
-  wl = NULL;
-  w2 = t->win;
-  while (XQueryTree(GDK_DISPLAY(), w2, &root, &ret, &wl, &size))
-    {
-      if ((wl) && (size > 0))
-       XFree(wl);
-      w2 = ret;
-      if (ret == root)
-       break;
-      val = util_get_atom(ret, "ENLIGHTENMENT_DESKTOP", XA_CARDINAL, &size);
-      if (val)
-       {
-         break;
-         g_free(val);
-       }
-    }
-  /* Wheee w2 is our actualy "root" window even on virtual root windows */
-  XTranslateCoordinates(GDK_DISPLAY(), t->win, w2, 0, 0, 
+  XTranslateCoordinates(GDK_DISPLAY(), t->frame, t->root, 0, 0, 
                        &(t->x), &(t->y), &ret);
+
   if (psticky != t->sticky)
     {
       populate_tasks();
@@ -1145,7 +1132,11 @@
   t->desktop = 0;
   t->dummy = NULL;
   t->gdkwin = NULL;
+  t->frame_dummy = NULL;
+  t->frame_gdkwin = NULL;
   
+  get_window_root_and_frame_id(t->win, &t->frame, &t->root);
+
   /* create dummy GTK widget to get events from */
   t->gdkwin = gdk_window_lookup(win);
   if (t->gdkwin)
@@ -1158,6 +1149,18 @@
   gdk_window_add_filter(t->gdkwin, cb_filter_intercept, t->dummy);  
   /* fake events form win producing signals on dummy widget */
 /*  gdk_window_set_user_data(t->gdkwin, t->dummy);*/
+
+  /* DO it all again for the frame window */
+  t->frame_gdkwin = gdk_window_lookup(t->frame);
+  if (t->frame_gdkwin)
+    gdk_window_ref(t->frame_gdkwin);
+  else
+    t->frame_gdkwin = gdk_window_foreign_new(t->frame);
+  gdk_window_add_filter(t->frame_gdkwin, cb_filter_intercept, t->dummy);  
+  /* fake events form win producing signals on dummy widget */
+/*  gdk_window_set_user_data(t->gdkwin, t->dummy);*/
+
+
   /* conntect to "faked" signals */
 /*  gtk_signal_connect(GTK_OBJECT(t->dummy), "property_notify_event",
                     GTK_SIGNAL_FUNC(cb_task_change), t);
@@ -1171,6 +1174,10 @@
   /* make sure we get the events */
   XSelectInput(GDK_DISPLAY(), win, PropertyChangeMask | FocusChangeMask |
               StructureNotifyMask);
+
+  /* make sure we get the events */
+  XSelectInput(GDK_DISPLAY(), t->frame, StructureNotifyMask);
+
   /* add this client to the list of clients */
   tasks = g_list_append(tasks, t);
 
@@ -1550,6 +1557,110 @@
                       SubstructureNotifyMask, (XEvent*) &xev);
 }
 
+
+void
+get_window_root_and_frame_id(Window w, Window *ret_frame, Window *ret_root)
+{
+  Window               w3, w2, ret, root, *wl;
+  gint                 size;
+  CARD32              *val;
+
+  w3 = w2 = w;
+
+  while (XQueryTree(GDK_DISPLAY(), w2, &root, &ret, &wl, &size))
+    {
+      if ((wl) && (size > 0))
+       XFree(wl);
+      w3 = w2;
+      w2 = ret;
+      if (ret == root)
+       break;
+      val = util_get_atom(ret, "ENLIGHTENMENT_DESKTOP", XA_CARDINAL, &size);
+      if (val)
+       {
+         break;
+         g_free(val);
+       }
+    }
+
+  *ret_root = w2;
+  *ret_frame = w3;
+
+  return;
+}
+
+
+
+GList  *get_task_stacking(GList *tasks, gint desk)
+{
+  GList *tasks_on_desk=NULL;
+  GList *root_ids=NULL;
+  GList *retval=NULL;
+  GList *p, *p2, *p3;
+  Task *t;
+  Window dummy1, dummy2, root, *wl;
+  gint size, count;
+
+  /* Find the tasks that are sticky or on the specified desk 
+     which are not iconified. */
+
+  for (p = tasks; p != NULL; p = p->next) {
+    t = (Task *)p->data;
+    
+    if (((t->desktop == desk) || (t->sticky)) && (!(t->iconified))) {
+      tasks_on_desk = g_list_prepend(tasks_on_desk, (gpointer) t);
+    }
+  }
+  tasks_on_desk = g_list_reverse(tasks_on_desk);
+
+  /* Find the IDs of all root or virtual root windows they 
+     may be on. */
+
+  for (p = tasks_on_desk; p != NULL; p = p->next) {
+    t = (Task *)p->data;
+
+    if (NULL == g_list_find(root_ids, (gpointer) t->root)) {
+      root_ids = g_list_prepend(root_ids, (gpointer) t->root);
+    }
+  }
+
+  /* XQueryTree each virtual root window, and for each window ID we
+     get back that matches a frame window, add the corresponding task
+     structure to retval. If we have tasks claiming to be on the same
+     desk which are on different "root" windows, the stacking order
+     between windows on the different roots will be aribtrary, but
+     that is a WM bug (or temporary state) anyway. */
+  
+  for (p = root_ids; p != NULL; p = p->next) {
+    root = (Window) p->data;
+    
+    XQueryTree(GDK_DISPLAY(), root, &dummy1, &dummy2, &wl, &size);
+
+    for (count = 0; count < size; count++) {
+      Window w = wl[count];
+
+      for (p2 = tasks_on_desk; p2 != NULL; p2 = p2->next) {
+       t = (Task *)p2->data;
+
+       if (t->frame == wl[count]) {
+         retval = g_list_prepend(retval, (gpointer) t);
+         tasks_on_desk=g_list_remove_link(tasks_on_desk, p2);
+         break;
+       }
+      }
+    }
+      
+    XFree(wl);
+  }
+  retval = g_list_reverse(retval);
+
+  g_list_free(tasks_on_desk);
+  g_list_free(root_ids);
+
+  return retval;
+}
+
+
 #include "stripe.xbm"
 
 void
@@ -1559,7 +1670,7 @@
   GdkWindow *win;
   gint sel, sw, sh, w, h, desk, x, y, ww, hh;
   Task *t;
-  GList *p;
+  GList *p, *stacking;
   GdkBitmap *bm;
   GdkGC *gc;
 
@@ -1614,7 +1725,8 @@
     gtk_draw_vline(s, win, GTK_STATE_NORMAL, 2, 1 + h, 1 + ((x * w) / area_w));
   for (y = 1; y < area_h; y++)
     gtk_draw_hline(s, win, GTK_STATE_NORMAL, 2, 1 + w, 1 + ((y * h) / area_h));
-  p = tasks;
+  stacking = get_task_stacking(tasks, desk);
+  p = stacking;
   while (p)
     {
       t = (Task *)p->data;
@@ -1634,6 +1746,7 @@
        }
       p = p->next;
     }
+  g_list_free(stacking);
 }
 
 GtkWidget *



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