Subject: stacking order changes on restart

From: Austin Donnelly <[email-masked]>
Date: Sun, 29 Jun 1997 02:58:34 +0100 (BST)

Hi,

One of our Debian users filed the following bug report recently:

On 25 Jun 1997, Joey Hess <[email-masked]> wrote:

> Package: fvwm2
> Version: 2.0.45-BETA-4
> 
> I have a standard Restart fvwm2 command in my fvwm2 menus. I've noticed that
> when I restart fvwm2, the topmost window ends up buried under all other
> windows, and in general, the z-order of all the windows just seems to be
> reversed.

The stacking order changes, this much is clear, however, it's not the
reverse of the current stacking order.

What happens is that when fvwm2 exits, it reparents all the windows
back to the root window, and does so in reverse order of creation: ie
from newest to oldest (since the Scr.FvwmRoot list's head item is the
most recently created window).  This means the oldest window ends up
on top.

In an ideal world, the stacking order should be preserved: I've got a
patch which does this attached below.  The only fly in the ointment is
that it's O(N^2) in the number of windows.  An O(N) solution might be
to reparent from oldest to newest window, thus stacking the oldest at
the back, with the newest at the front: the assumption is that the
newest windows are the ones currently in use, and so at the front.
However, given that restarts happen infrequently, I think its worth
paying the extra to get the fully correct solution.

Please consider including this patch in future releases.

Thanks,
Austin
------------------------------------------------------------
--- fvwm.c.old	Sun Jun 29 02:33:34 1997
+++ fvwm.c	Sun Jun 29 02:34:49 1997
@@ -1245,6 +1245,21 @@
   return;
 }
 
+/* Convert from an X server "Window *" to an FVWM "FvwmWindow *" */
+static FvwmWindow *win2fvwmWin(Window win)
+{
+  FvwmWindow *ret = Scr.FvwmRoot.next;
+
+  while(ret)
+  {
+    if (ret->frame == win)
+      return ret;
+    ret = ret->next;
+  }
+
+  return NULL;
+}
+
 /***********************************************************************
  *
  *  Procedure:
@@ -1254,16 +1269,41 @@
 void Reborder(void)
 {
   FvwmWindow *tmp;			/* temp fvwm window structure */
+  Window root, parent, *children;
+  unsigned int nchildren;
+  int i;
 
   /* put a border back around all windows */
   MyXGrabServer (dpy);
 
   InstallWindowColormaps (&Scr.FvwmRoot);	/* force reinstall */
-  for (tmp = Scr.FvwmRoot.next; tmp != NULL; tmp = tmp->next)
+
+  /* We'd like to preserve the stacking order over restarts.  Since
+   * RestroreWithdrawnLocation() has the side effect of raising the
+   * window in question, we need to proceed from the bottom-most
+   * window to the top-most.  We get the current stacking order from
+   * the X server, however, it also includes all of our decorations.
+   * Therefore, we check against the Scr.FvwmRoot window list for
+   * valid windows.  Unfortunately this is an O(N^2) process, but
+   * since this is during a restart, I think it's acceptable. */
+  if(!XQueryTree(dpy, Scr.Root, &root, &parent, &children, &nchildren))
+  {
+    fvwm_msg(ERR,"Reborder","XQueryTree failed?!?");
+    MyXUngrabServer (dpy);
+    return;
+  }
+
+  if (children != NULL)
   {
-    RestoreWithdrawnLocation (tmp,True); 
-    XUnmapWindow(dpy,tmp->frame);
-    XDestroyWindow(dpy,tmp->frame);
+    for(i=0; i < nchildren; i++)
+    {
+      tmp = win2fvwmWin(children[i]);
+      if (!tmp)
+	continue; /* probably one of our decorations */
+      RestoreWithdrawnLocation (tmp,True); 
+      XUnmapWindow(dpy,tmp->frame);
+      XDestroyWindow(dpy,tmp->frame);
+    }
   }
 
   MyXUngrabServer (dpy);
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].