From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/ntuser_private.h | 1 + dlls/win32u/vulkan.c | 62 ++++++++++++++++++++++++++++++++++++ dlls/win32u/window.c | 1 + 3 files changed, 64 insertions(+)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 11b1a3ff8a1..04396abca72 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -257,6 +257,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 );
/* 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 241df9a462e..7f8a0f716a5 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -280,6 +280,68 @@ void vulkan_detach_surfaces( struct list *surfaces ) pthread_mutex_unlock( &vulkan_mutex ); }
+static void append_window_surfaces( HWND toplevel, struct list *surfaces ) +{ + WND *win; + + if (!(win = get_win_ptr( toplevel )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) + { + pthread_mutex_lock( &vulkan_mutex ); + list_move_tail( &offscreen_surfaces, surfaces ); + pthread_mutex_unlock( &vulkan_mutex ); + } + else + { + list_move_tail( &win->vulkan_surfaces, surfaces ); + release_win_ptr( win ); + } +} + +static void enum_window_surfaces( HWND toplevel, HWND hwnd, struct list *surfaces ) +{ + struct list tmp_surfaces = LIST_INIT(tmp_surfaces); + struct surface *surface, *next; + WND *win; + + if (!(win = get_win_ptr( toplevel )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) + { + pthread_mutex_lock( &vulkan_mutex ); + list_move_tail( &tmp_surfaces, &offscreen_surfaces ); + pthread_mutex_unlock( &vulkan_mutex ); + } + else + { + list_move_tail( &tmp_surfaces, &win->vulkan_surfaces ); + release_win_ptr( win ); + } + + LIST_FOR_EACH_ENTRY_SAFE( surface, next, &tmp_surfaces, struct surface, entry ) + { + if (surface->hwnd != hwnd && !NtUserIsChild( hwnd, surface->hwnd )) continue; + list_remove( &surface->entry ); + list_add_tail( surfaces, &surface->entry ); + } + + append_window_surfaces( toplevel, &tmp_surfaces ); +} + +void vulkan_set_parent( HWND hwnd, HWND new_parent, HWND old_parent ) +{ + struct list surfaces = LIST_INIT(surfaces); + HWND new_toplevel, old_toplevel; + + TRACE( "hwnd %p new_parent %p old_parent %p\n", hwnd, new_parent, old_parent ); + + if (new_parent == NtUserGetDesktopWindow()) new_toplevel = hwnd; + else new_toplevel = NtUserGetAncestor( new_parent, GA_ROOT ); + if (old_parent == NtUserGetDesktopWindow()) old_toplevel = hwnd; + else old_toplevel = NtUserGetAncestor( old_parent, GA_ROOT ); + if (old_toplevel == new_toplevel) return; + + enum_window_surfaces( old_toplevel, hwnd, &surfaces ); + append_window_surfaces( new_toplevel, &surfaces ); +} + /*********************************************************************** * __wine_get_vulkan_driver (win32u.so) */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 13dd1c8d80a..f630f107b00 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -463,6 +463,7 @@ HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent ) context = SetThreadDpiAwarenessContext( get_window_dpi_awareness_context( hwnd ));
user_driver->pSetParent( full_handle, parent, old_parent ); + vulkan_set_parent( full_handle, parent, old_parent );
winpos.hwnd = hwnd; winpos.hwndInsertAfter = HWND_TOP;