[Spice-commits] 14 commits - src/map-file src/spice-glib-sym-file src/spice-widget.c src/spice-widget-cairo.c src/spice-widget-egl.c src/spice-widget.h src/spice-widget-priv.h tools/spicy.c
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Aug 19 09:46:50 UTC 2020
src/map-file | 1
src/spice-glib-sym-file | 1
src/spice-widget-cairo.c | 22 ++++--
src/spice-widget-egl.c | 2
src/spice-widget-priv.h | 1
src/spice-widget.c | 167 +++++++++++++++++++++++++++++++++++++----------
src/spice-widget.h | 1
tools/spicy.c | 3
8 files changed, 157 insertions(+), 41 deletions(-)
New commits:
commit 515a84ba125c72a9b64431cb62b91ce96caa6790
Author: Haochen Tong <i at hexchain.org>
Date: Sat Aug 8 18:10:38 2020 +0200
spice-widget: prevent mouse cursor from being too small
Caps the minimum scale of the mouse cursor to 50% so that it is still
visible even if the window is too small.
This also workarounds a GDK warning when SpiceDisplay is used in
remote-viewer. Upon its initialization there is a possible race
condition, where update_mouse_cursor is called but the widget still has
a size of 1x1. In such case, the calculated scale is very small and the
mouse surface width and height are both zero, causing a warning:
gdk_cursor_new_from_surface: assertion '0 <= x && x < cairo_image_surface_get_width (surface)' failed
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 4f2bb65..6e0fa54 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -3018,6 +3018,8 @@ static void update_mouse_cursor(SpiceDisplay *display)
spice_display_get_scaling(display, &scale, NULL, NULL, NULL, NULL);
scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+ scale = MAX(0.5, scale);
+
cairo_surface_destroy(d->cursor_surface);
/* scale mouse cursor surface */
commit cbdda3334724f5bb7afe9e21ce0e972e53e71fdc
Author: Haochen Tong <i at hexchain.org>
Date: Sat Jul 11 01:46:49 2020 +0200
spice-widget: ensure a 640x480 initial size on HiDPI
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 8574779..4f2bb65 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -209,19 +209,16 @@ static void update_size_request(SpiceDisplay *display)
gint reqwidth, reqheight;
gint scale_factor;
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+
if (d->resize_guest_enable || d->allow_scaling) {
- reqwidth = 640;
- reqheight = 480;
+ reqwidth = 640 / scale_factor;
+ reqheight = 480 / scale_factor;
} else {
- reqwidth = d->area.width;
- reqheight = d->area.height;
+ reqwidth = d->area.width / scale_factor;
+ reqheight = d->area.height / scale_factor;
}
- scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
-
- reqwidth /= scale_factor;
- reqheight /= scale_factor;
-
gtk_widget_set_size_request(GTK_WIDGET(display), reqwidth, reqheight);
recalc_geometry(GTK_WIDGET(display));
update_mouse_cursor(display);
commit d589fdafe35d78608820843b0932ff1377f5e016
Author: Haochen Tong <i at hexchain.org>
Date: Sat Jul 25 00:15:53 2020 +0200
spice-widget-egl: make mouse cursor scale with window size
This is the corresponding fix for EGL server mouse.
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget-egl.c b/src/spice-widget-egl.c
index 3bffd05..e31e322 100644
--- a/src/spice-widget-egl.c
+++ b/src/spice-widget-egl.c
@@ -593,6 +593,8 @@ void spice_egl_update_display(SpiceDisplay *display)
GdkPixbuf *image = d->mouse_pixbuf;
int width = gdk_pixbuf_get_width(image);
int height = gdk_pixbuf_get_height(image);
+ width = ceil(width * s);
+ height = ceil(height * s);
glBindTexture(GL_TEXTURE_2D, d->egl.tex_pointer_id);
glEnable(GL_BLEND);
commit 5e0a461bec4fbd4d4573938b49bcde23409ec55c
Author: Haochen Tong <i at hexchain.org>
Date: Sat Jul 11 01:41:10 2020 +0200
spice-widget: make mouse cursor scale with window size
Make mouse cursor size scale with the window size on Cairo/EGL client
mouse and Cairo server mouse. The cursor size should always be the same
as how big it really is inside the virtual machine.
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 4ab0e6a..8574779 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -127,6 +127,7 @@ static void channel_new(SpiceSession *s, SpiceChannel *channel, SpiceDisplay *di
static void channel_destroy(SpiceSession *s, SpiceChannel *channel, SpiceDisplay *display);
static void cursor_invalidate(SpiceDisplay *display);
static bool egl_enabled(SpiceDisplayPrivate *d);
+static void update_mouse_cursor(SpiceDisplay *display);
static void update_area(SpiceDisplay *display, gint x, gint y, gint width, gint height);
static void release_keys(SpiceDisplay *display);
static void size_allocate(GtkWidget *widget, GtkAllocation *conf, gpointer data);
@@ -196,6 +197,7 @@ static void scaling_updated(SpiceDisplay *display)
recalc_geometry(GTK_WIDGET(display));
if (d->canvas.surface && window) { /* if not yet shown */
+ update_mouse_cursor(display);
gtk_widget_queue_draw(GTK_WIDGET(display));
}
update_size_request(display);
@@ -222,6 +224,7 @@ static void update_size_request(SpiceDisplay *display)
gtk_widget_set_size_request(GTK_WIDGET(display), reqwidth, reqheight);
recalc_geometry(GTK_WIDGET(display));
+ update_mouse_cursor(display);
}
static void update_keyboard_focus(SpiceDisplay *display, gboolean state)
@@ -2276,6 +2279,8 @@ static void size_allocate(GtkWidget *widget, GtkAllocation *conf, gpointer data)
d->mx = conf->x;
d->my = conf->y;
+ update_mouse_cursor(display);
+
#ifdef G_OS_WIN32
if (d->mouse_grab_active) {
try_mouse_ungrab(display);
@@ -2970,9 +2975,7 @@ static void cursor_set(SpiceCursorChannel *channel,
{
SpiceDisplay *display = data;
SpiceDisplayPrivate *d = display->priv;
- GdkCursor *cursor = NULL;
SpiceCursorShape *cursor_shape;
- gint hotspot_x, hotspot_y;
g_object_get(G_OBJECT(channel), "cursor", &cursor_shape, NULL);
if (G_UNLIKELY(cursor_shape == NULL || cursor_shape->data == NULL)) {
@@ -2984,7 +2987,6 @@ static void cursor_set(SpiceCursorChannel *channel,
cursor_invalidate(display);
g_clear_object(&d->mouse_pixbuf);
- cairo_surface_destroy(d->cursor_surface);
d->mouse_pixbuf = gdk_pixbuf_new_from_data(cursor_shape->data,
GDK_COLORSPACE_RGB,
TRUE, 8,
@@ -2992,15 +2994,59 @@ static void cursor_set(SpiceCursorChannel *channel,
cursor_shape->height,
cursor_shape->width * 4,
cursor_shape_destroy, cursor_shape);
- d->cursor_surface = gdk_cairo_surface_create_from_pixbuf(d->mouse_pixbuf, 0,
- gtk_widget_get_window(GTK_WIDGET(display)));
- hotspot_x = d->mouse_hotspot.x = cursor_shape->hot_spot_x;
- hotspot_y = d->mouse_hotspot.y = cursor_shape->hot_spot_y;
+ d->mouse_hotspot.x = cursor_shape->hot_spot_x;
+ d->mouse_hotspot.y = cursor_shape->hot_spot_y;
+
+ update_mouse_cursor(display);
+}
+
+static void update_mouse_cursor(SpiceDisplay *display)
+{
+ SpiceDisplayPrivate *d = display->priv;
+ GdkCursor *cursor = NULL;
+ cairo_t *cursor_ctx;
+ cairo_surface_t *surface, *target;
+ double scale;
+ gint scale_factor;
+ gint hotspot_x, hotspot_y;
+
+ if (G_UNLIKELY(!d->mouse_pixbuf)) {
+ return;
+ }
+
+ if (!d->ready || !d->monitor_ready) {
+ return;
+ }
+
+ spice_display_get_scaling(display, &scale, NULL, NULL, NULL, NULL);
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+
+ cairo_surface_destroy(d->cursor_surface);
+
+ /* scale mouse cursor surface */
+ surface = gdk_cairo_surface_create_from_pixbuf(d->mouse_pixbuf, 0, gtk_widget_get_window(GTK_WIDGET(display)));
+ target = cairo_image_surface_create(cairo_image_surface_get_format(surface),
+ scale * gdk_pixbuf_get_width(d->mouse_pixbuf),
+ scale * gdk_pixbuf_get_height(d->mouse_pixbuf));
+
+ cairo_surface_set_device_scale(target, scale_factor, scale_factor);
+ cursor_ctx = cairo_create(target);
+ cairo_scale(cursor_ctx, scale, scale);
+ cairo_set_source_surface(cursor_ctx, surface, 0, 0);
+ cairo_paint(cursor_ctx);
+
+ d->cursor_surface = cairo_surface_reference(cairo_get_target(cursor_ctx));
+
+ cairo_surface_destroy(target);
+ cairo_surface_destroy(surface);
+ cairo_destroy(cursor_ctx);
+
+ hotspot_x = d->mouse_hotspot.x * scale;
+ hotspot_y = d->mouse_hotspot.y * scale;
#ifdef GDK_WINDOWING_X11
/* undo hotspot scaling in gdkcursor */
if (GDK_IS_X11_DISPLAY(gtk_widget_get_display(GTK_WIDGET(display)))) {
- gint scale_factor = gdk_window_get_scale_factor(gtk_widget_get_window(GTK_WIDGET(display)));
hotspot_x /= scale_factor;
hotspot_y /= scale_factor;
}
commit a15ba78aff6550dc1204783e4322b3a79694b9c9
Author: Haochen Tong <i at hexchain.org>
Date: Sat Jul 11 01:04:37 2020 +0200
spice-widget: correctly position mouse on ungrab
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index d1f9ee6..4ab0e6a 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -1309,6 +1309,7 @@ static void try_mouse_ungrab(SpiceDisplay *display)
SpiceDisplayPrivate *d = display->priv;
double s;
int x, y;
+ gint scale_factor;
GdkWindow *window;
if (!d->mouse_grab_active)
@@ -1323,12 +1324,13 @@ static void try_mouse_ungrab(SpiceDisplay *display)
d->mouse_grab_active = false;
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
spice_display_get_scaling(display, &s, &x, &y, NULL, NULL);
window = gtk_widget_get_window(GTK_WIDGET(display));
gdk_window_get_root_coords(window,
- x + d->mouse_guest_x * s,
- y + d->mouse_guest_y * s,
+ (x + d->mouse_guest_x * s) / scale_factor,
+ (y + d->mouse_guest_y * s) / scale_factor,
&x, &y);
gdk_device_warp(spice_gdk_window_get_pointing_device(window),
commit 63644cdb2c78f70259b7c4b603625085fc86f264
Author: Haochen Tong <i at hexchain.org>
Date: Sat Jul 11 00:59:39 2020 +0200
spice-widget: treat cairo/egl equally on HiDPI
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 968a836..d1f9ee6 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -205,7 +205,7 @@ static void update_size_request(SpiceDisplay *display)
{
SpiceDisplayPrivate *d = display->priv;
gint reqwidth, reqheight;
- gint scale_factor = 1;
+ gint scale_factor;
if (d->resize_guest_enable || d->allow_scaling) {
reqwidth = 640;
@@ -215,9 +215,7 @@ static void update_size_request(SpiceDisplay *display)
reqheight = d->area.height;
}
- if (egl_enabled(d)) {
- scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
- }
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
reqwidth /= scale_factor;
reqheight /= scale_factor;
@@ -1358,14 +1356,12 @@ static void recalc_geometry(GtkWidget *widget)
SpiceDisplay *display = SPICE_DISPLAY(widget);
SpiceDisplayPrivate *d = display->priv;
gdouble zoom = 1.0;
- gint scale_factor = 1;
+ gint scale_factor;
if (spice_cairo_is_scaled(display))
zoom = (gdouble)d->zoom_level / 100;
- if (egl_enabled(d)) {
- scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
- }
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
DISPLAY_DEBUG(display,
"recalc geom monitor: %d:%d, guest +%d+%d:%dx%d, window %dx%d, zoom %g, scale %d",
@@ -2056,14 +2052,12 @@ static void transform_input(SpiceDisplay *display,
SpiceDisplayPrivate *d = display->priv;
int display_x, display_y, display_w, display_h;
double is;
- gint scale_factor = 1;
+ gint scale_factor;
spice_display_get_scaling(display, NULL,
&display_x, &display_y,
&display_w, &display_h);
- if (egl_enabled(d)) {
- scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
- }
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
/* For input we need a different scaling factor in order to
be able to reach the full width of a display. For instance, consider
a display of 100 pixels showing in a window 10 pixels wide. The normal
@@ -2906,6 +2900,7 @@ static void invalidate(SpiceChannel *channel,
int display_x, display_y;
int x1, y1, x2, y2;
double s;
+ gint scale_factor;
GdkRectangle rect = {
.x = x,
.y = y,
@@ -2926,11 +2921,13 @@ static void invalidate(SpiceChannel *channel,
if (d->canvas.convert)
do_color_convert(display, &rect);
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
spice_display_get_scaling(display, &s,
&display_x, &display_y,
NULL, NULL);
+ display_x /= scale_factor;
+ display_y /= scale_factor;
- gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
if (s * scale_factor > 1) {
rect.x -= 1;
rect.y -= 1;
@@ -2938,10 +2935,10 @@ static void invalidate(SpiceChannel *channel,
rect.height += 2;
}
- x1 = floor ((rect.x - d->area.x) * s);
- y1 = floor ((rect.y - d->area.y) * s);
- x2 = ceil ((rect.x - d->area.x + rect.width) * s);
- y2 = ceil ((rect.y - d->area.y + rect.height) * s);
+ x1 = floor ((rect.x - d->area.x) * s) / scale_factor;
+ y1 = floor ((rect.y - d->area.y) * s) / scale_factor;
+ x2 = ceil ((rect.x - d->area.x + rect.width) * s) / scale_factor;
+ y2 = ceil ((rect.y - d->area.y + rect.height) * s) / scale_factor;
queue_draw_area(display,
display_x + x1, display_y + y1,
@@ -3049,6 +3046,7 @@ static void cursor_hide(SpiceCursorChannel *channel, gpointer data)
update_mouse_pointer(display);
}
+/* Output is always in physical device pixel, not logical pixel, regardless of EGL */
G_GNUC_INTERNAL
void spice_display_get_scaling(SpiceDisplay *display,
double *s_out,
@@ -3060,12 +3058,9 @@ void spice_display_get_scaling(SpiceDisplay *display,
int ww, wh;
int x, y, w, h;
double s;
- gint scale_factor = 1;
if (gtk_widget_get_realized (GTK_WIDGET(display))) {
- if (egl_enabled(d)) {
- scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
- }
+ gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
ww = gtk_widget_get_allocated_width(GTK_WIDGET(display)) * scale_factor;
wh = gtk_widget_get_allocated_height(GTK_WIDGET(display)) * scale_factor;
} else {
@@ -3115,6 +3110,8 @@ static void cursor_invalidate(SpiceDisplay *display)
SpiceDisplayPrivate *d = display->priv;
double s;
int x, y;
+ gint redraw_x, redraw_y;
+ gint scale_factor;
if (!gtk_widget_get_realized (GTK_WIDGET(display)))
return;
@@ -3126,10 +3123,15 @@ static void cursor_invalidate(SpiceDisplay *display)
return;
spice_display_get_scaling(display, &s, &x, &y, NULL, NULL);
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+
+ redraw_x = floor((d->mouse_guest_x - d->mouse_hotspot.x - d->area.x) * s) + x;
+ redraw_y = floor((d->mouse_guest_y - d->mouse_hotspot.y - d->area.y) * s) + y;
+ redraw_x /= scale_factor;
+ redraw_y /= scale_factor;
queue_draw_area(display,
- floor ((d->mouse_guest_x - d->mouse_hotspot.x - d->area.x) * s) + x,
- floor ((d->mouse_guest_y - d->mouse_hotspot.y - d->area.y) * s) + y,
+ redraw_x, redraw_y,
ceil (gdk_pixbuf_get_width(d->mouse_pixbuf) * s),
ceil (gdk_pixbuf_get_height(d->mouse_pixbuf) * s));
}
commit c905e80e59f517ad1a04947f25dad47263443094
Author: Haochen Tong <i at hexchain.org>
Date: Sat Jul 11 00:57:26 2020 +0200
spice-widget-cairo: respect device scale factor
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget-cairo.c b/src/spice-widget-cairo.c
index 89b2154..4d25c08 100644
--- a/src/spice-widget-cairo.c
+++ b/src/spice-widget-cairo.c
@@ -25,6 +25,7 @@ G_GNUC_INTERNAL
int spice_cairo_image_create(SpiceDisplay *display)
{
SpiceDisplayPrivate *d = display->priv;
+ gint scale_factor;
if (d->canvas.surface != NULL)
return 0;
@@ -46,6 +47,9 @@ int spice_cairo_image_create(SpiceDisplay *display)
d->canvas.width, d->canvas.height, d->canvas.stride);
}
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+ cairo_surface_set_device_scale(d->canvas.surface, scale_factor, scale_factor);
+
return 0;
}
@@ -70,9 +74,17 @@ void spice_cairo_draw_event(SpiceDisplay *display, cairo_t *cr)
int x, y;
int ww, wh;
int w, h;
+ gint scale_factor;
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
spice_display_get_scaling(display, &s, &x, &y, &w, &h);
+ /* convert physical pixel to logical */
+ x /= scale_factor;
+ y /= scale_factor;
+ w /= scale_factor;
+ h /= scale_factor;
+
ww = gtk_widget_get_allocated_width(GTK_WIDGET(display));
wh = gtk_widget_get_allocated_height(GTK_WIDGET(display));
@@ -117,11 +129,11 @@ void spice_cairo_draw_event(SpiceDisplay *display, cairo_t *cr)
d->mouse_guest_x != -1 && d->mouse_guest_y != -1 &&
!d->show_cursor &&
spice_gtk_session_get_pointer_grabbed(d->gtk_session)) {
- GdkPixbuf *image = d->mouse_pixbuf;
- if (image != NULL) {
- gdk_cairo_set_source_pixbuf(cr, image,
- d->mouse_guest_x - d->mouse_hotspot.x,
- d->mouse_guest_y - d->mouse_hotspot.y);
+ cairo_surface_t *surface = d->cursor_surface;
+ if (surface != NULL) {
+ cairo_set_source_surface(cr, surface,
+ (double)(d->mouse_guest_x - d->mouse_hotspot.x) / scale_factor,
+ (double)(d->mouse_guest_y - d->mouse_hotspot.y) / scale_factor);
cairo_paint(cr);
}
}
commit 9db4ae96a2118ceb7ca682a00d971352c231c085
Author: Haochen Tong <i at hexchain.org>
Date: Fri Jul 10 22:51:55 2020 +0200
spice-widget: fix typo (wrap -> warp)
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 629ff5d..968a836 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -1209,7 +1209,7 @@ static void try_mouse_grab(SpiceDisplay *display)
d->mouse_last_y = -1;
}
-static void mouse_wrap(SpiceDisplay *display, GdkEventMotion *motion)
+static void mouse_warp(SpiceDisplay *display, GdkEventMotion *motion)
{
SpiceDisplayPrivate *d = display->priv;
gint xr, yr;
@@ -1219,7 +1219,7 @@ static void mouse_wrap(SpiceDisplay *display, GdkEventMotion *motion)
g_return_if_fail(GetClipCursor(&clip));
xr = clip.left + (clip.right - clip.left) / 2;
yr = clip.top + (clip.bottom - clip.top) / 2;
- /* the clip rectangle has no offset, so we can't use gdk_wrap_pointer */
+ /* the clip rectangle has no offset, so we can't use gdk_display_warp_pointer */
SetCursorPos(xr, yr);
d->mouse_last_x = -1;
d->mouse_last_y = -1;
@@ -2128,7 +2128,7 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
d->mouse_last_x = x;
d->mouse_last_y = y;
if (dx != 0 || dy != 0)
- mouse_wrap(display, motion);
+ mouse_warp(display, motion);
}
break;
default:
@@ -3538,4 +3538,4 @@ void spice_display_get_preferred_size(SpiceDisplay *display, int *width, int *he
if (height)
*height = d->area.height;
-}
\ No newline at end of file
+}
commit 18dfbb9e7974d153a1758aef58208591111de80e
Author: Haochen Tong <i at hexchain.org>
Date: Fri Jul 10 22:11:35 2020 +0200
spice-widget: add an API to get guest display size
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/map-file b/src/map-file
index d46f2bc..acdd38f 100644
--- a/src/map-file
+++ b/src/map-file
@@ -33,6 +33,7 @@ spice_display_channel_gl_draw_done;
spice_display_get_gl_scanout;
spice_display_get_grab_keys;
spice_display_get_pixbuf;
+spice_display_get_preferred_size;
spice_display_get_primary;
spice_display_get_type;
spice_display_gl_draw_done;
diff --git a/src/spice-glib-sym-file b/src/spice-glib-sym-file
index c3b2561..72e6ef0 100644
--- a/src/spice-glib-sym-file
+++ b/src/spice-glib-sym-file
@@ -29,6 +29,7 @@ spice_display_channel_get_primary
spice_display_channel_get_type
spice_display_channel_gl_draw_done
spice_display_get_gl_scanout
+spice_display_get_preferred_size
spice_display_get_primary
spice_display_gl_draw_done
spice_file_transfer_task_cancel
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 50775e2..629ff5d 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -3520,3 +3520,22 @@ GdkPixbuf *spice_display_get_pixbuf(SpiceDisplay *display)
return pixbuf;
}
+
+/**
+ * spice_display_get_preferred_size:
+ * @display: a #SpiceDisplay
+ * @width: the preferred width of the display, in physical pixel
+ * @height: the preferred height of the display, in physical pixel
+ *
+ * Get the preferred width and height of the display.
+ **/
+void spice_display_get_preferred_size(SpiceDisplay *display, int *width, int *height)
+{
+ SpiceDisplayPrivate *d = display->priv;
+
+ if (width)
+ *width = d->area.width;
+
+ if (height)
+ *height = d->area.height;
+}
\ No newline at end of file
diff --git a/src/spice-widget.h b/src/spice-widget.h
index e0b1fb3..ead5d7c 100644
--- a/src/spice-widget.h
+++ b/src/spice-widget.h
@@ -79,6 +79,7 @@ SpiceGrabSequence *spice_display_get_grab_keys(SpiceDisplay *display);
void spice_display_send_keys(SpiceDisplay *display, const guint *keyvals,
int nkeyvals, SpiceDisplayKeyEvent kind);
GdkPixbuf *spice_display_get_pixbuf(SpiceDisplay *display);
+void spice_display_get_preferred_size(SpiceDisplay *display, int *width, int *height);
G_END_DECLS
diff --git a/tools/spicy.c b/tools/spicy.c
index 8ca62f9..437a298 100644
--- a/tools/spicy.c
+++ b/tools/spicy.c
@@ -587,8 +587,7 @@ static void menu_cb_resize_to(GtkAction *action G_GNUC_UNUSED,
spin_x = gtk_spin_button_new_with_range(0, G_MAXINT, 10);
spin_y = gtk_spin_button_new_with_range(0, G_MAXINT, 10);
- gtk_widget_get_preferred_width(win->spice, NULL, &width);
- gtk_widget_get_preferred_height(win->spice, NULL, &height);
+ spice_display_get_preferred_size(SPICE_DISPLAY(win->spice), &width, &height);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_width), width);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_height), height);
commit b30598293b1c48b9dc0eddfde5a9fc996a83939c
Author: Haochen Tong <i at hexchain.org>
Date: Fri Jul 10 11:23:44 2020 +0200
spice-widget: fix widget size request on HiDPI when scaling is disabled
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index b7938c1..50775e2 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -126,6 +126,7 @@ static void recalc_geometry(GtkWidget *widget);
static void channel_new(SpiceSession *s, SpiceChannel *channel, SpiceDisplay *display);
static void channel_destroy(SpiceSession *s, SpiceChannel *channel, SpiceDisplay *display);
static void cursor_invalidate(SpiceDisplay *display);
+static bool egl_enabled(SpiceDisplayPrivate *d);
static void update_area(SpiceDisplay *display, gint x, gint y, gint width, gint height);
static void release_keys(SpiceDisplay *display);
static void size_allocate(GtkWidget *widget, GtkAllocation *conf, gpointer data);
@@ -204,6 +205,7 @@ static void update_size_request(SpiceDisplay *display)
{
SpiceDisplayPrivate *d = display->priv;
gint reqwidth, reqheight;
+ gint scale_factor = 1;
if (d->resize_guest_enable || d->allow_scaling) {
reqwidth = 640;
@@ -213,6 +215,13 @@ static void update_size_request(SpiceDisplay *display)
reqheight = d->area.height;
}
+ if (egl_enabled(d)) {
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+ }
+
+ reqwidth /= scale_factor;
+ reqheight /= scale_factor;
+
gtk_widget_set_size_request(GTK_WIDGET(display), reqwidth, reqheight);
recalc_geometry(GTK_WIDGET(display));
}
commit a945a3c24b11de017a3b22acb5085fec59efa662
Author: Haochen Tong <i at hexchain.org>
Date: Wed Jul 8 21:53:08 2020 +0200
spice-widget: fix hotspot position on X11/HiDPI
GDK scales hotspot coordinates using screen scale factor on X11. We need
to undo this to get the correct hotspot behavior, otherwise mouse
selection becomes very inaccurate and difficult in the guest.
See [1].
[1] https://gitlab.gnome.org/GNOME/gtk/-/blob/3.24.21/gdk/x11/gdkcursor-x11.c#L556-557
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index a620084..b7938c1 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -2964,6 +2964,7 @@ static void cursor_set(SpiceCursorChannel *channel,
SpiceDisplayPrivate *d = display->priv;
GdkCursor *cursor = NULL;
SpiceCursorShape *cursor_shape;
+ gint hotspot_x, hotspot_y;
g_object_get(G_OBJECT(channel), "cursor", &cursor_shape, NULL);
if (G_UNLIKELY(cursor_shape == NULL || cursor_shape->data == NULL)) {
@@ -2985,12 +2986,22 @@ static void cursor_set(SpiceCursorChannel *channel,
cursor_shape_destroy, cursor_shape);
d->cursor_surface = gdk_cairo_surface_create_from_pixbuf(d->mouse_pixbuf, 0,
gtk_widget_get_window(GTK_WIDGET(display)));
- d->mouse_hotspot.x = cursor_shape->hot_spot_x;
- d->mouse_hotspot.y = cursor_shape->hot_spot_y;
+ hotspot_x = d->mouse_hotspot.x = cursor_shape->hot_spot_x;
+ hotspot_y = d->mouse_hotspot.y = cursor_shape->hot_spot_y;
+
+#ifdef GDK_WINDOWING_X11
+ /* undo hotspot scaling in gdkcursor */
+ if (GDK_IS_X11_DISPLAY(gtk_widget_get_display(GTK_WIDGET(display)))) {
+ gint scale_factor = gdk_window_get_scale_factor(gtk_widget_get_window(GTK_WIDGET(display)));
+ hotspot_x /= scale_factor;
+ hotspot_y /= scale_factor;
+ }
+#endif
+
cursor = gdk_cursor_new_from_surface(gtk_widget_get_display(GTK_WIDGET(display)),
d->cursor_surface,
- d->mouse_hotspot.x,
- d->mouse_hotspot.y);
+ hotspot_x,
+ hotspot_y);
#if HAVE_EGL
if (egl_enabled(d))
commit 3c9efe24bdfb1bdbcdd5f734b22f49b521fdad77
Author: Haochen Tong <i at hexchain.org>
Date: Wed Jul 8 19:30:21 2020 +0200
spice-widget: fix EGL input coordinate on HiDPI
Fixes #127.
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 6407990..a620084 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -2072,8 +2072,8 @@ static void transform_input(SpiceDisplay *display,
*/
is = ((double)(d->area.width-1) / (double)(display_w-1)) * scale_factor;
- window_x -= display_x;
- window_y -= display_y;
+ window_x -= display_x / scale_factor;
+ window_y -= display_y / scale_factor;
*input_x = floor (window_x * is);
*input_y = floor (window_y * is);
commit dddd48ad3dc2dcafed96a3e9542c72e1e00ee9fe
Author: Haochen Tong <i at hexchain.org>
Date: Wed Jul 8 16:05:04 2020 +0200
spice-widget: correctly scale mouse pointer on HiDPI
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h
index 99b3da6..a9883d6 100644
--- a/src/spice-widget-priv.h
+++ b/src/spice-widget-priv.h
@@ -106,6 +106,7 @@ struct _SpiceDisplayPrivate {
int mouse_last_y;
int mouse_guest_x;
int mouse_guest_y;
+ cairo_surface_t *cursor_surface;
bool keyboard_grab_active;
bool keyboard_have_focus;
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 273167c..6407990 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -474,6 +474,7 @@ static void spice_display_finalize(GObject *obj)
g_clear_object(&d->show_cursor);
g_clear_object(&d->mouse_cursor);
g_clear_object(&d->mouse_pixbuf);
+ cairo_surface_destroy(d->cursor_surface);
G_OBJECT_CLASS(spice_display_parent_class)->finalize(obj);
}
@@ -2974,6 +2975,7 @@ static void cursor_set(SpiceCursorChannel *channel,
cursor_invalidate(display);
g_clear_object(&d->mouse_pixbuf);
+ cairo_surface_destroy(d->cursor_surface);
d->mouse_pixbuf = gdk_pixbuf_new_from_data(cursor_shape->data,
GDK_COLORSPACE_RGB,
TRUE, 8,
@@ -2981,12 +2983,14 @@ static void cursor_set(SpiceCursorChannel *channel,
cursor_shape->height,
cursor_shape->width * 4,
cursor_shape_destroy, cursor_shape);
+ d->cursor_surface = gdk_cairo_surface_create_from_pixbuf(d->mouse_pixbuf, 0,
+ gtk_widget_get_window(GTK_WIDGET(display)));
d->mouse_hotspot.x = cursor_shape->hot_spot_x;
d->mouse_hotspot.y = cursor_shape->hot_spot_y;
- cursor = gdk_cursor_new_from_pixbuf(gtk_widget_get_display(GTK_WIDGET(display)),
- d->mouse_pixbuf,
- d->mouse_hotspot.x,
- d->mouse_hotspot.y);
+ cursor = gdk_cursor_new_from_surface(gtk_widget_get_display(GTK_WIDGET(display)),
+ d->cursor_surface,
+ d->mouse_hotspot.x,
+ d->mouse_hotspot.y);
#if HAVE_EGL
if (egl_enabled(d))
commit 5e8a597f1ccf98c3fae358769f3f35e66d51c460
Author: Haochen Tong <i at hexchain.org>
Date: Wed Jul 8 16:01:25 2020 +0200
spice-widget: use pixel size for monitor geometry on scaled display
On HiDPI displays, guest screen used to be blurry because the screen
size is smaller than the widget size, and is scaled up. This patch fixes
that by considering scale factor when calculating geometry.
Signed-off-by: Haochen Tong <i at hexchain.org>
Acked-by: Frediano Ziglio <fziglio at redhat.com>
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 5cef966..273167c 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -1348,19 +1348,26 @@ static void recalc_geometry(GtkWidget *widget)
SpiceDisplay *display = SPICE_DISPLAY(widget);
SpiceDisplayPrivate *d = display->priv;
gdouble zoom = 1.0;
+ gint scale_factor = 1;
if (spice_cairo_is_scaled(display))
zoom = (gdouble)d->zoom_level / 100;
+ if (egl_enabled(d)) {
+ scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+ }
+
DISPLAY_DEBUG(display,
- "recalc geom monitor: %d:%d, guest +%d+%d:%dx%d, window %dx%d, zoom %g",
+ "recalc geom monitor: %d:%d, guest +%d+%d:%dx%d, window %dx%d, zoom %g, scale %d",
d->channel_id, d->monitor_id, d->area.x, d->area.y,
d->area.width, d->area.height,
- d->ww, d->wh, zoom);
+ d->ww, d->wh, zoom, scale_factor);
if (d->resize_guest_enable)
spice_main_channel_update_display(d->main, get_display_id(display),
- d->area.x, d->area.y, d->ww / zoom, d->wh / zoom, TRUE);
+ d->area.x, d->area.y,
+ d->ww * scale_factor / zoom,
+ d->wh * scale_factor / zoom, TRUE);
}
/* ---------------------------------------------------------------- */
More information about the Spice-commits
mailing list