mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/virt-viewer
synced 2026-01-08 21:14:16 +00:00
Enable use of scaling from spice >= 0.6
Make the SPICE widget operate in the same way as the VNC widget with display scaling, and auto-resize, but preserving guest aspect ratio
This commit is contained in:
parent
e37190e754
commit
27d7500e03
8
README
8
README
@ -3,9 +3,9 @@
|
||||
|
||||
Virt Viewer provides a graphical viewer for the guest OS
|
||||
display. At this time is supports guest OS using the VNC
|
||||
protocol. Further protocols may be supported in the future
|
||||
as user demand dicatates. The viewer can connect directly
|
||||
to both local and remotely hosted guest OS, optionally
|
||||
or SPICE protocols. Further protocols may be supported in
|
||||
the future as user demand dicatates. The viewer can connect
|
||||
directly to both local and remotely hosted guest OS, optionally
|
||||
using SSL/TLS encryption.
|
||||
|
||||
Virt Viewer uses the GTK-VNC widget to provide a display
|
||||
@ -14,7 +14,7 @@ of the VNC protocol. This is available from
|
||||
http://gtk-vnc.sourceforge.net/
|
||||
|
||||
Optionally Virt Viewer can also provide a SPICE client
|
||||
using the SPICE-GTK widget (>= 0.5) available from
|
||||
using the SPICE-GTK widget (>= 0.6) available from
|
||||
|
||||
http://spice-space.org/page/Spice-Gtk
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ AC_ARG_WITH([spice-gtk],
|
||||
AS_HELP_STRING([--without-spice-gtk], [Ignore presence of spice-gtk and disable it]))
|
||||
|
||||
AS_IF([test "x$with_spice_gtk" != "xno"],
|
||||
[PKG_CHECK_MODULES(SPICEGTK, spice-client-gtk-2.0 >= 0.5, [have_spice_gtk=yes], [have_spice_gtk=no])],
|
||||
[PKG_CHECK_MODULES(SPICEGTK, spice-client-gtk-2.0 >= 0.6, [have_spice_gtk=yes], [have_spice_gtk=no])],
|
||||
[have_spice_gtk=no])
|
||||
|
||||
AS_IF([test "x$have_spice_gtk" = "xyes"],
|
||||
|
||||
@ -184,6 +184,93 @@ static void _spice_main_channel_event(G_GNUC_UNUSED SpiceChannel *channel,
|
||||
g_free(password);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Triggers a resize of the main container to indirectly cause
|
||||
* the display widget to be resized to fit the available space
|
||||
*/
|
||||
static void
|
||||
viewer_resize_display_widget(VirtViewer *viewer)
|
||||
{
|
||||
gtk_widget_queue_resize(viewer->align);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when desktop size changes.
|
||||
*
|
||||
* It either tries to resize the main window, or it triggers
|
||||
* recalculation of the display within existing window size
|
||||
*/
|
||||
static void viewer_resize_desktop(SpiceChannel *channel G_GNUC_UNUSED, gint format G_GNUC_UNUSED,
|
||||
gint width, gint height, gint stride G_GNUC_UNUSED,
|
||||
gint shmid G_GNUC_UNUSED, gpointer imgdata G_GNUC_UNUSED,
|
||||
VirtViewer *viewer)
|
||||
{
|
||||
DEBUG_LOG("desktop resize %dx%d", width, height);
|
||||
viewer->desktopWidth = width;
|
||||
viewer->desktopHeight = height;
|
||||
|
||||
if (viewer->autoResize && viewer->window && !viewer->fullscreen) {
|
||||
viewer_resize_main_window(viewer);
|
||||
} else {
|
||||
viewer_resize_display_widget(viewer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when the main container widget's size has been set.
|
||||
* It attempts to fit the display widget into this space while
|
||||
* maintaining aspect ratio
|
||||
*/
|
||||
static gboolean viewer_resize_align(GtkWidget *widget,
|
||||
GtkAllocation *alloc,
|
||||
VirtViewer *viewer)
|
||||
{
|
||||
double desktopAspect;
|
||||
double scrollAspect;
|
||||
int height, width;
|
||||
GtkAllocation child;
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
if (!viewer->active) {
|
||||
DEBUG_LOG("Skipping inactive resize");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (viewer->desktopWidth == 0 || viewer->desktopHeight == 0)
|
||||
desktopAspect = 1;
|
||||
else
|
||||
desktopAspect = (double)viewer->desktopWidth / (double)viewer->desktopHeight;
|
||||
scrollAspect = (double)alloc->width / (double)alloc->height;
|
||||
|
||||
if (scrollAspect > desktopAspect) {
|
||||
width = alloc->height * desktopAspect;
|
||||
dx = (alloc->width - width) / 2;
|
||||
height = alloc->height;
|
||||
} else {
|
||||
width = alloc->width;
|
||||
height = alloc->width / desktopAspect;
|
||||
dy = (alloc->height - height) / 2;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Align widget=%p is %dx%d, desktop is %dx%d, setting display to %dx%d",
|
||||
widget,
|
||||
alloc->width, alloc->height,
|
||||
viewer->desktopWidth, viewer->desktopHeight,
|
||||
width, height);
|
||||
|
||||
child.x = alloc->x + dx;
|
||||
child.y = alloc->y + dy;
|
||||
child.width = width;
|
||||
child.height = height;
|
||||
if (viewer->display && viewer->display->widget)
|
||||
gtk_widget_size_allocate(viewer->display->widget, &child);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _spice_channel_new(SpiceSession *s, SpiceChannel *channel,
|
||||
VirtViewerDisplay *display)
|
||||
{
|
||||
@ -206,15 +293,24 @@ static void _spice_channel_new(SpiceSession *s, SpiceChannel *channel,
|
||||
DEBUG_LOG("new display channel (#%d)", id);
|
||||
if (display->widget != NULL)
|
||||
return;
|
||||
|
||||
g_signal_connect(channel, "display-primary-create",
|
||||
G_CALLBACK(viewer_resize_desktop), display->viewer);
|
||||
|
||||
self->display = spice_display_new(s, id);
|
||||
display->widget = GTK_WIDGET(self->display);
|
||||
g_object_set(self->display,
|
||||
"grab-keyboard", TRUE,
|
||||
"grab-mouse", TRUE,
|
||||
"resize-guest", TRUE,
|
||||
"resize-guest", FALSE,
|
||||
"scaling", TRUE,
|
||||
"auto-clipboard", TRUE,
|
||||
NULL);
|
||||
viewer_add_display_and_realize(display->viewer);
|
||||
|
||||
g_signal_connect(display->viewer->align, "size-allocate",
|
||||
G_CALLBACK(viewer_resize_align), display->viewer);
|
||||
|
||||
viewer_initialized(display->viewer);
|
||||
}
|
||||
|
||||
@ -264,7 +360,6 @@ VirtViewerDisplaySpice* virt_viewer_display_spice_new(VirtViewer *viewer)
|
||||
self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE, NULL);
|
||||
d = VIRT_VIEWER_DISPLAY(self);
|
||||
d->viewer = viewer;
|
||||
d->need_align = FALSE;
|
||||
|
||||
self->session = spice_session_new();
|
||||
g_signal_connect(self->session, "channel-new",
|
||||
|
||||
@ -261,7 +261,6 @@ VirtViewerDisplayVNC* virt_viewer_display_vnc_new(VirtViewer *viewer)
|
||||
d->viewer = viewer;
|
||||
viewer->display = d;
|
||||
|
||||
d->need_align = TRUE;
|
||||
d->widget = vnc_display_new();
|
||||
self->vnc = VNC_DISPLAY(d->widget);
|
||||
vnc_display_set_keyboard_grab(self->vnc, TRUE);
|
||||
|
||||
@ -49,7 +49,6 @@ G_BEGIN_DECLS
|
||||
/* perhaps this become an interface, and be pushed in gtkvnc and spice? */
|
||||
struct _VirtViewerDisplay {
|
||||
GObject parent;
|
||||
gboolean need_align;
|
||||
VirtViewer *viewer;
|
||||
GtkWidget *widget;
|
||||
};
|
||||
|
||||
12
src/viewer.c
12
src/viewer.c
@ -132,14 +132,7 @@ void viewer_add_display_and_realize(VirtViewer *viewer)
|
||||
g_return_if_fail(viewer->display != NULL);
|
||||
g_return_if_fail(viewer->display->widget != NULL);
|
||||
|
||||
if (viewer->display->need_align) {
|
||||
gtk_container_add(GTK_CONTAINER(viewer->align), viewer->display->widget);
|
||||
} else {
|
||||
gtk_notebook_remove_page(GTK_NOTEBOOK(viewer->notebook), 2);
|
||||
if (gtk_notebook_insert_page(GTK_NOTEBOOK(viewer->notebook), viewer->display->widget,
|
||||
NULL, 2) == -1)
|
||||
g_warning("failed to insert a notebook page");
|
||||
}
|
||||
gtk_container_add(GTK_CONTAINER(viewer->align), viewer->display->widget);
|
||||
|
||||
if (!viewer->window) {
|
||||
gtk_container_add(GTK_CONTAINER(viewer->container), GTK_WIDGET(viewer->notebook));
|
||||
@ -839,8 +832,7 @@ static void viewer_show_display(VirtViewer *viewer)
|
||||
|
||||
gtk_widget_show(viewer->display->widget);
|
||||
gtk_widget_grab_focus(viewer->display->widget);
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(viewer->notebook),
|
||||
viewer->display->need_align ? 1 : 2);
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(viewer->notebook), 1);
|
||||
}
|
||||
|
||||
static void viewer_connect_info_free(VirtViewer *viewer)
|
||||
|
||||
@ -26,7 +26,7 @@ BuildRequires: libxml2-devel
|
||||
BuildRequires: libglade2-devel
|
||||
BuildRequires: gtk-vnc-devel >= 0.3.8
|
||||
%if %{with_spice}
|
||||
BuildRequires: spice-gtk-devel >= 0.5
|
||||
BuildRequires: spice-gtk-devel >= 0.6
|
||||
%endif
|
||||
BuildRequires: /usr/bin/pod2man
|
||||
BuildRequires: intltool
|
||||
@ -40,8 +40,8 @@ BuildRequires: firefox-devel
|
||||
|
||||
%description
|
||||
Virtual Machine Viewer provides a graphical console client for connecting
|
||||
to virtual machines. It uses the GTK-VNC widget to provide the display,
|
||||
and libvirt for looking up VNC server details.
|
||||
to virtual machines. It uses the GTK-VNC or SPICE-GTK widgets to provide
|
||||
the display, and libvirt for looking up VNC/SPICE server details.
|
||||
|
||||
%if %{_with_plugin}
|
||||
%package plugin
|
||||
@ -50,8 +50,9 @@ Group: Development/Libraries
|
||||
Requires: %{name} = %{version}
|
||||
|
||||
%description plugin
|
||||
gtk-vnc is a VNC viewer widget for GTK. It is built using coroutines
|
||||
allowing it to be completely asynchronous while remaining single threaded.
|
||||
Virtual Machine Viewer provides a graphical console client for connecting
|
||||
to virtual machines. It uses the GTK-VNC or SPICE-GTK widgets to provide
|
||||
the display, and libvirt for looking up VNC/SPICE server details.
|
||||
|
||||
This package provides a web browser plugin for Mozilla compatible
|
||||
browsers.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user