Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370
-- v3: winex11: Always generate ConfigureNotify events for embedded windows. winex11: Generate ConfigureNotify events for the children tree. winex11: Avoid overriding previously received ConfigureNotify events. winex11: Retrieve the HWND for the host window's child window. winex11: Introduce a new host_window_send_configure_events helper. winex11: Reset the window relative position when it gets reparented. winex11: Reset embedded window position to 0x0 before docking it.
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/window.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0c1738c26c6..98772f3d44e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2474,6 +2474,7 @@ BOOL X11DRV_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon ) window = data->whole_window; release_win_data( data );
+ NtUserSetWindowPos( hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOZORDER ); NtUserShowWindow( hwnd, SW_SHOWNA );
TRACE_(systray)( "icon window %p/%lx\n", hwnd, window );
From: Rémi Bernon rbernon@codeweavers.com
Instead of keeping the same offset as from the previous window parent, which may cause offsets to stack up with embedded windows.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/window.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 98772f3d44e..02a1eb13c48 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2320,7 +2320,12 @@ 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 ); + if (data->parent) + { + RECT rect = data->rects.visible; + OffsetRect( &rect, -rect.left, -rect.top ); + host_window_configure_child( data->parent, data->whole_window, rect, TRUE ); + } data->parent_invalid = 0; }
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/event.c | 68 +++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 32 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 22c15b50274..51554725700 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -171,6 +171,41 @@ static inline void free_event_data( XEvent *event ) #endif }
+static void host_window_send_configure_events( struct host_window *win, Display *display, unsigned long serial ) +{ + XConfigureEvent configure = {.type = ConfigureNotify, .serial = serial, .display = display}; + unsigned int i; + + for (i = 0; i < win->children_count; i++) + { + RECT rect = win->children[i].rect; + struct x11drv_win_data *data; + BOOL has_serial; + HWND hwnd; + + /* Only send a fake event if we're not expecting one from a state/config request. + * We may know what was requested, but not what the WM will decide to reply, and our + * fake event might trigger some undesired changes before the real ConfigureNotify. + */ + if (XFindContext( display, win->window, winContext, (char **)&hwnd )) continue; + if (!(data = get_win_data( hwnd ))) continue; + has_serial = data->wm_state_serial || data->configure_serial; + release_win_data( data ); + if (has_serial) continue; + + 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; + + TRACE( "generating ConfigureNotify for window %p/%lx, rect %s\n", hwnd, configure.window, wine_dbgstr_rect(&rect) ); + XPutBackEvent( configure.display, (XEvent *)&configure ); + } +} + static BOOL host_window_filter_event( XEvent *event ) { struct host_window *win; @@ -211,38 +246,7 @@ 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; - struct x11drv_win_data *data; - BOOL has_serial; - HWND hwnd; - - /* Only send a fake event if we're not expecting one from a state/config request. - * We may know what was requested, but not what the WM will decide to reply, and our - * fake event might trigger some undesired changes before the real ConfigureNotify. - */ - if (XFindContext( event->xany.display, event->xany.window, winContext, (char **)&hwnd )) continue; - if (!(data = get_win_data( hwnd ))) continue; - has_serial = data->wm_state_serial || data->configure_serial; - release_win_data( data ); - if (has_serial) continue; - - 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 ); - } - } + host_window_send_configure_events( win, event->xany.display, event->xany.serial );
return TRUE; }
From: Rémi Bernon rbernon@codeweavers.com
Instead of the host window itself, which will never have one.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/event.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 51554725700..b8ec2dc84d3 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -183,24 +183,24 @@ static void host_window_send_configure_events( struct host_window *win, Display BOOL has_serial; HWND hwnd;
+ 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; + /* Only send a fake event if we're not expecting one from a state/config request. * We may know what was requested, but not what the WM will decide to reply, and our * fake event might trigger some undesired changes before the real ConfigureNotify. */ - if (XFindContext( display, win->window, winContext, (char **)&hwnd )) continue; + if (XFindContext( configure.display, configure.window, winContext, (char **)&hwnd )) continue; if (!(data = get_win_data( hwnd ))) continue; has_serial = data->wm_state_serial || data->configure_serial; release_win_data( data ); if (has_serial) continue;
- 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; - TRACE( "generating ConfigureNotify for window %p/%lx, rect %s\n", hwnd, configure.window, wine_dbgstr_rect(&rect) ); XPutBackEvent( configure.display, (XEvent *)&configure ); }
From: Rémi Bernon rbernon@codeweavers.com
The X event merging logic removes events from the queue in advance, and putting a dummy ConfigureNotify back in the queue will override any previously received event.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/event.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index b8ec2dc84d3..6778197967d 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -171,7 +171,7 @@ static inline void free_event_data( XEvent *event ) #endif }
-static void host_window_send_configure_events( struct host_window *win, Display *display, unsigned long serial ) +static void host_window_send_configure_events( struct host_window *win, Display *display, unsigned long serial, XEvent *previous ) { XConfigureEvent configure = {.type = ConfigureNotify, .serial = serial, .display = display}; unsigned int i; @@ -201,12 +201,13 @@ static void host_window_send_configure_events( struct host_window *win, Display release_win_data( data ); if (has_serial) continue;
+ if (previous->type == ConfigureNotify && previous->xconfigure.window == configure.window) continue; TRACE( "generating ConfigureNotify for window %p/%lx, rect %s\n", hwnd, configure.window, wine_dbgstr_rect(&rect) ); XPutBackEvent( configure.display, (XEvent *)&configure ); } }
-static BOOL host_window_filter_event( XEvent *event ) +static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) { struct host_window *win; RECT old_rect; @@ -246,7 +247,7 @@ static BOOL host_window_filter_event( XEvent *event ) }
if (old_rect.left != win->rect.left || old_rect.top != win->rect.top) - host_window_send_configure_events( win, event->xany.display, event->xany.serial ); + host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous );
return TRUE; } @@ -525,7 +526,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X continue; /* filtered, ignore it */ }
- if (host_window_filter_event( &event )) continue; + if (host_window_filter_event( &event, &prev_event )) continue;
get_event_data( &event ); if (prev_event.type) action = merge_events( &prev_event, &event );
From: Rémi Bernon rbernon@codeweavers.com
When an ancestor window is moved.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/event.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 6778197967d..c0e19fee093 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -180,7 +180,6 @@ static void host_window_send_configure_events( struct host_window *win, Display { RECT rect = win->children[i].rect; struct x11drv_win_data *data; - BOOL has_serial; HWND hwnd;
configure.event = win->children[i].window; @@ -195,11 +194,13 @@ static void host_window_send_configure_events( struct host_window *win, Display * We may know what was requested, but not what the WM will decide to reply, and our * fake event might trigger some undesired changes before the real ConfigureNotify. */ - if (XFindContext( configure.display, configure.window, winContext, (char **)&hwnd )) continue; - if (!(data = get_win_data( hwnd ))) continue; - has_serial = data->wm_state_serial || data->configure_serial; - release_win_data( data ); - if (has_serial) continue; + if (!XFindContext( configure.display, configure.window, winContext, (char **)&hwnd ) && + (data = get_win_data( hwnd ))) + { + BOOL has_serial = data->wm_state_serial || data->configure_serial; + release_win_data( data ); + if (has_serial) continue; + }
if (previous->type == ConfigureNotify && previous->xconfigure.window == configure.window) continue; TRACE( "generating ConfigureNotify for window %p/%lx, rect %s\n", hwnd, configure.window, wine_dbgstr_rect(&rect) );
From: Rémi Bernon rbernon@codeweavers.com
We won't receive a ConfigureNotify event if the embedded window has been reparented without moving or resizing it. Top-level windows always receive synthetic ConfigureNotify from the window manager.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57370 --- dlls/winex11.drv/event.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index c0e19fee093..5300982d6b2 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -197,7 +197,8 @@ static void host_window_send_configure_events( struct host_window *win, Display if (!XFindContext( configure.display, configure.window, winContext, (char **)&hwnd ) && (data = get_win_data( hwnd ))) { - BOOL has_serial = data->wm_state_serial || data->configure_serial; + /* embedded windows won't receive synthetic ConfigureNotify and are positioned by the WM */ + BOOL has_serial = !data->embedded && (data->wm_state_serial || data->configure_serial); release_win_data( data ); if (has_serial) continue; } @@ -211,10 +212,8 @@ static void host_window_send_configure_events( struct host_window *win, Display static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) { 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) { @@ -227,6 +226,7 @@ static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) 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 ); + host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); break; } case GravityNotify: @@ -235,6 +235,7 @@ static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) 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) ); + host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); break; } case ConfigureNotify: @@ -243,13 +244,11 @@ static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) 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) ); + host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); break; } }
- if (old_rect.left != win->rect.left || old_rect.top != win->rect.top) - host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); - return TRUE; }
v2: Check the event which was popped for merging before generating ConfigureNotify to avoid overwriting it.