From e36bf32490831c826495a05f0696c14bcad3e15c Mon Sep 17 00:00:00 2001 From: Greg V Date: Fri, 4 Jan 2019 01:58:44 +0300 Subject: [PATCH] Wayland: track current output and its scale Ideally, we would track all outputs we're on and choose the highest DPI among them, but that is pretty difficult. Let's at least use the latest output we've entered as the current one. --- gfx/drivers_context/wayland_ctx.c | 71 +++++++++++++++++-------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 80ac759581..7b0622dbfb 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -121,9 +121,11 @@ typedef struct gfx_ctx_wayland_data struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; struct zwp_idle_inhibitor_v1 *idle_inhibitor; struct wl_list all_outputs; + output_info_t *current_output; int swap_interval; bool core_hw_context_enable; + unsigned last_buffer_scale; unsigned buffer_scale; struct @@ -581,7 +583,32 @@ bool wayland_context_gettouchpos(void *data, unsigned id, return active_touch_positions[id].active; } +/* Surface callbacks. */ +static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height); +static void wl_surface_enter(void *data, struct wl_surface *wl_surface, + struct wl_output *output) +{ + // TODO: track all outputs the surface is on, pick highest scale + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + output_info_t *oi; + wl_list_for_each(oi, &wl->all_outputs, link) { + if (oi->output == output) { + RARCH_LOG("[Wayland]: Entering output #%d, scale %d\n", oi->global_id, oi->scale); + wl->current_output = oi; + wl->last_buffer_scale = wl->buffer_scale; + wl->buffer_scale = oi->scale; + break; + } + }; +} + +static void nop() { } + +static const struct wl_surface_listener wl_surface_listener = { + wl_surface_enter, + nop, +}; /* Shell surface callbacks. */ static void xdg_shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) @@ -749,18 +776,6 @@ static const struct wl_shell_surface_listener shell_surface_listener = { shell_surface_handle_popup_done, }; -static output_info_t *get_current_output(gfx_ctx_wayland_data_t *wl) -{ - // Just return the first one. - output_info_t *oi; - - wl_list_for_each(oi, &wl->all_outputs, link) { - return oi; - } - - return NULL; -} - static void display_handle_geometry(void *data, struct wl_output *output, int x, int y, @@ -1047,8 +1062,8 @@ static void gfx_ctx_wl_check_window(void *data, bool *quit, flush_wayland_fd(&wl->input); - new_width = *width * wl->buffer_scale; - new_height = *height * wl->buffer_scale; + new_width = *width * wl->last_buffer_scale; + new_height = *height * wl->last_buffer_scale; gfx_ctx_wl_get_video_size(data, &new_width, &new_height); @@ -1066,11 +1081,12 @@ static void gfx_ctx_wl_check_window(void *data, bool *quit, break; } - if (new_width != *width * wl->buffer_scale || new_height != *height * wl->buffer_scale) + if (new_width != *width * wl->last_buffer_scale || new_height != *height * wl->last_buffer_scale) { *resize = true; *width = new_width; *height = new_height; + wl->last_buffer_scale = wl->buffer_scale; } *quit = (bool)frontend_driver_get_signal_handler_state(); @@ -1111,6 +1127,7 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height) break; } + wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); return true; } @@ -1147,26 +1164,21 @@ static bool gfx_ctx_wl_get_metrics(void *data, { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - if (!wl) - return false; - - output_info_t *oi = get_current_output(wl); - - if (!oi || oi->physical_width == 0 || oi->physical_height == 0) + if (!wl || !wl->current_output || wl->current_output->physical_width == 0 || wl->current_output->physical_height == 0) return false; switch (type) { case DISPLAY_METRIC_MM_WIDTH: - *value = (float)oi->physical_width; + *value = (float)wl->current_output->physical_width; break; case DISPLAY_METRIC_MM_HEIGHT: - *value = (float)oi->physical_height; + *value = (float)wl->current_output->physical_height; break; case DISPLAY_METRIC_DPI: - *value = (float)oi->width * 25.4f / (float)oi->physical_width; + *value = (float)wl->current_output->width * 25.4f / (float)wl->current_output->physical_width; break; default: @@ -1279,6 +1291,7 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) frontend_driver_destroy_signal_handler_state(); wl->input.dpy = wl_display_connect(NULL); + wl->last_buffer_scale = 1; wl->buffer_scale = 1; if (!wl->input.dpy) @@ -1539,6 +1552,7 @@ static bool gfx_ctx_wl_set_video_mode(void *data, wl->surface = wl_compositor_create_surface(wl->compositor); wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); + wl_surface_add_listener(wl->surface, &wl_surface_listener, wl); switch (wl_api) { @@ -1909,15 +1923,10 @@ static float gfx_ctx_wl_get_refresh_rate(void *data) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - if (!wl) + if (!wl || !wl->current_output) return false; - output_info_t *oi = get_current_output(wl); - - if (!oi) - return false; - - return (float) oi->refresh_rate / 1000.0f; + return (float) wl->current_output->refresh_rate / 1000.0f; } const gfx_ctx_driver_t gfx_ctx_wayland = {