From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 17 +++++++++++++---- dlls/winewayland.drv/wayland_surface.c | 6 ++++-- dlls/winewayland.drv/window.c | 2 +- dlls/winex11.drv/init.c | 4 ++-- include/wine/gdi_driver.h | 1 + 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b5136b69379..7925092385d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -308,6 +308,7 @@ void detach_client_surfaces( HWND hwnd ) client_surface_add_ref( surface ); surface->funcs->detach( surface ); + surface->toplevel = NULL; surface->hwnd = NULL; } @@ -320,6 +321,13 @@ void detach_client_surfaces( HWND hwnd ) } } +static void client_surface_update_locked( struct client_surface *surface ) +{ + surface->toplevel = NtUserGetAncestor( surface->hwnd, GA_ROOT ); + surface->funcs->update( surface ); + InterlockedExchange( &surface->updated, 1 ); +} + void update_client_surfaces( HWND hwnd ) { struct client_surface *surface, *next; @@ -329,8 +337,7 @@ void update_client_surfaces( HWND hwnd ) LIST_FOR_EACH_ENTRY_SAFE( surface, next, &client_surfaces, struct client_surface, entry ) { if (NtUserGetAncestor( surface->hwnd, GA_ROOT ) != hwnd) continue; - surface->funcs->update( surface ); - InterlockedExchange( &surface->updated, 1 ); + client_surface_update_locked( surface ); } pthread_mutex_unlock( &surfaces_lock ); @@ -338,12 +345,14 @@ void update_client_surfaces( HWND hwnd ) void *client_surface_create( UINT size, const struct client_surface_funcs *funcs, HWND hwnd ) { + HWND toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); struct client_surface *surface; if (!(surface = calloc( 1, size ))) return NULL; surface->funcs = funcs; surface->ref = 1; surface->hwnd = hwnd; + surface->toplevel = toplevel; list_init( &surface->entry ); TRACE( "created %s\n", debugstr_client_surface( surface ) ); @@ -394,7 +403,7 @@ void client_surface_present( struct client_surface *surface ) void client_surface_update( struct client_surface *surface ) { pthread_mutex_lock( &surfaces_lock ); - if (surface->hwnd) surface->funcs->update( surface ); + if (surface->hwnd) client_surface_update_locked( surface ); pthread_mutex_unlock( &surfaces_lock ); } @@ -404,7 +413,7 @@ void add_window_client_surface( HWND hwnd, struct client_surface *surface ) surface->hwnd = hwnd; list_add_tail( &client_surfaces, &surface->entry ); - surface->funcs->update( surface ); + client_surface_update_locked( surface ); pthread_mutex_unlock( &surfaces_lock ); } diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 0f811ec904c..eb74b78061b 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -1181,9 +1181,11 @@ static void wayland_client_surface_detach(struct client_surface *client) static void wayland_client_surface_update(struct client_surface *client) { struct wayland_client_surface *surface = impl_from_client_surface(client); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + HWND hwnd = client->hwnd, toplevel = client->toplevel; struct wayland_win_data *data; + TRACE("%s\n", debugstr_client_surface(client)); + if (!(data = wayland_win_data_get(hwnd))) return; if (toplevel && NtUserIsWindowVisible(hwnd)) @@ -1197,7 +1199,7 @@ static void wayland_client_surface_update(struct client_surface *client) static void wayland_client_surface_present(struct client_surface *client, HDC hdc) { struct wayland_client_surface *surface = impl_from_client_surface(client); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + HWND hwnd = client->hwnd, toplevel = client->toplevel; struct wayland_surface *wayland_surface; struct wayland_win_data *data; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index a3f0f35ff79..59baaf258db 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -807,7 +807,7 @@ void WAYLAND_UpdateLayeredWindow(HWND hwnd, BYTE alpha, UINT flags) void set_client_surface(HWND hwnd, struct wayland_client_surface *new_client) { - HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + HWND toplevel = new_client->client.toplevel; struct wayland_client_surface *old_client; struct wayland_win_data *data; diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index d5b4fdbf0aa..92b2683ae87 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -297,7 +297,7 @@ static void x11drv_client_surface_detach( struct client_surface *client ) static void client_surface_update_geometry( HWND hwnd, struct x11drv_client_surface *surface ) { UINT dpi = NtUserGetDpiForWindow( hwnd ); /* use window DPI here, DPI scaling is handled through offscreen presentation */ - HWND origin = hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + HWND origin = hwnd, toplevel = surface->client.toplevel; XWindowChanges changes = surface->changes; struct x11drv_win_data *data; int mask = 0; @@ -400,7 +400,7 @@ static void x11drv_client_surface_update( struct client_surface *client ) static void X11DRV_client_surface_present( struct client_surface *client, HDC hdc ) { struct x11drv_client_surface *surface = impl_from_client_surface( client ); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + HWND hwnd = client->hwnd, toplevel = client->toplevel; struct x11drv_win_data *data; RECT rect_dst, rect; Drawable window; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index a5ec6807cf3..0ed84a51ba7 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -265,6 +265,7 @@ struct client_surface LONG ref; /* reference count */ HWND hwnd; /* window the surface was created for */ LONG updated; /* has been moved / resized / reparented */ + HWND toplevel; /* toplevel window of the surface */ LONG offscreen; /* client window is offscreen */ }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11289