Module: wine Branch: master Commit: b76db19e88cf6de04687048a8b28367854a7bbb0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b76db19e88cf6de04687048a8b...
Author: Alexandre Julliard julliard@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;