From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 24 ++++++++++++++++++++++++ dlls/winex11.drv/window.c | 25 +++++++++++++++++++++++-- dlls/winex11.drv/x11drv.h | 3 +++ 3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index c5523ba27f6..718277ce4cb 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -172,6 +172,27 @@ static inline void free_event_data( XEvent *event ) #endif }
+static BOOL host_window_filter_event( XEvent *event ) +{ + struct host_window *win; + + if (!(win = get_host_window( event->xany.window, FALSE ))) return FALSE; + + switch (event->type) + { + case ReparentNotify: + { + XReparentEvent *reparent = (XReparentEvent *)event; + TRACE( "host window %p/%lx ReparentNotify, parent %lx\n", win, win->window, reparent->parent ); + host_window_set_parent( win, reparent->parent ); + break; + } + } + + /* keep processing the event for foreign windows */ + return FALSE; +} + /*********************************************************************** * xembed_request_focus */ @@ -445,6 +466,9 @@ BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer else continue; /* filtered, ignore it */ } + + if (host_window_filter_event( &event )) continue; + get_event_data( &event ); if (prev_event.type) action = merge_events( &prev_event, &event ); switch( action ) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 6d76a7849e7..81effbaa45c 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -130,14 +130,22 @@ static void host_window_release( struct host_window *win ) struct x11drv_thread_data *data = x11drv_thread_data();
XDeleteContext( data->display, host_window_context, win->window ); + if (win->parent) host_window_release( win->parent ); free( win ); } }
-static struct host_window *get_host_window( Window window, BOOL create ) +static int host_window_error( Display *display, XErrorEvent *event, void *arg ) +{ + return (event->error_code == BadWindow); +} + +struct host_window *get_host_window( Window window, BOOL create ) { struct x11drv_thread_data *data = x11drv_thread_data(); + Window xparent = 0, xroot, *xchildren; struct host_window *win; + unsigned int nchildren;
if (window == root_window) return NULL; if (!XFindContext( data->display, window, host_window_context, (XPointer *)&win )) return win; @@ -145,7 +153,14 @@ static struct host_window *get_host_window( Window window, BOOL create ) if (!create || !(win = calloc( 1, sizeof(*win) ))) return NULL; win->window = window;
- TRACE( "created host window %p/%lx\n", win, win->window ); + X11DRV_expect_error( data->display, host_window_error, NULL ); + if (!XQueryTree( data->display, window, &xroot, &xparent, &xchildren, &nchildren )) xparent = root_window; + else XFree( xchildren ); + if (X11DRV_check_error()) WARN( "window %lx already destroyed\n", window ); + + host_window_set_parent( win, xparent ); + + TRACE( "created host window %p/%lx, parent %lx\n", win, win->window, xparent ); XSaveContext( data->display, window, host_window_context, (char *)win ); return win; } @@ -157,6 +172,12 @@ static void host_window_reparent( struct host_window **win, Window parent, Windo if (old) host_window_release( old ); }
+void host_window_set_parent( struct host_window *win, Window parent ) +{ + TRACE( "host window %p/%lx, parent %lx\n", win, win->window, parent ); + host_window_reparent( &win->parent, parent, win->window ); +} +
/*********************************************************************** * http://standards.freedesktop.org/startup-notification-spec diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e6ec04ce050..4f555d8e32f 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -366,9 +366,12 @@ struct host_window { LONG refcount; Window window; + struct host_window *parent; };
extern void host_window_destroy( struct host_window *win ); +extern void host_window_set_parent( struct host_window *win, Window parent ); +extern struct host_window *get_host_window( Window window, BOOL create );
struct x11drv_thread_data {