-- v7: winewayland: Let the render threads commit changes to client surfaces. winewayland: Attach client client surfaces to their toplevel surface. winewayland: Pass the client surface rect to wayland_surface_reconfigure_client. winewayland: Split wayland_win_data_update_wayland_surface helper. winewayland: Update the client separately from the window surface updates. winewayland: Keep the toplevel hwnd on the wayland_client_surface. winewayland: Call ensure_window_surface_contents with the toplevel window. winewayland: Use window DPI for the OpenGL client surface size. win32u: Notify drivers of the child surfaces state when their ancestor moves.
From: Rémi Bernon rbernon@codeweavers.com
Since changes in a parent window state may affect the children state in the driver, ensure the driver gets a chance to update its internal state. --- dlls/win32u/window.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index c325f9438d3..cf073fb9fcf 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1483,6 +1483,18 @@ int win32u_get_window_pixel_format( HWND hwnd ) return ret; }
+static int window_has_client_surface( HWND hwnd ) +{ + WND *win = get_win_ptr( hwnd ); + BOOL ret; + + if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE; + ret = win->pixel_format || win->internal_pixel_format || !list_empty(&win->vulkan_surfaces); + release_win_ptr( win ); + + return ret; +} + /*********************************************************************** * NtUserGetProp (win32u.@) * @@ -1960,6 +1972,22 @@ static struct window_surface *get_window_surface( HWND hwnd, UINT swp_flags, BOO return new_surface; }
+static void update_children_window_state( HWND hwnd ) +{ + HWND *children; + int i; + + if (!(children = list_window_children( 0, hwnd, NULL, 0 ))) return; + + for (i = 0; children[i]; i++) + { + if (!window_has_client_surface( children[i] )) continue; + update_window_state( children[i] ); + } + + free( children ); +} + /*********************************************************************** * apply_window_pos * @@ -2105,6 +2133,8 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru }
user_driver->pWindowPosChanged( hwnd, insert_after, swp_flags, is_fullscreen, &monitor_rects, get_driver_window_surface( new_surface, monitor_dpi ) ); + + update_children_window_state( hwnd ); }
return ret;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 37 ++++++++++++------------------- dlls/winewayland.drv/vulkan.c | 3 +-- dlls/winewayland.drv/waylanddrv.h | 2 +- dlls/winewayland.drv/window.c | 6 +---- 4 files changed, 17 insertions(+), 31 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index ecb1a65c38c..a19aa9faf71 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -192,8 +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; - int client_width = 0, client_height = 0; - RECT client_rect; + int client_width, client_height; + RECT client_rect = {0};
TRACE("hwnd=%p format=%d\n", hwnd, format);
@@ -204,14 +204,15 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for gl->hwnd = hwnd; gl->swap_interval = 1;
+ NtUserGetClientRect(gl->hwnd, &client_rect, NtUserGetDpiForWindow(gl->hwnd)); + 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; + /* 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 (!(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 = get_client_surface(hwnd))) goto err;
gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, client_width, client_height); @@ -273,25 +274,15 @@ static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *ne
static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl) { - int client_width = 0, client_height = 0; - struct wayland_surface *wayland_surface; - struct wayland_win_data *data; + int client_width, client_height; + RECT client_rect = {0};
if (InterlockedCompareExchange(&gl->resized, FALSE, TRUE)) { - if (!(data = wayland_win_data_get(gl->hwnd))) return; - - if ((wayland_surface = data->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); + NtUserGetClientRect(gl->hwnd, &client_rect, NtUserGetDpiForWindow(gl->hwnd)); + 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;
wl_egl_window_resize(gl->wl_egl_window, client_width, client_height, 0, 0); } diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 2874ae339d3..6e794a88cf7 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -74,11 +74,10 @@ static VkResult wayland_vulkan_surface_create(HWND hwnd, VkInstance instance, Vk VkResult res; VkWaylandSurfaceCreateInfoKHR create_info_host; struct wayland_client_surface *client; - RECT client_rect;
TRACE("%p %p %p %p\n", hwnd, instance, surface, private);
- if (!(client = get_client_surface(hwnd, &client_rect))) + if (!(client = get_client_surface(hwnd))) { 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 3dee8e432df..9c98fdb1586 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -293,7 +293,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); +struct wayland_client_surface *get_client_surface(HWND hwnd); 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 66e34d4f5bc..077c7576825 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -696,7 +696,7 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) /********************************************************************** * get_client_surface */ -struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect) +struct wayland_client_surface *get_client_surface(HWND hwnd) { struct wayland_client_surface *client; struct wayland_surface *surface; @@ -709,15 +709,11 @@ struct wayland_client_surface *get_client_surface(HWND hwnd, RECT *client_rect) /* 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 = data->client_surface)) InterlockedIncrement(&client->ref); - - 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); }
if (!client && !(client = wayland_client_surface_create(hwnd)))
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 3 ++- dlls/winewayland.drv/vulkan.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index a19aa9faf71..b8b673f398a 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -708,12 +708,13 @@ static BOOL wayland_wglShareLists(struct wgl_context *orig, struct wgl_context * static BOOL wayland_wglSwapBuffers(HDC hdc) { struct wgl_context *ctx = NtCurrentTeb()->glContext; + HWND hwnd = NtUserWindowFromDC(hdc), toplevel = NtUserGetAncestor(hwnd, GA_ROOT); struct wayland_gl_drawable *gl;
if (!(gl = wayland_gl_drawable_get(NtUserWindowFromDC(hdc), hdc))) return FALSE;
if (ctx) wgl_context_refresh(ctx); - ensure_window_surface_contents(gl->hwnd); + ensure_window_surface_contents(toplevel); /* Although all the EGL surfaces we create are double-buffered, we want to * use some as single-buffered, so avoid swapping those. */ if (gl->double_buffered) p_eglSwapBuffers(egl_display, gl->surface); diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 6e794a88cf7..4398cad0558 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -120,7 +120,8 @@ static void wayland_vulkan_surface_detach(HWND hwnd, void *private)
static void wayland_vulkan_surface_presented(HWND hwnd, void *private, VkResult result) { - ensure_window_surface_contents(hwnd); + HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + ensure_window_surface_contents(toplevel); }
static VkBool32 wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev,
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);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 7 +++---- dlls/winewayland.drv/waylanddrv.h | 4 ++-- dlls/winewayland.drv/window.c | 19 ++++++++----------- 3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index d526123b569..4dc3101de76 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -535,7 +535,7 @@ void wayland_surface_reconfigure_client(struct wayland_surface *surface, struct * Reconfigures the wayland surface as needed to match the latest requested * state. */ -BOOL wayland_surface_reconfigure(struct wayland_surface *surface, struct wayland_client_surface *client) +BOOL wayland_surface_reconfigure(struct wayland_surface *surface) { struct wayland_window_config *window = &surface->window; int win_width, win_height, width, height; @@ -586,7 +586,6 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface, struct wayland
wayland_surface_reconfigure_geometry(surface, width, height); wayland_surface_reconfigure_size(surface, width, height); - if (client) wayland_surface_reconfigure_client(surface, client);
return TRUE; } @@ -881,7 +880,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, struct wayland_client_surface *client) +void wayland_surface_ensure_contents(struct wayland_surface *surface) { struct wayland_shm_buffer *dummy_shm_buffer; HRGN damage; @@ -912,7 +911,7 @@ void wayland_surface_ensure_contents(struct wayland_surface *surface, struct way if (!(damage = NtGdiCreateRectRgn(0, 0, width, height))) WARN("Failed to create damage region for dummy buffer\n");
- if (wayland_surface_reconfigure(surface, client)) + if (wayland_surface_reconfigure(surface)) { 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 a0d5deb5fab..ec15e5d5394 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -242,7 +242,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); -BOOL wayland_surface_reconfigure(struct wayland_surface *surface, struct wayland_client_surface *client); +BOOL wayland_surface_reconfigure(struct wayland_surface *surface); 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, @@ -257,7 +257,7 @@ 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, 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_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 0cc5f323b24..82dae28c4f3 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -228,27 +228,23 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat goto out; }
+ visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; + if (!visible && client) wayland_client_surface_detach(client); + /* Otherwise ensure that we have a wayland surface. */ if (!surface && !(surface = wayland_surface_create(data->hwnd))) return; - - visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; xdg_visible = surface->xdg_toplevel != NULL;
if (visible != xdg_visible) { /* If we have a pre-existing surface ensure it has no role. */ - if (data->wayland_surface) - { - if (client) wayland_client_surface_detach(client); - wayland_surface_clear_role(surface); - } + if (data->wayland_surface) 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, data->hwnd); if (surface->xdg_toplevel) { if (!NtUserInternalGetWindowText(data->hwnd, text, ARRAY_SIZE(text))) @@ -258,6 +254,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat } }
+ 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 @@ -757,7 +754,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, data->client_surface)) + if (wayland_surface_reconfigure(wayland_surface)) { wayland_surface_attach_shm(wayland_surface, shm_buffer, damage_region); wl_surface_commit(wayland_surface->wl_surface); @@ -802,13 +799,13 @@ void ensure_window_surface_contents(HWND hwnd)
if ((wayland_surface = data->wayland_surface)) { - wayland_surface_ensure_contents(wayland_surface, data->client_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, data->client_surface)) + wayland_surface_reconfigure(wayland_surface)) { wl_surface_commit(wayland_surface->wl_surface); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/window.c | 42 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 82dae28c4f3..afa5b917fbb 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -206,33 +206,19 @@ static void reapply_cursor_clipping(void) NtUserSetThreadDpiAwarenessContext(context); }
-static void wayland_win_data_update_wayland_surface(struct wayland_win_data *data) +static BOOL 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); + struct wayland_surface *surface; BOOL visible, xdg_visible; WCHAR text[1024];
TRACE("hwnd=%p\n", data->hwnd);
- /* We don't want wayland surfaces for child windows. */ - if (parent != NtUserGetDesktopWindow() && parent != 0) - { - if (surface) - { - if (client) wayland_client_surface_detach(client); - wayland_surface_destroy(surface); - } - surface = NULL; - goto out; - } - visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; if (!visible && client) wayland_client_surface_detach(client);
- /* Otherwise ensure that we have a wayland surface. */ - if (!surface && !(surface = wayland_surface_create(data->hwnd))) return; + if (!(surface = data->wayland_surface) && !(surface = wayland_surface_create(data->hwnd))) return FALSE; xdg_visible = surface->xdg_toplevel != NULL;
if (visible != xdg_visible) @@ -261,9 +247,9 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat * it as needed. */ if (data->hwnd == NtUserGetForegroundWindow()) reapply_cursor_clipping();
-out: TRACE("hwnd=%p surface=%p=>%p\n", data->hwnd, data->wayland_surface, surface); data->wayland_surface = surface; + return TRUE; }
static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) @@ -448,6 +434,7 @@ BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, BOOL shaped, const str void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL fullscreen, const struct window_rects *new_rects, struct window_surface *surface) { + struct wayland_client_surface *client; struct wayland_win_data *data; BOOL managed;
@@ -464,8 +451,23 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL data->is_fullscreen = fullscreen; data->managed = managed;
- wayland_win_data_update_wayland_surface(data); - if (data->wayland_surface) wayland_win_data_update_wayland_state(data); + if (!surface) + { + if ((client = data->client_surface)) + { + wayland_client_surface_detach(client); + } + + if (data->wayland_surface) + { + wayland_surface_destroy(data->wayland_surface); + data->wayland_surface = NULL; + } + } + else if (wayland_win_data_update_wayland_surface(data)) + { + wayland_win_data_update_wayland_state(data); + }
wayland_win_data_release(data); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 17 +++++++++++------ dlls/winewayland.drv/waylanddrv.h | 2 +- dlls/winewayland.drv/window.c | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 4dc3101de76..c58aeca7286 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -494,18 +494,20 @@ 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, struct wayland_client_surface *client) +static void wayland_surface_reconfigure_client(struct wayland_surface *surface, + struct wayland_client_surface *client, + const RECT *client_rect) { struct wayland_window_config *window = &surface->window; int client_x, client_y, x, y; int client_width, client_height, width, height;
/* 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; + client_x = client_rect->left + window->client_rect.left - window->rect.left; + client_y = client_rect->top + window->client_rect.top - window->rect.top;
- client_width = window->client_rect.right - window->client_rect.left; - client_height = window->client_rect.bottom - window->client_rect.top; + client_width = client_rect->right - client_rect->left; + client_height = client_rect->bottom - client_rect->top;
wayland_surface_coords_from_window(surface, client_x, client_y, &x, &y); wayland_surface_coords_from_window(surface, client_width, client_height, @@ -820,6 +822,7 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t { struct wayland_win_data *toplevel_data = wayland_win_data_get_nolock(toplevel); struct wayland_surface *surface; + RECT client_rect;
if (!toplevel_data || !(surface = toplevel_data->wayland_surface)) { @@ -846,7 +849,9 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t client->toplevel = toplevel; }
- wayland_surface_reconfigure_client(surface, client); + NtUserGetClientRect(client->hwnd, &client_rect, get_win_monitor_dpi(client->hwnd)); + + wayland_surface_reconfigure_client(surface, client, &client_rect); /* Commit to apply subsurface positioning. */ wl_surface_commit(surface->wl_surface); } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index ec15e5d5394..4b49b4fbb2f 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -243,7 +243,6 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region); BOOL wayland_surface_reconfigure(struct wayland_surface *surface); -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); @@ -291,6 +290,7 @@ struct wayland_win_data BOOL managed; };
+UINT get_win_monitor_dpi(HWND hwnd); 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); diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index afa5b917fbb..b0b8f1a549b 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -40,7 +40,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv); /********************************************************************** * get_win_monitor_dpi */ -static UINT get_win_monitor_dpi(HWND hwnd) +UINT get_win_monitor_dpi(HWND hwnd) { return NtUserGetSystemDpiForProcess(NULL); /* FIXME: get monitor dpi */ }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 1 + dlls/winewayland.drv/window.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index c58aeca7286..4f72150949b 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -850,6 +850,7 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t }
NtUserGetClientRect(client->hwnd, &client_rect, get_win_monitor_dpi(client->hwnd)); + NtUserMapWindowPoints(client->hwnd, toplevel, (POINT *)&client_rect, 2, get_win_monitor_dpi(client->hwnd));
wayland_surface_reconfigure_client(surface, client, &client_rect); /* Commit to apply subsurface positioning. */ diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index b0b8f1a549b..2a9f4ff8036 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -434,6 +434,7 @@ BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, BOOL shaped, const str void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL fullscreen, const struct window_rects *new_rects, struct window_surface *surface) { + HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); struct wayland_client_surface *client; struct wayland_win_data *data; BOOL managed; @@ -455,7 +456,10 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL { if ((client = data->client_surface)) { - wayland_client_surface_detach(client); + if (toplevel && NtUserIsWindowVisible(hwnd)) + wayland_client_surface_attach(client, toplevel); + else + wayland_client_surface_detach(client); }
if (data->wayland_surface) @@ -710,21 +714,18 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) */ struct wayland_client_surface *get_client_surface(HWND hwnd) { + HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); struct wayland_client_surface *client; - struct wayland_surface *surface; struct wayland_win_data *data;
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 = data->client_surface)) InterlockedIncrement(&client->ref); } else { - surface = NULL; client = NULL; }
@@ -735,8 +736,8 @@ struct wayland_client_surface *get_client_surface(HWND hwnd) } if (!data) return client;
- if (surface && NtUserIsWindowVisible(hwnd)) - wayland_client_surface_attach(client, data->hwnd); + if (toplevel && NtUserIsWindowVisible(hwnd)) + wayland_client_surface_attach(client, toplevel); else wayland_client_surface_detach(client);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 4f72150949b..e5794ee440f 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -526,8 +526,6 @@ static void wayland_surface_reconfigure_client(struct wayland_surface *surface, else /* We can't have a 0x0 destination, use 1x1 instead. */ wp_viewport_set_destination(client->wp_viewport, 1, 1);
- wl_surface_commit(client->wl_surface); - wayland_resize_gl_drawable(client->hwnd); }
v7: Updated with client_rect initialized.
This merge request was approved by Alexandros Frantzis.