mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/virt-viewer
synced 2026-01-11 18:37:34 +00:00
Implement SPICE desktop resizing that takes account of zoom level
The standard SPICE widget guest resize implementation does not
take into account the zoom level settings in virt-viewer, because
it has no knowledge of this functionality. The guest resize can,
however, be done by calling spice_main_set_display() directly.
This allows virt-viewer to resize the guest taking into account
zoom levels.
ie, if virt-viewer is run with --zoom 50 and the window
is resized to 400x300, then the guest agent should
be told to set its resolution to 800x600
This commit is contained in:
parent
3a8cdd901f
commit
50632ea038
@ -151,8 +151,35 @@ virt_viewer_display_spice_mouse_grab(SpiceDisplay *display G_GNUC_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virt_viewer_display_spice_size_allocate(SpiceDisplay *display G_GNUC_UNUSED,
|
||||
GtkAllocation *allocation,
|
||||
VirtViewerDisplaySpice *self G_GNUC_UNUSED)
|
||||
{
|
||||
gdouble dw = allocation->width, dh = allocation->height;
|
||||
guint zoom = 100;
|
||||
guint channelid;
|
||||
|
||||
if (virt_viewer_display_get_zoom(VIRT_VIEWER_DISPLAY(self))) {
|
||||
zoom = virt_viewer_display_get_zoom_level(VIRT_VIEWER_DISPLAY(self));
|
||||
|
||||
dw /= ((double)zoom / 100.0);
|
||||
dh /= ((double)zoom / 100.0);
|
||||
}
|
||||
|
||||
g_object_get(self->priv->channel, "channel-id", &channelid, NULL);
|
||||
|
||||
SpiceMainChannel *main_channel = virt_viewer_session_spice_get_main_channel(
|
||||
VIRT_VIEWER_SESSION_SPICE(virt_viewer_display_get_session(VIRT_VIEWER_DISPLAY(self))));
|
||||
spice_main_set_display(main_channel,
|
||||
channelid,
|
||||
0, 0, dw, dh);
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *
|
||||
virt_viewer_display_spice_new(SpiceChannel *channel,
|
||||
virt_viewer_display_spice_new(VirtViewerSessionSpice *session,
|
||||
SpiceChannel *channel,
|
||||
SpiceDisplay *display)
|
||||
{
|
||||
VirtViewerDisplaySpice *self;
|
||||
@ -164,6 +191,7 @@ virt_viewer_display_spice_new(SpiceChannel *channel,
|
||||
g_object_get(channel, "channel-id", &channelid, NULL);
|
||||
|
||||
self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE,
|
||||
"session", session,
|
||||
"nth-display", channelid,
|
||||
NULL);
|
||||
self->priv->channel = g_object_ref(channel);
|
||||
@ -189,6 +217,10 @@ virt_viewer_display_spice_new(SpiceChannel *channel,
|
||||
g_signal_connect(self->priv->display,
|
||||
"mouse-grab",
|
||||
G_CALLBACK(virt_viewer_display_spice_mouse_grab), self);
|
||||
g_signal_connect(self->priv->display,
|
||||
"size-allocate",
|
||||
G_CALLBACK(virt_viewer_display_spice_size_allocate), self);
|
||||
|
||||
|
||||
return GTK_WIDGET(self);
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <spice-audio.h>
|
||||
|
||||
#include "virt-viewer-display.h"
|
||||
#include "virt-viewer-session-spice.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -65,7 +66,8 @@ struct _VirtViewerDisplaySpiceClass {
|
||||
|
||||
GType virt_viewer_display_spice_get_type(void);
|
||||
|
||||
GtkWidget* virt_viewer_display_spice_new(SpiceChannel *channel,
|
||||
GtkWidget* virt_viewer_display_spice_new(VirtViewerSessionSpice *session,
|
||||
SpiceChannel *channel,
|
||||
SpiceDisplay *display);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "virt-viewer-session.h"
|
||||
#include "virt-viewer-display.h"
|
||||
#include "virt-viewer-util.h"
|
||||
|
||||
@ -40,6 +41,7 @@ struct _VirtViewerDisplayPrivate
|
||||
gboolean zoom;
|
||||
gint nth_display;
|
||||
gint show_hint;
|
||||
VirtViewerSession *session;
|
||||
};
|
||||
|
||||
static void virt_viewer_display_size_request(GtkWidget *widget,
|
||||
@ -75,6 +77,7 @@ enum {
|
||||
PROP_ZOOM,
|
||||
PROP_ZOOM_LEVEL,
|
||||
PROP_SHOW_HINT,
|
||||
PROP_SESSION,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -154,6 +157,15 @@ virt_viewer_display_class_init(VirtViewerDisplayClass *class)
|
||||
0,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property(object_class,
|
||||
PROP_SESSION,
|
||||
g_param_spec_object("session",
|
||||
"Session",
|
||||
"VirtSession",
|
||||
VIRT_VIEWER_TYPE_SESSION,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
|
||||
g_signal_new("display-pointer-grab",
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
@ -252,6 +264,11 @@ virt_viewer_display_set_property(GObject *object,
|
||||
case PROP_NTH_DISPLAY:
|
||||
priv->nth_display = g_value_get_int(value);
|
||||
break;
|
||||
case PROP_SESSION:
|
||||
g_warn_if_fail(priv->session == NULL);
|
||||
priv->session = g_value_dup_object(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -280,6 +297,9 @@ virt_viewer_display_get_property(GObject *object,
|
||||
case PROP_SHOW_HINT:
|
||||
g_value_set_int(value, priv->show_hint);
|
||||
break;
|
||||
case PROP_SESSION:
|
||||
g_value_set_object(value, virt_viewer_display_get_session(display));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@ -468,6 +488,13 @@ void virt_viewer_display_set_zoom_level(VirtViewerDisplay *display,
|
||||
}
|
||||
|
||||
|
||||
guint virt_viewer_display_get_zoom_level(VirtViewerDisplay *display)
|
||||
{
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
return priv->zoom_level;
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_set_zoom(VirtViewerDisplay *display,
|
||||
gboolean zoom)
|
||||
{
|
||||
@ -481,6 +508,14 @@ void virt_viewer_display_set_zoom(VirtViewerDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gboolean virt_viewer_display_get_zoom(VirtViewerDisplay *display)
|
||||
{
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
return priv->zoom;
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_send_keys(VirtViewerDisplay *display,
|
||||
const guint *keyvals, int nkeyvals)
|
||||
{
|
||||
@ -509,6 +544,13 @@ void virt_viewer_display_set_show_hint(VirtViewerDisplay *self, gint hint)
|
||||
g_object_notify(G_OBJECT(self), "show-hint");
|
||||
}
|
||||
|
||||
VirtViewerSession* virt_viewer_display_get_session(VirtViewerDisplay *self)
|
||||
{
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(self), NULL);
|
||||
|
||||
return self->priv->session;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
|
||||
@ -45,6 +45,9 @@ G_BEGIN_DECLS
|
||||
#define VIRT_VIEWER_DISPLAY_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_DISPLAY, VirtViewerDisplayClass))
|
||||
|
||||
typedef struct _VirtViewerSession VirtViewerSession;
|
||||
typedef struct _VirtViewerSessionClass VirtViewerSessionClass;
|
||||
|
||||
typedef struct _VirtViewerDisplay VirtViewerDisplay;
|
||||
typedef struct _VirtViewerDisplayClass VirtViewerDisplayClass;
|
||||
typedef struct _VirtViewerDisplayPrivate VirtViewerDisplayPrivate;
|
||||
@ -94,13 +97,16 @@ void virt_viewer_display_get_desktop_size(VirtViewerDisplay *display,
|
||||
|
||||
void virt_viewer_display_set_zoom_level(VirtViewerDisplay *display,
|
||||
guint zoom);
|
||||
guint virt_viewer_display_get_zoom_level(VirtViewerDisplay *display);
|
||||
void virt_viewer_display_set_zoom(VirtViewerDisplay *display,
|
||||
gboolean zoom);
|
||||
gboolean virt_viewer_display_get_zoom(VirtViewerDisplay *display);
|
||||
|
||||
void virt_viewer_display_send_keys(VirtViewerDisplay *display,
|
||||
const guint *keyvals, int nkeyvals);
|
||||
GdkPixbuf* virt_viewer_display_get_pixbuf(VirtViewerDisplay *display);
|
||||
void virt_viewer_display_set_show_hint(VirtViewerDisplay *display, gint hint);
|
||||
VirtViewerSession* virt_viewer_display_get_session(VirtViewerDisplay *display);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ G_DEFINE_TYPE (VirtViewerSessionSpice, virt_viewer_session_spice, VIRT_VIEWER_TY
|
||||
struct _VirtViewerSessionSpicePrivate {
|
||||
SpiceSession *session;
|
||||
SpiceGtkSession *gtk_session;
|
||||
SpiceMainChannel *main_channel;
|
||||
SpiceAudio *audio;
|
||||
};
|
||||
|
||||
@ -103,6 +104,8 @@ virt_viewer_session_spice_dispose(GObject *obj)
|
||||
}
|
||||
if (spice->priv->audio)
|
||||
g_object_unref(spice->priv->audio);
|
||||
if (spice->priv->main_channel)
|
||||
g_object_unref(spice->priv->main_channel);
|
||||
|
||||
G_OBJECT_CLASS(virt_viewer_session_spice_parent_class)->finalize(obj);
|
||||
}
|
||||
@ -370,8 +373,16 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
|
||||
g_object_get(channel, "channel-id", &id, NULL);
|
||||
|
||||
if (SPICE_IS_MAIN_CHANNEL(channel)) {
|
||||
if (self->priv->main_channel != NULL) {
|
||||
/* FIXME: use telepathy-glib g_signal_connect_object to automatically disconnect.. */
|
||||
g_signal_handlers_disconnect_by_func(self->priv->main_channel,
|
||||
virt_viewer_session_spice_main_channel_event, self);
|
||||
g_object_unref(self->priv->main_channel);
|
||||
}
|
||||
|
||||
g_signal_connect(channel, "channel-event",
|
||||
G_CALLBACK(virt_viewer_session_spice_main_channel_event), self);
|
||||
self->priv->main_channel = g_object_ref(channel);
|
||||
}
|
||||
|
||||
if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
|
||||
@ -380,7 +391,8 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
|
||||
g_signal_emit_by_name(session, "session-connected");
|
||||
|
||||
DEBUG_LOG("new session channel (#%d)", id);
|
||||
display = virt_viewer_display_spice_new(channel,
|
||||
display = virt_viewer_display_spice_new(self,
|
||||
channel,
|
||||
spice_display_new(s, id));
|
||||
|
||||
virt_viewer_session_add_display(VIRT_VIEWER_SESSION(session),
|
||||
@ -414,6 +426,10 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
|
||||
g_object_get(channel, "channel-id", &id, NULL);
|
||||
if (SPICE_IS_MAIN_CHANNEL(channel)) {
|
||||
DEBUG_LOG("zap main channel");
|
||||
if (channel == SPICE_CHANNEL(self->priv->main_channel)) {
|
||||
g_object_unref(self->priv->main_channel);
|
||||
self->priv->main_channel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
|
||||
@ -439,6 +455,14 @@ virt_viewer_session_spice_new(void)
|
||||
return VIRT_VIEWER_SESSION(self);
|
||||
}
|
||||
|
||||
SpiceMainChannel*
|
||||
virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self)
|
||||
{
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_SESSION_SPICE(self), NULL);
|
||||
|
||||
return self->priv->main_channel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
|
||||
@ -66,6 +66,7 @@ struct _VirtViewerSessionSpiceClass {
|
||||
GType virt_viewer_session_spice_get_type(void);
|
||||
|
||||
VirtViewerSession* virt_viewer_session_spice_new(void);
|
||||
SpiceMainChannel* virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@ -47,8 +47,6 @@ G_BEGIN_DECLS
|
||||
#define VIRT_VIEWER_SESSION_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_SESSION, VirtViewerSessionClass))
|
||||
|
||||
typedef struct _VirtViewerSession VirtViewerSession;
|
||||
typedef struct _VirtViewerSessionClass VirtViewerSessionClass;
|
||||
typedef struct _VirtViewerSessionPrivate VirtViewerSessionPrivate;
|
||||
|
||||
typedef struct _VirtViewerSessionChannel VirtViewerSessionChannel;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user