On Wed Feb 14 18:12:55 2024 +0000, Gabriel Ivăncescu wrote:
How about something like this?
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8ab6944..7bda648 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1822,14 +1822,32 @@ void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BO destroy_whole_window( data, client_window != 0 /* don't destroy whole_window until reparented */ ); data->vis = *vis; create_whole_window( data ); - if (!client_window) return; - /* move the client to the new parent */ - XReparentWindow( gdi_display, client_window, data->whole_window, - data->client_rect.left - data->whole_rect.left, - data->client_rect.top - data->whole_rect.top ); - data->client_window = client_window; - XSync( gdi_display, False ); /* make sure XReparentWindow requests have completed before destroying whole_window */ - XDestroyWindow( data->display, whole_window ); + if (client_window) + { + /* move the client to the new parent */ + XReparentWindow( gdi_display, client_window, data->whole_window, + data->client_rect.left - data->whole_rect.left, + data->client_rect.top - data->whole_rect.top ); + data->client_window = client_window; + XSync( gdi_display, False ); /* make sure XReparentWindow requests have completed before destroying whole_window */ + XDestroyWindow( data->display, whole_window ); + } + + /* if we were docked, re-send the docking request message */ + if (data->docked_to) + { + XEvent ev; + ev.xclient.type = ClientMessage; + ev.xclient.window = data->docked_to; + ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE ); + ev.xclient.format = 32; + ev.xclient.data.l[0] = CurrentTime; + ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK; + ev.xclient.data.l[2] = data->whole_window; + ev.xclient.data.l[3] = 0; + ev.xclient.data.l[4] = 0; + XSendEvent( data->display, data->docked_to, False, NoEventMask, &ev ); + } } @@ -2272,6 +2290,7 @@ BOOL X11DRV_SystrayDockRemove( HWND hwnd ) if ((data = get_win_data( hwnd ))) { if ((ret = data->embedded)) data->mapped = FALSE; + data->docked_to = 0; release_win_data( data ); return ret; } @@ -2334,6 +2353,7 @@ BOOL X11DRV_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon ) set_window_visual( data, &visual, TRUE ); make_window_embedded( data ); window = data->whole_window; + data->docked_to = systray_window; release_win_data( data ); NtUserShowWindow( hwnd, SW_SHOWNA ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 71a3582..b1ea370 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -628,6 +628,7 @@ struct x11drv_win_data 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 */ + Window docked_to; /* window id of systray if we are docked to it */ unsigned long configure_serial; /* serial number of last configure request */ struct window_surface *surface; Pixmap icon_pixmap;
It also fixes it without any change to explorer, since it seems to be a winex11.drv quirk we have (destroying and re-creating the window…). Is this acceptable?
I think it's better to change it in `explorer.exe`, the systray dock interface contract currently kind of advertise that it'll provide layered icon windows to the drivers. Making sure they are fully layered before calling WINE_SYSTRAY_DOCK_INSERT seems the proper thing to do.