[PATCH v2 0/4] MR11225: winewayland: Use update_client_surfaces to detach client surfaces.
Misc winewayland client surface management tweaks in preparation for some DPI rounding fixes in win32u. -- v2: winewayland: Move ensure_window_surface_contents into wayland_surface.c. winewayland: Remove unnecessary client surface attach / detach. winewayland: Use update_client_surfaces to detach client surfaces. winewayland: Make window lock mutex recursive. https://gitlab.winehq.org/wine/wine/-/merge_requests/11225
From: Rémi Bernon <rbernon@codeweavers.com> Every other driver does it, it will make life easier. --- dlls/winewayland.drv/wayland.c | 1 + dlls/winewayland.drv/wayland_surface.c | 25 ++++++++++--------- dlls/winewayland.drv/waylanddrv.h | 2 +- dlls/winewayland.drv/window.c | 34 ++++++++++++-------------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 5b2b0c5b25b..c5d04b81fe5 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -117,6 +117,7 @@ static void registry_handle_global(void *data, struct wl_registry *registry, { process_wayland.wl_compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4); + wayland_window_init(); } else if (strcmp(interface, "xdg_wm_base") == 0) { diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 0dae0922179..39064b61e62 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -766,9 +766,10 @@ static void wayland_surface_reconfigure_subsurface(struct wayland_surface *surfa struct wayland_win_data *owner_data; struct wayland_surface *owner_surface; - if (surface->processing.serial && surface->processing.processed && - (owner_data = wayland_win_data_get_nolock(surface->owner_hwnd)) && - (owner_surface = owner_data->wayland_surface)) + if (!surface->processing.serial || !surface->processing.processed) return; + if (!(owner_data = wayland_win_data_get(surface->owner_hwnd))) return; + + if ((owner_surface = owner_data->wayland_surface)) { RECT rect = surface->window.rect; @@ -786,6 +787,8 @@ static void wayland_surface_reconfigure_subsurface(struct wayland_surface *surfa memset(&surface->processing, 0, sizeof(surface->processing)); } + + wayland_win_data_release(owner_data); } /********************************************************************** @@ -1276,10 +1279,10 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t return; } - if (!(toplevel_data = wayland_win_data_get_nolock(toplevel)) || !(surface = toplevel_data->wayland_surface)) + if (!(toplevel_data = wayland_win_data_get(toplevel)) || !(surface = toplevel_data->wayland_surface)) { - wayland_client_surface_attach(client, NULL); - return; + if (toplevel_data) wayland_win_data_release(toplevel_data); + return wayland_client_surface_attach(client, NULL); } if (client->toplevel != toplevel) @@ -1290,11 +1293,8 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, client->wl_surface, surface->wl_surface); - if (!client->wl_subsurface) - { - ERR("Failed to create client wl_subsurface\n"); - return; - } + if (!client->wl_subsurface) goto done; + /* Present contents independently of the parent surface. */ wl_subsurface_set_desync(client->wl_subsurface); @@ -1307,6 +1307,9 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t wayland_surface_reconfigure_client(surface, client, &client_rect); /* Commit to apply subsurface positioning. */ wl_surface_commit(surface->wl_surface); + +done: + wayland_win_data_release(toplevel_data); } static void dummy_buffer_release(void *data, struct wl_buffer *buffer) diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index e0df8e56bb5..8df6fa5a986 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -385,7 +385,6 @@ struct wayland_win_data }; struct wayland_win_data *wayland_win_data_get(HWND hwnd); -struct wayland_win_data *wayland_win_data_get_nolock(HWND hwnd); void wayland_win_data_release(struct wayland_win_data *data); struct wayland_client_surface *get_client_surface(HWND hwnd); @@ -393,6 +392,7 @@ void set_client_surface(HWND hwnd, struct wayland_client_surface *client); BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region); struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd); void ensure_window_surface_contents(HWND hwnd); +void wayland_window_init(void); /********************************************************************** * Wayland Keyboard diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index afef743755b..de4188957bd 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -104,22 +104,6 @@ static void wayland_win_data_destroy(struct wayland_win_data *data) free(data); } -/*********************************************************************** - * wayland_win_data_get_nolock - * - * Return the data structure associated with a window. This function does - * not lock the win_data_mutex, so it must be externally synchronized. - */ -struct wayland_win_data *wayland_win_data_get_nolock(HWND hwnd) -{ - struct rb_entry *rb_entry; - - if ((rb_entry = rb_get(&win_data_rb, hwnd))) - return RB_ENTRY_VALUE(rb_entry, struct wayland_win_data, entry); - - return NULL; -} - /*********************************************************************** * wayland_win_data_get * @@ -127,10 +111,11 @@ struct wayland_win_data *wayland_win_data_get_nolock(HWND hwnd) */ struct wayland_win_data *wayland_win_data_get(HWND hwnd) { - struct wayland_win_data *data; + struct rb_entry *entry; pthread_mutex_lock(&win_data_mutex); - if ((data = wayland_win_data_get_nolock(hwnd))) return data; + if ((entry = rb_get(&win_data_rb, hwnd))) + return RB_ENTRY_VALUE(entry, struct wayland_win_data, entry); pthread_mutex_unlock(&win_data_mutex); return NULL; @@ -460,7 +445,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, HWND owner_hint, UIN if (!(managed = is_window_managed(hwnd, swp_flags, fullscreen)) && surface) owner = owner_hint; if (!(data = wayland_win_data_get(hwnd))) return; - owner_data = owner && owner != hwnd ? wayland_win_data_get_nolock(owner) : NULL; + owner_data = owner && owner != hwnd ? wayland_win_data_get(owner) : NULL; owner_surface = owner_data ? owner_data->wayland_surface : NULL; data->rects = *new_rects; @@ -489,6 +474,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, HWND owner_hint, UIN wayland_win_data_update_wayland_state(data); } + if (owner_data) wayland_win_data_release(owner_data); wayland_win_data_release(data); } @@ -924,3 +910,13 @@ void ensure_window_surface_contents(HWND hwnd) wayland_win_data_release(data); } + +void wayland_window_init(void) +{ + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&win_data_mutex, &attr); + pthread_mutexattr_destroy(&attr); +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11225
From: Rémi Bernon <rbernon@codeweavers.com> Temporarily, when we're changing roles. The client surfaces should be attached back again by win32u calling update_client_surfaces after WindowPosChanged. --- dlls/win32u/window.c | 2 +- dlls/winewayland.drv/wayland_surface.c | 6 ++---- dlls/winewayland.drv/window.c | 9 +++++---- include/wine/gdi_driver.h | 1 + 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index f4dc335c5cf..b5136b69379 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -320,7 +320,7 @@ void detach_client_surfaces( HWND hwnd ) } } -static void update_client_surfaces( HWND hwnd ) +void update_client_surfaces( HWND hwnd ) { struct client_surface *surface, *next; diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 39064b61e62..8d4dfb0f618 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -142,7 +142,6 @@ void wp_fractional_scale_handle_scale(void* user_data, uint32_t scale_fixed) { struct wayland_win_data *data; - struct wayland_client_surface *client; struct wayland_surface *surface; double scale = scale_fixed / 120.0; HWND hwnd = user_data; @@ -158,9 +157,8 @@ void wp_fractional_scale_handle_scale(void* user_data, surface->window.scale = scale; - /* reattach the client surface as its rect has changed */ - if ((client = data->client_surface)) - wayland_client_surface_attach(client, client->toplevel); + /* reattach client surfaces as their rects have changed */ + update_client_surfaces(hwnd); /* the subsurface rect has changed */ if (surface->role == WAYLAND_SURFACE_ROLE_SUBSURFACE) diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index de4188957bd..887e233c8ed 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -175,7 +175,6 @@ static void reapply_cursor_clipping(void) static BOOL wayland_win_data_create_wayland_surface(struct wayland_win_data *data, struct wayland_surface *owner_surface) { - struct wayland_client_surface *client = data->client_surface; struct wayland_surface *surface; enum wayland_surface_role role; BOOL visible; @@ -194,9 +193,12 @@ static BOOL wayland_win_data_create_wayland_surface(struct wayland_win_data *dat /* we can temporarily clear the role of a surface but cannot assign a different one after it's set */ if ((surface = data->wayland_surface) && role && surface->role && surface->role != role) { - if (client) wayland_client_surface_attach(client, NULL); - wayland_surface_destroy(data->wayland_surface); + /* Make sure any attached client surface is detached before we destroy the surface. + * They will be reattached when win32u updates them again after WindowPosChanged. + */ data->wayland_surface = NULL; + update_client_surfaces(data->hwnd); + wayland_surface_destroy(surface); } if (!(surface = data->wayland_surface) && !(surface = wayland_surface_create(data->hwnd))) return FALSE; @@ -225,7 +227,6 @@ static BOOL wayland_win_data_create_wayland_surface(struct wayland_win_data *dat break; } - if (visible && client) wayland_client_surface_attach(client, data->hwnd); wayland_win_data_get_config(data, &surface->window); /* Size/position changes affect the effective pointer constraint, so update diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 630e035a589..a5ec6807cf3 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -273,6 +273,7 @@ W32KAPI void client_surface_add_ref( struct client_surface *surface ); W32KAPI void client_surface_release( struct client_surface *surface ); W32KAPI void client_surface_present( struct client_surface *surface ); W32KAPI void client_surface_update( struct client_surface *surface ); +W32KAPI void update_client_surfaces( HWND hwnd ); W32KAPI void detach_client_surfaces( HWND hwnd ); static inline const char *debugstr_client_surface( struct client_surface *surface ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11225
From: Rémi Bernon <rbernon@codeweavers.com> The client surfaces should have been attached to their new toplevel window already. If not, it should probably be fixed in win32u. --- dlls/winewayland.drv/window.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 887e233c8ed..1ee04f53021 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -434,7 +434,6 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, HWND owner_hint, UIN { HWND owner = NtUserGetAncestor(hwnd, GA_ROOT); struct wayland_surface *owner_surface; - struct wayland_client_surface *client; struct wayland_win_data *data, *owner_data; BOOL managed, fullscreen = swp_flags & WINE_SWP_FULLSCREEN; @@ -456,14 +455,6 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, HWND owner_hint, UIN if (!surface) { - if ((client = data->client_surface)) - { - if (owner && NtUserIsWindowVisible(hwnd)) - wayland_client_surface_attach(client, owner); - else - wayland_client_surface_attach(client, NULL); - } - if (data->wayland_surface) { wayland_surface_destroy(data->wayland_surface); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11225
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/winewayland.drv/wayland_surface.c | 22 +++++++++++++++++++++- dlls/winewayland.drv/waylanddrv.h | 1 - dlls/winewayland.drv/window.c | 24 ------------------------ 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 8d4dfb0f618..0f811ec904c 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -1198,7 +1198,27 @@ static void wayland_client_surface_present(struct client_surface *client, HDC hd { struct wayland_client_surface *surface = impl_from_client_surface(client); HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor(hwnd, GA_ROOT); - ensure_window_surface_contents(toplevel); + struct wayland_surface *wayland_surface; + struct wayland_win_data *data; + + if (!(data = wayland_win_data_get(toplevel))) return; + + if ((wayland_surface = data->wayland_surface)) + { + wayland_surface_ensure_contents(wayland_surface); + + /* Handle any processed configure request, to ensure the related + * surface state is applied by the compositor. */ + if (wayland_surface->processing.serial && + wayland_surface->processing.processed && + wayland_surface_reconfigure(wayland_surface)) + { + wl_surface_commit(wayland_surface->wl_surface); + } + } + + wayland_win_data_release(data); + set_client_surface(hwnd, surface); } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 8df6fa5a986..f88c562112c 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -391,7 +391,6 @@ struct wayland_client_surface *get_client_surface(HWND hwnd); void set_client_surface(HWND hwnd, struct wayland_client_surface *client); BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region); struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd); -void ensure_window_surface_contents(HWND hwnd); void wayland_window_init(void); /********************************************************************** diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 1ee04f53021..a3f0f35ff79 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -879,30 +879,6 @@ struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd) return shm_buffer; } -void ensure_window_surface_contents(HWND hwnd) -{ - struct wayland_surface *wayland_surface; - struct wayland_win_data *data; - - if (!(data = wayland_win_data_get(hwnd))) return; - - if ((wayland_surface = data->wayland_surface)) - { - wayland_surface_ensure_contents(wayland_surface); - - /* Handle any processed configure request, to ensure the related - * surface state is applied by the compositor. */ - if (wayland_surface->processing.serial && - wayland_surface->processing.processed && - wayland_surface_reconfigure(wayland_surface)) - { - wl_surface_commit(wayland_surface->wl_surface); - } - } - - wayland_win_data_release(data); -} - void wayland_window_init(void) { pthread_mutexattr_t attr; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11225
This merge request was approved by Etaash Mathamsetty. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11225
participants (3)
-
Etaash Mathamsetty (@etaash.mathamsetty) -
Rémi Bernon -
Rémi Bernon (@rbernon)