<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jun 30, 2014 at 10:49 PM, Jonathon Jongsma <span dir="ltr"><<a href="mailto:jjongsma@redhat.com" target="_blank">jjongsma@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="">use <display>:<monitor>;<display>:<monitor> instead of simply implying the<br>
display from the array index (e.g. <monitor>;<monitor>). This allows you to set<br>
up sparse guest displays (e.g. display 1 + 3).<br>
<br>
For example, to configure display 1 to be fullscreen on monitor 2 and display 2<br>
to be fullscreen on monitor 3:<br>
<br>
    monitor-mapping=1:2;2:3<br>
---<br>
</div> src/virt-viewer-app.c | 131 +++++++++++++++++++++++++++++++++++++-------------<br>
 1 file changed, 97 insertions(+), 34 deletions(-)<br>
<br>
diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c<br>
index e0f33bd..6bd49f4 100644<br>
<div><div class="h5">--- a/src/virt-viewer-app.c<br>
+++ b/src/virt-viewer-app.c<br>
@@ -108,7 +108,7 @@ struct _VirtViewerAppPrivate {<br>
     VirtViewerWindow *main_window;<br>
     GtkWidget *main_notebook;<br>
     GHashTable *windows;<br>
-    GArray *initial_display_map;<br>
+    GHashTable *initial_display_map;<br>
     gchar *clipboard;<br>
<br>
     gboolean direct;<br>
@@ -273,20 +273,19 @@ virt_viewer_app_quit(VirtViewerApp *self)<br>
 gint virt_viewer_app_get_n_initial_displays(VirtViewerApp* self)<br>
 {<br>
     if (self->priv->initial_display_map)<br>
-        return self->priv->initial_display_map->len;<br>
+        return g_hash_table_size(self->priv->initial_display_map);<br>
<br>
     return gdk_screen_get_n_monitors(gdk_screen_get_default());<br>
 }<br>
<br>
 gint virt_viewer_app_get_initial_monitor_for_display(VirtViewerApp* self, gint display)<br>
 {<br>
-    gint monitor = -1;<br>
+    gint monitor = display;<br>
<br>
     if (self->priv->initial_display_map) {<br>
-        if (display < self->priv->initial_display_map->len)<br>
-            monitor = g_array_index(self->priv->initial_display_map, gint, display);<br>
-    } else {<br>
-        monitor = display;<br>
+        gpointer value = NULL;<br>
+        if (g_hash_table_lookup_extended(self->priv->initial_display_map, GINT_TO_POINTER(display), NULL, &value))<br>
+            monitor = GPOINTER_TO_INT(value);<br>
     }<br>
<br>
     return monitor;<br>
</div></div>@@ -307,43 +306,107 @@ app_window_try_fullscreen(VirtViewerApp *self G_GNUC_UNUSED,<br>
<div><div class="h5"> }<br>
<br>
<br>
+static GHashTable*<br>
+virt_viewer_app_parse_monitor_mappings(gchar** mappings, gsize nmappings)<br>
+{<br>
+    gint nmonitors = gdk_screen_get_n_monitors(gdk_screen_get_default());<br>
+    GHashTable* displaymap = g_hash_table_new(g_direct_hash, g_direct_equal);<br></div></div></blockquote><div><br></div><div>I know the code has been in this way before, but once you're moving it, please, fix the coding style as well:</div>
<div>GHashTable *displaymap (...)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
+    GHashTable* monitormap = g_hash_table_new(g_direct_hash, g_direct_equal);<br></div></div></blockquote><div><br></div><div>Same here:</div><div>GHashTable *monitormap (...)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="h5">
+    int i = 0;<br>
+    gchar** tokens = NULL;<br></div></div></blockquote><div><br></div><div>Same here:</div><div>gchar **tokens (...)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="h5">
+<br>
+    for (i = 0; i < nmappings; i++) {<br>
+        gchar* endptr = NULL;<br></div></div></blockquote><div><br></div><div>Same here:</div><div>gchar *endptr (...)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="h5">
+        gint display = 0, monitor = 0;<br>
+<br>
+        tokens = g_strsplit(mappings[i], ":", 2);<br>
+        if (g_strv_length(tokens) != 2) {<br>
+            g_warning("Invalid monitor-mapping configuration: '%s'. Expected format is '<DISPLAY-ID>:<MONITOR-ID>'.  Got %lu elements", mappings[i], G_N_ELEMENTS(tokens));<br>
+            g_strfreev(tokens);<br>
+            goto configerror;<br>
+        }<br>
+<br>
+        display = strtol(tokens[0], &endptr, 10);<br>
+        if ((endptr && *endptr != '\0') || display < 1) {<br>
+            g_warning("Invalid monitor-mapping configuration: display id is invalid: %s %p='%s'", tokens[0], endptr, endptr);<br>
+            g_strfreev(tokens);<br>
+            goto configerror;<br>
+        }<br>
+        monitor = strtol(tokens[1], &endptr, 10);<br>
+        if ((endptr && *endptr != '\0') || monitor < 1) {<br>
+            g_warning("Invalid monitor-mapping configuration: monitor id '%s' is invalid", tokens[1]);<br>
+            g_strfreev(tokens);<br>
+            goto configerror;<br>
+        }<br>
+        g_strfreev(tokens);<br>
+<br>
+        if (monitor > nmonitors)<br>
+            g_warning("Initial monitor #%i for display #%i does not exist, skipping...", monitor, display);<br>
+        else {<br>
+            /* config file format is 1-based, not 0-based */<br>
+            display--;<br>
+            monitor--;<br>
+<br>
+            if (g_hash_table_lookup_extended(displaymap, GINT_TO_POINTER(display), NULL, NULL) ||<br>
+                g_hash_table_lookup_extended(monitormap, GINT_TO_POINTER(monitor), NULL, NULL)) {<br>
+                g_warning("Invalid monitor-mapping configuration: a display or monitor id was specified twice");<br>
+                goto configerror;<br>
+            }<br>
+            g_debug("Fullscreen config: mapping guest display %i to monitor %i", display, monitor);<br>
+            g_hash_table_insert(displaymap, GINT_TO_POINTER(display), GINT_TO_POINTER(monitor));<br>
+            g_hash_table_insert(monitormap, GINT_TO_POINTER(monitor), GINT_TO_POINTER(display));<br>
+        }<br>
+    }<br>
+<br>
+    g_hash_table_unref(monitormap);<br>
+    return displaymap;<br>
+<br>
+configerror:<br>
+    g_hash_table_unref(monitormap);<br>
+    g_hash_table_unref(displaymap);<br>
+    return NULL;<br>
+}<br>
+<br>
</div></div>+static GHashTable*<br>
+virt_viewer_app_get_monitor_mapping_for_section(VirtViewerApp* self, const gchar* section)<br></blockquote><div><br></div><div>Same here ...</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+{<br>
+    GError* error = NULL;<br>
<div class="">+    gsize nmappings = 0;<br>
+    gchar** mappings = NULL;<br>
+    GHashTable* mapping = NULL;<br></div></blockquote><div><br></div><div>Same here ...</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="">

</div><div class="">+<br>
+    mappings = g_key_file_get_string_list(self->priv->config,<br>
</div>+                                          section, "monitor-mapping", &nmappings, &error);<br>
<div class="">+    if (error) {<br>
+        if (error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND<br>
+            && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)<br>
</div>+            g_warning("Error reading monitor assignments for %s: %s", section, error->message);<br>
<div class="">+        g_clear_error(&error);<br>
+    } else {<br>
+        mapping = virt_viewer_app_parse_monitor_mappings(mappings, nmappings);<br>
</div>+    }<br>
+    g_strfreev(mappings);<br>
+<br>
+    return mapping;<br>
<div class="">+}<br>
+<br>
 static<br>
 void virt_viewer_app_set_uuid_string(VirtViewerApp* self, const gchar* uuid_string)<br>
 {<br>
-    GArray* mapping = NULL;<br>
</div>-    GError* error = NULL;<br>
<div class="">-    gsize ndisplays = 0;<br>
-    gint* displays = NULL;<br>
-    gint nmonitors = gdk_screen_get_n_monitors(gdk_screen_get_default());<br>
</div><div class="">+    GHashTable* mapping = NULL;<br></div></blockquote><div><br></div><div>Same here ...</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="">
<br>
     g_debug("%s: UUID changed to %s", G_STRFUNC, uuid_string);<br>
<br>
     g_free(self->priv->uuid);<br>
     self->priv->uuid = g_strdup(uuid_string);<br>
-    displays = g_key_file_get_integer_list(self->priv->config,<br>
-                                           uuid_string, "monitor-mapping", &ndisplays, &error);<br>
</div>-    if (error) {<br>
<div class="">-        if (error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND)<br>
</div>-            g_warning("Error reading monitor assignments: %s", error->message);<br>
-        g_clear_error(&error);<br>
-    } else {<br>
<div class="">-        int i = 0;<br>
-        mapping = g_array_sized_new(FALSE, FALSE, sizeof(displays[0]), ndisplays);<br>
-        // config file format is 1-based, not 0-based<br>
-        for (i = 0; i < ndisplays; i++) {<br>
-            gint val = displays[i] - 1;<br>
-<br>
-            // sanity check<br>
-            if (val >= nmonitors)<br>
-                g_warning("Initial monitor #%i for display #%i does not exist, skipping...", val, i);<br>
-            else<br>
-                g_array_append_val(mapping, val);<br>
</div>-        }<br>
-        g_free(displays);<br>
+    mapping = virt_viewer_app_get_monitor_mapping_for_section(self, uuid_string);<br>
+    if (!mapping) {<br>
+        g_debug("No guest-specific fullscreen config, using fallback");<br>
+        mapping = virt_viewer_app_get_monitor_mapping_for_section(self, "fallback");<br>
     }<br>
<br>
     if (self->priv->initial_display_map)<br>
<div class="">-        g_array_unref(self->priv->initial_display_map);<br>
+        g_hash_table_unref(self->priv->initial_display_map);<br>
<br>
     self->priv->initial_display_map = mapping;<br>
<br>
</div>@@ -1557,7 +1620,7 @@ virt_viewer_app_dispose (GObject *object)<br>
<div class="HOEnZb"><div class="h5">     g_free(priv->config_file);<br>
     priv->config_file = NULL;<br>
     g_clear_pointer(&priv->config, g_key_file_free);<br>
-    g_clear_pointer(&priv->initial_display_map, g_array_unref);<br>
+    g_clear_pointer(&priv->initial_display_map, g_hash_table_unref);<br>
<br>
     virt_viewer_app_free_connect_info(self);<br>
<br>
--<br>
1.9.3<br>
<br>
_______________________________________________<br>
virt-tools-list mailing list<br>
<a href="mailto:virt-tools-list@redhat.com">virt-tools-list@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/virt-tools-list" target="_blank">https://www.redhat.com/mailman/listinfo/virt-tools-list</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Fabiano Fidêncio</div>
</div></div>