On Wed Feb 14 16:39:19 2024 +0000, Rémi Bernon wrote:
I could move the call to make it layered before calling the driver
function of course, but the function can return FALSE, and then what happens? Should I revert it back, or not sure how to fix it. Yes, setting it then calling `paint_layered_icon` once, before trying to dock them, and removing the attribute if docking returns FALSE looks correct.
BTW I think I found the reason it fails. It's not the `make_window_embedded` or `set_window_visual` calls. Neither is the `NtUserShowWindow`. For example the following works:
```diff diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8ab6944..1ce0165 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2337,6 +2337,11 @@ BOOL X11DRV_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon ) release_win_data( data );
NtUserShowWindow( hwnd, SW_SHOWNA ); + NtUserSetWindowLong( hwnd, GWL_EXSTYLE, NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_LAYERED, FALSE ); + + if (!(data = get_win_data( hwnd ))) return FALSE; + window = data->whole_window; + release_win_data( data );
TRACE_(systray)( "icon window %p/%lx\n", hwnd, window );
``` One important thing to notice is that the whole `window = data->whole_window` **after** setting it to layered is important, so the correct window is sent to `XSendEvent` for the docking message. Without that, it will still fail.
So why does this happen? Because setting it to WS_EX_LAYERED makes it eventually end up in `set_window_visual` (from `X11DRV_SetWindowStyle`), which **destroys and recreates the X window**. As in, the old X window no longer exists, so there's nothing to dock!
Sure enough the following hack also fixes it:
```diff diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8ab6944..0e2ef96 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1812,6 +1812,7 @@ void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BO Window client_window = data->client_window; Window whole_window = data->whole_window;
+ return; if (!data->use_alpha == !use_alpha) return; if (data->surface) window_surface_release( data->surface ); data->surface = NULL; ```
Why does it even need to destroy and recreate the window? I'm going to experiment a bit but otherwise I'll go with just setting it earlier.