mirror of
https://gitlab.com/virt-viewer/virt-viewer.git
synced 2025-03-07 00:58:17 +03:00
Turn VirtViewerDisplay into a proper Gtk widget
Turn VirtViewerDisplay into a Gtk widget instead of just a GObject, by merging the functionality from VirtViewerAlign
This commit is contained in:
parent
7f91cdf4ab
commit
7a7112a9fa
@ -16,7 +16,6 @@ virt_viewer_SOURCES = \
|
||||
virt-viewer-events.h virt-viewer-events.c \
|
||||
virt-viewer.h virt-viewer.c \
|
||||
virt-viewer-priv.h \
|
||||
virt-viewer-align.h virt-viewer-align.c \
|
||||
virt-viewer-display.h virt-viewer-display.c \
|
||||
virt-viewer-display-vnc.h virt-viewer-display-vnc.c \
|
||||
view/autoDrawer.c \
|
||||
|
@ -1,395 +0,0 @@
|
||||
/*
|
||||
* Virt Viewer: A virtual machine console viewer
|
||||
*
|
||||
* Copyright (C) 2007-2011 Red Hat,
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "virt-viewer-align.h"
|
||||
#include "virt-viewer-util.h"
|
||||
|
||||
|
||||
#define VIRT_VIEWER_ALIGN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), VIRT_VIEWER_TYPE_ALIGN, VirtViewerAlignPrivate))
|
||||
|
||||
struct _VirtViewerAlignPrivate
|
||||
{
|
||||
gboolean dirty;
|
||||
guint preferred_width;
|
||||
guint preferred_height;
|
||||
guint zoom_level;
|
||||
gboolean zoom;
|
||||
};
|
||||
|
||||
static void virt_viewer_align_size_request(GtkWidget *widget,
|
||||
GtkRequisition *requisition);
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
static void virt_viewer_align_get_preferred_width(GtkWidget *widget,
|
||||
int *minwidth,
|
||||
int *defwidth);
|
||||
static void virt_viewer_align_get_preferred_height(GtkWidget *widget,
|
||||
int *minheight,
|
||||
int *defheight);
|
||||
#endif
|
||||
static void virt_viewer_align_size_allocate(GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
static void virt_viewer_align_set_property(GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void virt_viewer_align_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
G_DEFINE_TYPE(VirtViewerAlign, virt_viewer_align, GTK_TYPE_BIN)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_PREFERRED_WIDTH,
|
||||
PROP_PREFERRED_HEIGHT,
|
||||
PROP_ZOOM,
|
||||
PROP_ZOOM_LEVEL,
|
||||
};
|
||||
|
||||
static void
|
||||
virt_viewer_align_class_init(VirtViewerAlignClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
gobject_class = (GObjectClass*) class;
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
|
||||
gobject_class->set_property = virt_viewer_align_set_property;
|
||||
gobject_class->get_property = virt_viewer_align_get_property;
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
widget_class->get_preferred_width = virt_viewer_align_get_preferred_width;
|
||||
widget_class->get_preferred_height = virt_viewer_align_get_preferred_height;
|
||||
#else
|
||||
widget_class->size_request = virt_viewer_align_size_request;
|
||||
#endif
|
||||
widget_class->size_allocate = virt_viewer_align_size_allocate;
|
||||
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_PREFERRED_WIDTH,
|
||||
g_param_spec_int("preferred-width",
|
||||
"Width",
|
||||
"Preferred width",
|
||||
100,
|
||||
G_MAXINT32,
|
||||
100,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_PREFERRED_HEIGHT,
|
||||
g_param_spec_int("preferred-height",
|
||||
"Height",
|
||||
"Preferred height",
|
||||
100,
|
||||
G_MAXINT32,
|
||||
100,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_ZOOM,
|
||||
g_param_spec_boolean("zoom",
|
||||
"Zoom",
|
||||
"Zoom",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_ZOOM_LEVEL,
|
||||
g_param_spec_int("zoom-level",
|
||||
"Zoom",
|
||||
"Zoom level",
|
||||
10,
|
||||
400,
|
||||
100,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private(gobject_class, sizeof(VirtViewerAlignPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_align_init(VirtViewerAlign *align)
|
||||
{
|
||||
gtk_widget_set_has_window(GTK_WIDGET(align), FALSE);
|
||||
gtk_widget_set_redraw_on_allocate(GTK_WIDGET(align), FALSE);
|
||||
|
||||
align->priv = VIRT_VIEWER_ALIGN_GET_PRIVATE(align);
|
||||
|
||||
align->priv->preferred_width = 100;
|
||||
align->priv->preferred_height = 100;
|
||||
align->priv->zoom_level = 100;
|
||||
align->priv->zoom = TRUE;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
virt_viewer_align_new(void)
|
||||
{
|
||||
return g_object_new (VIRT_VIEWER_TYPE_ALIGN, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_align_set_property(GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
VirtViewerAlign *align = VIRT_VIEWER_ALIGN(object);
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PREFERRED_WIDTH:
|
||||
virt_viewer_align_set_preferred_size(align,
|
||||
g_value_get_int(value),
|
||||
priv->preferred_height);
|
||||
break;
|
||||
case PROP_PREFERRED_HEIGHT:
|
||||
virt_viewer_align_set_preferred_size(align,
|
||||
priv->preferred_width,
|
||||
g_value_get_int(value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_align_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
VirtViewerAlign *align = VIRT_VIEWER_ALIGN(object);
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PREFERRED_WIDTH:
|
||||
g_value_set_int(value, priv->preferred_width);
|
||||
break;
|
||||
case PROP_PREFERRED_HEIGHT:
|
||||
g_value_set_int(value, priv->preferred_height);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
virt_viewer_align_idle(gpointer opaque)
|
||||
{
|
||||
VirtViewerAlign *align = opaque;
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
if (!priv->dirty)
|
||||
gtk_widget_queue_resize_no_redraw(GTK_WIDGET(align));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virt_viewer_align_size_request(GtkWidget *widget,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
VirtViewerAlign *align = VIRT_VIEWER_ALIGN(widget);
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
int border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
|
||||
|
||||
requisition->width = border_width * 2;
|
||||
requisition->height = border_width * 2;
|
||||
|
||||
if (priv->dirty) {
|
||||
if (priv->zoom)
|
||||
requisition->width += priv->preferred_width * priv->zoom_level / 100;
|
||||
else
|
||||
requisition->width += priv->preferred_width;
|
||||
} else {
|
||||
requisition->width += 50;
|
||||
}
|
||||
if (priv->dirty) {
|
||||
if (priv->zoom)
|
||||
requisition->height += priv->preferred_height * priv->zoom_level / 100;
|
||||
else
|
||||
requisition->height += priv->preferred_height;
|
||||
} else {
|
||||
requisition->height += 50;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Align size request %dx%d (preferred %dx%d)",
|
||||
requisition->width, requisition->height,
|
||||
priv->preferred_width, priv->preferred_height);
|
||||
}
|
||||
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
static void virt_viewer_align_get_preferred_width(GtkWidget *widget,
|
||||
int *minwidth,
|
||||
int *defwidth)
|
||||
{
|
||||
GtkRequisition req;
|
||||
|
||||
virt_viewer_align_size_request(widget, &req);
|
||||
|
||||
*minwidth = *defwidth = req.width;
|
||||
}
|
||||
|
||||
|
||||
static void virt_viewer_align_get_preferred_height(GtkWidget *widget,
|
||||
int *minheight,
|
||||
int *defheight)
|
||||
{
|
||||
GtkRequisition req;
|
||||
|
||||
virt_viewer_align_size_request(widget, &req);
|
||||
|
||||
*minheight = *defheight = req.height;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
virt_viewer_align_size_allocate(GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkBin *bin = GTK_BIN(widget);
|
||||
VirtViewerAlign *align = VIRT_VIEWER_ALIGN(widget);
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
GtkAllocation child_allocation;
|
||||
gint width, height;
|
||||
gint border_width;
|
||||
double preferredAspect;
|
||||
double actualAspect;
|
||||
GtkWidget *child = gtk_bin_get_child(bin);
|
||||
|
||||
DEBUG_LOG("Allocated %dx%d", allocation->width, allocation->height);
|
||||
gtk_widget_set_allocation(widget, allocation);
|
||||
|
||||
preferredAspect = (double)priv->preferred_width / (double)priv->preferred_height;
|
||||
|
||||
if (child && gtk_widget_get_visible(child)) {
|
||||
border_width = gtk_container_get_border_width(GTK_CONTAINER(align));
|
||||
|
||||
width = MAX(1, allocation->width - 2 * border_width);
|
||||
height = MAX(1, allocation->height - 2 * border_width);
|
||||
actualAspect = (double)width / (double)height;
|
||||
|
||||
if (actualAspect > preferredAspect) {
|
||||
child_allocation.width = height * preferredAspect;
|
||||
child_allocation.height = height;
|
||||
} else {
|
||||
child_allocation.width = width;
|
||||
child_allocation.height = width / preferredAspect;
|
||||
}
|
||||
|
||||
child_allocation.x = 0.5 * (width - child_allocation.width) + allocation->x + border_width;
|
||||
child_allocation.y = 0.5 * (height - child_allocation.height) + allocation->y + border_width;
|
||||
|
||||
DEBUG_LOG("Child allocate %dx%d", child_allocation.width, child_allocation.height);
|
||||
gtk_widget_size_allocate(child, &child_allocation);
|
||||
}
|
||||
|
||||
|
||||
/* This unsets the size request, so that the user can
|
||||
* manually resize the window smaller again
|
||||
*/
|
||||
if (priv->dirty) {
|
||||
g_idle_add(virt_viewer_align_idle, widget);
|
||||
priv->dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_align_set_preferred_size(VirtViewerAlign *align,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
|
||||
priv->preferred_width = width;
|
||||
priv->preferred_height = height;
|
||||
priv->dirty = TRUE;
|
||||
|
||||
gtk_widget_queue_resize(GTK_WIDGET(align));
|
||||
}
|
||||
|
||||
void virt_viewer_align_set_zoom_level(VirtViewerAlign *align,
|
||||
guint zoom)
|
||||
{
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
GtkWidget *child = gtk_bin_get_child(GTK_BIN(align));
|
||||
|
||||
if (zoom < 10)
|
||||
zoom = 10;
|
||||
if (zoom > 400)
|
||||
zoom = 400;
|
||||
priv->zoom_level = zoom;
|
||||
|
||||
if (child && gtk_widget_get_visible(child)) {
|
||||
priv->dirty = TRUE;
|
||||
gtk_widget_queue_resize(GTK_WIDGET(align));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_align_zoom_in(VirtViewerAlign *align)
|
||||
{
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
virt_viewer_align_set_zoom_level(align, priv->zoom_level + 10);
|
||||
}
|
||||
|
||||
void virt_viewer_align_zoom_out(VirtViewerAlign *align)
|
||||
{
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
virt_viewer_align_set_zoom_level(align, priv->zoom_level - 10);
|
||||
}
|
||||
|
||||
void virt_viewer_align_zoom_normal(VirtViewerAlign *align)
|
||||
{
|
||||
virt_viewer_align_set_zoom_level(align, 100);
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_align_set_zoom(VirtViewerAlign *align,
|
||||
gboolean zoom)
|
||||
{
|
||||
VirtViewerAlignPrivate *priv = align->priv;
|
||||
GtkWidget *child = gtk_bin_get_child(GTK_BIN(align));
|
||||
|
||||
priv->zoom = zoom;
|
||||
if (child && gtk_widget_get_visible(child)) {
|
||||
priv->dirty = TRUE;
|
||||
gtk_widget_queue_resize(GTK_WIDGET(align));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Virt Viewer: A virtual machine console viewer
|
||||
*
|
||||
* Copyright (C) 2007-2011 Red Hat,
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||
*/
|
||||
#ifndef _VIRT_VIEWER_ALIGN_H
|
||||
#define _VIRT_VIEWER_ALIGN_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define VIRT_VIEWER_TYPE_ALIGN virt_viewer_align_get_type()
|
||||
|
||||
#define VIRT_VIEWER_ALIGN(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), VIRT_VIEWER_TYPE_ALIGN, VirtViewerAlign))
|
||||
|
||||
#define VIRT_VIEWER_ALIGN_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_ALIGN, VirtViewerAlignClass))
|
||||
|
||||
#define VIRT_VIEWER_IS_ALIGN(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_ALIGN))
|
||||
|
||||
#define VIRT_VIEWER_IS_ALIGN_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_ALIGN))
|
||||
|
||||
#define VIRT_VIEWER_ALIGN_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_ALIGN, VirtViewerAlignClass))
|
||||
|
||||
typedef struct _VirtViewerAlign VirtViewerAlign;
|
||||
typedef struct _VirtViewerAlignClass VirtViewerAlignClass;
|
||||
typedef struct _VirtViewerAlignPrivate VirtViewerAlignPrivate;
|
||||
|
||||
|
||||
struct _VirtViewerAlign {
|
||||
GtkBin parent;
|
||||
|
||||
VirtViewerAlignPrivate *priv;
|
||||
};
|
||||
|
||||
struct _VirtViewerAlignClass {
|
||||
GtkBinClass parent_class;
|
||||
};
|
||||
|
||||
GType virt_viewer_align_get_type(void);
|
||||
|
||||
GtkWidget *virt_viewer_align_new(void);
|
||||
|
||||
void virt_viewer_align_set_preferred_size(VirtViewerAlign *align,
|
||||
guint width,
|
||||
guint height);
|
||||
|
||||
void virt_viewer_align_zoom_in(VirtViewerAlign *align);
|
||||
void virt_viewer_align_zoom_out(VirtViewerAlign *align);
|
||||
void virt_viewer_align_zoom_normal(VirtViewerAlign *align);
|
||||
void virt_viewer_align_set_zoom_level(VirtViewerAlign *align,
|
||||
guint zoom);
|
||||
void virt_viewer_align_set_zoom(VirtViewerAlign *align,
|
||||
gboolean zoom);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _VIRT_VIEWER_ALIGN_H */
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
@ -200,17 +200,6 @@ virt_viewer_display_spice_main_channel_event(SpiceChannel *channel G_GNUC_UNUSED
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Triggers a resize of the main container to indirectly cause
|
||||
* the display widget to be resized to fit the available space
|
||||
*/
|
||||
static void
|
||||
virt_viewer_display_spice_resize_widget(VirtViewer *viewer)
|
||||
{
|
||||
gtk_widget_queue_resize(viewer->align);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when desktop size changes.
|
||||
*
|
||||
@ -228,70 +217,14 @@ virt_viewer_display_spice_resize_desktop(SpiceChannel *channel 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) {
|
||||
virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(viewer->display), width, height);
|
||||
|
||||
if (viewer->autoResize && viewer->window && !viewer->fullscreen)
|
||||
virt_viewer_resize_main_window(viewer);
|
||||
} else {
|
||||
virt_viewer_display_spice_resize_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
|
||||
virt_viewer_display_spice_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
|
||||
virt_viewer_display_spice_channel_new(SpiceSession *s,
|
||||
SpiceChannel *channel,
|
||||
@ -314,14 +247,12 @@ virt_viewer_display_spice_channel_new(SpiceSession *s,
|
||||
|
||||
if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
|
||||
DEBUG_LOG("new display channel (#%d)", id);
|
||||
if (display->widget != NULL)
|
||||
return;
|
||||
|
||||
g_signal_connect(channel, "display-primary-create",
|
||||
G_CALLBACK(virt_viewer_display_spice_resize_desktop), display->viewer);
|
||||
|
||||
self->display = spice_display_new(s, id);
|
||||
display->widget = GTK_WIDGET(self->display);
|
||||
gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(self->display));
|
||||
gtk_widget_show(GTK_WIDGET(self->display));
|
||||
g_object_set(self->display,
|
||||
"grab-keyboard", TRUE,
|
||||
"grab-mouse", TRUE,
|
||||
@ -329,10 +260,6 @@ virt_viewer_display_spice_channel_new(SpiceSession *s,
|
||||
"scaling", TRUE,
|
||||
"auto-clipboard", TRUE,
|
||||
NULL);
|
||||
virt_viewer_add_display_and_realize(display->viewer);
|
||||
|
||||
g_signal_connect(display->viewer->align, "size-allocate",
|
||||
G_CALLBACK(virt_viewer_display_spice_resize_align), display->viewer);
|
||||
|
||||
virt_viewer_initialized(display->viewer);
|
||||
}
|
||||
@ -375,7 +302,7 @@ virt_viewer_display_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
|
||||
}
|
||||
}
|
||||
|
||||
VirtViewerDisplaySpice *
|
||||
GtkWidget *
|
||||
virt_viewer_display_spice_new(VirtViewer *viewer)
|
||||
{
|
||||
VirtViewerDisplaySpice *self;
|
||||
@ -393,7 +320,7 @@ virt_viewer_display_spice_new(VirtViewer *viewer)
|
||||
g_signal_connect(self->session, "channel-destroy",
|
||||
G_CALLBACK(virt_viewer_display_spice_channel_destroy), self);
|
||||
|
||||
return self;
|
||||
return GTK_WIDGET(self);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -63,7 +63,7 @@ typedef struct {
|
||||
|
||||
GType virt_viewer_display_spice_get_type(void);
|
||||
|
||||
VirtViewerDisplaySpice* virt_viewer_display_spice_new(VirtViewer *viewer);
|
||||
GtkWidget* virt_viewer_display_spice_new(VirtViewer *viewer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -196,17 +196,6 @@ virt_viewer_display_vnc_auth_failure(VirtViewer *viewer,
|
||||
viewer->authretry = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Triggers a resize of the main container to indirectly cause
|
||||
* the display widget to be resized to fit the available space
|
||||
*/
|
||||
static void
|
||||
virt_viewer_display_vnc_resize_widget(VirtViewer *viewer)
|
||||
{
|
||||
gtk_widget_queue_resize(viewer->align);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when desktop size changes.
|
||||
*
|
||||
@ -217,68 +206,15 @@ static void
|
||||
virt_viewer_display_vnc_resize_desktop(VirtViewer *viewer, gint width, gint height)
|
||||
{
|
||||
DEBUG_LOG("desktop resize %dx%d", width, height);
|
||||
viewer->desktopWidth = width;
|
||||
viewer->desktopHeight = height;
|
||||
|
||||
if (viewer->autoResize && viewer->window && !viewer->fullscreen) {
|
||||
virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(viewer->display), width, height);
|
||||
|
||||
if (viewer->autoResize && viewer->window && !viewer->fullscreen)
|
||||
virt_viewer_resize_main_window(viewer);
|
||||
} else {
|
||||
virt_viewer_display_vnc_resize_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
|
||||
virt_viewer_display_vnc_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
VirtViewerDisplayVNC*
|
||||
GtkWidget *
|
||||
virt_viewer_display_vnc_new(VirtViewer *viewer)
|
||||
{
|
||||
VirtViewerDisplayVNC *self;
|
||||
@ -289,10 +225,9 @@ virt_viewer_display_vnc_new(VirtViewer *viewer)
|
||||
self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_VNC, NULL);
|
||||
d = VIRT_VIEWER_DISPLAY(self);
|
||||
d->viewer = viewer;
|
||||
viewer->display = d;
|
||||
|
||||
d->widget = vnc_display_new();
|
||||
self->vnc = VNC_DISPLAY(d->widget);
|
||||
self->vnc = VNC_DISPLAY(vnc_display_new());
|
||||
gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(self->vnc));
|
||||
vnc_display_set_keyboard_grab(self->vnc, TRUE);
|
||||
vnc_display_set_pointer_grab(self->vnc, TRUE);
|
||||
|
||||
@ -339,12 +274,7 @@ virt_viewer_display_vnc_new(VirtViewer *viewer)
|
||||
g_signal_connect(self->vnc, "vnc-auth-credential",
|
||||
G_CALLBACK(virt_viewer_auth_vnc_credentials), &viewer->pretty_address);
|
||||
|
||||
virt_viewer_add_display_and_realize(viewer);
|
||||
|
||||
g_signal_connect(viewer->align, "size-allocate",
|
||||
G_CALLBACK(virt_viewer_display_vnc_resize_align), viewer);
|
||||
|
||||
return self;
|
||||
return GTK_WIDGET(self);
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ typedef struct {
|
||||
|
||||
GType virt_viewer_display_vnc_get_type(void);
|
||||
|
||||
VirtViewerDisplayVNC* virt_viewer_display_vnc_new(VirtViewer *viewer);
|
||||
GtkWidget* virt_viewer_display_vnc_new(VirtViewer *viewer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -21,64 +21,412 @@
|
||||
*
|
||||
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "virt-viewer-display.h"
|
||||
#include "virt-viewer-util.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(VirtViewerDisplay, virt_viewer_display, G_TYPE_OBJECT)
|
||||
#define VIRT_VIEWER_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), VIRT_VIEWER_TYPE_DISPLAY, VirtViewerDisplayPrivate))
|
||||
|
||||
|
||||
static void virt_viewer_display_class_init(VirtViewerDisplayClass *klass G_GNUC_UNUSED)
|
||||
struct _VirtViewerDisplayPrivate
|
||||
{
|
||||
gboolean dirty;
|
||||
guint desktopWidth;
|
||||
guint desktopHeight;
|
||||
guint zoom_level;
|
||||
gboolean zoom;
|
||||
};
|
||||
|
||||
static void virt_viewer_display_size_request(GtkWidget *widget,
|
||||
GtkRequisition *requisition);
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
static void virt_viewer_display_get_preferred_width(GtkWidget *widget,
|
||||
int *minwidth,
|
||||
int *defwidth);
|
||||
static void virt_viewer_display_get_preferred_height(GtkWidget *widget,
|
||||
int *minheight,
|
||||
int *defheight);
|
||||
#endif
|
||||
static void virt_viewer_display_size_allocate(GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
static void virt_viewer_display_set_property(GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void virt_viewer_display_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(VirtViewerDisplay, virt_viewer_display, GTK_TYPE_BIN)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_DESKTOP_WIDTH,
|
||||
PROP_DESKTOP_HEIGHT,
|
||||
PROP_ZOOM,
|
||||
PROP_ZOOM_LEVEL,
|
||||
};
|
||||
|
||||
static void
|
||||
virt_viewer_display_class_init(VirtViewerDisplayClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
gobject_class = (GObjectClass*) class;
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
|
||||
gobject_class->set_property = virt_viewer_display_set_property;
|
||||
gobject_class->get_property = virt_viewer_display_get_property;
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
widget_class->get_preferred_width = virt_viewer_display_get_preferred_width;
|
||||
widget_class->get_preferred_height = virt_viewer_display_get_preferred_height;
|
||||
#else
|
||||
widget_class->size_request = virt_viewer_display_size_request;
|
||||
#endif
|
||||
widget_class->size_allocate = virt_viewer_display_size_allocate;
|
||||
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_DESKTOP_WIDTH,
|
||||
g_param_spec_int("desktop-width",
|
||||
"Width",
|
||||
"Desktop width",
|
||||
100,
|
||||
G_MAXINT32,
|
||||
100,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_DESKTOP_HEIGHT,
|
||||
g_param_spec_int("desktop-height",
|
||||
"Height",
|
||||
"Desktop height",
|
||||
100,
|
||||
G_MAXINT32,
|
||||
100,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_ZOOM,
|
||||
g_param_spec_boolean("zoom",
|
||||
"Zoom",
|
||||
"Zoom",
|
||||
TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property(gobject_class,
|
||||
PROP_ZOOM_LEVEL,
|
||||
g_param_spec_int("zoom-level",
|
||||
"Zoom",
|
||||
"Zoom level",
|
||||
10,
|
||||
400,
|
||||
100,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private(gobject_class, sizeof(VirtViewerDisplayPrivate));
|
||||
}
|
||||
|
||||
static void virt_viewer_display_init(VirtViewerDisplay *self G_GNUC_UNUSED)
|
||||
static void
|
||||
virt_viewer_display_init(VirtViewerDisplay *display)
|
||||
{
|
||||
gtk_widget_set_has_window(GTK_WIDGET(display), FALSE);
|
||||
gtk_widget_set_redraw_on_allocate(GTK_WIDGET(display), FALSE);
|
||||
|
||||
display->priv = VIRT_VIEWER_DISPLAY_GET_PRIVATE(display);
|
||||
|
||||
display->priv->desktopWidth = 100;
|
||||
display->priv->desktopHeight = 100;
|
||||
display->priv->zoom_level = 100;
|
||||
display->priv->zoom = TRUE;
|
||||
}
|
||||
|
||||
void virt_viewer_display_close(VirtViewerDisplay *self)
|
||||
GtkWidget*
|
||||
virt_viewer_display_new(void)
|
||||
{
|
||||
g_return_if_fail(VIRT_VIEWER_IS_DISPLAY(self));
|
||||
|
||||
VIRT_VIEWER_DISPLAY_GET_CLASS(self)->close(self);
|
||||
return g_object_new (VIRT_VIEWER_TYPE_DISPLAY, NULL);
|
||||
}
|
||||
|
||||
void virt_viewer_display_send_keys(VirtViewerDisplay *self,
|
||||
static void
|
||||
virt_viewer_display_set_property(GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(object);
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DESKTOP_WIDTH:
|
||||
virt_viewer_display_set_desktop_size(display,
|
||||
g_value_get_int(value),
|
||||
priv->desktopHeight);
|
||||
break;
|
||||
case PROP_DESKTOP_HEIGHT:
|
||||
virt_viewer_display_set_desktop_size(display,
|
||||
priv->desktopWidth,
|
||||
g_value_get_int(value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_display_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(object);
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DESKTOP_WIDTH:
|
||||
g_value_set_int(value, priv->desktopWidth);
|
||||
break;
|
||||
case PROP_DESKTOP_HEIGHT:
|
||||
g_value_set_int(value, priv->desktopHeight);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
virt_viewer_display_idle(gpointer opaque)
|
||||
{
|
||||
VirtViewerDisplay *display = opaque;
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
if (!priv->dirty)
|
||||
gtk_widget_queue_resize_no_redraw(GTK_WIDGET(display));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virt_viewer_display_size_request(GtkWidget *widget,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(widget);
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
int border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
|
||||
|
||||
requisition->width = border_width * 2;
|
||||
requisition->height = border_width * 2;
|
||||
|
||||
if (priv->dirty) {
|
||||
if (priv->zoom)
|
||||
requisition->width += priv->desktopWidth * priv->zoom_level / 100;
|
||||
else
|
||||
requisition->width += priv->desktopWidth;
|
||||
} else {
|
||||
requisition->width += 50;
|
||||
}
|
||||
if (priv->dirty) {
|
||||
if (priv->zoom)
|
||||
requisition->height += priv->desktopHeight * priv->zoom_level / 100;
|
||||
else
|
||||
requisition->height += priv->desktopHeight;
|
||||
} else {
|
||||
requisition->height += 50;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Display size request %dx%d (desktop %dx%d)",
|
||||
requisition->width, requisition->height,
|
||||
priv->desktopWidth, priv->desktopHeight);
|
||||
}
|
||||
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 0, 0)
|
||||
static void virt_viewer_display_get_preferred_width(GtkWidget *widget,
|
||||
int *minwidth,
|
||||
int *defwidth)
|
||||
{
|
||||
GtkRequisition req;
|
||||
|
||||
virt_viewer_display_size_request(widget, &req);
|
||||
|
||||
*minwidth = *defwidth = req.width;
|
||||
}
|
||||
|
||||
|
||||
static void virt_viewer_display_get_preferred_height(GtkWidget *widget,
|
||||
int *minheight,
|
||||
int *defheight)
|
||||
{
|
||||
GtkRequisition req;
|
||||
|
||||
virt_viewer_display_size_request(widget, &req);
|
||||
|
||||
*minheight = *defheight = req.height;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
virt_viewer_display_size_allocate(GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkBin *bin = GTK_BIN(widget);
|
||||
VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(widget);
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
GtkAllocation child_allocation;
|
||||
gint width, height;
|
||||
gint border_width;
|
||||
double desktopAspect;
|
||||
double actualAspect;
|
||||
GtkWidget *child = gtk_bin_get_child(bin);
|
||||
|
||||
DEBUG_LOG("Allocated %dx%d", allocation->width, allocation->height);
|
||||
gtk_widget_set_allocation(widget, allocation);
|
||||
|
||||
desktopAspect = (double)priv->desktopWidth / (double)priv->desktopHeight;
|
||||
|
||||
if (child && gtk_widget_get_visible(child)) {
|
||||
border_width = gtk_container_get_border_width(GTK_CONTAINER(display));
|
||||
|
||||
width = MAX(1, allocation->width - 2 * border_width);
|
||||
height = MAX(1, allocation->height - 2 * border_width);
|
||||
actualAspect = (double)width / (double)height;
|
||||
|
||||
if (actualAspect > desktopAspect) {
|
||||
child_allocation.width = height * desktopAspect;
|
||||
child_allocation.height = height;
|
||||
} else {
|
||||
child_allocation.width = width;
|
||||
child_allocation.height = width / desktopAspect;
|
||||
}
|
||||
|
||||
child_allocation.x = 0.5 * (width - child_allocation.width) + allocation->x + border_width;
|
||||
child_allocation.y = 0.5 * (height - child_allocation.height) + allocation->y + border_width;
|
||||
|
||||
DEBUG_LOG("Child allocate %dx%d", child_allocation.width, child_allocation.height);
|
||||
gtk_widget_size_allocate(child, &child_allocation);
|
||||
}
|
||||
|
||||
|
||||
/* This unsets the size request, so that the user can
|
||||
* manually resize the window smaller again
|
||||
*/
|
||||
if (priv->dirty) {
|
||||
g_idle_add(virt_viewer_display_idle, widget);
|
||||
priv->dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_set_desktop_size(VirtViewerDisplay *display,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
|
||||
priv->desktopWidth = width;
|
||||
priv->desktopHeight = height;
|
||||
priv->dirty = TRUE;
|
||||
|
||||
gtk_widget_queue_resize(GTK_WIDGET(display));
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_get_desktop_size(VirtViewerDisplay *display,
|
||||
guint *width,
|
||||
guint *height)
|
||||
{
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
|
||||
*width = priv->desktopWidth;
|
||||
*height = priv->desktopHeight;
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_set_zoom_level(VirtViewerDisplay *display,
|
||||
guint zoom)
|
||||
{
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
GtkWidget *child = gtk_bin_get_child(GTK_BIN(display));
|
||||
|
||||
if (zoom < 10)
|
||||
zoom = 10;
|
||||
if (zoom > 400)
|
||||
zoom = 400;
|
||||
priv->zoom_level = zoom;
|
||||
|
||||
if (child && gtk_widget_get_visible(child)) {
|
||||
priv->dirty = TRUE;
|
||||
gtk_widget_queue_resize(GTK_WIDGET(display));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_set_zoom(VirtViewerDisplay *display,
|
||||
gboolean zoom)
|
||||
{
|
||||
VirtViewerDisplayPrivate *priv = display->priv;
|
||||
GtkWidget *child = gtk_bin_get_child(GTK_BIN(display));
|
||||
|
||||
priv->zoom = zoom;
|
||||
if (child && gtk_widget_get_visible(child)) {
|
||||
priv->dirty = TRUE;
|
||||
gtk_widget_queue_resize(GTK_WIDGET(display));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void virt_viewer_display_close(VirtViewerDisplay *display)
|
||||
{
|
||||
g_return_if_fail(VIRT_VIEWER_IS_DISPLAY(display));
|
||||
|
||||
VIRT_VIEWER_DISPLAY_GET_CLASS(display)->close(display);
|
||||
}
|
||||
|
||||
void virt_viewer_display_send_keys(VirtViewerDisplay *display,
|
||||
const guint *keyvals, int nkeyvals)
|
||||
{
|
||||
g_return_if_fail(VIRT_VIEWER_IS_DISPLAY(self));
|
||||
g_return_if_fail(VIRT_VIEWER_IS_DISPLAY(display));
|
||||
|
||||
VIRT_VIEWER_DISPLAY_GET_CLASS(self)->send_keys(self, keyvals, nkeyvals);
|
||||
VIRT_VIEWER_DISPLAY_GET_CLASS(display)->send_keys(display, keyvals, nkeyvals);
|
||||
}
|
||||
|
||||
GdkPixbuf* virt_viewer_display_get_pixbuf(VirtViewerDisplay *self)
|
||||
GdkPixbuf* virt_viewer_display_get_pixbuf(VirtViewerDisplay *display)
|
||||
{
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(self), NULL);
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(display), NULL);
|
||||
|
||||
return VIRT_VIEWER_DISPLAY_GET_CLASS(self)->get_pixbuf(self);
|
||||
return VIRT_VIEWER_DISPLAY_GET_CLASS(display)->get_pixbuf(display);
|
||||
}
|
||||
|
||||
gboolean virt_viewer_display_open_fd(VirtViewerDisplay *self, int fd)
|
||||
gboolean virt_viewer_display_open_fd(VirtViewerDisplay *display, int fd)
|
||||
{
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(self), FALSE);
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(display), FALSE);
|
||||
|
||||
return VIRT_VIEWER_DISPLAY_GET_CLASS(self)->open_fd(self, fd);
|
||||
return VIRT_VIEWER_DISPLAY_GET_CLASS(display)->open_fd(display, fd);
|
||||
}
|
||||
|
||||
gboolean virt_viewer_display_open_host(VirtViewerDisplay *self, char *host, char *port)
|
||||
gboolean virt_viewer_display_open_host(VirtViewerDisplay *display, char *host, char *port)
|
||||
{
|
||||
VirtViewerDisplayClass *klass;
|
||||
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(self), FALSE);
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(display), FALSE);
|
||||
|
||||
klass = VIRT_VIEWER_DISPLAY_GET_CLASS(self);
|
||||
return klass->open_host(self, host, port);
|
||||
klass = VIRT_VIEWER_DISPLAY_GET_CLASS(display);
|
||||
return klass->open_host(display, host, port);
|
||||
}
|
||||
|
||||
gboolean virt_viewer_display_channel_open_fd(VirtViewerDisplay *self,
|
||||
gboolean virt_viewer_display_channel_open_fd(VirtViewerDisplay *display,
|
||||
VirtViewerDisplayChannel *channel, int fd)
|
||||
{
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(self), FALSE);
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_DISPLAY(display), FALSE);
|
||||
|
||||
return VIRT_VIEWER_DISPLAY_GET_CLASS(self)->channel_open_fd(self, channel, fd);
|
||||
return VIRT_VIEWER_DISPLAY_GET_CLASS(display)->channel_open_fd(display, channel, fd);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,7 +24,7 @@
|
||||
#ifndef _VIRT_VIEWER_DISPLAY_H
|
||||
#define _VIRT_VIEWER_DISPLAY_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "virt-viewer-priv.h"
|
||||
|
||||
@ -47,15 +47,22 @@ G_BEGIN_DECLS
|
||||
#define VIRT_VIEWER_DISPLAY_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_DISPLAY, VirtViewerDisplayClass))
|
||||
|
||||
typedef struct _VirtViewerDisplay VirtViewerDisplay;
|
||||
typedef struct _VirtViewerDisplayClass VirtViewerDisplayClass;
|
||||
typedef struct _VirtViewerDisplayPrivate VirtViewerDisplayPrivate;
|
||||
|
||||
|
||||
/* perhaps this become an interface, and be pushed in gtkvnc and spice? */
|
||||
struct _VirtViewerDisplay {
|
||||
GObject parent;
|
||||
GtkBin parent;
|
||||
|
||||
VirtViewer *viewer;
|
||||
GtkWidget *widget;
|
||||
|
||||
VirtViewerDisplayPrivate *priv;
|
||||
};
|
||||
|
||||
struct _VirtViewerDisplayClass {
|
||||
GObjectClass parent_class;
|
||||
GtkBinClass parent_class;
|
||||
|
||||
/* virtual methods */
|
||||
void (* close) (VirtViewerDisplay* display);
|
||||
@ -70,6 +77,22 @@ struct _VirtViewerDisplayClass {
|
||||
|
||||
GType virt_viewer_display_get_type(void);
|
||||
|
||||
GtkWidget *virt_viewer_display_new(void);
|
||||
|
||||
void virt_viewer_display_set_desktop_size(VirtViewerDisplay *display,
|
||||
guint width,
|
||||
guint height);
|
||||
|
||||
void virt_viewer_display_get_desktop_size(VirtViewerDisplay *display,
|
||||
guint *width,
|
||||
guint *height);
|
||||
|
||||
void virt_viewer_display_set_zoom_level(VirtViewerDisplay *display,
|
||||
guint zoom);
|
||||
void virt_viewer_display_set_zoom(VirtViewerDisplay *display,
|
||||
gboolean zoom);
|
||||
|
||||
|
||||
void virt_viewer_display_close(VirtViewerDisplay* display);
|
||||
void virt_viewer_display_send_keys(VirtViewerDisplay* display,
|
||||
const guint *keyvals, int nkeyvals);
|
||||
|
@ -57,7 +57,6 @@ struct _VirtViewer {
|
||||
GtkWidget *container;
|
||||
|
||||
GtkWidget *notebook;
|
||||
GtkWidget *align;
|
||||
GtkWidget *status;
|
||||
|
||||
GtkWidget *toolbar;
|
||||
@ -65,8 +64,6 @@ struct _VirtViewer {
|
||||
|
||||
char *pretty_address;
|
||||
|
||||
int desktopWidth;
|
||||
int desktopHeight;
|
||||
gboolean autoResize;
|
||||
gboolean fullscreen;
|
||||
gboolean withEvents;
|
||||
@ -87,7 +84,9 @@ struct _VirtViewer {
|
||||
|
||||
gchar *clipboard;
|
||||
|
||||
VirtViewerDisplay *display;
|
||||
GtkWidget *display;
|
||||
|
||||
gint zoomlevel;
|
||||
|
||||
char *unixsock;
|
||||
char *ghost;
|
||||
@ -113,7 +112,6 @@ void virt_viewer_set_status(VirtViewer *viewer, const char *text);
|
||||
void virt_viewer_set_title(VirtViewer *viewer, gboolean grabbed);
|
||||
void virt_viewer_enable_modifiers(VirtViewer *viewer);
|
||||
void virt_viewer_disable_modifiers(VirtViewer *viewer);
|
||||
void virt_viewer_add_display_and_realize(VirtViewer *viewer);
|
||||
void virt_viewer_server_cut_text(VirtViewer *viewer, const gchar *text);
|
||||
void virt_viewer_resize_main_window(VirtViewer *viewer);
|
||||
void virt_viewer_channel_open_fd(VirtViewer *viewer, VirtViewerDisplayChannel *channel);
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
extern gboolean doDebug;
|
||||
|
||||
#define DEBUG_LOG(s, ...) do { if (doDebug) g_debug((s), ## __VA_ARGS__); } while (0)
|
||||
#define DEBUG_LOG(s, ...) do { if (doDebug) g_debug(s, ## __VA_ARGS__); } while (0)
|
||||
#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
|
||||
|
||||
|
||||
|
@ -47,7 +47,6 @@
|
||||
|
||||
#include "virt-viewer.h"
|
||||
#include "virt-viewer-priv.h"
|
||||
#include "virt-viewer-align.h"
|
||||
#include "virt-viewer-events.h"
|
||||
#include "virt-viewer-auth.h"
|
||||
#include "virt-viewer-display-vnc.h"
|
||||
@ -163,24 +162,6 @@ virt_viewer_simple_message_dialog(GtkWidget *window,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virt_viewer_add_display_and_realize(VirtViewer *viewer)
|
||||
{
|
||||
g_return_if_fail(viewer != NULL);
|
||||
g_return_if_fail(viewer->display != NULL);
|
||||
g_return_if_fail(viewer->display->widget != NULL);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(viewer->align), viewer->display->widget);
|
||||
|
||||
if (!viewer->window) {
|
||||
gtk_container_add(GTK_CONTAINER(viewer->container), GTK_WIDGET(viewer->notebook));
|
||||
gtk_widget_show_all(viewer->container);
|
||||
}
|
||||
|
||||
gtk_widget_realize(viewer->display->widget);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This code attempts to resize the top level window to be large enough
|
||||
* to contain the entire display desktop at 1:1 ratio. If the local desktop
|
||||
@ -195,6 +176,8 @@ virt_viewer_resize_main_window(VirtViewer *viewer)
|
||||
int width, height;
|
||||
double desktopAspect;
|
||||
double screenAspect;
|
||||
guint desktopWidth;
|
||||
guint desktopHeight;
|
||||
|
||||
DEBUG_LOG("Preparing main window resize");
|
||||
if (!viewer->active) {
|
||||
@ -202,7 +185,10 @@ virt_viewer_resize_main_window(VirtViewer *viewer)
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_window_resize(GTK_WINDOW (viewer->window), 1, 1);
|
||||
gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1);
|
||||
|
||||
virt_viewer_display_get_desktop_size(VIRT_VIEWER_DISPLAY(viewer->display),
|
||||
&desktopWidth, &desktopHeight);
|
||||
|
||||
screen = gtk_widget_get_screen(viewer->window);
|
||||
gdk_screen_get_monitor_geometry(screen,
|
||||
@ -210,30 +196,30 @@ virt_viewer_resize_main_window(VirtViewer *viewer)
|
||||
(screen, gtk_widget_get_window(viewer->window)),
|
||||
&fullscreen);
|
||||
|
||||
desktopAspect = (double)viewer->desktopWidth / (double)viewer->desktopHeight;
|
||||
desktopAspect = (double)desktopWidth / (double)desktopHeight;
|
||||
screenAspect = (double)(fullscreen.width - 128) / (double)(fullscreen.height - 128);
|
||||
|
||||
if ((viewer->desktopWidth > (fullscreen.width - 128)) ||
|
||||
(viewer->desktopHeight > (fullscreen.height - 128))) {
|
||||
if ((desktopWidth > (fullscreen.width - 128)) ||
|
||||
(desktopHeight > (fullscreen.height - 128))) {
|
||||
/* Doesn't fit native res, so go as large as possible
|
||||
maintaining aspect ratio */
|
||||
if (screenAspect > desktopAspect) {
|
||||
width = viewer->desktopHeight * desktopAspect;
|
||||
height = viewer->desktopHeight;
|
||||
width = desktopHeight * desktopAspect;
|
||||
height = desktopHeight;
|
||||
} else {
|
||||
width = viewer->desktopWidth;
|
||||
height = viewer->desktopWidth / desktopAspect;
|
||||
width = desktopWidth;
|
||||
height = desktopWidth / desktopAspect;
|
||||
}
|
||||
} else {
|
||||
width = viewer->desktopWidth;
|
||||
height = viewer->desktopHeight;
|
||||
width = desktopWidth;
|
||||
height = desktopHeight;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Decided todo %dx%d (desktop is %dx%d, fullscreen is %dx%d",
|
||||
width, height, viewer->desktopWidth, viewer->desktopHeight,
|
||||
width, height, desktopWidth, desktopHeight,
|
||||
fullscreen.width, fullscreen.height);
|
||||
|
||||
virt_viewer_align_set_preferred_size(VIRT_VIEWER_ALIGN(viewer->align),
|
||||
virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(viewer->display),
|
||||
width, height);
|
||||
}
|
||||
|
||||
@ -242,7 +228,11 @@ virt_viewer_menu_view_zoom_out(GtkWidget *menu G_GNUC_UNUSED,
|
||||
VirtViewer *viewer)
|
||||
{
|
||||
gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1);
|
||||
virt_viewer_align_zoom_out(VIRT_VIEWER_ALIGN(viewer->align));
|
||||
if (viewer->zoomlevel > 10)
|
||||
viewer->zoomlevel -= 10;
|
||||
|
||||
if (viewer->display)
|
||||
virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(viewer->display), viewer->zoomlevel);
|
||||
}
|
||||
|
||||
void
|
||||
@ -250,7 +240,11 @@ virt_viewer_menu_view_zoom_in(GtkWidget *menu G_GNUC_UNUSED,
|
||||
VirtViewer *viewer)
|
||||
{
|
||||
gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1);
|
||||
virt_viewer_align_zoom_in(VIRT_VIEWER_ALIGN(viewer->align));
|
||||
if (viewer->zoomlevel < 400)
|
||||
viewer->zoomlevel += 10;
|
||||
|
||||
if (viewer->display)
|
||||
virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(viewer->display), viewer->zoomlevel);
|
||||
}
|
||||
|
||||
void
|
||||
@ -258,7 +252,10 @@ virt_viewer_menu_view_zoom_reset(GtkWidget *menu G_GNUC_UNUSED,
|
||||
VirtViewer *viewer)
|
||||
{
|
||||
gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1);
|
||||
virt_viewer_align_zoom_normal(VIRT_VIEWER_ALIGN(viewer->align));
|
||||
viewer->zoomlevel = 100;
|
||||
|
||||
if (viewer->display)
|
||||
virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(viewer->display), viewer->zoomlevel);
|
||||
}
|
||||
|
||||
void
|
||||
@ -366,7 +363,7 @@ virt_viewer_quit(VirtViewer *viewer)
|
||||
g_return_if_fail(viewer != NULL);
|
||||
|
||||
if (viewer->display)
|
||||
virt_viewer_display_close(viewer->display);
|
||||
virt_viewer_display_close(VIRT_VIEWER_DISPLAY(viewer->display));
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
@ -464,7 +461,7 @@ virt_viewer_menu_send(GtkWidget *menu G_GNUC_UNUSED,
|
||||
for (i = 0 ; i < G_N_ELEMENTS(keyCombos) ; i++) {
|
||||
if (!strcmp(text, keyCombos[i].label)) {
|
||||
DEBUG_LOG("Sending key combo %s", gtk_label_get_text(GTK_LABEL(label)));
|
||||
virt_viewer_display_send_keys(viewer->display,
|
||||
virt_viewer_display_send_keys(VIRT_VIEWER_DISPLAY(viewer->display),
|
||||
keyCombos[i].keys,
|
||||
keyCombos[i].nkeys);
|
||||
return;
|
||||
@ -478,7 +475,7 @@ static void
|
||||
virt_viewer_save_screenshot(VirtViewer *viewer,
|
||||
const char *file)
|
||||
{
|
||||
GdkPixbuf *pix = virt_viewer_display_get_pixbuf(viewer->display);
|
||||
GdkPixbuf *pix = virt_viewer_display_get_pixbuf(VIRT_VIEWER_DISPLAY(viewer->display));
|
||||
gdk_pixbuf_save(pix, file, "png", NULL,
|
||||
"tEXt::Generator App", PACKAGE, NULL);
|
||||
gdk_pixbuf_unref(pix);
|
||||
@ -853,10 +850,8 @@ virt_viewer_show_display(VirtViewer *viewer)
|
||||
{
|
||||
g_return_if_fail(viewer != NULL);
|
||||
g_return_if_fail(viewer->display != NULL);
|
||||
g_return_if_fail(viewer->display->widget != NULL);
|
||||
|
||||
gtk_widget_show(viewer->display->widget);
|
||||
gtk_widget_grab_focus(viewer->display->widget);
|
||||
gtk_widget_grab_focus(gtk_bin_get_child(GTK_BIN(viewer->display)));
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(viewer->notebook), 1);
|
||||
}
|
||||
|
||||
@ -899,12 +894,12 @@ virt_viewer_extract_connect_info(VirtViewer *viewer,
|
||||
if (g_strcasecmp(type, "vnc") == 0) {
|
||||
virt_viewer_trace(viewer, "Guest %s has a %s display\n",
|
||||
viewer->domkey, type);
|
||||
viewer->display = VIRT_VIEWER_DISPLAY(virt_viewer_display_vnc_new(viewer));
|
||||
viewer->display = virt_viewer_display_vnc_new(viewer);
|
||||
#ifdef HAVE_SPICE_GTK
|
||||
} else if (g_strcasecmp(type, "spice") == 0) {
|
||||
virt_viewer_trace(viewer, "Guest %s has a %s display\n",
|
||||
viewer->domkey, type);
|
||||
viewer->display = VIRT_VIEWER_DISPLAY(virt_viewer_display_spice_new(viewer));
|
||||
viewer->display = virt_viewer_display_spice_new(viewer);
|
||||
#endif
|
||||
} else {
|
||||
virt_viewer_trace(viewer, "Guest %s has unsupported %s display type\n",
|
||||
@ -913,6 +908,10 @@ virt_viewer_extract_connect_info(VirtViewer *viewer,
|
||||
viewer->domkey);
|
||||
goto cleanup;
|
||||
}
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(viewer->notebook), viewer->display, NULL);
|
||||
if (gtk_bin_get_child(GTK_BIN(viewer->display)))
|
||||
gtk_widget_realize(GTK_WIDGET(gtk_bin_get_child(GTK_BIN(viewer->display))));
|
||||
gtk_widget_show_all(viewer->display);
|
||||
|
||||
xpath = g_strdup_printf("string(/domain/devices/graphics[@type='%s']/@port)", type);
|
||||
if ((viewer->gport = virt_viewer_extract_xpath_string(xmldesc, xpath)) == NULL) {
|
||||
@ -969,7 +968,7 @@ virt_viewer_channel_open_fd(VirtViewer *viewer,
|
||||
virt_viewer_simple_message_dialog(viewer->window, _("Can't connect to channel, SSH only supported."));
|
||||
|
||||
if (fd >= 0)
|
||||
virt_viewer_display_channel_open_fd(viewer->display, channel, fd);
|
||||
virt_viewer_display_channel_open_fd(VIRT_VIEWER_DISPLAY(viewer->display), channel, fd);
|
||||
}
|
||||
#else
|
||||
void
|
||||
@ -1029,11 +1028,11 @@ virt_viewer_activate(VirtViewer *viewer,
|
||||
#endif
|
||||
|
||||
if (fd >= 0) {
|
||||
ret = virt_viewer_display_open_fd(viewer->display, fd);
|
||||
ret = virt_viewer_display_open_fd(VIRT_VIEWER_DISPLAY(viewer->display), fd);
|
||||
} else {
|
||||
virt_viewer_trace(viewer, "Opening direct TCP connection to display at %s:%s\n",
|
||||
viewer->ghost, viewer->gport);
|
||||
ret = virt_viewer_display_open_host(viewer->display,
|
||||
ret = virt_viewer_display_open_host(VIRT_VIEWER_DISPLAY(viewer->display),
|
||||
viewer->ghost, viewer->gport);
|
||||
}
|
||||
|
||||
@ -1107,7 +1106,7 @@ virt_viewer_deactivate(VirtViewer *viewer)
|
||||
return;
|
||||
|
||||
if (viewer->display)
|
||||
virt_viewer_display_close(viewer->display);
|
||||
virt_viewer_display_close(VIRT_VIEWER_DISPLAY(viewer->display));
|
||||
free(viewer->domtitle);
|
||||
viewer->domtitle = NULL;
|
||||
|
||||
@ -1346,8 +1345,6 @@ virt_viewer_start(const char *uri,
|
||||
viewer->domkey = g_strdup(name);
|
||||
viewer->uri = g_strdup(uri);
|
||||
|
||||
viewer->desktopWidth = viewer->desktopHeight = 400;
|
||||
|
||||
g_value_init(&viewer->accelSetting, G_TYPE_STRING);
|
||||
|
||||
virt_viewer_events_register();
|
||||
@ -1376,16 +1373,14 @@ virt_viewer_start(const char *uri,
|
||||
}
|
||||
|
||||
viewer->status = gtk_label_new("");
|
||||
viewer->align = virt_viewer_align_new();
|
||||
|
||||
virt_viewer_align_set_zoom_level(VIRT_VIEWER_ALIGN(viewer->align), zoom);
|
||||
viewer->zoomlevel = zoom;
|
||||
|
||||
viewer->notebook = gtk_notebook_new();
|
||||
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(viewer->notebook), FALSE);
|
||||
gtk_notebook_set_show_border(GTK_NOTEBOOK(viewer->notebook), FALSE);
|
||||
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(viewer->notebook), viewer->status, NULL);
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(viewer->notebook), viewer->align, NULL);
|
||||
|
||||
if (container) {
|
||||
viewer->container = container;
|
||||
@ -1396,10 +1391,7 @@ virt_viewer_start(const char *uri,
|
||||
GtkWidget *vbox = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "viewer-box"));
|
||||
virt_viewer_toolbar_setup(viewer);
|
||||
|
||||
//gtk_box_pack_end(GTK_BOX(vbox), viewer->toolbar, TRUE, TRUE, 0);
|
||||
//gtk_box_pack_end(GTK_BOX(vbox), viewer->notebook, TRUE, TRUE, 0);
|
||||
gtk_box_pack_end(GTK_BOX(vbox), viewer->layout, TRUE, TRUE, 0);
|
||||
gtk_widget_show_all(GTK_WIDGET(vbox));
|
||||
|
||||
GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "viewer"));
|
||||
GSList *accels;
|
||||
|
Loading…
x
Reference in New Issue
Block a user