From 115eda96501102ba26d4a46c7184c7f079c25602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 13 Feb 2019 02:30:28 +0100 Subject: [PATCH] shell-screenshot: Apply monitor scale to cursor surface When we grab a screenshot of a framebuffer scaled shell, we shoudl apply the device scale to the image surface, while the monitor scaling should be applied to the cursor surface, so that it's painted at proper coordinates and in proper size in the generated image. This is not needed for XWayland clients as they are not scaled anyways, while for wayland clients that are painted in multiple monitors, this might cause a lower quality cursor in the lower dpi monitor, because the cursor sprite is generated for the monitor scale, and not for the surface scale. https://bugzilla.gnome.org/show_bug.cgi?id=765011 https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5 --- src/shell-screenshot.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c index 00c8cd227..61fdc1d1e 100644 --- a/src/shell-screenshot.c +++ b/src/shell-screenshot.c @@ -323,6 +323,22 @@ draw_cursor_image (cairo_surface_t *surface, width, height, stride); + cairo_surface_get_device_scale (surface, &xscale, &yscale); + + if (xscale != 1.0 || yscale != 1.0) + { + int monitor; + float monitor_scale; + MetaRectangle cursor_rect = { + .x = x, .y = y, .width = width, .height = height + }; + + monitor = meta_display_get_monitor_index_for_rect (display, &cursor_rect); + monitor_scale = meta_display_get_monitor_scale (display, monitor); + + cairo_surface_set_device_scale (cursor_surface, monitor_scale, monitor_scale); + } + cr = cairo_create (surface); cairo_set_source_surface (cr, cursor_surface, @@ -462,7 +478,18 @@ grab_window_screenshot (ClutterActor *stage, priv->datetime = g_date_time_new_now_local (); if (priv->include_cursor) - draw_cursor_image (priv->image, priv->screenshot_area); + { + if (meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_WAYLAND) + { + float resource_scale; + if (!clutter_actor_get_resource_scale (window_actor, &resource_scale)) + resource_scale = 1.0f; + + cairo_surface_set_device_scale (priv->image, resource_scale, resource_scale); + } + + draw_cursor_image (priv->image, priv->screenshot_area); + } g_signal_handlers_disconnect_by_func (stage, grab_window_screenshot, result); task = g_task_new (screenshot, NULL, on_screenshot_written, result);