From: Rémi Bernon <rbernon@codeweavers.com> The workaround to avoid breaking Cinnamon / Muffin caused some logic change, where GetWindowStateUpdates started returning the previously active window as foreground, as there's no _NET_ACTIVE_WINDOW pending request being recorded anymore. If GetWindowStateUpdates gets called after the window activation request but before its mapping is requested from WindowStateChanged, it would change the Win32 foreground window too, causing spurious focus loss. Fixes: c8422a619b46d25e55907fd5526b1d9fae8c3943 --- dlls/winex11.drv/window.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ed493389260..1b069ca9cbe 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2018,14 +2018,14 @@ void net_active_window_init( struct x11drv_thread_data *data ) data->current_state.net_active_window = window; } -static BOOL window_set_pending_activate( HWND hwnd ) +static BOOL window_set_pending_activate( HWND hwnd, BOOL *withdrawn ) { struct x11drv_win_data *data; BOOL pending; if (!(data = get_win_data( hwnd ))) return FALSE; if ((pending = !!data->wm_state_serial)) data->pending_state.activate = TRUE; - if (data->pending_state.wm_state == WithdrawnState) pending = TRUE; + *withdrawn = data->pending_state.wm_state == WithdrawnState; release_win_data( data ); return pending; @@ -2034,13 +2034,14 @@ static BOOL window_set_pending_activate( HWND hwnd ) void set_net_active_window( HWND hwnd, HWND previous ) { struct x11drv_thread_data *data = x11drv_thread_data(); + BOOL withdrawn = FALSE; Window window; XEvent xev; if (!is_net_supported( x11drv_atom(_NET_ACTIVE_WINDOW) )) return; if (!(window = X11DRV_get_whole_window( hwnd ))) return; if (data->pending_state.net_active_window == window) return; - if (window_set_pending_activate( hwnd )) return; + if (window_set_pending_activate( hwnd, &withdrawn )) return; xev.xclient.type = ClientMessage; xev.xclient.window = window; @@ -2057,6 +2058,15 @@ void set_net_active_window( HWND hwnd, HWND previous ) data->pending_state.net_active_window = window; data->net_active_window_serial = NextRequest( data->display ); + + if (withdrawn) + { + /* workaround requesting activation of withdrawn windows which breaks some WM, assume the window will soon be mapped */ + WARN( "skipping _NET_ACTIVE_WINDOW for withdrawn window %p/%lx serial %lu\n", hwnd, window, data->net_active_window_serial ); + XNoOp( data->display ); + return; + } + TRACE( "requesting _NET_ACTIVE_WINDOW %p/%lx serial %lu\n", hwnd, window, data->net_active_window_serial ); XSendEvent( data->display, DefaultRootWindow( data->display ), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9807