The fix ensures the window manager knows the correct stacking order by setting the transient hint to the **insert_after** window when when using **SetWindowPos** with **insert_after** parameter. Signed-off-by: Zhao Yi zhaoyi@uniontech.com
From: Zhao Yi zhaoyi@uniontech.com
Signed-off-by: Zhao Yi zhaoyi@uniontech.com --- dlls/winex11.drv/window.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index bf3b8f66603..1691b10600e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -407,6 +407,7 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd ) static BOOL is_window_managed( HWND hwnd, UINT swp_flags, BOOL fullscreen ) { DWORD style, ex_style; + struct x11drv_win_data *data;
if (!managed_mode) return FALSE;
@@ -432,6 +433,17 @@ static BOOL is_window_managed( HWND hwnd, UINT swp_flags, BOOL fullscreen ) if (ex_style & WS_EX_APPWINDOW) return TRUE; /* windows that own popups are managed */ if (has_owned_popups( hwnd )) return TRUE; + /* layered windows are managed */ + if (ex_style & WS_EX_LAYERED) + { + data = get_win_data(hwnd); + if (data && data->layered) + { + release_win_data(data); + return TRUE; + } + release_win_data(data); + } /* default: not managed */ return FALSE; }
From: Zhao Yi zhaoyi@uniontech.com
When a window is positioned after another window (using SetWindowPos with insert_after), set the transient for hint to the insert_after window if it is not withdrawn. This can manage the window stacking correctly.
Signed-off-by: Zhao Yi zhaoyi@uniontech.com --- dlls/winex11.drv/window.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 1691b10600e..d7e5e2e00e8 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -3163,6 +3163,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN const struct window_rects *new_rects, struct window_surface *surface ) { struct x11drv_win_data *data; + struct x11drv_win_data *insert_after_data; UINT new_style = NtUserGetWindowLongW( hwnd, GWL_STYLE ), old_style; struct window_rects old_rects; BOOL was_fullscreen, activate = !(swp_flags & SWP_NOACTIVATE); @@ -3224,7 +3225,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN } #endif } - + insert_after_data = get_win_data(insert_after); if ((new_style & WS_VISIBLE) && ((new_style & WS_MINIMIZE) || is_window_rect_mapped( &new_rects->window ))) { @@ -3236,9 +3237,13 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN /* layered windows are mapped only once their attributes are set */ if (NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED) needs_map = data->layered || IsRectEmpty( &new_rects->window ); - release_win_data( data ); + if (needs_icon) fetch_icon_data( hwnd, 0, 0 ); if (needs_map) map_window( hwnd, new_style, activate ); + if (insert_after_data && insert_after_data->desired_state.wm_state != WithdrawnState && hwnd != insert_after) + XSetTransientForHint( data->display, insert_after_data->whole_window, data->whole_window ); + release_win_data( data ); + release_win_data( insert_after_data ); return; } else if ((swp_flags & SWP_STATECHANGED) && ((old_style ^ new_style) & WS_MINIMIZE)) @@ -3253,8 +3258,11 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN } }
+ if (insert_after_data && insert_after_data->desired_state.wm_state != WithdrawnState && hwnd != insert_after) + XSetTransientForHint( data->display, insert_after_data->whole_window, data->whole_window ); XFlush( data->display ); /* make sure changes are done before we start painting again */ release_win_data( data ); + release_win_data( insert_after_data ); }
/* check if the window icon should be hidden (i.e. moved off-screen) */
I am afraid such way of trying selectively fix up Z order will break more than fix. The correct Z order is not handled in general and enforcing that for specific particular case is likely not correct. This way 'transient for' should be set throughout for each and every our window to ensure the ordering, but then it has side effects and unlikely to work very well.
On Thu Oct 16 05:39:38 2025 +0000, Paul Gofman wrote:
I am afraid such way of trying selectively fix up Z order will break more than fix. The correct Z order is not handled in general and enforcing that for specific particular case is likely not correct. This way 'transient for' should be set throughout for each and every our window to ensure the ordering, but then it has side effects and unlikely to work very well.
Such modifications might, as you mentioned, introduce other issues. Although I haven't tested them yet, the code logic in Wine currently does not process the '**insert_after**' parameter passed to the **SetWindowPos** function. This is certain to cause problems, as this parameter affects the window Z-order. For specific details, you can refer to MSDN:https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwi...