From 91089c7b5b08d96854bb41d0d9fc4f435bd72d11 Mon Sep 17 00:00:00 2001 From: Michal Vanis Date: Sat, 2 Aug 2025 17:12:00 +0200 Subject: [PATCH] wayback-compositor: apply output scale factor This is a reliable way of scaling the output when we are working with a singular Xwayland client window. The xorg dpi flag is not reliable, as not all X applications adhere to it. Currently the scale factor is always applied to the output, but ideally it should be an optional feature. We should not attempt to scale the output when the xorg dpi flag is used, as the logic is dependent on the default xorg dpi value of 96. WIP. Flag handling from wayback-session for the optional enabling of this feature is needed. Closes wayback/wayback#11 Signed-off-by: Michal Vanis --- wayback-compositor/wayback-compositor.c | 39 +++++++++++++++++++++++-- xwayback/xwayback.c | 6 +++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/wayback-compositor/wayback-compositor.c b/wayback-compositor/wayback-compositor.c index 5ea49b5..7ad4c67 100644 --- a/wayback-compositor/wayback-compositor.c +++ b/wayback-compositor/wayback-compositor.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,9 @@ #include #include +#define XORG_DEFAULT_DPI 96 +#define INCHES_TO_MM_CONVERSION 25.4 + /* For brevity's sake, struct members are annotated where they are used. */ struct tinywl_server { @@ -131,6 +135,8 @@ struct wayback_client struct wl_listener destroy; }; +static bool output_is_scaled = false; + static void keyboard_handle_modifiers(struct wl_listener *listener, void *data) { /* This event is raised when a modifier key, such as shift or alt, is @@ -489,6 +495,28 @@ static void output_destroy(struct wl_listener *listener, void *data) free(output); } +static float compute_output_scale_factor(struct wlr_output *wlr_output) +{ + /* If the output should not be scaled, as the appropriate flag has not been passed in or Wayback + * is not run as a system compositor, the scale factor of one is returned */ + if (!output_is_scaled || !wlr_output->phys_height || !wlr_output->phys_width) { + return 1; + } + /* Calculates physical length of the diagonal in inches using Pythagorean theorem */ + float output_diagonal_length_inches = + sqrt(pow(wlr_output->phys_height, 2) + pow(wlr_output->phys_width, 2)) / + INCHES_TO_MM_CONVERSION; + /* Calculates length of the diagonal in pixels using Pythagorean theorem */ + float output_diagonal_length_pixels = + sqrt(pow(wlr_output->height, 2) + pow(wlr_output->width, 2)); + /* DPI of the output is equal to diagonal length in pixels divided by diagonal length in inches + */ + float dpi = output_diagonal_length_pixels / output_diagonal_length_inches; + /* The scale factor is the number which when multiplied with the default xorg DPI gives us our + * calculated DPI */ + return dpi / XORG_DEFAULT_DPI; +} + static void server_new_output(struct wl_listener *listener, void *data) { /* This event is raised by the backend when a new output (aka a display or @@ -504,6 +532,7 @@ static void server_new_output(struct wl_listener *listener, void *data) struct wlr_output_state state; wlr_output_state_init(&state); wlr_output_state_set_enabled(&state, true); + wlr_output_state_set_scale(&state, compute_output_scale_factor(wlr_output)); /* Some backends don't have modes. DRM+KMS does, and we need to set a mode * before we can use the output. The mode is a tuple of (width, height, @@ -799,6 +828,10 @@ int main(int argc, char *argv[]) int xwayback_session_socket = atoi(argv[1]); int xwayland_session_socket = atoi(argv[2]); + if (strcmp(argv[3], "-wayland-dpi") == 0) { + output_is_scaled = true; + } + struct tinywl_server server = { 0 }; /* The Wayland display is managed by libwayland. It handles accepting * clients from the Unix socket, manging Wayland globals, and so on. */ @@ -970,11 +1003,13 @@ int main(int argc, char *argv[]) bool have_output = false; if (output != NULL) { struct tinywl_output *out, *out_tmp; - wl_list_for_each_safe(out, out_tmp, &server.outputs, link) { + wl_list_for_each_safe(out, out_tmp, &server.outputs, link) + { char *output_make_model; asprintf_or_exit( &output_make_model, "%s %s", out->wlr_output->make, out->wlr_output->model); - bool enabled = (strcmp(output_make_model, output) == 0) || (strcmp(out->wlr_output->name, output) == 0); + bool enabled = (strcmp(output_make_model, output) == 0) || + (strcmp(out->wlr_output->name, output) == 0); if (!enabled) wlr_output_destroy(out->wlr_output); else diff --git a/xwayback/xwayback.c b/xwayback/xwayback.c index b3fbc59..c5c0619 100644 --- a/xwayback/xwayback.c +++ b/xwayback/xwayback.c @@ -371,7 +371,11 @@ int main(int argc, char *argv[]) wayback_compositor_path, &file_actions, NULL, - (char *[]){ (char *)wayback_compositor_path, fd_xwayback, fd_xwayland, NULL }, + (char *[]){ (char *)wayback_compositor_path, + fd_xwayback, + fd_xwayland, + /* Hard-coded for development purposes */ "-wayland-dpi", + NULL }, environ) != 0) { wayback_log(LOG_ERROR, "Failed to launch wayback-compositor: %s", strerror(errno)); exit(EXIT_FAILURE); -- GitLab