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:
Daniel P. Berrange 2011-07-01 11:18:36 +01:00
parent e37190e754
commit 27d7500e03
7 changed files with 110 additions and 24 deletions

8
README
View File

@ -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

View File

@ -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"],

View File

@ -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",

View File

@ -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);

View File

@ -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;
};

View File

@ -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)

View File

@ -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.