From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 36 +++++++++++++++++++------- dlls/winewayland.drv/waylanddrv.h | 4 ++- dlls/winewayland.drv/window.c | 29 +++++++++++++++------ 3 files changed, 50 insertions(+), 19 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 1cf5dd3f8ce..d526123b569 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -817,21 +817,35 @@ err: return NULL; }
-void wayland_client_surface_attach(struct wayland_client_surface *client, struct wayland_surface *surface) +void wayland_client_surface_attach(struct wayland_client_surface *client, HWND toplevel) { - wayland_client_surface_detach(client); + struct wayland_win_data *toplevel_data = wayland_win_data_get_nolock(toplevel); + struct wayland_surface *surface;
- client->wl_subsurface = - wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, - client->wl_surface, - surface->wl_surface); - if (!client->wl_subsurface) + if (!toplevel_data || !(surface = toplevel_data->wayland_surface)) { - ERR("Failed to create client wl_subsurface\n"); + wayland_client_surface_detach(client); return; } - /* Present contents independently of the parent surface. */ - wl_subsurface_set_desync(client->wl_subsurface); + + if (client->toplevel != toplevel) + { + wayland_client_surface_detach(client); + + client->wl_subsurface = + 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; + } + /* Present contents independently of the parent surface. */ + wl_subsurface_set_desync(client->wl_subsurface); + + client->toplevel = toplevel; + }
wayland_surface_reconfigure_client(surface, client); /* Commit to apply subsurface positioning. */ @@ -845,6 +859,8 @@ void wayland_client_surface_detach(struct wayland_client_surface *client) wl_subsurface_destroy(client->wl_subsurface); client->wl_subsurface = NULL; } + + client->toplevel = 0; }
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 9c98fdb1586..a0d5deb5fab 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -185,6 +185,7 @@ struct wayland_client_surface { LONG ref; HWND hwnd; + HWND toplevel; struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct wp_viewport *wp_viewport; @@ -254,7 +255,7 @@ void wayland_surface_coords_to_window(struct wayland_surface *surface, int *window_x, int *window_y); struct wayland_client_surface *wayland_client_surface_create(HWND hwnd); BOOL wayland_client_surface_release(struct wayland_client_surface *client); -void wayland_client_surface_attach(struct wayland_client_surface *client, struct wayland_surface *surface); +void wayland_client_surface_attach(struct wayland_client_surface *client, HWND toplevel); void wayland_client_surface_detach(struct wayland_client_surface *client); void wayland_surface_ensure_contents(struct wayland_surface *surface, struct wayland_client_surface *client); void wayland_surface_set_title(struct wayland_surface *surface, LPCWSTR title); @@ -291,6 +292,7 @@ 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); diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 077c7576825..0cc5f323b24 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -125,19 +125,32 @@ static void wayland_win_data_destroy(struct wayland_win_data *data) }
/*********************************************************************** - * wayland_win_data_get + * wayland_win_data_get_nolock * - * Lock and return the data structure associated with a window. + * 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(HWND hwnd) +struct wayland_win_data *wayland_win_data_get_nolock(HWND hwnd) { struct rb_entry *rb_entry;
- pthread_mutex_lock(&win_data_mutex); - 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 + * + * Lock and return the data structure associated with a window. + */ +struct wayland_win_data *wayland_win_data_get(HWND hwnd) +{ + struct wayland_win_data *data; + + pthread_mutex_lock(&win_data_mutex); + if ((data = wayland_win_data_get_nolock(hwnd))) return data; pthread_mutex_unlock(&win_data_mutex);
return NULL; @@ -208,7 +221,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat { if (surface) { - if (client) wayland_client_surface_attach(client, surface); + if (client) wayland_client_surface_detach(client); wayland_surface_destroy(surface); } surface = NULL; @@ -235,7 +248,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat if (visible) { wayland_surface_make_toplevel(surface); - if (client) wayland_client_surface_attach(client, surface); + if (client) wayland_client_surface_attach(client, data->hwnd); if (surface->xdg_toplevel) { if (!NtUserInternalGetWindowText(data->hwnd, text, ARRAY_SIZE(text))) @@ -724,7 +737,7 @@ struct wayland_client_surface *get_client_surface(HWND hwnd) if (!data) return client;
if (surface && NtUserIsWindowVisible(hwnd)) - wayland_client_surface_attach(client, surface); + wayland_client_surface_attach(client, data->hwnd); else wayland_client_surface_detach(client);