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.
-- v7: 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 | 2 ++ dlls/winex11.drv/window.c | 68 +++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 12 +++++++ 3 files changed, 82 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 34a364e11e3..c5523ba27f6 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -996,6 +996,7 @@ static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *xev ) struct x11drv_win_data *data;
if (!(data = get_win_data( hwnd ))) return FALSE; + set_window_parent( data, event->parent );
if (!data->embedded) { @@ -1592,6 +1593,7 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event ) break; }
+ set_window_parent( data, data->embedder ); 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..81547b72bb4 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -98,6 +98,7 @@ XContext winContext = 0;
/* X context to associate a struct x11drv_win_data to an hwnd */ static XContext win_data_context = 0; +static XContext host_window_context = 0;
/* time of last user event and window where it's stored */ static Time last_user_time; @@ -112,6 +113,50 @@ static const WCHAR clip_window_prop[] =
static pthread_mutex_t win_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void host_window_add_ref( struct host_window *win ) +{ + int ref = ++win->refcount; + TRACE( "host window %p/%lx increasing refcount to %d\n", win, win->window, ref ); +} + +static void host_window_release( struct host_window *win ) +{ + int ref = --win->refcount; + + TRACE( "host window %p/%lx decreasing refcount to %d\n", win, win->window, ref ); + + if (!ref) + { + struct x11drv_thread_data *data = x11drv_thread_data(); + + XDeleteContext( data->display, win->window, host_window_context ); + free( win ); + } +} + +static struct host_window *get_host_window( Window window, BOOL create ) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + struct host_window *win; + + if (window == root_window) return NULL; + if (!XFindContext( data->display, window, host_window_context, (XPointer *)&win )) return win; + + if (!create || !(win = calloc( 1, sizeof(*win) ))) return NULL; + win->window = window; + + TRACE( "created host window %p/%lx\n", win, win->window ); + XSaveContext( data->display, window, host_window_context, (char *)win ); + return win; +} + +static void host_window_reparent( struct host_window **win, Window parent, Window window ) +{ + struct host_window *old = *win, *new = get_host_window( parent, TRUE ); + if ((*win = new)) host_window_add_ref( new ); + if (old) host_window_release( old ); +} +
/*********************************************************************** * http://standards.freedesktop.org/startup-notification-spec @@ -1762,6 +1807,18 @@ 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 ); + + /* It's possible that we are in a different thread, when called from + * set_window_visual, and about to recreate the window. In this case + * just set a window flag to indicate the parent isn't valid and let + * the thread eventually replace it with the proper one later on. + */ + if (data->display != thread_init_display()) data->parent_invalid = 1; + else if (data->parent) + { + host_window_release( data->parent ); + data->parent = NULL; + } }
@@ -1847,6 +1904,7 @@ void X11DRV_DestroyWindow( HWND hwnd ) if (thread_data->last_xic_hwnd == hwnd) thread_data->last_xic_hwnd = 0; if (data->icon_pixmap) XFreePixmap( gdi_display, data->icon_pixmap ); if (data->icon_mask) XFreePixmap( gdi_display, data->icon_mask ); + if (data->parent) host_window_release( data->parent ); free( data->icon_bits ); XDeleteContext( gdi_display, (XID)hwnd, win_data_context ); release_win_data( data ); @@ -2032,6 +2090,15 @@ void release_win_data( struct x11drv_win_data *data ) if (data) pthread_mutex_unlock( &win_data_mutex ); }
+/* update the whole window parent host window, must be called from the window's owner thread */ +void set_window_parent( struct x11drv_win_data *data, Window parent ) +{ + if (!data->whole_window) return; /* only keep track of parent if we have a toplevel */ + TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, parent ); + host_window_reparent( &data->parent, parent, data->whole_window ); + data->parent_invalid = 0; +} +
/*********************************************************************** * X11DRV_create_win_data @@ -3110,5 +3177,6 @@ void init_win_context(void)
winContext = XUniqueContext(); win_data_context = XUniqueContext(); + host_window_context = XUniqueContext(); cursor_context = XUniqueContext(); } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 2ecf3cb54cd..e6ec04ce050 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -361,6 +361,15 @@ extern HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ); * X11 USER driver */
+/* thread-local host-only window, for X11 relative position tracking */ +struct host_window +{ + LONG refcount; + Window window; +}; + +extern void host_window_destroy( struct host_window *win ); + struct x11drv_thread_data { Display *display; @@ -600,6 +609,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 or embedder, NULL if root_window */ XIC xic; /* X input context */ UINT managed : 1; /* is window managed? */ UINT mapped : 1; /* is window mapped? (in either normal or iconic state) */ @@ -612,6 +622,7 @@ struct x11drv_win_data UINT add_taskbar : 1; /* does window should be added to taskbar regardless of style */ UINT net_wm_fullscreen_monitors_set : 1; /* is _NET_WM_FULLSCREEN_MONITORS set */ UINT is_fullscreen : 1; /* is the window visible rect fullscreen */ + UINT parent_invalid : 1; /* is the parent host window possibly invalid */ int wm_state; /* current value of the WM_STATE property */ DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */ Window embedder; /* window id of embedder */ @@ -624,6 +635,7 @@ struct x11drv_win_data
extern struct x11drv_win_data *get_win_data( HWND hwnd ); extern void release_win_data( struct x11drv_win_data *data ); +extern void set_window_parent( struct x11drv_win_data *data, Window parent ); extern Window X11DRV_get_whole_window( HWND hwnd ); extern Window get_dummy_parent(void);
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 81547b72bb4..64fc91e02bf 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, win->window, host_window_context ); + 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 {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 26 ++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 ++ 2 files changed, 28 insertions(+)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 64fc91e02bf..f4ea317824d 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -131,10 +131,18 @@ static void host_window_release( struct host_window *win )
XDeleteContext( data->display, win->window, host_window_context ); if (win->parent) host_window_release( win->parent ); + free( win->children ); free( 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); @@ -168,7 +176,25 @@ struct host_window *get_host_window( Window window, BOOL create ) static void host_window_reparent( struct host_window **win, Window parent, Window window ) { struct host_window *old = *win, *new = get_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 4f555d8e32f..1c2468e8a63 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -367,6 +367,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 | 23 +++++++++++++++++++++++ dlls/winex11.drv/window.c | 31 ++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 2 ++ 3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 718277ce4cb..c13762996fc 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -187,6 +187,22 @@ static BOOL host_window_filter_event( XEvent *event ) host_window_set_parent( win, reparent->parent ); break; } + case GravityNotify: + { + XGravityEvent *gravity = (XGravityEvent *)event; + OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); + if (win->parent) 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; + SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); + if (win->parent) 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; + } }
/* keep processing the event for foreign windows */ @@ -1091,6 +1107,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 && data->parent && !data->parent_invalid) + { + 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 */ diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index f4ea317824d..0c8db3dedef 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -136,6 +136,20 @@ static 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}; + + while (win) + { + 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; @@ -153,6 +167,7 @@ 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; + XWindowAttributes attr; unsigned int nchildren;
if (window == root_window) return NULL; @@ -162,13 +177,16 @@ struct host_window *get_host_window( Window window, BOOL create ) win->window = 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_set_parent( win, xparent ); + 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) ); XSaveContext( data->display, window, host_window_context, (char *)win ); return win; } @@ -198,6 +216,17 @@ static void host_window_reparent( struct host_window **win, Window parent, Windo if (old) host_window_release( old ); }
+RECT host_window_configure_child( struct host_window *win, Window window, RECT rect, BOOL root_coords ) +{ + if (root_coords) + { + POINT offset = host_window_map_point( win, 0, 0 ); + OffsetRect( &rect, -offset.x, -offset.y ); + } + + return rect; +} + void host_window_set_parent( struct host_window *win, Window parent ) { TRACE( "host window %p/%lx, parent %lx\n", win, win->window, parent ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 1c2468e8a63..59c18a91a13 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -366,6 +366,7 @@ struct host_window { LONG refcount; Window window; + RECT rect; /* host window rect, relative to parent */ struct host_window *parent; unsigned int children_count; struct { Window window; } *children; @@ -373,6 +374,7 @@ struct host_window
extern void host_window_destroy( struct host_window *win ); extern void host_window_set_parent( struct host_window *win, Window parent ); +extern RECT host_window_configure_child( struct host_window *win, Window window, RECT rect, BOOL root_coords ); extern struct host_window *get_host_window( Window window, BOOL create );
struct x11drv_thread_data
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 12 ++++++++++++ dlls/winex11.drv/x11drv.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0c8db3dedef..0e2c587e858 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -184,6 +184,7 @@ struct host_window *get_host_window( Window window, BOOL create )
host_window_set_parent( win, xparent ); SetRect( &win->rect, attr.x, attr.y, attr.x + attr.width, attr.y + attr.height ); + if (win->parent) 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, xparent, wine_dbgstr_rect(&win->rect) ); @@ -195,12 +196,14 @@ static void host_window_reparent( struct host_window **win, Window parent, Windo { struct host_window *old = *win, *new = get_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--; } @@ -209,7 +212,11 @@ static void host_window_reparent( struct host_window **win, Window parent, 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++; }
@@ -218,12 +225,16 @@ static void host_window_reparent( struct host_window **win, Window parent, Windo
RECT host_window_configure_child( struct host_window *win, Window window, RECT rect, BOOL root_coords ) { + unsigned int index; + if (root_coords) { POINT offset = host_window_map_point( win, 0, 0 ); OffsetRect( &rect, -offset.x, -offset.y ); }
+ index = find_host_window_child( win, window ); + if (index < win->children_count) win->children[index].rect = rect; return rect; }
@@ -2172,6 +2183,7 @@ void set_window_parent( struct x11drv_win_data *data, Window parent ) if (!data->whole_window) return; /* only keep track of parent if we have a toplevel */ TRACE( "window %p/%lx, parent %lx\n", data->hwnd, data->whole_window, parent ); host_window_reparent( &data->parent, parent, data->whole_window ); + if (data->parent) host_window_configure_child( data->parent, data->whole_window, data->rects.visible, TRUE ); data->parent_invalid = 0; }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 59c18a91a13..b8711f30b1a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -369,7 +369,7 @@ 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 );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 4 ++++ dlls/winex11.drv/window.c | 7 ++----- dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index c13762996fc..ab2d0117238 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -180,6 +180,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 0e2c587e858..299ea8cdcd5 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -129,6 +129,7 @@ static void host_window_release( struct host_window *win ) { struct x11drv_thread_data *data = x11drv_thread_data();
+ if (!win->destroyed) XSelectInput( data->display, win->window, 0 ); XDeleteContext( data->display, win->window, host_window_context ); if (win->parent) host_window_release( win->parent ); free( win->children ); @@ -177,6 +178,7 @@ struct host_window *get_host_window( Window window, BOOL create ) win->window = 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 ); @@ -1861,7 +1863,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 ); } @@ -2267,13 +2268,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 b8711f30b1a..388a6d4fc86 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -366,6 +366,7 @@ struct host_window { 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 ab2d0117238..b5077a2fecf 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -175,8 +175,10 @@ static inline void free_event_data( XEvent *event ) static BOOL host_window_filter_event( XEvent *event ) { struct host_window *win; + RECT old_rect;
if (!(win = get_host_window( event->xany.window, FALSE ))) return FALSE; + old_rect = win->rect;
switch (event->type) { @@ -209,6 +211,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 | 119 +++------------------------------ dlls/winex11.drv/mouse.c | 16 ++--- dlls/winex11.drv/systray.c | 55 --------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/window.c | 98 +-------------------------- dlls/winex11.drv/x11drv.h | 3 +- dlls/winex11.drv/x11drv_dll.h | 3 - dlls/winex11.drv/x11drv_main.c | 2 - 10 files changed, 18 insertions(+), 281 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 b5077a2fecf..000ba3e55ce 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 */ @@ -1020,40 +1019,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 */ @@ -1086,39 +1051,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 */ @@ -1127,9 +1062,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; @@ -1142,9 +1077,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", @@ -1153,9 +1086,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 );
@@ -1224,43 +1159,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 */ @@ -1670,7 +1568,6 @@ static void handle_xembed_protocol( HWND hwnd, XClientMessageEvent *event ) set_window_parent( data, data->embedder ); 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 299ea8cdcd5..b3ffbfb2a90 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -104,8 +104,6 @@ static XContext host_window_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[] = @@ -137,7 +135,7 @@ static void host_window_release( struct host_window *win ) } }
-static POINT host_window_map_point( struct host_window *win, int x, int y ) +POINT host_window_map_point( struct host_window *win, int x, int y ) { POINT pos = {x, y};
@@ -1858,16 +1856,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 { @@ -2229,89 +2218,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 388a6d4fc86..d0a9b57ebc2 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -376,6 +376,7 @@ struct host_window extern void host_window_destroy( struct host_window *win ); extern void host_window_set_parent( struct host_window *win, Window parent ); extern RECT host_window_configure_child( struct host_window *win, Window window, RECT rect, BOOL root_coords ); +extern POINT host_window_map_point( struct host_window *win, int x, int y ); extern struct host_window *get_host_window( Window window, BOOL create );
struct x11drv_thread_data @@ -450,7 +451,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 +664,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 3f8e48a7a8d..490a662c16a 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 );
v6: Rebase and remove the bogus thread detach cleanup, it should be unnecessary now if all window data is properly released.
I don't see anything too suspicious in the tests failures, I think it should be alright now.