[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    BadWindow errors
From:       gerard patel <g.patel () wanadoo ! fr>
Date:       2000-08-27 15:20:24
[Download RAW message or body]

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


["restack.dif" (text/plain)]

--- 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);




[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic