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

oldstable
Alexandre Julliard 2008-02-27 19:13:09 +01:00
parent 5a5344b4ad
commit b76db19e88
3 changed files with 56 additions and 8 deletions

View File

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

View File

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

View File

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