-- v5: 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 ce0508636b3..284b692d13c 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 77e0c70ad71..fa1746012b6 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -202,7 +202,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);
@@ -219,16 +218,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);
This merge request was approved by Alexandre Julliard.
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 284b692d13c..263d8c4f657 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 263d8c4f657..58c6c5ea1ba 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 12f63921ee7..9205f015228 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 fa1746012b6..8b16e9d746c 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -201,24 +201,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 | 59 ++++++++++++++++++-------- 1 file changed, 41 insertions(+), 18 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 58c6c5ea1ba..1e771948c0b 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,43 @@ 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 (!surface->xdg_surface) break; /* surface role has been cleared */ + 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 | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 8b16e9d746c..b23230200c0 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -245,18 +245,13 @@ 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; - - if (!surface->xdg_toplevel) goto out; - - processing_config = surface->processing.serial && - !surface->processing.processed; + BOOL processing_config = surface->processing.serial && + !surface->processing.processed;
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);
@@ -292,8 +287,22 @@ 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: + if (!surface->xdg_surface) break; /* surface role has been cleared */ + 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 | 90 ++++++++++++++++++++++++++ dlls/winewayland.drv/waylanddrv.h | 8 +++ dlls/winewayland.drv/window.c | 37 +++++++++-- 3 files changed, 131 insertions(+), 4 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 1e771948c0b..ab8f8ac4989 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 * @@ -616,6 +702,10 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) if (!surface->xdg_surface) break; /* surface role has been cleared */ if (!wayland_surface_reconfigure_xdg(surface, width, height)) return FALSE; break; + case WAYLAND_SURFACE_ROLE_SUBSURFACE: + if (!surface->wl_subsurface) break; /* surface role has been cleared */ + 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 9205f015228..008e91708cb 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 b23230200c0..04642ca28c7 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -46,6 +46,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) @@ -197,7 +206,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; @@ -208,6 +217,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 */ @@ -231,6 +241,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); @@ -301,6 +314,13 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) if (!surface->xdg_surface) break; /* surface role has been cleared */ 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); @@ -437,8 +457,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); @@ -446,9 +467,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; @@ -470,7 +499,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 Fri Sep 27 09:05:39 2024 +0000, Rémi Bernon wrote:
Yes, that's what I meant of course :)
As far as major features missing, wintab support is something that is still missing. I can't really think of much else, the winewayland driver certainly isn't perfect, but it *is* astonishingly good given the impedance mismatch of Wayland and Win32!
For some reason, seeing this comment thread today inspired me to actually try to implement wintab support in the winewayland driver. I managed to [get a functional WIP going](https://gitlab.winehq.org/jchw/wine/-/tree/wayland-tablet)%E2%80%94It%27s a pretty big mess though, I think the first order of business would be to get some patches going to clean up the winex11 wintab code and ideally move most of the actual wintab32-specific logic out of winex11. (But that's pretty off-topic here. If anyone wants to talk about that feel free to [reach out directly](mailto:john@jchw.io).)
I'd love to see winewayland get to a shape where it could potentially be preferred over winex11 on XWayland.