backend/wayland: Fix HiDPI support for nested compositors

When running a wlroots-based compositor nested under another Wayland
compositor with HiDPI scaling, the nested window appears blurry and
incorrectly sized. This is because the Wayland backend does not:

1. Detect and track the parent compositor's output scale
2. Set wl_surface_set_buffer_scale() to match the parent's scale
3. Multiply output dimensions by the scale factor when handling
   configure events

This patch fixes all three issues by:

- Adding wlr_wl_parent_output structure to track parent outputs
- Listening to wl_output.scale events from the parent compositor
- Setting buffer_scale on all backend surfaces (output and layers)
- Scaling output dimensions to account for buffer scale
- Setting wlr_output.scale so nested clients render at correct DPI

Implements: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/854
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5186
Co-Authored-By: Hugo Osvaldo Barrera <hugo@whynothugo.nl>
This commit is contained in:
Anatolii Smolianinov 2025-10-30 11:13:32 +01:00 committed by Hugo Osvaldo Barrera
parent a94cd29eb1
commit 514eeebd3c
6 changed files with 171 additions and 15 deletions

View file

@ -88,12 +88,13 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
return;
}
struct wlr_output *wlr_output = &pointer->output->wlr_output;
// Parent compositor sends coordinates in logical (unscaled) space.
struct wlr_wl_output *output = pointer->output;
struct wlr_pointer_motion_absolute_event event = {
.pointer = &pointer->wlr_pointer,
.time_msec = time,
.x = wl_fixed_to_double(sx) / wlr_output->width,
.y = wl_fixed_to_double(sy) / wlr_output->height,
.x = wl_fixed_to_double(sx) / output->logical_width,
.y = wl_fixed_to_double(sy) / output->logical_height,
};
wl_signal_emit_mutable(&pointer->wlr_pointer.events.motion_absolute, &event);
}