Making all the windows handled by the driver to be either GL/VK client surfaces, or top-level windows. This avoids leaking host windows into the Win32 space, and makes it possible to get rid of some remaining NtUserMapWindowPoints in `map_event_coords` for mouse input.
-- v3: winex11: Get rid of the now unnecessary foreign windows. winex11: Generate relative ConfigureNotify on parent ConfigureNotify events. winex11: Use the new host windows to register foreign window events. winex11: Keep track of the host windows children window rects. winex11: Keep track of the host windows relative rects. winex11: Keep track of the host window children of interest. winex11: Create host windows recursively up to root_window. winex11: Introduce a new struct host_window for host-only windows.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 61 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/window.c | 12 +++++++ dlls/winex11.drv/x11drv.h | 14 ++++++++ dlls/winex11.drv/x11drv_main.c | 8 +++++ 4 files changed, 95 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 34a364e11e3..f1f5fced091 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -172,6 +172,55 @@ static inline void free_event_data( XEvent *event ) #endif }
+static void host_window_add_ref( struct host_window *win ) +{ + int ref = InterlockedIncrement( &win->refcount ); + TRACE( "host window %p/%lx increasing refcount to %d\n", win, win->window, ref ); +} + +void host_window_destroy( struct host_window *win ) +{ + TRACE( "host window %p/%lx\n", win, win->window ); + + free( win ); +} + +void host_window_release( struct host_window *win ) +{ + int ref = InterlockedDecrement( &win->refcount ); + + TRACE( "host window %p/%lx decreasing refcount to %d\n", win, win->window, ref ); + + if (!ref) + { + list_remove( &win->entry ); + host_window_destroy( win ); + } +} + +static struct host_window *find_host_window( Window window, BOOL create ) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + struct host_window *win; + + LIST_FOR_EACH_ENTRY( win, &data->host_windows, struct host_window, entry ) + if (win->window == window) return win; + + if (!create || !(win = calloc( 1, sizeof(*win) ))) return NULL; + win->window = window; + + TRACE( "created host window %p/%lx\n", win, win->window ); + list_add_tail( &data->host_windows, &win->entry ); + return win; +} + +void host_window_reparent( struct host_window **win, Window parent, Window window ) +{ + struct host_window *old = *win, *new = find_host_window( parent, TRUE ); + if ((*win = new)) host_window_add_ref( new ); + if (old) host_window_release( old ); +} + /*********************************************************************** * xembed_request_focus */ @@ -997,6 +1046,12 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev )
if (!(data = get_win_data( hwnd ))) return FALSE;
+ if (data->whole_window) + { + TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, event->parent ); + host_window_reparent( &data->parent, event->parent, data->whole_window ); + } + if (!data->embedded) { release_win_data( data ); @@ -1592,6 +1647,12 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event ) break; }
+ if (data->whole_window) + { + TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, data->embedder ); + host_window_reparent( &data->parent, data->embedder, data->whole_window ); + } + make_window_embedded( data ); release_win_data( data ); reparent_notify( event->display, hwnd, event->data.l[3], 0, 0 ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ab17cb40a1c..403ba346c45 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1686,6 +1686,7 @@ static void create_whole_window( struct x11drv_win_data *data ) cx, cy, 0, data->vis.depth, InputOutput, data->vis.visual, mask, &attr ); if (!data->whole_window) goto done; + host_window_reparent( &data->parent, root_window, data->whole_window );
x11drv_xinput2_enable( data->display, data->whole_window ); set_initial_wm_hints( data->display, data->whole_window ); @@ -1762,6 +1763,12 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des /* Outlook stops processing messages after destroying a dialog, so we need an explicit flush */ XFlush( data->display ); NtUserRemoveProp( data->hwnd, whole_window_prop ); + + if (data->parent) + { + host_window_release( data->parent ); + data->parent = NULL; + } }
@@ -1864,6 +1871,11 @@ BOOL X11DRV_DestroyNotify( HWND hwnd, XEvent *event ) BOOL embedded;
if (!(data = get_win_data( hwnd ))) return FALSE; + if (data->parent) + { + host_window_release( data->parent ); + data->parent = NULL; + } embedded = data->embedded; if (!embedded) FIXME( "window %p/%lx destroyed from the outside\n", hwnd, data->whole_window );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 622658a6377..e77eaafc215 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -361,6 +361,18 @@ extern HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ); * X11 USER driver */
+/* host-only window, for X11 relative position tracking */ +struct host_window +{ + struct list entry; + LONG refcount; + Window window; +}; + +extern void host_window_destroy( struct host_window *win ); +extern void host_window_release( struct host_window *win ); +extern void host_window_reparent( struct host_window **win, Window parent, Window window ); + struct x11drv_thread_data { Display *display; @@ -380,6 +392,7 @@ struct x11drv_thread_data XIValuatorClassInfo y_valuator; int xinput2_pointer; /* XInput2 master pointer device id */ #endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */ + struct list host_windows; /* list of host windows tracked from this thread */ };
extern struct x11drv_thread_data *x11drv_init_thread_data(void); @@ -600,6 +613,7 @@ struct x11drv_win_data Window whole_window; /* X window for the complete window */ Window client_window; /* X window for the client area */ struct window_rects rects; /* window rects in monitor DPI, relative to parent client area */ + struct host_window *parent; /* the host window parent, frame, root window or embedder */ XIC xic; /* X input context */ UINT managed : 1; /* is window managed? */ UINT mapped : 1; /* is window mapped? (in either normal or iconic state) */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 3f8e48a7a8d..056f9fb176e 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -699,9 +699,16 @@ static NTSTATUS x11drv_init( void *arg ) void X11DRV_ThreadDetach(void) { struct x11drv_thread_data *data = x11drv_thread_data(); + struct host_window *win, *next;
if (data) { + LIST_FOR_EACH_ENTRY_SAFE( win, next, &data->host_windows, struct host_window, entry ) + { + list_remove( &win->entry ); + host_window_destroy( win ); + } + if (data->xim) XCloseIM( data->xim ); if (data->font_set) XFreeFontSet( data->display, data->font_set ); XSync( gdi_display, False ); /* make sure XReparentWindow requests have completed before closing the thread display */ @@ -758,6 +765,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) ERR_(winediag)( "x11drv: Can't open display: %s. Please ensure that your X server is running and that $DISPLAY is set correctly.\n", XDisplayName(NULL)); NtTerminateProcess( 0, 1 ); } + list_init( &data->host_windows );
fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 44 ++++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 1 + 2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index f1f5fced091..05ecbeb8050 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -182,6 +182,7 @@ void host_window_destroy( struct host_window *win ) { TRACE( "host window %p/%lx\n", win, win->window );
+ if (win->parent) host_window_release( win->parent ); free( win ); }
@@ -198,10 +199,17 @@ void host_window_release( struct host_window *win ) } }
+static int host_window_error( Display *display, XErrorEvent *event, void *arg ) +{ + return (event->error_code == BadWindow); +} + static struct host_window *find_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;
LIST_FOR_EACH_ENTRY( win, &data->host_windows, struct host_window, entry ) if (win->window == window) return win; @@ -209,7 +217,17 @@ static struct host_window *find_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 ); + if (window != root_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_reparent( &win->parent, xparent, win->window ); + } + + TRACE( "created host window %p/%lx, parent %lx\n", win, win->window, xparent ); list_add_tail( &data->host_windows, &win->entry ); return win; } @@ -221,6 +239,27 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo if (old) host_window_release( old ); }
+static BOOL host_window_filter_event( XEvent *event ) +{ + struct host_window *win; + + if (!(win = find_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_reparent( &win->parent, reparent->parent, win->window ); + break; + } + } + + /* keep processing the event for foreign windows */ + return FALSE; +} + /*********************************************************************** * xembed_request_focus */ @@ -494,6 +533,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/x11drv.h b/dlls/winex11.drv/x11drv.h index e77eaafc215..8aa678e9f92 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,7 @@ struct host_window struct list entry; LONG refcount; Window window; + struct host_window *parent; };
extern void host_window_destroy( struct host_window *win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 26 ++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 ++ 2 files changed, 28 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 05ecbeb8050..41d486c8922 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -183,6 +183,7 @@ void host_window_destroy( struct host_window *win ) TRACE( "host window %p/%lx\n", win, win->window );
if (win->parent) host_window_release( win->parent ); + free( win->children ); free( win ); }
@@ -199,6 +200,13 @@ void host_window_release( struct host_window *win ) } }
+static unsigned int find_host_window_child( struct host_window *win, Window child ) +{ + unsigned int i; + for (i = 0; i < win->children_count; i++) if (win->children[i].window == child) break; + return i; +} + static int host_window_error( Display *display, XErrorEvent *event, void *arg ) { return (event->error_code == BadWindow); @@ -235,7 +243,25 @@ static struct host_window *find_host_window( Window window, BOOL create ) void host_window_reparent( struct host_window **win, Window parent, Window window ) { struct host_window *old = *win, *new = find_host_window( parent, TRUE ); + unsigned int index; + void *tmp; + if ((*win = new)) host_window_add_ref( new ); + + if (old && (index = find_host_window_child( old, window )) < old->children_count) + { + old->children[index] = old->children[old->children_count - 1]; + old->children_count--; + } + + if (new && (index = find_host_window_child( new, window )) == new->children_count) + { + if (!(tmp = realloc( new->children, (index + 1) * sizeof(*new->children) ))) return; + new->children = tmp; + new->children[index].window = window; + new->children_count++; + } + if (old) host_window_release( old ); }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 8aa678e9f92..fc5ab81f282 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -368,6 +368,8 @@ struct host_window LONG refcount; Window window; struct host_window *parent; + unsigned int children_count; + struct { Window window; } *children; };
extern void host_window_destroy( struct host_window *win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 38 +++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 41d486c8922..2b857340c78 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -200,6 +200,21 @@ void host_window_release( struct host_window *win ) } }
+static POINT host_window_map_point( struct host_window *win, int x, int y ) +{ + POINT pos = {x, y}; + + if (!win) return pos; + while (win->parent) + { + pos.x += win->rect.left; + pos.y += win->rect.top; + win = win->parent; + } + + return pos; +} + static unsigned int find_host_window_child( struct host_window *win, Window child ) { unsigned int i; @@ -217,6 +232,7 @@ static struct host_window *find_host_window( Window window, BOOL create ) struct x11drv_thread_data *data = x11drv_thread_data(); Window xparent = 0, xroot, *xchildren; struct host_window *win; + XWindowAttributes attr; unsigned int nchildren;
LIST_FOR_EACH_ENTRY( win, &data->host_windows, struct host_window, entry ) @@ -228,14 +244,17 @@ static struct host_window *find_host_window( Window window, BOOL create ) if (window != root_window) { X11DRV_expect_error( data->display, host_window_error, NULL ); + if (!XGetWindowAttributes( data->display, window, &attr )) memset( &attr, 0, sizeof(attr) ); 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_reparent( &win->parent, xparent, win->window ); + SetRect( &win->rect, attr.x, attr.y, attr.x + attr.width, attr.y + attr.height ); }
- TRACE( "created host window %p/%lx, parent %lx\n", win, win->window, xparent ); + TRACE( "created host window %p/%lx, parent %lx rect %s\n", win, win->window, + xparent, wine_dbgstr_rect(&win->rect) ); list_add_tail( &data->host_windows, &win->entry ); return win; } @@ -280,6 +299,23 @@ static BOOL host_window_filter_event( XEvent *event ) host_window_reparent( &win->parent, reparent->parent, win->window ); break; } + case GravityNotify: + { + XGravityEvent *gravity = (XGravityEvent *)event; + OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); + TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); + break; + } + case ConfigureNotify: + { + XConfigureEvent *configure = (XConfigureEvent *)event; + POINT offset = {0}; + SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); + if (configure->send_event) offset = host_window_map_point( win->parent, 0, 0 ); + OffsetRect( &win->rect, -offset.x, -offset.y ); + TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); + break; + } }
/* keep processing the event for foreign windows */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index fc5ab81f282..3518f005f6c 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,7 @@ struct host_window struct list entry; LONG refcount; Window window; + RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count; struct { Window window; } *children;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 36 +++++++++++++++++++++++++++++++++--- dlls/winex11.drv/window.c | 1 + dlls/winex11.drv/x11drv.h | 3 ++- 3 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 2b857340c78..34778fd6c5d 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -222,6 +222,21 @@ static unsigned int find_host_window_child( struct host_window *win, Window chil return i; }
+RECT host_window_configure_child( struct host_window *parent, Window window, RECT rect, BOOL root_coords ) +{ + unsigned int index; + POINT offset = {0}; + + if (parent && (index = find_host_window_child( parent, window )) != parent->children_count) + { + if (root_coords) offset = host_window_map_point( parent, 0, 0 ); + OffsetRect( &rect, -offset.x, -offset.y ); + parent->children[index].rect = rect; + } + + return rect; +} + static int host_window_error( Display *display, XErrorEvent *event, void *arg ) { return (event->error_code == BadWindow); @@ -251,6 +266,7 @@ static struct host_window *find_host_window( Window window, BOOL create )
host_window_reparent( &win->parent, xparent, win->window ); SetRect( &win->rect, attr.x, attr.y, attr.x + attr.width, attr.y + attr.height ); + host_window_configure_child( win->parent, win->window, win->rect, FALSE ); }
TRACE( "created host window %p/%lx, parent %lx rect %s\n", win, win->window, @@ -263,12 +279,14 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo { struct host_window *old = *win, *new = find_host_window( parent, TRUE ); unsigned int index; + RECT rect = {0}; void *tmp;
if ((*win = new)) host_window_add_ref( new );
if (old && (index = find_host_window_child( old, window )) < old->children_count) { + rect = old->children[index].rect; old->children[index] = old->children[old->children_count - 1]; old->children_count--; } @@ -277,7 +295,11 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo { if (!(tmp = realloc( new->children, (index + 1) * sizeof(*new->children) ))) return; new->children = tmp; + + OffsetRect( &rect, -rect.left, -rect.top ); new->children[index].window = window; + new->children[index].rect = rect; + new->children_count++; }
@@ -303,16 +325,15 @@ static BOOL host_window_filter_event( XEvent *event ) { XGravityEvent *gravity = (XGravityEvent *)event; OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); + win->rect = host_window_configure_child( win->parent, win->window, win->rect, FALSE ); TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); break; } case ConfigureNotify: { XConfigureEvent *configure = (XConfigureEvent *)event; - POINT offset = {0}; SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); - if (configure->send_event) offset = host_window_map_point( win->parent, 0, 0 ); - OffsetRect( &win->rect, -offset.x, -offset.y ); + win->rect = host_window_configure_child( win->parent, win->window, win->rect, configure->send_event ); TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); break; } @@ -1154,6 +1175,7 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev ) { TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, event->parent ); host_window_reparent( &data->parent, event->parent, data->whole_window ); + host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE ); }
if (!data->embedded) @@ -1225,6 +1247,13 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
if (!hwnd) return FALSE; if (!(data = get_win_data( hwnd ))) return FALSE; + + if (data->whole_window) + { + SetRect( &rect, event->x, event->y, event->x + event->width, event->y + event->height ); + host_window_configure_child( data->parent, data->whole_window, rect, event->send_event ); + } + if (!data->mapped || data->iconic) goto done; if (data->whole_window && !data->managed) goto done; /* ignore synthetic events on foreign windows */ @@ -1755,6 +1784,7 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event ) { TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, data->embedder ); host_window_reparent( &data->parent, data->embedder, data->whole_window ); + host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE ); }
make_window_embedded( data ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 403ba346c45..bc15837190a 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1687,6 +1687,7 @@ static void create_whole_window( struct x11drv_win_data *data ) data->vis.visual, mask, &attr ); if (!data->whole_window) goto done; host_window_reparent( &data->parent, root_window, data->whole_window ); + host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE );
x11drv_xinput2_enable( data->display, data->whole_window ); set_initial_wm_hints( data->display, data->whole_window ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 3518f005f6c..e447c81e5df 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -370,12 +370,13 @@ struct host_window RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count; - struct { Window window; } *children; + struct { Window window; RECT rect; } *children; };
extern void host_window_destroy( struct host_window *win ); extern void host_window_release( struct host_window *win ); extern void host_window_reparent( struct host_window **win, Window parent, Window window ); +extern RECT host_window_configure_child( struct host_window *win, Window window, RECT rect, BOOL root_coords );
struct x11drv_thread_data {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 8 ++++++++ dlls/winex11.drv/window.c | 5 ----- dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 34778fd6c5d..0c16d8151d2 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -180,9 +180,12 @@ static void host_window_add_ref( struct host_window *win )
void host_window_destroy( struct host_window *win ) { + struct x11drv_thread_data *data = x11drv_thread_data(); + TRACE( "host window %p/%lx\n", win, win->window );
if (win->parent) host_window_release( win->parent ); + if (!win->destroyed) XSelectInput( data->display, win->window, 0 ); free( win->children ); free( win ); } @@ -259,6 +262,7 @@ static struct host_window *find_host_window( Window window, BOOL create ) if (window != root_window) { X11DRV_expect_error( data->display, host_window_error, NULL ); + XSelectInput( data->display, window, StructureNotifyMask ); if (!XGetWindowAttributes( data->display, window, &attr )) memset( &attr, 0, sizeof(attr) ); if (!XQueryTree( data->display, window, &xroot, &xparent, &xchildren, &nchildren )) xparent = root_window; else XFree( xchildren ); @@ -314,6 +318,10 @@ static BOOL host_window_filter_event( XEvent *event )
switch (event->type) { + case DestroyNotify: + TRACE( "host window %p/%lx DestroyNotify\n", win, win->window ); + win->destroyed = TRUE; + break; case ReparentNotify: { XReparentEvent *reparent = (XReparentEvent *)event; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index bc15837190a..8caa7fc72a3 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1731,7 +1731,6 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des Window xwin = (Window)NtUserGetProp( data->hwnd, foreign_window_prop ); if (xwin) { - if (!already_destroyed) XSelectInput( data->display, xwin, 0 ); XDeleteContext( data->display, xwin, winContext ); NtUserRemoveProp( data->hwnd, foreign_window_prop ); } @@ -2125,13 +2124,9 @@ HWND create_foreign_window( Display *display, Window xwin ) if (XFindContext( display, xwin, winContext, (char **)&hwnd )) hwnd = 0; if (hwnd) return hwnd; /* already created */
- XSelectInput( display, xwin, StructureNotifyMask ); if (!XGetWindowAttributes( display, xwin, &attr ) || !XQueryTree( display, xwin, &xroot, &xparent, &xchildren, &nchildren )) - { - XSelectInput( display, xwin, 0 ); return 0; - } XFree( xchildren );
if (xparent == xroot) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e447c81e5df..ff63220df9a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,7 @@ struct host_window struct list entry; LONG refcount; Window window; + BOOL destroyed; /* host window has already been destroyed */ RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 0c16d8151d2..44198cae371 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -313,8 +313,10 @@ void host_window_reparent( struct host_window **win, Window parent, Window windo static BOOL host_window_filter_event( XEvent *event ) { struct host_window *win; + RECT old_rect;
if (!(win = find_host_window( event->xany.window, FALSE ))) return FALSE; + old_rect = win->rect;
switch (event->type) { @@ -347,6 +349,27 @@ static BOOL host_window_filter_event( XEvent *event ) } }
+ if (old_rect.left != win->rect.left || old_rect.top != win->rect.top) + { + XConfigureEvent configure = {.type = ConfigureNotify, .serial = event->xany.serial, .display = event->xany.display}; + unsigned int i; + + for (i = 0; i < win->children_count; i++) + { + RECT rect = win->children[i].rect; + + configure.event = win->children[i].window; + configure.window = configure.event; + configure.x = rect.left; + configure.y = rect.top; + configure.width = rect.right - rect.left; + configure.height = rect.bottom - rect.top; + configure.send_event = 0; + + XPutBackEvent( configure.display, (XEvent *)&configure ); + } + } + /* keep processing the event for foreign windows */ return FALSE; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/Makefile.in | 1 - dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/event.c | 122 +++------------------------------ dlls/winex11.drv/mouse.c | 16 ++--- dlls/winex11.drv/systray.c | 55 --------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/window.c | 96 +------------------------- dlls/winex11.drv/x11drv.h | 2 - dlls/winex11.drv/x11drv_dll.h | 3 - dlls/winex11.drv/x11drv_main.c | 2 - 10 files changed, 17 insertions(+), 282 deletions(-) delete mode 100644 dlls/winex11.drv/systray.c
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in index f570b026db4..155c0be5345 100644 --- a/dlls/winex11.drv/Makefile.in +++ b/dlls/winex11.drv/Makefile.in @@ -20,7 +20,6 @@ SOURCES = \ opengl.c \ palette.c \ pen.c \ - systray.c \ version.rc \ vulkan.c \ window.c \ diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 14336adf583..01e5d417800 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -34,7 +34,6 @@ BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) .dnd_post_drop_callback = (UINT_PTR)x11drv_dnd_post_drop, .dnd_drop_event_callback = (UINT_PTR)x11drv_dnd_drop_event, .dnd_leave_event_callback = (UINT_PTR)x11drv_dnd_leave_event, - .foreign_window_proc = (UINT_PTR)foreign_window_proc, };
if (reason != DLL_PROCESS_ATTACH) return TRUE; diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 44198cae371..5e6611c5676 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -89,7 +89,6 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ClientMessage( HWND hwnd, XEvent *event ); -static BOOL X11DRV_GravityNotify( HWND hwnd, XEvent *event );
#define MAX_EVENT_HANDLERS 128
@@ -119,7 +118,7 @@ static x11drv_event_handler handlers[MAX_EVENT_HANDLERS] = X11DRV_ReparentNotify, /* 21 ReparentNotify */ X11DRV_ConfigureNotify, /* 22 ConfigureNotify */ NULL, /* 23 ConfigureRequest */ - X11DRV_GravityNotify, /* 24 GravityNotify */ + NULL, /* 24 GravityNotify */ NULL, /* 25 ResizeRequest */ NULL, /* 26 CirculateNotify */ NULL, /* 27 CirculateRequest */ @@ -370,8 +369,7 @@ static BOOL host_window_filter_event( XEvent *event ) } }
- /* keep processing the event for foreign windows */ - return FALSE; + return TRUE; }
/*********************************************************************** @@ -1158,40 +1156,6 @@ static BOOL X11DRV_UnmapNotify( HWND hwnd, XEvent *event ) }
-/*********************************************************************** - * reparent_notify - */ -static void reparent_notify( Display *display, HWND hwnd, Window xparent, int x, int y ) -{ - HWND parent, old_parent; - DWORD style, flags = 0; - RECT rect; - - style = NtUserGetWindowLongW( hwnd, GWL_STYLE ); - if (xparent == root_window) - { - parent = NtUserGetDesktopWindow(); - style = (style & ~WS_CHILD) | WS_POPUP; - } - else - { - if (!(parent = create_foreign_window( display, xparent ))) return; - style = (style & ~WS_POPUP) | WS_CHILD; - } - - NtUserShowWindow( hwnd, SW_HIDE ); - old_parent = NtUserSetParent( hwnd, parent ); - NtUserSetWindowLong( hwnd, GWL_STYLE, style, FALSE ); - - if (style & WS_VISIBLE) flags = SWP_SHOWWINDOW; - SetRect( &rect, x, y, x, y ); - NtUserSetRawWindowPos( hwnd, rect, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS | flags, FALSE ); - - /* make old parent destroy itself if it no longer has children */ - if (old_parent != NtUserGetDesktopWindow()) NtUserPostMessage( old_parent, WM_CLOSE, 0, 0 ); -} - - /*********************************************************************** * X11DRV_ReparentNotify */ @@ -1230,39 +1194,9 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev )
TRACE( "%p/%lx reparented to %lx\n", hwnd, data->whole_window, event->parent ); release_win_data( data ); - - reparent_notify( event->display, hwnd, event->parent, event->x, event->y ); return TRUE; }
-/* map XConfigureNotify event coordinates to parent-relative monitor DPI coordinates */ -static POINT map_configure_event_coords( struct x11drv_win_data *data, XConfigureEvent *event ) -{ - Window child, parent = data->embedder ? data->embedder : root_window; - POINT pos; - - if (event->send_event && parent == DefaultRootWindow( event->display )) - { - pos.x = event->x; - pos.y = event->y; - } - else if (event->send_event) - { - /* synthetic events are always in root coords */ - XTranslateCoordinates( event->display, DefaultRootWindow( event->display ), parent, - event->x, event->y, (int *)&pos.x, (int *)&pos.y, &child ); - } - else - { - /* query the current window position, events are relative to their parent */ - XTranslateCoordinates( event->display, event->window, parent, 0, 0, - (int *)&pos.x, (int *)&pos.y, &child ); - } - - if (parent == root_window) pos = root_to_virtual_screen( pos.x, pos.y ); - return pos; -} - /*********************************************************************** * X11DRV_ConfigureNotify */ @@ -1271,9 +1205,9 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) XConfigureEvent *event = &xev->xconfigure; struct x11drv_win_data *data; RECT rect; - POINT pos; + POINT pos = {event->x, event->y}; UINT flags; - int cx, cy, x = event->x, y = event->y; + int cx, cy, x, y; DWORD style;
if (!hwnd) return FALSE; @@ -1286,9 +1220,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) }
if (!data->mapped || data->iconic) goto done; - if (data->whole_window && !data->managed) goto done; - /* ignore synthetic events on foreign windows */ - if (event->send_event && !data->whole_window) goto done; + if (!data->whole_window || !data->managed) goto done; if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0) { TRACE( "win %p/%lx event %d,%d,%dx%d ignoring old serial %lu/%lu\n", @@ -1297,9 +1229,11 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) goto done; }
- /* Get geometry */ + /* synthetic events are already in absolute coordinates */ + if (!event->send_event) pos = host_window_map_point( data->parent, event->x, event->y ); + else if (is_virtual_desktop()) FIXME( "synthetic event mapping not implemented\n" );
- pos = map_configure_event_coords( data, event ); + pos = root_to_virtual_screen( pos.x, pos.y ); SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height ); rect = window_rect_from_visible( &data->rects, rect );
@@ -1368,43 +1302,6 @@ done: }
-/********************************************************************** - * X11DRV_GravityNotify - */ -static BOOL X11DRV_GravityNotify( HWND hwnd, XEvent *xev ) -{ - XGravityEvent *event = &xev->xgravity; - struct x11drv_win_data *data = get_win_data( hwnd ); - RECT window_rect; - int x, y; - - if (!data) return FALSE; - - if (data->whole_window) /* only handle this for foreign windows */ - { - release_win_data( data ); - return FALSE; - } - - x = event->x + data->rects.window.left - data->rects.visible.left; - y = event->y + data->rects.window.top - data->rects.visible.top; - - TRACE( "win %p/%lx new X pos %d,%d (event %d,%d)\n", - hwnd, data->whole_window, x, y, event->x, event->y ); - - window_rect = data->rects.window; - release_win_data( data ); - - if (window_rect.left != x || window_rect.top != y) - { - RECT rect = {x, y, x, y}; - NtUserSetRawWindowPos( hwnd, rect, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS, FALSE ); - } - - return TRUE; -} - - /*********************************************************************** * get_window_wm_state */ @@ -1820,7 +1717,6 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event )
make_window_embedded( data ); release_win_data( data ); - reparent_notify( event->display, hwnd, event->data.l[3], 0, 0 ); } break;
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 15557c3d917..cbbb27d6798 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -509,17 +509,15 @@ static void map_event_coords( HWND hwnd, Window window, Window event_root, int x { if (window == root_window) pt = root_to_virtual_screen( pt.x, pt.y ); else if (event_root == root_window) pt = root_to_virtual_screen( x_root, y_root ); + else if (window == data->client_window) + { + pt.x += data->rects.client.left; + pt.y += data->rects.client.top; + } else { - if (window == data->whole_window) - { - pt.x += data->rects.visible.left - data->rects.client.left; - pt.y += data->rects.visible.top - data->rects.client.top; - } - - if (NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) - pt.x = data->rects.client.right - data->rects.client.left - 1 - pt.x; - NtUserMapWindowPoints( hwnd, 0, &pt, 1, 0 /* per-monitor DPI */ ); + pt.x += data->rects.visible.left; + pt.y += data->rects.visible.top; } release_win_data( data ); } diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c deleted file mode 100644 index e21ce481f9b..00000000000 --- a/dlls/winex11.drv/systray.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * X11 system tray management - * - * Copyright (C) 2004 Mike Hearn, for CodeWeavers - * Copyright (C) 2005 Robert Shearman - * Copyright (C) 2008 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "x11drv_dll.h" -#include "commctrl.h" -#include "shellapi.h" - -#include "wine/list.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(systray); - -/* window procedure for foreign windows */ -LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) -{ - switch(msg) - { - case WM_WINDOWPOSCHANGED: - { - HWND hwnd = FindWindowW( L"Shell_TrayWnd", NULL ); - PostMessageW( hwnd, WM_USER + 0, 0, 0 ); - break; - } - case WM_PARENTNOTIFY: - if (LOWORD(wparam) == WM_DESTROY) - { - TRACE( "%p: got parent notify destroy for win %Ix\n", hwnd, lparam ); - PostMessageW( hwnd, WM_CLOSE, 0, 0 ); /* so that we come back here once the child is gone */ - } - return 0; - case WM_CLOSE: - if (GetWindow( hwnd, GW_CHILD )) return 0; /* refuse to die if we still have children */ - break; - } - return DefWindowProcW( hwnd, msg, wparam, lparam ); -} diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 522411f8e55..f23d7204bcd 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -40,7 +40,6 @@ struct init_params UINT64 dnd_post_drop_callback; UINT64 dnd_drop_event_callback; UINT64 dnd_leave_event_callback; - UINT64 foreign_window_proc; };
/* x11drv_tablet_info params */ diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8caa7fc72a3..9f01eb46f6c 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -103,8 +103,6 @@ static XContext win_data_context = 0; static Time last_user_time; static Window user_time_window;
-static const WCHAR foreign_window_prop[] = - {'_','_','w','i','n','e','_','x','1','1','_','f','o','r','e','i','g','n','_','w','i','n','d','o','w',0}; static const WCHAR whole_window_prop[] = {'_','_','w','i','n','e','_','x','1','1','_','w','h','o','l','e','_','w','i','n','d','o','w',0}; static const WCHAR clip_window_prop[] = @@ -1726,16 +1724,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
if (!data->whole_window) { - if (data->embedded) - { - Window xwin = (Window)NtUserGetProp( data->hwnd, foreign_window_prop ); - if (xwin) - { - XDeleteContext( data->display, xwin, winContext ); - NtUserRemoveProp( data->hwnd, foreign_window_prop ); - } - return; - } + if (data->embedded) return; } else { @@ -2085,89 +2074,6 @@ static struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd, const struct w }
-/*********************************************************************** - * create_foreign_window - * - * Create a foreign window for the specified X window and its ancestors - */ -HWND create_foreign_window( Display *display, Window xwin ) -{ - static BOOL class_registered; - struct x11drv_win_data *data; - HWND hwnd, parent; - POINT pos; - Window xparent, xroot; - Window *xchildren; - unsigned int nchildren; - XWindowAttributes attr; - UINT style = WS_CLIPCHILDREN; - UNICODE_STRING class_name = RTL_CONSTANT_STRING( foreign_window_prop ); - - if (!class_registered) - { - UNICODE_STRING version = { 0 }; - WNDCLASSEXW class; - - memset( &class, 0, sizeof(class) ); - class.cbSize = sizeof(class); - class.lpfnWndProc = (WNDPROC)(UINT_PTR)client_foreign_window_proc; - class.lpszClassName = foreign_window_prop; - if (!NtUserRegisterClassExWOW( &class, &class_name, &version, NULL, 0, 0, NULL ) && - RtlGetLastWin32Error() != ERROR_CLASS_ALREADY_EXISTS) - { - ERR( "Could not register foreign window class\n" ); - return FALSE; - } - class_registered = TRUE; - } - - if (XFindContext( display, xwin, winContext, (char **)&hwnd )) hwnd = 0; - if (hwnd) return hwnd; /* already created */ - - if (!XGetWindowAttributes( display, xwin, &attr ) || - !XQueryTree( display, xwin, &xroot, &xparent, &xchildren, &nchildren )) - return 0; - XFree( xchildren ); - - if (xparent == xroot) - { - parent = NtUserGetDesktopWindow(); - style |= WS_POPUP; - pos = root_to_virtual_screen( attr.x, attr.y ); - } - else - { - parent = create_foreign_window( display, xparent ); - style |= WS_CHILD; - pos.x = attr.x; - pos.y = attr.y; - } - - hwnd = NtUserCreateWindowEx( 0, &class_name, &class_name, NULL, style, pos.x, pos.y, - attr.width, attr.height, parent, 0, NULL, NULL, 0, NULL, - 0, FALSE ); - if (!(data = get_win_data( hwnd ))) - { - NtUserDestroyWindow( hwnd ); - return 0; - } - destroy_whole_window( data, FALSE ); - data->embedded = TRUE; - data->mapped = TRUE; - - NtUserSetProp( hwnd, foreign_window_prop, (HANDLE)xwin ); - XSaveContext( display, xwin, winContext, (char *)data->hwnd ); - - TRACE( "win %lx parent %p style %08x %s -> hwnd %p\n", - xwin, parent, style, wine_dbgstr_rect(&data->rects.window), hwnd ); - - release_win_data( data ); - - NtUserShowWindow( hwnd, SW_SHOW ); - return hwnd; -} - - /*********************************************************************** * SystrayDockInit (X11DRV.@) */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index ff63220df9a..26e9016cd34 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -452,7 +452,6 @@ extern int alloc_system_colors; extern int xrender_error_base; extern char *process_name; extern Display *clipboard_display; -extern UINT64 client_foreign_window_proc; extern UINT64 dnd_enter_event_callback; extern UINT64 dnd_position_event_callback; extern UINT64 dnd_post_drop_callback; @@ -664,7 +663,6 @@ extern void attach_client_window( struct x11drv_win_data *data, Window client_wi extern void destroy_client_window( HWND hwnd, Window client_window ); extern void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BOOL use_alpha ); extern void change_systray_owner( Display *display, Window systray_window ); -extern HWND create_foreign_window( Display *display, Window window ); extern BOOL update_clipboard( HWND hwnd ); extern void init_win_context(void); extern DROPFILES *file_list_to_drop_files( const void *data, size_t size, size_t *ret_size ); diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index bc68c3996c3..6113f01344a 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -33,9 +33,6 @@ extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ); extern NTSTATUS WINAPI x11drv_dnd_drop_event( void *params, ULONG size ); extern NTSTATUS WINAPI x11drv_dnd_leave_event( void *params, ULONG size );
-extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, - LPARAM lparam ); - extern HMODULE x11drv_module;
#endif /* __WINE_X11DRV_DLL_H */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 056f9fb176e..a607df01e3b 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -85,7 +85,6 @@ int copy_default_colors = 128; int alloc_system_colors = 256; int xrender_error_base = 0; char *process_name = NULL; -UINT64 client_foreign_window_proc = 0; UINT64 dnd_enter_event_callback = 0; UINT64 dnd_position_event_callback = 0; UINT64 dnd_post_drop_callback = 0; @@ -653,7 +652,6 @@ static NTSTATUS x11drv_init( void *arg ) dnd_post_drop_callback = params->dnd_post_drop_callback; dnd_drop_event_callback = params->dnd_drop_event_callback; dnd_leave_event_callback = params->dnd_leave_event_callback; - client_foreign_window_proc = params->foreign_window_proc;
fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */ root_window = DefaultRootWindow( display );
v2/v3: Fix a couple of crashes during cleanup. I think it should be good now, it seems to pass the tests mostly like current head (with the "usual" windowing failures). Getting rid of the MapWindowPoint is interesting for display mode virtualization.
Hmm actually there's still one fishy user32:msg test, having a look.