From: Rémi Bernon rbernon@codeweavers.com
And attach them back when they are. --- dlls/win32u/ntuser_private.h | 1 + dlls/win32u/vulkan.c | 49 +++++++++++++++++++++++++++++++++--- dlls/win32u/window.c | 4 ++- 3 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 04396abca72..7662436a588 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -258,6 +258,7 @@ extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar /* vulkan.c */ extern void vulkan_detach_surfaces( struct list *surfaces ); extern void vulkan_set_parent( HWND hwnd, HWND new_parent, HWND old_parent ); +extern void vulkan_set_region( HWND toplevel, HRGN region );
/* window.c */ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ); diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 2aa61ed565d..7ad9b72256e 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -59,6 +59,7 @@ struct surface struct list entry; VkSurfaceKHR host_surface; void *driver_private; + BOOL is_detached; HWND hwnd; };
@@ -93,6 +94,8 @@ static VkResult win32u_vkCreateWin32SurfaceKHR( VkInstance instance, const VkWin if (!(win = get_win_ptr( toplevel )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) { driver_funcs->p_vulkan_surface_detach( surface->hwnd, surface->driver_private ); + surface->is_detached = TRUE; + pthread_mutex_lock( &vulkan_mutex ); list_add_tail( &offscreen_surfaces, &surface->entry ); pthread_mutex_unlock( &vulkan_mutex ); @@ -279,7 +282,11 @@ void vulkan_detach_surfaces( struct list *surfaces ) struct surface *surface;
LIST_FOR_EACH_ENTRY( surface, surfaces, struct surface, entry ) + { + if (surface->is_detached) continue; driver_funcs->p_vulkan_surface_detach( surface->hwnd, surface->driver_private ); + surface->is_detached = TRUE; + }
pthread_mutex_lock( &vulkan_mutex ); list_move_tail( &offscreen_surfaces, surfaces ); @@ -288,7 +295,6 @@ void vulkan_detach_surfaces( struct list *surfaces )
static void append_window_surfaces( HWND toplevel, struct list *surfaces ) { - struct surface *surface; WND *win;
if (!(win = get_win_ptr( toplevel )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) @@ -301,9 +307,6 @@ static void append_window_surfaces( HWND toplevel, struct list *surfaces ) { list_move_tail( &win->vulkan_surfaces, surfaces ); release_win_ptr( win ); - - LIST_FOR_EACH_ENTRY( surface, surfaces, struct surface, entry ) - driver_funcs->p_vulkan_surface_attach( surface->hwnd, surface->driver_private ); } }
@@ -351,12 +354,50 @@ void vulkan_set_parent( HWND hwnd, HWND new_parent, HWND old_parent )
enum_window_surfaces( old_toplevel, hwnd, &surfaces );
+ /* surfaces will be re-attached as needed from surface region updates */ LIST_FOR_EACH_ENTRY( surface, &surfaces, struct surface, entry ) + { + if (surface->is_detached) continue; driver_funcs->p_vulkan_surface_detach( surface->hwnd, surface->driver_private ); + surface->is_detached = TRUE; + }
append_window_surfaces( new_toplevel, &surfaces ); }
+void vulkan_set_region( HWND toplevel, HRGN region ) +{ + struct list surfaces = LIST_INIT(surfaces); + struct surface *surface; + + enum_window_surfaces( toplevel, toplevel, &surfaces ); + + LIST_FOR_EACH_ENTRY( surface, &surfaces, struct surface, entry ) + { + RECT client_rect; + BOOL is_clipped; + + NtUserGetClientRect( surface->hwnd, &client_rect ); + NtUserMapWindowPoints( surface->hwnd, toplevel, (POINT *)&client_rect, 2 ); + is_clipped = NtGdiRectInRegion( region, &client_rect ); + + if (is_clipped && !surface->is_detached) + { + TRACE( "surface %p is now clipped\n", surface->hwnd ); + driver_funcs->p_vulkan_surface_detach( surface->hwnd, surface->driver_private ); + surface->is_detached = TRUE; + } + else if (!is_clipped && surface->is_detached) + { + TRACE( "surface %p is now unclipped\n", surface->hwnd ); + driver_funcs->p_vulkan_surface_attach( surface->hwnd, surface->driver_private ); + surface->is_detached = FALSE; + } + } + + append_window_surfaces( toplevel, &surfaces ); +} + /*********************************************************************** * __wine_get_vulkan_driver (win32u.so) */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index f630f107b00..4cef4b71757 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1762,10 +1762,12 @@ static void update_surface_region( HWND hwnd ) if (status) goto done;
win->surface->funcs->set_region( win->surface, region ); - if (region) NtGdiDeleteObjectApp( region );
done: release_win_ptr( win ); + + vulkan_set_region( hwnd, region ); + if (region) NtGdiDeleteObjectApp( region ); }
/***********************************************************************