From 1301fdb2ecc9c2d001baacd92fcf3fda9daec1ed Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Tue, 17 Feb 2026 10:39:03 -0600 Subject: [PATCH] wayland: directly use surface local coords for viewport when possible Previously, we calculated out the value for simplicity but there can be a mismatch due to round where what we calculate as the viewport width/height is not what surface local coordinates the compositor gave us. Note that we don't always want to use these values directly (e.g. whenever we set our own geometry), so some notion of overriding has to be added. --- video/out/wayland_common.c | 19 +++++++++++++++---- video/out/wayland_common.h | 2 ++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 9699cd35f2..16474de09c 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -1806,6 +1806,8 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, wl->initial_size_hint = true; wl->window_size = (struct mp_rect){0, 0, width, height}; wl->geometry = wl->window_size; + } else { + wl->override_surface_local = true; } return; } @@ -1920,6 +1922,11 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, wl->geometry.x1 = handle_round(wl->scaling, width); wl->geometry.y1 = handle_round(wl->scaling, height); + wl->surface_local.x0 = 0; + wl->surface_local.y0 = 0; + wl->surface_local.x1 = width; + wl->surface_local.y1 = height; + if (mp_rect_equals(&old_geometry, &wl->geometry)) return; @@ -1929,6 +1936,7 @@ resize: mp_rect_w(wl->geometry), mp_rect_h(wl->geometry)); wl->pending_vo_events |= VO_EVENT_RESIZE; + wl->override_surface_local = false; wl->toplevel_configured = true; } @@ -3824,6 +3832,7 @@ static void set_geometry(struct vo_wayland_state *wl, bool resize) if (resize) { if (!wl->locked_size) wl->geometry = wl->window_size; + wl->override_surface_local = true; wl->pending_vo_events |= VO_EVENT_RESIZE; } } @@ -4181,7 +4190,6 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) if (opt == &opts->geometry || opt == &opts->autofit || opt == &opts->autofit_smaller || opt == &opts->autofit_larger) { - wl->state_change = true; set_geometry(wl, true); } } @@ -4225,7 +4233,6 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) wl->window_size.x1 = s[0]; wl->window_size.y1 = s[1]; if (!wl->opts->fullscreen && !wl->tiled) { - wl->state_change = true; if (wl->opts->window_maximized) { xdg_toplevel_unset_maximized(wl->xdg_toplevel); wl_display_dispatch_pending(wl->display); @@ -4234,6 +4241,7 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) return VO_TRUE; } wl->geometry = wl->window_size; + wl->override_surface_local = true; wl->pending_vo_events |= VO_EVENT_RESIZE; } return VO_TRUE; @@ -4352,8 +4360,11 @@ void vo_wayland_handle_color(struct vo_wayland_state *wl, struct mp_image_params void vo_wayland_handle_scale(struct vo_wayland_state *wl) { - wp_viewport_set_destination(wl->viewport, lround(mp_rect_w(wl->geometry) / wl->scaling_factor), - lround(mp_rect_h(wl->geometry) / wl->scaling_factor)); + int width = wl->override_surface_local ? lround(mp_rect_w(wl->geometry) / wl->scaling_factor) : + mp_rect_w(wl->surface_local); + int height = wl->override_surface_local ? lround(mp_rect_h(wl->geometry) / wl->scaling_factor) : + mp_rect_h(wl->surface_local); + wp_viewport_set_destination(wl->viewport, width, height); } bool vo_wayland_valid_format(struct vo_wayland_state *wl, uint32_t drm_format, uint64_t modifier) diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index e49522b441..804dcf9afa 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -57,6 +57,7 @@ struct vo_wayland_state { /* Geometry */ struct mp_rect geometry; struct mp_rect window_size; + struct mp_rect surface_local; struct wl_list output_list; struct vo_wayland_output *current_output; struct mp_rect old_geometry; @@ -65,6 +66,7 @@ struct vo_wayland_state { int bounded_width; int reduced_height; int reduced_width; + bool override_surface_local; /* State */ bool activated;