-- v3: winewayland: Use subsurfaces for unmanaged windows. winewayland: Introduce a new update_wayland_surface_state_toplevel helper. winewayland: Introduce a new wayland_surface_reconfigure_xdg helper. winewayland: Introduce a new wayland_surface role enumeration. winewayland: Call wayland_surface_clear_role in wayland_surface_destroy. winewayland: Move surface title change to wayland_surface_make_toplevel.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 6 ++++++ dlls/winewayland.drv/window.c | 12 +----------- 2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index e5794ee440f..a3b81b66f02 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -240,6 +240,8 @@ void wayland_surface_destroy(struct wayland_surface *surface) */ void wayland_surface_make_toplevel(struct wayland_surface *surface) { + WCHAR text[1024]; + TRACE("surface=%p\n", surface);
surface->xdg_surface = @@ -257,6 +259,10 @@ void wayland_surface_make_toplevel(struct wayland_surface *surface) wl_surface_commit(surface->wl_surface); wl_display_flush(process_wayland.wl_display);
+ if (!NtUserInternalGetWindowText(surface->hwnd, text, ARRAY_SIZE(text))) + text[0] = 0; + wayland_surface_set_title(surface, text); + return;
err: diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 2a9f4ff8036..4ab08de9388 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -211,7 +211,6 @@ static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *dat struct wayland_client_surface *client = data->client_surface; struct wayland_surface *surface; BOOL visible, xdg_visible; - WCHAR text[1024];
TRACE("hwnd=%p\n", data->hwnd);
@@ -228,16 +227,7 @@ static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *dat /* 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 (surface->xdg_toplevel) - { - if (!NtUserInternalGetWindowText(data->hwnd, text, ARRAY_SIZE(text))) - text[0] = 0; - wayland_surface_set_title(surface, text); - } - } + if (visible) wayland_surface_make_toplevel(surface); }
if (visible && client) wayland_client_surface_attach(client, data->hwnd);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index a3b81b66f02..ba2ba4a345f 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -204,24 +204,14 @@ void wayland_surface_destroy(struct wayland_surface *surface) process_wayland.keyboard.focused_hwnd = NULL; pthread_mutex_unlock(&process_wayland.keyboard.mutex);
+ wayland_surface_clear_role(surface); + if (surface->wp_viewport) { wp_viewport_destroy(surface->wp_viewport); surface->wp_viewport = NULL; }
- if (surface->xdg_toplevel) - { - xdg_toplevel_destroy(surface->xdg_toplevel); - surface->xdg_toplevel = NULL; - } - - if (surface->xdg_surface) - { - xdg_surface_destroy(surface->xdg_surface); - surface->xdg_surface = NULL; - } - if (surface->wl_surface) { wl_surface_destroy(surface->wl_surface);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 30 +++++++++++++++++------- dlls/winewayland.drv/waylanddrv.h | 20 ++++++++++++++-- dlls/winewayland.drv/window.c | 32 ++++++++++++++++++-------- 3 files changed, 62 insertions(+), 20 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index ba2ba4a345f..33fa19ee161 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -234,6 +234,12 @@ void wayland_surface_make_toplevel(struct wayland_surface *surface)
TRACE("surface=%p\n", surface);
+ assert(!surface->role || surface->role == WAYLAND_SURFACE_ROLE_TOPLEVEL); + if (surface->xdg_surface && surface->xdg_toplevel) return; + + wayland_surface_clear_role(surface); + surface->role = WAYLAND_SURFACE_ROLE_TOPLEVEL; + surface->xdg_surface = xdg_wm_base_get_xdg_surface(process_wayland.xdg_wm_base, surface->wl_surface); if (!surface->xdg_surface) goto err; @@ -271,16 +277,24 @@ void wayland_surface_clear_role(struct wayland_surface *surface) { TRACE("surface=%p\n", surface);
- if (surface->xdg_toplevel) + switch (surface->role) { - xdg_toplevel_destroy(surface->xdg_toplevel); - surface->xdg_toplevel = NULL; - } + case WAYLAND_SURFACE_ROLE_NONE: + break;
- if (surface->xdg_surface) - { - xdg_surface_destroy(surface->xdg_surface); - surface->xdg_surface = NULL; + case WAYLAND_SURFACE_ROLE_TOPLEVEL: + if (surface->xdg_toplevel) + { + xdg_toplevel_destroy(surface->xdg_toplevel); + surface->xdg_toplevel = NULL; + } + + if (surface->xdg_surface) + { + xdg_surface_destroy(surface->xdg_surface); + surface->xdg_surface = NULL; + } + break; }
memset(&surface->pending, 0, sizeof(surface->pending)); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 4b49b4fbb2f..5234ad0e49b 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -73,6 +73,12 @@ enum wayland_surface_config_state WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN = (1 << 3) };
+enum wayland_surface_role +{ + WAYLAND_SURFACE_ROLE_NONE, + WAYLAND_SURFACE_ROLE_TOPLEVEL, +}; + struct wayland_keyboard { struct wl_keyboard *wl_keyboard; @@ -194,10 +200,20 @@ struct wayland_client_surface struct wayland_surface { HWND hwnd; + struct wl_surface *wl_surface; - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; struct wp_viewport *wp_viewport; + + enum wayland_surface_role role; + union + { + struct + { + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + }; + }; + struct wayland_surface_config pending, requested, processing, current; BOOL resizing; struct wayland_window_config window; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 4ab08de9388..c31374cc564 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -210,24 +210,36 @@ static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *dat { struct wayland_client_surface *client = data->client_surface; struct wayland_surface *surface; - BOOL visible, xdg_visible; + enum wayland_surface_role role; + BOOL visible;
TRACE("hwnd=%p\n", data->hwnd);
visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; - if (!visible && client) wayland_client_surface_detach(client); + if (!visible) role = WAYLAND_SURFACE_ROLE_NONE; + else role = WAYLAND_SURFACE_ROLE_TOPLEVEL; + + /* 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_detach(client); + wayland_surface_destroy(data->wayland_surface); + data->wayland_surface = NULL; + }
if (!(surface = data->wayland_surface) && !(surface = wayland_surface_create(data->hwnd))) return FALSE; - xdg_visible = surface->xdg_toplevel != NULL;
- if (visible != xdg_visible) + /* 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. */ + switch (role) { - /* If we have a pre-existing surface ensure it has no role. */ - 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); + case WAYLAND_SURFACE_ROLE_NONE: + wayland_surface_clear_role(surface); + break; + case WAYLAND_SURFACE_ROLE_TOPLEVEL: + wayland_surface_make_toplevel(surface); + break; }
if (visible && client) wayland_client_surface_attach(client, data->hwnd);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 58 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 18 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 33fa19ee161..0a056a19084 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -540,29 +540,15 @@ static void wayland_surface_reconfigure_client(struct wayland_surface *surface, }
/********************************************************************** - * wayland_surface_reconfigure + * wayland_surface_reconfigure_xdg * - * Reconfigures the wayland surface as needed to match the latest requested + * Reconfigures the xdg surface as needed to match the latest requested * state. */ -BOOL wayland_surface_reconfigure(struct wayland_surface *surface) +static BOOL wayland_surface_reconfigure_xdg(struct wayland_surface *surface, + int width, int height) { struct wayland_window_config *window = &surface->window; - int win_width, win_height, width, height; - - if (!surface->xdg_toplevel) return TRUE; - - win_width = surface->window.rect.right - surface->window.rect.left; - win_height = surface->window.rect.bottom - surface->window.rect.top; - - wayland_surface_coords_from_window(surface, win_width, win_height, - &width, &height); - - TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n", - surface->hwnd, win_width, win_height, window->state, - surface->processing.width, surface->processing.height, - surface->processing.state, surface->current.width, - surface->current.height, surface->current.state);
/* Acknowledge any compatible processed config. */ if (surface->processing.serial && surface->processing.processed && @@ -595,6 +581,42 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) }
wayland_surface_reconfigure_geometry(surface, width, height); + + return TRUE; +} + +/********************************************************************** + * wayland_surface_reconfigure + * + * Reconfigures the wayland surface as needed to match the latest requested + * state. + */ +BOOL wayland_surface_reconfigure(struct wayland_surface *surface) +{ + struct wayland_window_config *window = &surface->window; + int win_width, win_height, width, height; + + win_width = surface->window.rect.right - surface->window.rect.left; + win_height = surface->window.rect.bottom - surface->window.rect.top; + + wayland_surface_coords_from_window(surface, win_width, win_height, + &width, &height); + + TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n", + surface->hwnd, win_width, win_height, window->state, + surface->processing.width, surface->processing.height, + surface->processing.state, surface->current.width, + surface->current.height, surface->current.state); + + switch (surface->role) + { + case WAYLAND_SURFACE_ROLE_NONE: + break; + case WAYLAND_SURFACE_ROLE_TOPLEVEL: + if (!wayland_surface_reconfigure_xdg(surface, width, height)) return FALSE; + break; + } + wayland_surface_reconfigure_size(surface, width, height);
return TRUE;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/window.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index c31374cc564..67d5ff5ddf2 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -254,18 +254,15 @@ static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *dat return TRUE; }
-static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) +static void wayland_surface_update_state_toplevel(struct wayland_surface *surface) { - struct wayland_surface *surface = data->wayland_surface; - BOOL processing_config; + BOOL processing_config = surface->processing.serial && + !surface->processing.processed;
- if (!surface->xdg_toplevel) goto out; - - processing_config = surface->processing.serial && - !surface->processing.processed; + if (!surface->xdg_toplevel) return; /* surface current role may be cleared */
TRACE("hwnd=%p window_state=%#x %s->state=%#x\n", - data->hwnd, surface->window.state, + surface->hwnd, surface->window.state, processing_config ? "processing" : "current", processing_config ? surface->processing.state : surface->current.state);
@@ -301,8 +298,21 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) { surface->processing.processed = TRUE; } +} + +static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) +{ + struct wayland_surface *surface = data->wayland_surface; + + switch (surface->role) + { + case WAYLAND_SURFACE_ROLE_NONE: + break; + case WAYLAND_SURFACE_ROLE_TOPLEVEL: + wayland_surface_update_state_toplevel(surface); + break; + }
-out: wl_display_flush(process_wayland.wl_display); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 89 ++++++++++++++++++++++++++ dlls/winewayland.drv/waylanddrv.h | 8 +++ dlls/winewayland.drv/window.c | 37 +++++++++-- 3 files changed, 130 insertions(+), 4 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 0a056a19084..4e9f3e31aa7 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -266,6 +266,47 @@ err: ERR("Failed to assign toplevel role to wayland surface\n"); }
+/********************************************************************** + * wayland_surface_make_subsurface + * + * Gives the subsurface role to a plain wayland surface. + */ +void wayland_surface_make_subsurface(struct wayland_surface *surface, + struct wayland_surface *parent) +{ + assert(!surface->role || surface->role == WAYLAND_SURFACE_ROLE_SUBSURFACE); + if (surface->wl_subsurface && surface->toplevel_hwnd == parent->hwnd) return; + + wayland_surface_clear_role(surface); + surface->role = WAYLAND_SURFACE_ROLE_SUBSURFACE; + + TRACE("surface=%p parent=%p\n", surface, parent); + + surface->wl_subsurface = + wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, + surface->wl_surface, + parent->wl_surface); + if (!surface->wl_subsurface) + { + ERR("Failed to create client wl_subsurface\n"); + goto err; + } + + surface->role = WAYLAND_SURFACE_ROLE_SUBSURFACE; + surface->toplevel_hwnd = parent->hwnd; + + /* Present contents independently of the parent surface. */ + wl_subsurface_set_desync(surface->wl_subsurface); + + wl_display_flush(process_wayland.wl_display); + + return; + +err: + wayland_surface_clear_role(surface); + ERR("Failed to assign subsurface role to wayland surface\n"); +} + /********************************************************************** * wayland_surface_clear_role * @@ -295,12 +336,23 @@ void wayland_surface_clear_role(struct wayland_surface *surface) surface->xdg_surface = NULL; } break; + + case WAYLAND_SURFACE_ROLE_SUBSURFACE: + if (surface->wl_subsurface) + { + wl_subsurface_destroy(surface->wl_subsurface); + surface->wl_subsurface = NULL; + } + + surface->toplevel_hwnd = 0; + break; }
memset(&surface->pending, 0, sizeof(surface->pending)); memset(&surface->requested, 0, sizeof(surface->requested)); memset(&surface->processing, 0, sizeof(surface->processing)); memset(&surface->current, 0, sizeof(surface->current)); + surface->toplevel_hwnd = 0;
/* Ensure no buffer is attached, otherwise future role assignments may fail. */ wl_surface_attach(surface->wl_surface, NULL, 0, 0); @@ -585,6 +637,40 @@ static BOOL wayland_surface_reconfigure_xdg(struct wayland_surface *surface, return TRUE; }
+/********************************************************************** + * wayland_surface_reconfigure_subsurface + * + * Reconfigures the subsurface as needed to match the latest requested + * state. + */ +static void wayland_surface_reconfigure_subsurface(struct wayland_surface *surface) +{ + struct wayland_win_data *toplevel_data; + struct wayland_surface *toplevel_surface; + int local_x, local_y, x, y; + + if (surface->processing.serial && surface->processing.processed && + (toplevel_data = wayland_win_data_get_nolock(surface->toplevel_hwnd)) && + (toplevel_surface = toplevel_data->wayland_surface)) + { + local_x = surface->window.rect.left - toplevel_surface->window.rect.left; + local_y = surface->window.rect.top - toplevel_surface->window.rect.top; + + wayland_surface_coords_from_window(surface, local_x, local_y, &x, &y); + + TRACE("hwnd=%p pos=%d,%d\n", surface->hwnd, x, y); + + wl_subsurface_set_position(surface->wl_subsurface, x, y); + if (toplevel_data->client_surface) + wl_subsurface_place_above(surface->wl_subsurface, toplevel_data->client_surface->wl_surface); + else + wl_subsurface_place_above(surface->wl_subsurface, toplevel_surface->wl_surface); + wl_surface_commit(toplevel_surface->wl_surface); + + memset(&surface->processing, 0, sizeof(surface->processing)); + } +} + /********************************************************************** * wayland_surface_reconfigure * @@ -615,6 +701,9 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) case WAYLAND_SURFACE_ROLE_TOPLEVEL: if (!wayland_surface_reconfigure_xdg(surface, width, height)) return FALSE; break; + case WAYLAND_SURFACE_ROLE_SUBSURFACE: + wayland_surface_reconfigure_subsurface(surface); + break; }
wayland_surface_reconfigure_size(surface, width, height); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 5234ad0e49b..ef744b715fc 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -77,6 +77,7 @@ enum wayland_surface_role { WAYLAND_SURFACE_ROLE_NONE, WAYLAND_SURFACE_ROLE_TOPLEVEL, + WAYLAND_SURFACE_ROLE_SUBSURFACE, };
struct wayland_keyboard @@ -212,6 +213,11 @@ struct wayland_surface struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; }; + struct + { + struct wl_subsurface *wl_subsurface; + HWND toplevel_hwnd; + }; };
struct wayland_surface_config pending, requested, processing, current; @@ -254,6 +260,8 @@ void wayland_output_use_xdg_extension(struct wayland_output *output); struct wayland_surface *wayland_surface_create(HWND hwnd); void wayland_surface_destroy(struct wayland_surface *surface); void wayland_surface_make_toplevel(struct wayland_surface *surface); +void wayland_surface_make_subsurface(struct wayland_surface *surface, + struct wayland_surface *parent); void wayland_surface_clear_role(struct wayland_surface *surface); void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 67d5ff5ddf2..eeeb41c952a 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -55,6 +55,15 @@ static BOOL set_window_pos(HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, return ret; }
+/* per-monitor DPI aware NtUserWindowFromPoint call */ +static HWND window_from_point(INT x, INT y) +{ + UINT context = NtUserSetThreadDpiAwarenessContext(NTUSER_DPI_PER_MONITOR_AWARE_V2); + HWND ret = NtUserWindowFromPoint(x, y); + NtUserSetThreadDpiAwarenessContext(context); + return ret; +} +
static int wayland_win_data_cmp_rb(const void *key, const struct rb_entry *entry) @@ -206,7 +215,7 @@ static void reapply_cursor_clipping(void) NtUserSetThreadDpiAwarenessContext(context); }
-static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *data) +static BOOL wayland_win_data_create_wayland_surface(struct wayland_win_data *data, struct wayland_surface *toplevel_surface) { struct wayland_client_surface *client = data->client_surface; struct wayland_surface *surface; @@ -217,6 +226,7 @@ static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; if (!visible) role = WAYLAND_SURFACE_ROLE_NONE; + else if (toplevel_surface) role = WAYLAND_SURFACE_ROLE_SUBSURFACE; else role = WAYLAND_SURFACE_ROLE_TOPLEVEL;
/* we can temporarily clear the role of a surface but cannot assign a different one after it's set */ @@ -240,6 +250,9 @@ static BOOL wayland_win_data_update_wayland_surface(struct wayland_win_data *dat case WAYLAND_SURFACE_ROLE_TOPLEVEL: wayland_surface_make_toplevel(surface); break; + case WAYLAND_SURFACE_ROLE_SUBSURFACE: + wayland_surface_make_subsurface(surface, toplevel_surface); + break; }
if (visible && client) wayland_client_surface_attach(client, data->hwnd); @@ -311,6 +324,13 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) case WAYLAND_SURFACE_ROLE_TOPLEVEL: wayland_surface_update_state_toplevel(surface); break; + case WAYLAND_SURFACE_ROLE_SUBSURFACE: + TRACE("hwnd=%p subsurface parent=%p\n", surface->hwnd, surface->toplevel_hwnd); + /* Although subsurfaces don't have a dedicated surface config mechanism, + * we use the config fields to mark them as updated. */ + surface->processing.serial = 1; + surface->processing.processed = TRUE; + break; }
wl_display_flush(process_wayland.wl_display); @@ -447,8 +467,9 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL const struct window_rects *new_rects, struct window_surface *surface) { HWND toplevel = NtUserGetAncestor(hwnd, GA_ROOT); + struct wayland_surface *toplevel_surface; struct wayland_client_surface *client; - struct wayland_win_data *data; + struct wayland_win_data *data, *toplevel_data; BOOL managed;
TRACE("hwnd %p new_rects %s after %p flags %08x\n", hwnd, debugstr_window_rects(new_rects), insert_after, swp_flags); @@ -456,9 +477,17 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL /* Get the managed state with win_data unlocked, as is_window_managed * may need to query win_data information about other HWNDs and thus * acquire the lock itself internally. */ - managed = is_window_managed(hwnd, swp_flags, &new_rects->window); + if (!(managed = is_window_managed(hwnd, swp_flags, &new_rects->window)) && surface) + { + toplevel = NtUserGetWindowRelative(hwnd, GW_OWNER); + /* fallback to any window that is right below our top left corner */ + if (!toplevel) toplevel = window_from_point(new_rects->window.left - 1, new_rects->window.top - 1); + if (toplevel) toplevel = NtUserGetAncestor(toplevel, GA_ROOT); + }
if (!(data = wayland_win_data_get(hwnd))) return; + toplevel_data = toplevel && toplevel != hwnd ? wayland_win_data_get_nolock(toplevel) : NULL; + toplevel_surface = toplevel_data ? toplevel_data->wayland_surface : NULL;
data->rects = *new_rects; data->is_fullscreen = fullscreen; @@ -480,7 +509,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, BOOL data->wayland_surface = NULL; } } - else if (wayland_win_data_update_wayland_surface(data)) + else if (wayland_win_data_create_wayland_surface(data, toplevel_surface)) { wayland_win_data_update_wayland_state(data); }
On Thu Sep 26 07:15:22 2024 +0000, Alexandros Frantzis wrote:
One fix is to add `if (!surface->xdg_toplevel) return;` at the beginning of `wayland_surface_update_state_toplevel()`. It depends on what we want `surface->role` to mean. If it is "possible role" (which seems to match how other parts of the code are implemented) then this should be OK. Alternatively, perhaps a more explicit arrangement `surface->role` vs `surface->possible_role` would make things clearer?
Thanks for catching this! The if was there originally, I added it back.
On Thu Sep 26 07:52:52 2024 +0000, Rémi Bernon wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/6560/diffs?diff_id=134469&start_sha=29b85c352d6ca11b0778ecd606ca91753bd3b48e#be6b1a6381414c8dae6f91e46942652a04a69f08_474_484)
Done, also made sure that we call the function with per-monitor DPI awareness as the rects are in monitor DPI.
On Thu Sep 26 07:53:40 2024 +0000, Rémi Bernon wrote:
Thanks for catching this! The if was there originally, I added it back.
Looks like it's working fine now, thanks.
Alexandros Frantzis (@afrantzis) commented about dlls/winewayland.drv/wayland_surface.c:
- wayland_surface_coords_from_window(surface, win_width, win_height,
&width, &height);
- TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n",
surface->hwnd, win_width, win_height, window->state,
surface->processing.width, surface->processing.height,
surface->processing.state, surface->current.width,
surface->current.height, surface->current.state);
- switch (surface->role)
- {
- case WAYLAND_SURFACE_ROLE_NONE:
break;
- case WAYLAND_SURFACE_ROLE_TOPLEVEL:
if (!wayland_surface_reconfigure_xdg(surface, width, height)) return FALSE;
Although the surface configuration checks we have inside wayland_surface_reconfigure_{xdg,subsurface} currently seem to protect us from accessing invalid objects (i.e., when the actual current role is NONE), it seems fragile to depend on these checks. Perhaps it would be best to explicitly check for the invalid object case in those functions, too?