[PATCH remote-viewer v2 1/1] Remember monitor mapping on close.
Julien Ropé
jrope at redhat.com
Fri Feb 7 09:14:57 UTC 2020
When the application is stopped, if the windows are in fullscreen, their
position on the client will be remembered.
This change uses the existing option 'monitor-mapping' in the settings
file to save the position and reuse it on next launch.
This implements part of the requirement from
https://bugzilla.redhat.com/show_bug.cgi?id=1179070
NOTE: this feature is effective only with GTK >= 3.22
Signed-off-by: Julien Ropé <jrope at redhat.com>
---
src/virt-viewer-app.c | 120 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c
index da8cfa9..f3a9a4a 100644
--- a/src/virt-viewer-app.c
+++ b/src/virt-viewer-app.c
@@ -106,6 +106,7 @@ static void virt_viewer_app_set_fullscreen(VirtViewerApp *self, gboolean fullscr
static void virt_viewer_app_update_menu_displays(VirtViewerApp *self);
static void virt_viewer_update_smartcard_accels(VirtViewerApp *self);
static void virt_viewer_app_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group);
+static VirtViewerWindow *virt_viewer_app_get_nth_window(VirtViewerApp *self, gint nth);
struct _VirtViewerAppPrivate {
@@ -400,6 +401,122 @@ virt_viewer_app_get_monitor_mapping_for_section(VirtViewerApp *self, const gchar
return mapping;
}
+/*
+ * save the association display/monitor in the config for reuse on next connection
+ */
+static void virt_viewer_app_set_monitor_mapping_for_display(VirtViewerApp *self,
+ VirtViewerDisplay *display)
+{
+ GError *error = NULL;
+ gsize nmappings = 0;
+ gchar **mappings = NULL;
+ gchar **tokens = NULL;
+
+ int i;
+
+ gint virt_viewer_display = virt_viewer_display_get_nth(display);
+ gint virt_viewer_monitor = virt_viewer_display_get_monitor(display);
+
+ if (virt_viewer_monitor == -1) {
+ // find which monitor the window is on
+#if GTK_CHECK_VERSION(3, 22, 0)
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ GdkDisplay *gdk_dpy = gdk_display_get_default();
+ VirtViewerWindow *vvWindow = virt_viewer_app_get_nth_window(self, virt_viewer_display);
+ GdkWindow *window = gtk_widget_get_window(
+ GTK_WIDGET(virt_viewer_window_get_window(vvWindow)));
+ GdkMonitor *pMonitor = gdk_display_get_monitor_at_window(gdk_dpy, window);
+
+ // compare this monitor with the list of monitors from the display
+ gint num_monitors = gdk_display_get_n_monitors(gdk_dpy);
+ if (num_monitors > 0) {
+ for (i = 0; i < num_monitors; i++) {
+ GdkMonitor *tmp = gdk_display_get_monitor(gdk_dpy, i);
+ if (tmp == pMonitor) {
+ virt_viewer_monitor = i;
+ break;
+ }
+ }
+ }
+ G_GNUC_END_IGNORE_DEPRECATIONS
+#endif
+ if (virt_viewer_monitor == -1) {
+ // could not determine the monitor - abort
+ return;
+ }
+ }
+
+ // IDs are 0 based, but the config uses 1-based numbering
+ virt_viewer_display++;
+ virt_viewer_monitor++;
+
+ mappings = g_key_file_get_string_list(self->priv->config, self->priv->uuid,
+ "monitor-mapping", &nmappings, &error);
+ if (error) {
+ if (error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND
+ && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
+ g_warning("Error reading monitor assignments for %s: %s",
+ self->priv->uuid, error->message);
+ g_clear_error(&error);
+
+ // no mapping available for the VM: we will create a new one
+ }
+
+ for (i = 0; i < nmappings; i++) {
+ gchar *endptr = NULL;
+ gint disp, monitor;
+
+ tokens = g_strsplit(mappings[i], ":", 2);
+ if (g_strv_length(tokens) != 2) {
+ // config error
+ g_strfreev(tokens);
+ goto end;
+ }
+
+ disp = strtol(tokens[0], &endptr, 10);
+ if ((endptr && *endptr != '\0') || disp < 1) {
+ // config error
+ g_strfreev(tokens);
+ goto end;
+ }
+
+ if (disp == virt_viewer_display) {
+ // found the display we have to save. Verify if it changed mappings
+ monitor = strtol(tokens[1], &endptr, 10);
+ if ((endptr && *endptr != '\0') || monitor < 1) {
+ // config error
+ g_strfreev(tokens);
+ goto end;
+ }
+
+ g_strfreev(tokens);
+ if (monitor == virt_viewer_monitor) {
+ // no change in the config - just exit
+ goto end;
+ }
+
+ // save the modified mapping
+ g_snprintf(mappings[i], strlen(mappings[i]) + 1, "%d:%d",
+ virt_viewer_display, virt_viewer_monitor);
+ break;
+ }
+ g_strfreev(tokens);
+ }
+ if (i == nmappings) {
+ // this display was not saved yet - add it
+ nmappings++;
+ mappings = g_realloc(mappings, (nmappings + 1) * sizeof(gchar *));
+ mappings[nmappings - 1] = g_strdup_printf("%d:%d", virt_viewer_display, virt_viewer_monitor);
+ mappings[nmappings] = NULL;
+ }
+ g_key_file_set_string_list(self->priv->config, self->priv->uuid, "monitor-mapping",
+ (const gchar * const *) mappings, nmappings);
+ virt_viewer_app_save_config(self);
+
+end:
+ g_strfreev(mappings);
+}
+
static
void virt_viewer_app_apply_monitor_mapping(VirtViewerApp *self)
{
@@ -1010,6 +1127,9 @@ virt_viewer_app_display_removed(VirtViewerSession *session G_GNUC_UNUSED,
{
gint nth;
+ if(virt_viewer_display_get_fullscreen(display))
+ virt_viewer_app_set_monitor_mapping_for_display(self, display) ;
+
g_object_get(display, "nth-display", &nth, NULL);
virt_viewer_app_remove_nth_window(self, nth);
g_hash_table_remove(self->priv->displays, GINT_TO_POINTER(nth));
--
2.21.1
More information about the virt-tools-list
mailing list