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