Preparation for https://gitlab.winehq.org/wine/wine/-/merge_requests/6323
-- v3: winewayland: Detach client surfaces when they are not visible. winewayland: Move client surface to wayland_win_data struct. winewayland: Pass hwnd to and return client rect from wayland_surface_get_client. winewayland: Introduce a new wayland_client_surface_attach helper. winewayland: Move wayland_surface_get_client to window.c.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 42 +------------------------- dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 40 ++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 41 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 488132ca8d5..13503cc849d 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -494,7 +494,7 @@ static void wayland_surface_reconfigure_size(struct wayland_surface *surface, * * Reconfigures the subsurface covering the client area. */ -static void wayland_surface_reconfigure_client(struct wayland_surface *surface) +void wayland_surface_reconfigure_client(struct wayland_surface *surface) { struct wayland_window_config *window = &surface->window; int client_x, client_y, x, y; @@ -815,46 +815,6 @@ err: return NULL; }
-/********************************************************************** - * wayland_surface_get_client - */ -struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) -{ - struct wayland_client_surface *client; - - if ((client = surface->client)) - { - InterlockedIncrement(&client->ref); - return client; - } - - if (!(client = wayland_client_surface_create(surface->hwnd))) - return NULL; - - 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"); - goto err; - } - /* Present contents independently of the parent surface. */ - wl_subsurface_set_desync(client->wl_subsurface); - - wayland_surface_reconfigure_client(surface); - /* Commit to apply subsurface positioning. */ - wl_surface_commit(surface->wl_surface); - - surface->client = client; - return client; - -err: - wayland_client_surface_release(client); - return NULL; -} - static void dummy_buffer_release(void *data, struct wl_buffer *buffer) { struct wayland_shm_buffer *shm_buffer = data; diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 4551540e0d4..bd6fcb50147 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -241,6 +241,7 @@ void wayland_surface_clear_role(struct wayland_surface *surface); void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region); +void wayland_surface_reconfigure_client(struct wayland_surface *surface); BOOL wayland_surface_reconfigure(struct wayland_surface *surface); BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf, int width, int height, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 942d56870a3..0874ec5121e 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -682,6 +682,46 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) return ret; }
+/********************************************************************** + * wayland_surface_get_client + */ +struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) +{ + struct wayland_client_surface *client; + + if ((client = surface->client)) + { + InterlockedIncrement(&client->ref); + return client; + } + + if (!(client = wayland_client_surface_create(surface->hwnd))) + return NULL; + + 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"); + goto err; + } + /* Present contents independently of the parent surface. */ + wl_subsurface_set_desync(client->wl_subsurface); + + wayland_surface_reconfigure_client(surface); + /* Commit to apply subsurface positioning. */ + wl_surface_commit(surface->wl_surface); + + surface->client = client; + return client; + +err: + wayland_client_surface_release(client); + return NULL; +} + BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region) { struct wayland_surface *wayland_surface;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 19 +++++++++++++++ dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 33 +++++++------------------- 3 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 13503cc849d..5d3fe1e3938 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -815,6 +815,25 @@ err: return NULL; }
+void wayland_client_surface_attach(struct wayland_client_surface *client, 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) + { + ERR("Failed to create client wl_subsurface\n"); + return; + } + /* Present contents independently of the parent surface. */ + wl_subsurface_set_desync(client->wl_subsurface); + + wayland_surface_reconfigure_client(surface); + /* Commit to apply subsurface positioning. */ + wl_surface_commit(surface->wl_surface); +} + static void dummy_buffer_release(void *data, struct wl_buffer *buffer) { struct wayland_shm_buffer *shm_buffer = data; diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index bd6fcb50147..39f1e831084 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -255,6 +255,7 @@ void wayland_surface_coords_to_window(struct wayland_surface *surface, struct wayland_client_surface *wayland_client_surface_create(HWND hwnd); struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface); 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_surface_ensure_contents(struct wayland_surface *surface); void wayland_surface_set_title(struct wayland_surface *surface, LPCWSTR title);
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 0874ec5121e..1c871747d4e 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -688,38 +688,21 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) { struct wayland_client_surface *client; + HWND hwnd = surface->hwnd;
- if ((client = surface->client)) - { - InterlockedIncrement(&client->ref); - return client; - } + /* ownership is shared with one of the callers, the last caller to release + * its reference will also destroy it and clear our pointer. */ + if ((client = surface->client)) InterlockedIncrement(&client->ref);
- if (!(client = wayland_client_surface_create(surface->hwnd))) - return NULL; + if (!client && !(client = wayland_client_surface_create(hwnd))) return NULL;
- client->wl_subsurface = - wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, - client->wl_surface, - surface->wl_surface); - if (!client->wl_subsurface) + if (!surface->client) { - ERR("Failed to create client wl_subsurface\n"); - goto err; + wayland_client_surface_attach(client, surface); + surface->client = client; } - /* Present contents independently of the parent surface. */ - wl_subsurface_set_desync(client->wl_subsurface);
- wayland_surface_reconfigure_client(surface); - /* Commit to apply subsurface positioning. */ - wl_surface_commit(surface->wl_surface); - - surface->client = client; return client; - -err: - wayland_client_surface_release(client); - return NULL; }
BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 31 +++++--------------------- dlls/winewayland.drv/vulkan.c | 17 ++------------- dlls/winewayland.drv/waylanddrv.h | 2 +- dlls/winewayland.drv/window.c | 36 ++++++++++++++++++++++++------- 4 files changed, 36 insertions(+), 50 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 94ff32c81f1..74c3cb02d8e 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -192,9 +192,8 @@ static inline EGLConfig egl_config_for_format(int format) static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int format) { struct wayland_gl_drawable *gl; - struct wayland_surface *wayland_surface; int client_width = 0, client_height = 0; - struct wayland_win_data *data; + RECT client_rect;
TRACE("hwnd=%p format=%d\n", hwnd, format);
@@ -208,31 +207,11 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for /* Get the client surface for the HWND. If don't have a wayland surface * (e.g., HWND_MESSAGE windows) just create a dummy surface to act as the * target render surface. */ - if ((data = wayland_win_data_get(hwnd))) - { - if (!(wayland_surface = data->wayland_surface)) - { - gl->client = wayland_client_surface_create(hwnd); - client_width = client_height = 1; - } - else - { - gl->client = wayland_surface_get_client(wayland_surface); - client_width = wayland_surface->window.client_rect.right - - wayland_surface->window.client_rect.left; - client_height = wayland_surface->window.client_rect.bottom - - wayland_surface->window.client_rect.top; - if (client_width == 0 || client_height == 0) - client_width = client_height = 1; - } - wayland_win_data_release(data); - } - else - { - gl->client = wayland_client_surface_create(hwnd); + if (!(gl->client = get_client_surface(hwnd, &client_rect))) goto err; + client_width = client_rect.right - client_rect.left; + client_height = client_rect.bottom - client_rect.top; + if (client_width == 0 || client_height == 0) client_width = client_height = 1; - } - if (!gl->client) goto err;
gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, client_width, client_height); diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 7a075a925b7..9628fd81fe5 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -73,25 +73,12 @@ static VkResult wayland_vulkan_surface_create(HWND hwnd, VkInstance instance, Vk { VkResult res; VkWaylandSurfaceCreateInfoKHR create_info_host; - struct wayland_surface *wayland_surface; struct wayland_client_surface *client; - struct wayland_win_data *data; + RECT client_rect;
TRACE("%p %p %p %p\n", hwnd, instance, surface, private);
- if (!(data = wayland_win_data_get(hwnd))) - { - ERR("Failed to find wayland surface for hwnd=%p\n", hwnd); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - - if ((wayland_surface = data->wayland_surface)) - client = wayland_surface_get_client(wayland_surface); - else - client = wayland_client_surface_create(hwnd); - wayland_win_data_release(data); - - if (!client) + if (!(client = get_client_surface(hwnd, &client_rect))) { ERR("Failed to create client surface for hwnd=%p\n", hwnd); return VK_ERROR_OUT_OF_HOST_MEMORY; diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 39f1e831084..8e1895b9b8d 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -253,7 +253,6 @@ void wayland_surface_coords_to_window(struct wayland_surface *surface, double surface_x, double surface_y, int *window_x, int *window_y); struct wayland_client_surface *wayland_client_surface_create(HWND hwnd); -struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface); 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_surface_ensure_contents(struct wayland_surface *surface); @@ -290,6 +289,7 @@ struct wayland_win_data struct wayland_win_data *wayland_win_data_get(HWND hwnd); void wayland_win_data_release(struct wayland_win_data *data);
+struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect); 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); diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 1c871747d4e..32d1ade6fa2 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -683,25 +683,45 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) }
/********************************************************************** - * wayland_surface_get_client + * get_client_surface */ -struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) +struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect) { struct wayland_client_surface *client; - HWND hwnd = surface->hwnd; + struct wayland_surface *surface; + struct wayland_win_data *data;
- /* ownership is shared with one of the callers, the last caller to release - * its reference will also destroy it and clear our pointer. */ - if ((client = surface->client)) InterlockedIncrement(&client->ref); + if (!(data = wayland_win_data_get(hwnd))) surface = NULL; + else surface = data->wayland_surface;
- if (!client && !(client = wayland_client_surface_create(hwnd))) return NULL; + if (surface) + { + /* ownership is shared with one of the callers, the last caller to release + * its reference will also destroy it and clear our pointer. */ + if ((client = surface->client)) InterlockedIncrement(&client->ref);
- if (!surface->client) + *client_rect = surface->window.client_rect; + } + else + { + client = NULL; + SetRectEmpty(client_rect); + } + + if (!client && !(client = wayland_client_surface_create(hwnd))) + { + if (data) wayland_win_data_release(data); + return NULL; + } + if (!data) return client; + + if (surface && !surface->client) { wayland_client_surface_attach(client, surface); surface->client = client; }
+ wayland_win_data_release(data); return client; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 4 ++-- dlls/winewayland.drv/vulkan.c | 4 ++-- dlls/winewayland.drv/wayland_surface.c | 26 ++++++++++++-------------- dlls/winewayland.drv/waylanddrv.h | 10 ++++++---- dlls/winewayland.drv/window.c | 25 +++++++++++++------------ 5 files changed, 35 insertions(+), 34 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 74c3cb02d8e..ecb1a65c38c 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -168,8 +168,8 @@ static void wayland_gl_drawable_release(struct wayland_gl_drawable *gl) HWND hwnd = wl_surface_get_user_data(gl->client->wl_surface); struct wayland_win_data *data = wayland_win_data_get(hwnd);
- if (wayland_client_surface_release(gl->client) && data && data->wayland_surface) - data->wayland_surface->client = NULL; + if (wayland_client_surface_release(gl->client) && data) + data->client_surface = NULL;
if (data) wayland_win_data_release(data); } diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 9628fd81fe5..7c8537bfc40 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -63,8 +63,8 @@ static void wine_vk_surface_destroy(struct wayland_client_surface *client) HWND hwnd = wl_surface_get_user_data(client->wl_surface); struct wayland_win_data *data = wayland_win_data_get(hwnd);
- if (wayland_client_surface_release(client) && data && data->wayland_surface) - data->wayland_surface->client = NULL; + if (wayland_client_surface_release(client) && data) + data->client_surface = NULL;
if (data) wayland_win_data_release(data); } diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 5d3fe1e3938..27d1fde8c12 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -494,14 +494,12 @@ static void wayland_surface_reconfigure_size(struct wayland_surface *surface, * * Reconfigures the subsurface covering the client area. */ -void wayland_surface_reconfigure_client(struct wayland_surface *surface) +void wayland_surface_reconfigure_client(struct wayland_surface *surface, struct wayland_client_surface *client) { struct wayland_window_config *window = &surface->window; int client_x, client_y, x, y; int client_width, client_height, width, height;
- if (!surface->client) return; - /* The offset of the client area origin relatively to the window origin. */ client_x = window->client_rect.left - window->rect.left; client_y = window->client_rect.top - window->rect.top; @@ -515,17 +513,16 @@ void wayland_surface_reconfigure_client(struct wayland_surface *surface)
TRACE("hwnd=%p subsurface=%d,%d+%dx%d\n", surface->hwnd, x, y, width, height);
- wl_subsurface_set_position(surface->client->wl_subsurface, x, y); + wl_subsurface_set_position(client->wl_subsurface, x, y);
if (width != 0 && height != 0) - wp_viewport_set_destination(surface->client->wp_viewport, - width, height); + wp_viewport_set_destination(client->wp_viewport, width, height); else /* We can't have a 0x0 destination, use 1x1 instead. */ - wp_viewport_set_destination(surface->client->wp_viewport, 1, 1); + wp_viewport_set_destination(client->wp_viewport, 1, 1);
- wl_surface_commit(surface->client->wl_surface); + wl_surface_commit(client->wl_surface);
- wayland_resize_gl_drawable(surface->hwnd); + wayland_resize_gl_drawable(client->hwnd); }
/********************************************************************** @@ -534,7 +531,7 @@ void wayland_surface_reconfigure_client(struct wayland_surface *surface) * Reconfigures the wayland surface as needed to match the latest requested * state. */ -BOOL wayland_surface_reconfigure(struct wayland_surface *surface) +BOOL wayland_surface_reconfigure(struct wayland_surface *surface, struct wayland_client_surface *client) { struct wayland_window_config *window = &surface->window; int win_width, win_height, width, height; @@ -585,7 +582,7 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface)
wayland_surface_reconfigure_geometry(surface, width, height); wayland_surface_reconfigure_size(surface, width, height); - wayland_surface_reconfigure_client(surface); + if (client) wayland_surface_reconfigure_client(surface, client);
return TRUE; } @@ -779,6 +776,7 @@ struct wayland_client_surface *wayland_client_surface_create(HWND hwnd) return NULL; } client->ref = 1; + client->hwnd = hwnd;
client->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor); @@ -829,7 +827,7 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, struct /* Present contents independently of the parent surface. */ wl_subsurface_set_desync(client->wl_subsurface);
- wayland_surface_reconfigure_client(surface); + wayland_surface_reconfigure_client(surface, client); /* Commit to apply subsurface positioning. */ wl_surface_commit(surface->wl_surface); } @@ -852,7 +850,7 @@ static const struct wl_buffer_listener dummy_buffer_listener = * Ensure that the wayland surface has up-to-date contents, by committing * a dummy buffer if necessary. */ -void wayland_surface_ensure_contents(struct wayland_surface *surface) +void wayland_surface_ensure_contents(struct wayland_surface *surface, struct wayland_client_surface *client) { struct wayland_shm_buffer *dummy_shm_buffer; HRGN damage; @@ -883,7 +881,7 @@ void wayland_surface_ensure_contents(struct wayland_surface *surface) if (!(damage = NtGdiCreateRectRgn(0, 0, width, height))) WARN("Failed to create damage region for dummy buffer\n");
- if (wayland_surface_reconfigure(surface)) + if (wayland_surface_reconfigure(surface, client)) { wayland_surface_attach_shm(surface, dummy_shm_buffer, damage); wl_surface_commit(surface->wl_surface); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 8e1895b9b8d..ecefeeb77af 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -184,6 +184,7 @@ struct wayland_window_config struct wayland_client_surface { LONG ref; + HWND hwnd; struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct wp_viewport *wp_viewport; @@ -199,7 +200,6 @@ struct wayland_surface struct wayland_surface_config pending, requested, processing, current; BOOL resizing; struct wayland_window_config window; - struct wayland_client_surface *client; int content_width, content_height; HCURSOR hcursor; }; @@ -241,8 +241,8 @@ void wayland_surface_clear_role(struct wayland_surface *surface); void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region); -void wayland_surface_reconfigure_client(struct wayland_surface *surface); -BOOL wayland_surface_reconfigure(struct wayland_surface *surface); +BOOL wayland_surface_reconfigure(struct wayland_surface *surface, struct wayland_client_surface *client); +void wayland_surface_reconfigure_client(struct wayland_surface *surface, struct wayland_client_surface *client); BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf, int width, int height, enum wayland_surface_config_state state); @@ -255,7 +255,7 @@ void wayland_surface_coords_to_window(struct wayland_surface *surface, 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_surface_ensure_contents(struct wayland_surface *surface); +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);
/********************************************************************** @@ -281,6 +281,8 @@ struct wayland_win_data struct wayland_shm_buffer *window_contents; /* wayland surface (if any) for this window */ struct wayland_surface *wayland_surface; + /* wayland client surface (if any) for this window */ + struct wayland_client_surface *client_surface; /* window rects, relative to parent client area */ struct window_rects rects; BOOL managed; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 32d1ade6fa2..4fcada57e06 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -691,19 +691,20 @@ struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect) struct wayland_surface *surface; struct wayland_win_data *data;
- if (!(data = wayland_win_data_get(hwnd))) surface = NULL; - else surface = data->wayland_surface; - - if (surface) + if ((data = wayland_win_data_get(hwnd))) { + surface = data->wayland_surface; + /* ownership is shared with one of the callers, the last caller to release * its reference will also destroy it and clear our pointer. */ - if ((client = surface->client)) InterlockedIncrement(&client->ref); + if ((client = data->client_surface)) InterlockedIncrement(&client->ref);
- *client_rect = surface->window.client_rect; + if (!data->wayland_surface) *client_rect = data->rects.client; + else *client_rect = data->wayland_surface->window.client_rect; } else { + surface = NULL; client = NULL; SetRectEmpty(client_rect); } @@ -715,10 +716,10 @@ struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect) } if (!data) return client;
- if (surface && !surface->client) + if (!data->client_surface) { - wayland_client_surface_attach(client, surface); - surface->client = client; + if (surface) wayland_client_surface_attach(client, surface); + data->client_surface = client; }
wayland_win_data_release(data); @@ -735,7 +736,7 @@ BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffe
if ((wayland_surface = data->wayland_surface)) { - if (wayland_surface_reconfigure(wayland_surface)) + if (wayland_surface_reconfigure(wayland_surface, data->client_surface)) { wayland_surface_attach_shm(wayland_surface, shm_buffer, damage_region); wl_surface_commit(wayland_surface->wl_surface); @@ -780,13 +781,13 @@ void ensure_window_surface_contents(HWND hwnd)
if ((wayland_surface = data->wayland_surface)) { - wayland_surface_ensure_contents(wayland_surface); + wayland_surface_ensure_contents(wayland_surface, data->client_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)) + wayland_surface_reconfigure(wayland_surface, data->client_surface)) { wl_surface_commit(wayland_surface->wl_surface); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 17 ++++++++++++++++- dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 25 ++++++++++++++++++------- 3 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 27d1fde8c12..1cf5dd3f8ce 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -513,7 +513,11 @@ void wayland_surface_reconfigure_client(struct wayland_surface *surface, struct
TRACE("hwnd=%p subsurface=%d,%d+%dx%d\n", surface->hwnd, x, y, width, height);
- wl_subsurface_set_position(client->wl_subsurface, x, y); + if (client->wl_subsurface) + { + wl_subsurface_set_position(client->wl_subsurface, x, y); + wl_subsurface_place_above(client->wl_subsurface, surface->wl_surface); + }
if (width != 0 && height != 0) wp_viewport_set_destination(client->wp_viewport, width, height); @@ -815,6 +819,8 @@ err:
void wayland_client_surface_attach(struct wayland_client_surface *client, struct wayland_surface *surface) { + wayland_client_surface_detach(client); + client->wl_subsurface = wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, client->wl_surface, @@ -832,6 +838,15 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, struct wl_surface_commit(surface->wl_surface); }
+void wayland_client_surface_detach(struct wayland_client_surface *client) +{ + if (client->wl_subsurface) + { + wl_subsurface_destroy(client->wl_subsurface); + client->wl_subsurface = NULL; + } +} + static void dummy_buffer_release(void *data, struct wl_buffer *buffer) { struct wayland_shm_buffer *shm_buffer = data; diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index ecefeeb77af..9de42758aa1 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -255,6 +255,7 @@ void wayland_surface_coords_to_window(struct wayland_surface *surface, 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_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);
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 4fcada57e06..d27a16456d2 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -195,6 +195,7 @@ static void reapply_cursor_clipping(void)
static void wayland_win_data_update_wayland_surface(struct wayland_win_data *data) { + struct wayland_client_surface *client = data->client_surface; struct wayland_surface *surface = data->wayland_surface; HWND parent = NtUserGetAncestor(data->hwnd, GA_PARENT); BOOL visible, xdg_visible; @@ -205,7 +206,11 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat /* We don't want wayland surfaces for child windows. */ if (parent != NtUserGetDesktopWindow() && parent != 0) { - if (surface) wayland_surface_destroy(surface); + if (surface) + { + if (client) wayland_client_surface_attach(client, surface); + wayland_surface_destroy(surface); + } surface = NULL; goto out; } @@ -219,13 +224,18 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat if (visible != xdg_visible) { /* If we have a pre-existing surface ensure it has no role. */ - if (data->wayland_surface) wayland_surface_clear_role(surface); + if (data->wayland_surface) + { + if (client) wayland_client_surface_detach(client); + wayland_surface_clear_role(surface); + } /* If the window is a visible toplevel make it a wayland * xdg_toplevel. Otherwise keep it role-less to avoid polluting the * compositor with empty xdg_toplevels. */ if (visible) { wayland_surface_make_toplevel(surface); + if (client) wayland_client_surface_attach(client, surface); if (surface->xdg_toplevel) { if (!NtUserInternalGetWindowText(data->hwnd, text, ARRAY_SIZE(text))) @@ -716,11 +726,12 @@ struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect) } if (!data) return client;
- if (!data->client_surface) - { - if (surface) wayland_client_surface_attach(client, surface); - data->client_surface = client; - } + if (surface && NtUserIsWindowVisible(hwnd)) + wayland_client_surface_attach(client, surface); + else + wayland_client_surface_detach(client); + + if (!data->client_surface) data->client_surface = client;
wayland_win_data_release(data); return client;
On Tue Sep 10 07:28:15 2024 +0000, Rémi Bernon wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/6452/diffs?diff_id=131218&start_sha=a90ded8c526e963c8356b7936cd18f36cb230af4#be6b1a6381414c8dae6f91e46942652a04a69f08_732_734)
Ownership should be fixed hopefully now.
This merge request was approved by Alexandros Frantzis.