I have 3 applications that are sometimes outputing this kind of message in -managed 
mode, usually
when exiting or when terminating a dialog :

X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  12 (X_ConfigureWindow)
  Resource id in failed request:  0x10032ae
  Serial number of failed request:  21957
  Current serial number in output stream:  21958      

Usually the failed request is ConfigureWindow, sometimes QueryTree.
I have sometimes seen similar messages on cemw.

One of these applications has this problem much more often than the others, so I used 
it
to track what is happening.

The 'Resource id in failed request' are never Wine windows,  always the X parents of
Wine windows, that is,  the windows that my window manager is using to decorate/manage
the top window(s) of Wine. 

It seems that when Wine ask X to unmap a window, the WM is deleting the reparenting
window; all right, there is no reason for the WM to keep around a window that will
maybe never be used again. Unfortunately, it seems that the WM (well, my WM at least :
KDE 1.1) can take the decision to zap its reparenting window at any time, not 
immediately
when the real window is unmapped..Since Wine can try to reorder hidden windows,
any restacking can fail.

The attached patch implements an error handler for restacking the windows.

[ ICCCM 4.1.5 :
Clients that must position themselves in the stack relative to some window that was 
originally a sibling must do the ConfigureWindow request (in case they are running 
under a nonreparenting window manager), be prepared to deal with a resulting error 
(...) ]

Comments, insights, test results appreciated as I am way beyond my familiar territory 
here - but I
hope to submit a real patch based on what I have done so far.

Gerard
--- wnd.c.orig  Sun Aug 20 16:54:48 2000
+++ wnd.c       Mon Aug 28 00:07:11 2000
@@ -581,11 +581,12 @@
   WIN_ReleaseDesktop();
 }
 
+
 /***********************************************************************
  *             X11DRV_WND_FindDesktopXWindow   [Internal]
  *
  * Find the actual X window which needs be restacked.
- * Used by X11DRV_WND_SetWindowPos().
+ * Used by X11DRV_WND_SetWindowPos(). Entered with X locked.
  */
 static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
 {
@@ -598,9 +599,10 @@
       window = X11DRV_WND_GetXWindow(wndPtr);
       for (;;)
         {
-         TSXQueryTree( display, window, &root, &parent,
-                        &children, &nchildren );
-         TSXFree( children );
+         if (!XQueryTree( display, window, &root, &parent,
+                        &children, &nchildren ))
+              return 0;
+         XFree( children );
          if (parent == root)
            return window;
          window = parent;
@@ -608,6 +610,32 @@
     }
 }
 
+/* it's not possible to prevent all X errors when
+   reordering managed windows that were just unmapped
+   (the WM can delete the reparenting window at any 
+   time, so catch the error instead */
+static int restackerror_handler(Display *display, XErrorEvent *error_evt)
+{
+    ERR("restack err %d\n", error_evt->error_code);
+    return 0;
+}    
+
+static void X11DRV_WND_Restack(WND *wnd1, WND *wnd2)
+{
+    Window stack[2];
+    void *ptr;
+    EnterCriticalSection(&X11DRV_CritSection);
+    ptr = XSetErrorHandler(restackerror_handler);
+    if ((stack[0] = X11DRV_WND_FindDesktopXWindow( wnd1 )))
+    {
+        if ((stack[1] = X11DRV_WND_FindDesktopXWindow( wnd2 )))
+            XRestackWindows(display, stack, 2);
+    }
+    XSync(display, False);
+    XSetErrorHandler(ptr);
+    LeaveCriticalSection(&X11DRV_CritSection);
+}
+
 /***********************************************************************
  *           WINPOS_SetXWindowPos
  *
@@ -692,7 +720,6 @@
          else if (winpos->hwndInsertAfter != HWND_BOTTOM)
            {
              WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
-             Window stack[2];
 
           /* If the window where we should do the insert is zero-sized (not mapped)
              don't used this window since it will possibly crash the X server,
@@ -731,20 +758,14 @@
               }
               else
               {
-                  stack[0] = X11DRV_WND_FindDesktopXWindow( wndPrev );
-                  stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
-
-                  TSXRestackWindows(display, stack, 2);
+                  X11DRV_WND_Restack(wndPrev, winposPtr);
                   changeMask &= ~CWStackMode;
               }
           }
           else  /* Normal behavior, windows are not zero-sized */
           {
-              stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
-              stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
-             
-                 TSXRestackWindows(display, stack, 2);
-                 changeMask &= ~CWStackMode;
+              X11DRV_WND_Restack(insertPtr, winposPtr);
+             changeMask &= ~CWStackMode;
           }
 
           WIN_ReleaseWndPtr(insertPtr);



Reply via email to