On Thu, Jun 12, 2014 at 04:07:03PM -0500, Jonathon Jongsma wrote: > use <display>:<monitor>;<display>:<monitor> instead of simply implying the > display from the array index (e.g. <monitor>;<monitor>). This allows you to set > up sparse guest displays (e.g. display 1 + 3). > > For example, to configure display 1 to be fullscreen on monitor 2 and display 2 > to be fullscreen on monitor 3: > > monitor-mapping=1:2;2:3 > --- > src/virt-viewer-app.c | 121 ++++++++++++++++++++++++++++++++++++++------------ > 1 file changed, 93 insertions(+), 28 deletions(-) > > diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c > index f12cb0d..a986cba 100644 > --- a/src/virt-viewer-app.c > +++ b/src/virt-viewer-app.c > @@ -108,7 +108,7 @@ struct _VirtViewerAppPrivate { > VirtViewerWindow *main_window; > GtkWidget *main_notebook; > GHashTable *windows; > - GArray *initial_display_map; > + GHashTable *initial_display_map; > gchar *clipboard; > > gboolean direct; > @@ -273,20 +273,19 @@ virt_viewer_app_quit(VirtViewerApp *self) > gint virt_viewer_app_get_n_initial_displays(VirtViewerApp* self) > { > if (self->priv->initial_display_map) > - return self->priv->initial_display_map->len; > + return g_hash_table_size(self->priv->initial_display_map); > > return gdk_screen_get_n_monitors(gdk_screen_get_default()); > } > > gint virt_viewer_app_get_initial_monitor_for_display(VirtViewerApp* self, gint display) > { > - gint monitor = -1; > + gint monitor = display; > > if (self->priv->initial_display_map) { > - if (display < self->priv->initial_display_map->len) > - monitor = g_array_index(self->priv->initial_display_map, gint, display); > - } else { > - monitor = display; > + gpointer value = NULL; > + if (g_hash_table_lookup_extended(self->priv->initial_display_map, GINT_TO_POINTER(display), NULL, &value)) > + monitor = GPOINTER_TO_INT(value); > } > > return monitor; > @@ -307,43 +306,109 @@ app_window_try_fullscreen(VirtViewerApp *self G_GNUC_UNUSED, > } > > > +static GHashTable* > +virt_viewer_app_parse_monitor_mappings(gchar** mappings, gsize nmappings) > +{ > + gint nmonitors = gdk_screen_get_n_monitors(gdk_screen_get_default()); > + GHashTable* displaymap = g_hash_table_new(g_direct_hash, g_direct_equal); > + GHashTable* monitormap = g_hash_table_new(g_direct_hash, g_direct_equal); > + int i = 0; > + gchar** tokens = NULL; > + > + for (i = 0; i < nmappings; i++) { > + gchar* endptr = NULL; > + gint display = 0, monitor = 0; > + > + tokens = g_strsplit(mappings[i], ":", 2); > + if (g_strv_length(tokens) != 2) { > + g_warning("Invalid monitor-mapping configuration: '%s'. Expected format is '<DISPLAY-ID>:<MONITOR-ID>'. Got %lu elements", mappings[i], G_N_ELEMENTS(tokens)); > + g_strfreev(tokens); > + goto configerror; > + } > + > + display = strtol(tokens[0], &endptr, 10); > + if ((endptr && *endptr != '\0') || display < 1) { > + g_warning("Invalid monitor-mapping configuration: display id is invalid: %s %p='%s'", tokens[0], endptr, endptr); > + g_strfreev(tokens); > + goto configerror; > + } > + monitor = strtol(tokens[1], &endptr, 10); > + if ((endptr && *endptr != '\0') || monitor < 1) { > + g_warning("Invalid monitor-mapping configuration: monitor id '%s' is invalid", tokens[1]); > + g_strfreev(tokens); > + goto configerror; > + } > + g_strfreev(tokens); > + > + if (monitor > nmonitors) > + g_warning("Initial monitor #%i for display #%i does not exist, skipping...", monitor, display); > + else { > + /* config file format is 1-based, not 0-based */ > + display--; > + monitor--; > + > + if (g_hash_table_lookup_extended(displaymap, GINT_TO_POINTER(display), NULL, NULL) || > + g_hash_table_lookup_extended(monitormap, GINT_TO_POINTER(monitor), NULL, NULL)) { > + g_warning("Invalid monitor-mapping configuration: a display or monitor id was specified twice"); > + goto configerror; > + } > + g_debug("Fullscreen config: mapping guest display %i to monitor %i", display, monitor); > + g_hash_table_insert(displaymap, GINT_TO_POINTER(display), GINT_TO_POINTER(monitor)); > + g_hash_table_insert(monitormap, GINT_TO_POINTER(monitor), GINT_TO_POINTER(display)); > + } > + } > + > + g_hash_table_unref(monitormap); > + return displaymap; > + > +configerror: > + g_hash_table_unref(monitormap); > + g_hash_table_unref(displaymap); > + return NULL; > +} > + > static > void virt_viewer_app_set_uuid_string(VirtViewerApp* self, const gchar* uuid_string) > { > - GArray* mapping = NULL; > GError* error = NULL; > - gsize ndisplays = 0; > - gint* displays = NULL; > - gint nmonitors = gdk_screen_get_n_monitors(gdk_screen_get_default()); > + gsize nmappings = 0; > + gchar** mappings = NULL; > + GHashTable* mapping = NULL; > > g_debug("%s: UUID changed to %s", G_STRFUNC, uuid_string); > > g_free(self->priv->uuid); > self->priv->uuid = g_strdup(uuid_string); > - displays = g_key_file_get_integer_list(self->priv->config, > - uuid_string, "monitor-mapping", &ndisplays, &error); > + mappings = g_key_file_get_string_list(self->priv->config, > + uuid_string, "monitor-mapping", &nmappings, &error); > + > if (error) { > - if (error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND) > + 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: %s", error->message); > g_clear_error(&error); > } else { > - int i = 0; > - mapping = g_array_sized_new(FALSE, FALSE, sizeof(displays[0]), ndisplays); > - // config file format is 1-based, not 0-based > - for (i = 0; i < ndisplays; i++) { > - gint val = displays[i] - 1; > - > - // sanity check > - if (val >= nmonitors) > - g_warning("Initial monitor #%i for display #%i does not exist, skipping...", val, i); > - else > - g_array_append_val(mapping, val); > + mapping = virt_viewer_app_parse_monitor_mappings(mappings, nmappings); > + } > + g_strfreev(mappings); > + > + if (!mapping) { > + mappings = g_key_file_get_string_list(self->priv->config, > + "fallback", "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: %s", error->message); > + g_clear_error(&error); > + } else { > + mapping = virt_viewer_app_parse_monitor_mappings(mappings, nmappings); > } > - g_free(displays); > + g_strfreev(mappings); this code seems to be exactly the same as in the (uuid_string, monitor-mapping) case, can you move this to a separate helper? Looks good apart from this. Christophe
Attachment:
pgpOgkgdGAzN6.pgp
Description: PGP signature
_______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list