Alexandre Julliard : winex11: Use XWithdrawWindow to unmap managed windows, and wait until they are withdrawn before mapping them again.

Alexandre Julliard julliard at winehq.org
Thu Feb 28 06:21:15 CST 2008


Module: wine
Branch: master
Commit: b76db19e88cf6de04687048a8b28367854a7bbb0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b76db19e88cf6de04687048a8b28367854a7bbb0

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Feb 27 19:13:09 2008 +0100

winex11: Use XWithdrawWindow to unmap managed windows, and wait until they are withdrawn before mapping them again.

---

 dlls/winex11.drv/event.c  |   52 ++++++++++++++++++++++++++++++++++++++++----
 dlls/winex11.drv/winpos.c |    9 +++++--
 dlls/winex11.drv/x11drv.h |    3 ++
 3 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index ee96d02..01dfc6d 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -21,6 +21,12 @@
 
 #include "config.h"
 
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
 #include <X11/Xatom.h>
 #include <X11/keysym.h>
 #include <X11/Xlib.h>
@@ -239,7 +245,7 @@ static Bool filter_event( Display *display, XEvent *event, char *arg )
 /***********************************************************************
  *           process_events
  */
-static int process_events( Display *display, ULONG_PTR mask )
+static int process_events( Display *display, Bool (*filter)(), ULONG_PTR arg )
 {
     XEvent event;
     HWND hwnd;
@@ -247,14 +253,14 @@ static int process_events( Display *display, ULONG_PTR mask )
     x11drv_event_handler handler;
 
     wine_tsx11_lock();
-    while (XCheckIfEvent( display, &event, filter_event, (char *)mask ))
+    while (XCheckIfEvent( display, &event, filter, (char *)arg ))
     {
         count++;
         if (XFilterEvent( &event, None )) continue;  /* filtered, ignore it */
 
         if (!(handler = find_handler( event.type )))
         {
-            TRACE( "%s, ignoring\n", dbgstr_event( event.type ));
+            TRACE( "%s for win %lx, ignoring\n", dbgstr_event( event.type ), event.xany.window );
             continue;  /* no handler, ignore it */
         }
 
@@ -295,12 +301,12 @@ DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
 
     data->process_event_count++;
 
-    if (process_events( data->display, mask )) ret = count - 1;
+    if (process_events( data->display, filter_event, mask )) ret = count - 1;
     else if (count || timeout)
     {
         ret = WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
                                         timeout, flags & MWMO_ALERTABLE );
-        if (ret == count - 1) process_events( data->display, mask );
+        if (ret == count - 1) process_events( data->display, filter_event, mask );
     }
     else ret = WAIT_TIMEOUT;
 
@@ -645,6 +651,42 @@ static void EVENT_PropertyNotify( HWND hwnd, XEvent *xev )
     }
 }
 
+
+/* event filter to wait for a WM_STATE change notification on a window */
+static Bool is_wm_state_notify( Display *display, XEvent *event, XPointer arg )
+{
+    return (event->type == PropertyNotify &&
+            event->xproperty.window == (Window)arg &&
+            event->xproperty.atom == x11drv_atom(WM_STATE));
+}
+
+/***********************************************************************
+ *           wait_for_withdrawn_state
+ */
+void wait_for_withdrawn_state( Display *display, struct x11drv_win_data *data )
+{
+    DWORD end = GetTickCount() + 2000;
+
+    if (!data->whole_window || !data->managed) return;
+
+    while (data->wm_state != WithdrawnState &&
+           !process_events( display, is_wm_state_notify, data->whole_window ))
+    {
+        struct pollfd pfd;
+        int timeout = end - GetTickCount();
+
+        TRACE( "waiting for window %p/%lx to become withdrawn\n", data->hwnd, data->whole_window );
+        pfd.fd = ConnectionNumber(display);
+        pfd.events = POLLIN;
+        if (timeout <= 0 || poll( &pfd, 1, timeout ) != 1)
+        {
+            FIXME( "window %p/%lx wait timed out\n", data->hwnd, data->whole_window );
+            return;
+        }
+    }
+}
+
+
 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
 {
     RECT tempRect;
diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c
index 719627b..3fecec2 100644
--- a/dlls/winex11.drv/winpos.c
+++ b/dlls/winex11.drv/winpos.c
@@ -153,6 +153,7 @@ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style )
             if (!data->mapped)
             {
                 TRACE( "mapping win %p\n", hwnd );
+                wait_for_withdrawn_state( display, data );
                 X11DRV_sync_window_style( display, data );
                 wine_tsx11_lock();
                 XMapWindow( display, data->whole_window );
@@ -385,9 +386,10 @@ void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags,
 
     if (data->mapped && (!(new_style & WS_VISIBLE) || !X11DRV_is_window_rect_mapped( rectWindow )))
     {
-        TRACE( "unmapping win %p\n", hwnd );
+        TRACE( "unmapping win %p/%lx\n", hwnd, data->whole_window );
         wine_tsx11_lock();
-        XUnmapWindow( display, data->whole_window );
+        if (data->managed) XWithdrawWindow( display, data->whole_window, DefaultScreen(display) );
+        else XUnmapWindow( display, data->whole_window );
         wine_tsx11_unlock();
         data->mapped = FALSE;
         data->net_wm_state = 0;
@@ -403,7 +405,8 @@ void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags,
 
         if (!data->mapped)
         {
-            TRACE( "mapping win %p\n", hwnd );
+            TRACE( "mapping win %p/%lx\n", hwnd, data->whole_window );
+            wait_for_withdrawn_state( display, data );
             X11DRV_sync_window_style( display, data );
             wine_tsx11_lock();
             XMapWindow( display, data->whole_window );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 375b04b..20590b3 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -691,6 +691,9 @@ extern void mark_drawable_dirty( Drawable old, Drawable new );
 extern Drawable create_glxpixmap( Display *display, XVisualInfo *vis, Pixmap parent );
 extern void flush_gl_drawable( X11DRV_PDEVICE *physDev );
 
+extern int get_window_wm_state( Display *display, struct x11drv_win_data *data );
+extern void wait_for_withdrawn_state( Display *display, struct x11drv_win_data *data );
+
 /* X context to associate a hwnd to an X window */
 extern XContext winContext;
 




More information about the wine-cvs mailing list