mirror of
https://gitlab.com/virt-viewer/virt-viewer.git
synced 2025-02-04 17:47:05 +03:00
spice: implement --fullscreen=auto-conf
- auto-conf is an optionnal argument to --fullscreen: it will set the guest display configuration to match the client display configuration, by sending the client monitors size and position to capable guests.
This commit is contained in:
parent
395a44bd47
commit
cf8e5b029c
@ -43,6 +43,28 @@ remote_viewer_version(void)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
gboolean fullscreen = FALSE;
|
||||
gboolean fullscreen_auto_conf = FALSE;
|
||||
|
||||
static gboolean
|
||||
option_fullscreen(G_GNUC_UNUSED const gchar *option_name,
|
||||
const gchar *value,
|
||||
G_GNUC_UNUSED gpointer data, GError **error)
|
||||
{
|
||||
fullscreen = TRUE;
|
||||
|
||||
if (value == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (g_str_equal(value, "auto-conf")) {
|
||||
fullscreen_auto_conf = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, _("Invalid full-screen argument: %s"), value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -54,7 +76,6 @@ main(int argc, char **argv)
|
||||
gboolean verbose = FALSE;
|
||||
gboolean debug = FALSE;
|
||||
gboolean direct = FALSE;
|
||||
gboolean fullscreen = FALSE;
|
||||
RemoteViewer *viewer = NULL;
|
||||
#if HAVE_SPICE_GTK
|
||||
gboolean controller = FALSE;
|
||||
@ -72,8 +93,8 @@ main(int argc, char **argv)
|
||||
N_("Zoom level of window, in percentage"), "ZOOM" },
|
||||
{ "debug", '\0', 0, G_OPTION_ARG_NONE, &debug,
|
||||
N_("Display debugging information"), NULL },
|
||||
{ "full-screen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen,
|
||||
N_("Open in full screen mode"), NULL },
|
||||
{ "full-screen", 'f', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, option_fullscreen,
|
||||
N_("Open in full screen mode (=<auto-conf>)"), NULL },
|
||||
#if HAVE_SPICE_GTK
|
||||
{ "spice-controller", '\0', 0, G_OPTION_ARG_NONE, &controller,
|
||||
N_("Open connection using Spice controller communication"), NULL },
|
||||
@ -144,7 +165,10 @@ main(int argc, char **argv)
|
||||
goto cleanup;
|
||||
|
||||
app = VIRT_VIEWER_APP(viewer);
|
||||
g_object_set(app, "fullscreen", fullscreen, NULL);
|
||||
g_object_set(app,
|
||||
"fullscreen", fullscreen,
|
||||
"fullscreen-auto-conf", fullscreen_auto_conf,
|
||||
NULL);
|
||||
virt_viewer_window_set_zoom_level(virt_viewer_app_get_main_window(app), zoom);
|
||||
virt_viewer_app_set_direct(app, direct);
|
||||
|
||||
|
@ -116,6 +116,7 @@ struct _VirtViewerAppPrivate {
|
||||
gboolean authretry;
|
||||
gboolean started;
|
||||
gboolean fullscreen;
|
||||
gboolean fullscreen_auto_conf;
|
||||
gboolean attach;
|
||||
gboolean quiting;
|
||||
|
||||
@ -157,6 +158,7 @@ enum {
|
||||
PROP_TITLE,
|
||||
PROP_ENABLE_ACCEL,
|
||||
PROP_HAS_FOCUS,
|
||||
PROP_FULLSCREEN_AUTO_CONF,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -684,7 +686,7 @@ virt_viewer_app_create_session(VirtViewerApp *self, const gchar *type)
|
||||
GtkWindow *window = virt_viewer_window_get_window(priv->main_window);
|
||||
virt_viewer_app_trace(self, "Guest %s has a %s display\n",
|
||||
priv->guest_name, type);
|
||||
priv->session = virt_viewer_session_spice_new(window);
|
||||
priv->session = virt_viewer_session_spice_new(self, window);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -1170,6 +1172,10 @@ virt_viewer_app_get_property (GObject *object, guint property_id,
|
||||
g_value_set_boolean(value, priv->focused > 0);
|
||||
break;
|
||||
|
||||
case PROP_FULLSCREEN_AUTO_CONF:
|
||||
g_value_set_boolean(value, priv->fullscreen_auto_conf);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
@ -1218,6 +1224,10 @@ virt_viewer_app_set_property (GObject *object, guint property_id,
|
||||
priv->enable_accel = g_value_get_boolean(value);
|
||||
break;
|
||||
|
||||
case PROP_FULLSCREEN_AUTO_CONF:
|
||||
priv->fullscreen_auto_conf = g_value_get_boolean(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
@ -1377,8 +1387,16 @@ virt_viewer_app_class_init (VirtViewerAppClass *klass)
|
||||
"Fullscreen",
|
||||
"Fullscreen",
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property(object_class,
|
||||
PROP_FULLSCREEN_AUTO_CONF,
|
||||
g_param_spec_boolean("fullscreen-auto-conf",
|
||||
"auto conf",
|
||||
"Automatic display configuration in full screen",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property(object_class,
|
||||
@ -1503,7 +1521,7 @@ static void fullscreen_cb(gpointer key,
|
||||
|
||||
DEBUG_LOG("fullscreen display %d: %d", nth, options->fullscreen);
|
||||
if (options->fullscreen) {
|
||||
GdkScreen *screen = gdk_screen_get_default ();
|
||||
GdkScreen *screen = gdk_screen_get_default();
|
||||
GdkRectangle mon;
|
||||
|
||||
if (nth >= gdk_screen_get_n_monitors(screen)) {
|
||||
@ -1522,12 +1540,14 @@ virt_viewer_app_set_fullscreen(VirtViewerApp *self, gboolean fullscreen)
|
||||
VirtViewerAppPrivate *priv = self->priv;
|
||||
FullscreenOptions options = {
|
||||
.fullscreen = fullscreen,
|
||||
.move = virt_viewer_app_get_n_windows_visible(self) > 1,
|
||||
.move = virt_viewer_app_get_n_windows_visible(self) > 1 || self->priv->fullscreen_auto_conf,
|
||||
};
|
||||
|
||||
/* we iterate unconditionnaly, even if it was set before to update new windows */
|
||||
priv->fullscreen = fullscreen;
|
||||
g_hash_table_foreach(priv->windows, fullscreen_cb, &options);
|
||||
|
||||
g_object_notify(G_OBJECT(self), "fullscreen");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -74,6 +74,7 @@ static void virt_viewer_session_spice_channel_destroy(SpiceSession *s,
|
||||
VirtViewerSession *session);
|
||||
static void virt_viewer_session_spice_smartcard_insert(VirtViewerSession *session);
|
||||
static void virt_viewer_session_spice_smartcard_remove(VirtViewerSession *session);
|
||||
static gboolean virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self);
|
||||
|
||||
static void
|
||||
virt_viewer_session_spice_get_property(GObject *object, guint property_id,
|
||||
@ -393,6 +394,15 @@ virt_viewer_session_spice_usb_device_selection(VirtViewerSession *session,
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
agent_connected_changed(SpiceChannel *cmain,
|
||||
GParamSpec *pspec G_GNUC_UNUSED,
|
||||
VirtViewerSessionSpice *self)
|
||||
{
|
||||
if (virt_viewer_session_spice_fullscreen_auto_conf(self))
|
||||
g_signal_handlers_disconnect_by_func(cmain, agent_connected_changed, self);
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_session_spice_channel_new(SpiceSession *s,
|
||||
SpiceChannel *channel,
|
||||
@ -416,6 +426,9 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
|
||||
g_signal_connect(channel, "channel-event",
|
||||
G_CALLBACK(virt_viewer_session_spice_main_channel_event), self);
|
||||
self->priv->main_channel = SPICE_MAIN_CHANNEL(channel);
|
||||
|
||||
g_signal_connect(channel, "notify::agent-connected", G_CALLBACK(agent_connected_changed), self);
|
||||
agent_connected_changed(channel, NULL, self);
|
||||
}
|
||||
|
||||
if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
|
||||
@ -447,6 +460,41 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
|
||||
self->priv->channel_count++;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self)
|
||||
{
|
||||
GdkScreen *screen = gdk_screen_get_default();
|
||||
SpiceMainChannel* cmain = virt_viewer_session_spice_get_main_channel(self);
|
||||
VirtViewerApp *app = NULL;
|
||||
GdkRectangle dest;
|
||||
gboolean auto_conf, agent_connected;
|
||||
gint i;
|
||||
|
||||
app = virt_viewer_session_get_app(VIRT_VIEWER_SESSION(self));
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_APP(app), TRUE);
|
||||
|
||||
g_object_get(app, "fullscreen-auto-conf", &auto_conf, NULL);
|
||||
if (!auto_conf)
|
||||
return TRUE;
|
||||
|
||||
if (cmain == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_object_get(cmain, "agent-connected", &agent_connected, NULL);
|
||||
if (!agent_connected)
|
||||
return FALSE;
|
||||
|
||||
spice_main_set_display_enabled(cmain, -1, FALSE);
|
||||
for (i = 0; i < gdk_screen_get_n_monitors(screen); i++) {
|
||||
gdk_screen_get_monitor_geometry(screen, i, &dest);
|
||||
spice_main_set_display(cmain, i, dest.x, dest.y, dest.width, dest.height);
|
||||
spice_main_set_display_enabled(cmain, i, TRUE);
|
||||
}
|
||||
|
||||
spice_main_send_monitor_config(cmain);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
|
||||
SpiceChannel *channel,
|
||||
@ -479,16 +527,26 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
|
||||
g_signal_emit_by_name(self, "session-disconnected");
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_changed(GObject *gobject G_GNUC_UNUSED,
|
||||
GParamSpec *pspec G_GNUC_UNUSED,
|
||||
VirtViewerSessionSpice *self)
|
||||
{
|
||||
virt_viewer_session_spice_fullscreen_auto_conf(self);
|
||||
}
|
||||
|
||||
VirtViewerSession *
|
||||
virt_viewer_session_spice_new(GtkWindow *main_window)
|
||||
virt_viewer_session_spice_new(VirtViewerApp *app, GtkWindow *main_window)
|
||||
{
|
||||
VirtViewerSessionSpice *self;
|
||||
|
||||
self = g_object_new(VIRT_VIEWER_TYPE_SESSION_SPICE, NULL);
|
||||
self = g_object_new(VIRT_VIEWER_TYPE_SESSION_SPICE, "app", app, NULL);
|
||||
|
||||
create_spice_session(self);
|
||||
self->priv->main_window = g_object_ref(main_window);
|
||||
|
||||
g_signal_connect(app, "notify::fullscreen", G_CALLBACK(fullscreen_changed), self);
|
||||
|
||||
return VIRT_VIEWER_SESSION(self);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ struct _VirtViewerSessionSpiceClass {
|
||||
|
||||
GType virt_viewer_session_spice_get_type(void);
|
||||
|
||||
VirtViewerSession* virt_viewer_session_spice_new(GtkWindow *main_window);
|
||||
VirtViewerSession* virt_viewer_session_spice_new(VirtViewerApp *app, GtkWindow *main_window);
|
||||
SpiceMainChannel* virt_viewer_session_spice_get_main_channel(VirtViewerSessionSpice *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -35,7 +35,7 @@
|
||||
struct _VirtViewerSessionPrivate
|
||||
{
|
||||
GList *displays;
|
||||
|
||||
VirtViewerApp *app;
|
||||
gboolean auto_usbredir;
|
||||
};
|
||||
|
||||
@ -44,6 +44,7 @@ G_DEFINE_ABSTRACT_TYPE(VirtViewerSession, virt_viewer_session, G_TYPE_OBJECT)
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_APP,
|
||||
PROP_AUTO_USBREDIR,
|
||||
};
|
||||
|
||||
@ -74,6 +75,11 @@ virt_viewer_session_set_property(GObject *object,
|
||||
case PROP_AUTO_USBREDIR:
|
||||
virt_viewer_session_set_auto_usbredir(self, g_value_get_boolean(value));
|
||||
break;
|
||||
|
||||
case PROP_APP:
|
||||
self->priv->app = g_value_get_object(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
@ -92,6 +98,11 @@ virt_viewer_session_get_property(GObject *object,
|
||||
case PROP_AUTO_USBREDIR:
|
||||
g_value_set_boolean(value, virt_viewer_session_get_auto_usbredir(self));
|
||||
break;
|
||||
|
||||
case PROP_APP:
|
||||
g_value_set_object(value, self->priv->app);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
@ -117,6 +128,16 @@ virt_viewer_session_class_init(VirtViewerSessionClass *class)
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property(object_class,
|
||||
PROP_APP,
|
||||
g_param_spec_object("app",
|
||||
"VirtViewerApp",
|
||||
"VirtViewerApp",
|
||||
VIRT_VIEWER_TYPE_APP,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_signal_new("session-connected",
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
@ -408,6 +429,13 @@ void virt_viewer_session_smartcard_remove(VirtViewerSession *self)
|
||||
klass->smartcard_remove(self);
|
||||
}
|
||||
|
||||
VirtViewerApp* virt_viewer_session_get_app(VirtViewerSession *self)
|
||||
{
|
||||
g_return_val_if_fail(VIRT_VIEWER_IS_SESSION(self), NULL);
|
||||
|
||||
return self->priv->app;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "virt-viewer-app.h"
|
||||
#include "virt-viewer-display.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -118,6 +119,7 @@ gboolean virt_viewer_session_has_usb(VirtViewerSession *self);
|
||||
void virt_viewer_session_usb_device_selection(VirtViewerSession *self, GtkWindow *parent);
|
||||
void virt_viewer_session_smartcard_insert(VirtViewerSession *self);
|
||||
void virt_viewer_session_smartcard_remove(VirtViewerSession *self);
|
||||
VirtViewerApp* virt_viewer_session_get_app(VirtViewerSession *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -493,15 +493,17 @@ virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gboolean move, gint
|
||||
priv->before_saved = TRUE;
|
||||
}
|
||||
|
||||
if (!priv->fullscreen) {
|
||||
gtk_check_menu_item_set_active(check, TRUE);
|
||||
priv->fullscreen = TRUE;
|
||||
gtk_widget_hide(menu);
|
||||
gtk_widget_show(priv->toolbar);
|
||||
ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), TRUE);
|
||||
ViewAutoDrawer_Close(VIEW_AUTODRAWER(priv->layout));
|
||||
}
|
||||
if (priv->fullscreen)
|
||||
return;
|
||||
priv->fullscreen = TRUE;
|
||||
|
||||
gtk_check_menu_item_set_active(check, TRUE);
|
||||
gtk_widget_hide(menu);
|
||||
gtk_widget_show(priv->toolbar);
|
||||
ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), TRUE);
|
||||
ViewAutoDrawer_Close(VIEW_AUTODRAWER(priv->layout));
|
||||
|
||||
/* g_debug("enter fullscreen move:%d %d+%d", move, x, y); */
|
||||
if (move)
|
||||
gtk_window_move(GTK_WINDOW(priv->window), x, y);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user