[RFC/POC PATCH spice-gtk 07/16] Rework the handling of monitors_config

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The code relied on spice_main_channel_update_display() called from the
client application to create a list of monitor_configs to be sent to the
server (to enable/disable monitors and set resolution). One of the
disadvantages this approach has is that all data that you need in the
list have to go through the client application. Thus adding any
attribute to a monitor_config requires an API change.

This commit changes this by creating and maintaining our own list of
monitor_configs under the session object. The methods that are exposed
to the client app no longer create new items in this list (strictly
speaking, they never did, as the list was static and they only filled
them up with values and enabled/disabled the items, which also has it's
problems).

Now the spice_main_channel_update_display{,_enabled}() functions only
update existing items in the spice-gtk-maintained list. The identifier
for these functions was unfortunately the index in the array on the
spice-gtk side and channel_id + monitor_id in e.g. virt-viewer.
Presumably other clients can use whatever they like as the id, but since
the monitors sent in monitors_config on the main channel need to match
those received in monitors_config on the display channels, they probably
need to do basically the same. The code is making a lot of assumptions
here.

So, we make one more assumption that all clients use the channel_id +
monitor_id to pass to spice_main_channel_update_display{,_enabled}() as
the id argument and use that to look up the correct monitor_config.

Signed-off-by: Lukáš Hrázký <lhrazky@xxxxxxxxxx>
---
 spice-common             |   2 +-
 src/channel-display.c    |  23 ++++++-
 src/channel-main.c       | 139 ++++++++++++++++++++++++---------------
 src/channel-main.h       |   2 +-
 src/map-file             |   5 ++
 src/spice-glib-sym-file  |   5 ++
 src/spice-session-priv.h |   1 +
 src/spice-session.c      | 129 ++++++++++++++++++++++++++++++++++++
 src/spice-session.h      |  30 +++++++++
 9 files changed, 278 insertions(+), 58 deletions(-)

diff --git a/spice-common b/spice-common
index 8096b12..11aeda6 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit 8096b1206bb266b8d0b80b3e4c0d36fc621d772d
+Subproject commit 11aeda6b04628258f0cb604727f6f800710a2d9e
diff --git a/src/channel-display.c b/src/channel-display.c
index e0520a3..9e83e43 100644
--- a/src/channel-display.c
+++ b/src/channel-display.c
@@ -1051,8 +1051,10 @@ static void spice_display_channel_up(SpiceChannel *channel)
     out->marshallers->msgc_display_init(out->marshaller, &init);
     spice_msg_out_send_internal(out);
 
-    /* notify of existence of this monitor */
-    g_coroutine_object_notify(G_OBJECT(channel), "monitors");
+    // if we don't have MONITORS_CONFIG_CAPABILITY, notify of existence of this monitor
+    if (!spice_channel_test_capability(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
+        g_coroutine_object_notify(G_OBJECT(channel), "monitors");
+    }
 
     if (preferred_compression != SPICE_IMAGE_COMPRESSION_INVALID) {
         spice_display_channel_change_preferred_compression(channel, preferred_compression);
@@ -1868,6 +1870,7 @@ static void display_handle_surface_destroy(SpiceChannel *channel, SpiceMsgIn *in
 /* coroutine context */
 static void display_handle_monitors_config(SpiceChannel *channel, SpiceMsgIn *in)
 {
+    SpiceSession *session = spice_channel_get_session(channel);
     SpiceMsgDisplayMonitorsConfig *config = spice_msg_in_parsed(in);
     SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
     guint i;
@@ -1906,6 +1909,22 @@ static void display_handle_monitors_config(SpiceChannel *channel, SpiceMsgIn *in
         mc->y = head->y;
         mc->width = head->width;
         mc->height = head->height;
+
+        if (spice_session_find_monitor_config(session, channel->priv->channel_id, i)) {
+            spice_session_update_monitor_config(session, channel->priv->channel_id, i,
+                                                head->x, head->y, head->width, head->height);
+        } else {
+            spice_session_add_monitor_config(session, channel->priv->channel_id, i,
+                                             head->x, head->y, head->width, head->height);
+        }
+    }
+
+    // On top of the above, create disabled configs for all monitors up to max_allowed
+    // if they don't exist.
+    for (i = config->count; i < config->max_allowed; i++) {
+        if (!spice_session_find_monitor_config(session, channel->priv->channel_id, i)) {
+            spice_session_add_monitor_config(session, channel->priv->channel_id, i, 0, 0, 0, 0);
+        }
     }
 
     g_coroutine_object_notify(G_OBJECT(channel), "monitors");
diff --git a/src/channel-main.c b/src/channel-main.c
index 3d682d6..a35e9b9 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -55,20 +55,6 @@
 
 typedef struct spice_migrate spice_migrate;
 
-typedef enum {
-    DISPLAY_UNDEFINED,
-    DISPLAY_DISABLED,
-    DISPLAY_ENABLED,
-} SpiceDisplayState;
-
-typedef struct {
-    int                     x;
-    int                     y;
-    int                     width;
-    int                     height;
-    SpiceDisplayState       display_state;
-} SpiceDisplayConfig;
-
 typedef struct {
     GHashTable                 *xfer_task;
     SpiceMainChannel           *channel;
@@ -105,7 +91,6 @@ struct _SpiceMainChannelPrivate  {
     guint                       agent_msg_pos;
     uint8_t                     agent_msg_size;
     uint32_t                    agent_caps[VD_AGENT_CAPS_SIZE];
-    SpiceDisplayConfig          display[MAX_DISPLAY];
     gint                        timer_id;
     GQueue                      *agent_msg_queue;
     GHashTable                  *file_xfer_tasks;
@@ -1115,13 +1100,17 @@ gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
     c = channel->priv;
     g_return_val_if_fail(c->agent_connected, FALSE);
 
+    GArray *monitor_configs = spice_session_get_monitor_configs(
+        spice_channel_get_session(SPICE_CHANNEL(channel)));
+
     if (spice_main_channel_agent_test_capability(channel, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
-        monitors = SPICE_N_ELEMENTS(c->display);
+        monitors = monitor_configs->len;
     } else {
         monitors = 0;
-        for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
-            if (c->display[i].display_state == DISPLAY_ENABLED)
+        for (i = 0; i < monitor_configs->len; i++) {
+            if (g_array_index(monitor_configs, SpiceMonitorConfig, i).display_state == DISPLAY_ENABLED) {
                 monitors += 1;
+            }
         }
     }
 
@@ -1135,18 +1124,19 @@ gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
 
     CHANNEL_DEBUG(channel, "sending new monitors config to guest");
     j = 0;
-    for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
-        if (c->display[i].display_state != DISPLAY_ENABLED) {
+    for (i = 0; i < monitor_configs->len; i++) {
+        SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+        if (mc->display_state != DISPLAY_ENABLED) {
             if (spice_main_channel_agent_test_capability(channel,
                                                          VD_AGENT_CAP_SPARSE_MONITORS_CONFIG))
                 j++;
             continue;
         }
         mon->monitors[j].depth  = c->display_color_depth ? c->display_color_depth : 32;
-        mon->monitors[j].width  = c->display[i].width;
-        mon->monitors[j].height = c->display[i].height;
-        mon->monitors[j].x = c->display[i].x;
-        mon->monitors[j].y = c->display[i].y;
+        mon->monitors[j].width  = mc->width;
+        mon->monitors[j].height = mc->height;
+        mon->monitors[j].x = mc->x;
+        mon->monitors[j].y = mc->y;
         CHANNEL_DEBUG(channel, "monitor #%d: %ux%u+%d+%d @ %u bpp", j,
                       mon->monitors[j].width, mon->monitors[j].height,
                       mon->monitors[j].x, mon->monitors[j].y,
@@ -1481,15 +1471,18 @@ static void agent_clipboard_release(SpiceMainChannel *channel, guint selection)
 
 static gboolean any_display_has_dimensions(SpiceMainChannel *channel)
 {
-    SpiceMainChannelPrivate *c;
     guint i;
 
     g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
-    c = channel->priv;
 
-    for (i = 0; i < MAX_DISPLAY; i++) {
-        if (c->display[i].width > 0 && c->display[i].height > 0)
+    GArray *monitor_configs = spice_session_get_monitor_configs(
+        spice_channel_get_session(SPICE_CHANNEL(channel)));
+
+    for (i = 0; i < monitor_configs->len; i++) {
+        SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+        if (mc->width > 0 && mc->height > 0) {
             return TRUE;
+        }
     }
 
     return FALSE;
@@ -1513,12 +1506,19 @@ static gboolean timer_set_display(gpointer data)
     }
 
     session = spice_channel_get_session(SPICE_CHANNEL(channel));
+    GArray *monitor_configs = spice_session_get_monitor_configs(session);
 
     if (!spice_main_channel_agent_test_capability(channel, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
         /* ensure we have an explicit monitor configuration at least for
            number of display channels */
-        for (i = 0; i < spice_session_get_n_display_channels(session); i++)
-            if (c->display[i].display_state == DISPLAY_UNDEFINED) {
+
+        guint n_display_channels = spice_session_get_n_display_channels(session);
+        if (n_display_channels < monitor_configs->len) {
+            SPICE_DEBUG("Not sending monitors config, missing monitors");
+            return FALSE;
+        }
+        for (i = 0; i < n_display_channels; i++)
+            if (g_array_index(monitor_configs, SpiceMonitorConfig, i).display_state == DISPLAY_UNDEFINED) {
                 SPICE_DEBUG("Not sending monitors config, missing monitors");
                 return FALSE;
             }
@@ -2630,7 +2630,7 @@ gboolean spice_main_channel_agent_test_capability(SpiceMainChannel *channel, gui
 /**
  * spice_main_update_display:
  * @channel: a #SpiceMainChannel
- * @id: display ID
+ * @id: the display ID - assumed to be channel_id + monitor_id or equivalent
  * @x: x position
  * @y: y position
  * @width: display width
@@ -2656,7 +2656,7 @@ void spice_main_update_display(SpiceMainChannel *channel, int id,
 /**
  * spice_main_channel_update_display:
  * @channel: a #SpiceMainChannel
- * @id: display ID
+ * @id: the display ID - assumed to be channel_id + monitor_id or equivalent
  * @x: x position
  * @y: y position
  * @width: display width
@@ -2675,8 +2675,6 @@ void spice_main_update_display(SpiceMainChannel *channel, int id,
 void spice_main_channel_update_display(SpiceMainChannel *channel, int id, int x, int y, int width,
                                int height, gboolean update)
 {
-    SpiceMainChannelPrivate *c;
-
     g_return_if_fail(channel != NULL);
     g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
     g_return_if_fail(x >= 0);
@@ -2684,19 +2682,32 @@ void spice_main_channel_update_display(SpiceMainChannel *channel, int id, int x,
     g_return_if_fail(width >= 0);
     g_return_if_fail(height >= 0);
 
-    c = SPICE_MAIN_CHANNEL(channel)->priv;
-
-    g_return_if_fail(id < SPICE_N_ELEMENTS(c->display));
+    GArray *monitor_configs = spice_session_get_monitor_configs(
+        spice_channel_get_session(SPICE_CHANNEL(channel)));
 
-    SpiceDisplayConfig display = {
-        .x = x, .y = y, .width = width, .height = height,
-        .display_state = c->display[id].display_state
-    };
+    int found = 0;
+    SpiceMonitorConfig *mc = NULL;
+    for (size_t i = 0; i < monitor_configs->len; ++i) {
+        mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+        if ((mc->channel_id + mc->monitor_id) == id) {
+            found = 1;
+            break;
+        }
+    }
 
-    if (memcmp(&display, &c->display[id], sizeof(SpiceDisplayConfig)) == 0)
+    if (!found) {
+        g_warning("Display ID %d not found while trying to update the display (monitor config).", id);
         return;
+    }
 
-    c->display[id] = display;
+    CHANNEL_DEBUG(channel,
+        "Update display (monitor config) id: %d (channel_id: %u, monitor_id: %u), +%d+%d-%dx%d",
+        id, mc->channel_id, mc->monitor_id, x, y, width, height);
+
+    mc->x = x;
+    mc->y = y;
+    mc->width = width;
+    mc->height = height;
 
     if (update)
         update_display_timer(channel, 1);
@@ -2705,7 +2716,7 @@ void spice_main_channel_update_display(SpiceMainChannel *channel, int id, int x,
 /**
  * spice_main_set_display:
  * @channel: a #SpiceMainChannel
- * @id: display ID
+ * @id: the display ID - assumed to be channel_id + monitor_id or equivalent
  * @x: x position
  * @y: y position
  * @width: display width
@@ -2947,7 +2958,7 @@ void spice_main_channel_clipboard_selection_request(SpiceMainChannel *channel, g
 /**
  * spice_main_update_display_enabled:
  * @channel: a #SpiceMainChannel
- * @id: display ID (if -1: set all displays)
+ * @id: the display ID - assumed to be channel_id + monitor_id or equivalent, -1 to update all
  * @enabled: wether display @id is enabled
  * @update: if %TRUE, update guest display state after 1sec.
  *
@@ -2972,7 +2983,7 @@ void spice_main_update_display_enabled(SpiceMainChannel *channel, int id, gboole
 /**
  * spice_main_channel_update_display_enabled:
  * @channel: a #SpiceMainChannel
- * @id: display ID (if -1: set all displays)
+ * @id: the display ID - assumed to be channel_id + monitor_id or equivalent, -1 to update all
  * @enabled: wether display @id is enabled
  * @update: if %TRUE, update guest display state after 1sec.
  *
@@ -2990,23 +3001,43 @@ void spice_main_update_display_enabled(SpiceMainChannel *channel, int id, gboole
 void spice_main_channel_update_display_enabled(SpiceMainChannel *channel, int id, gboolean enabled,
                                                gboolean update)
 {
-    SpiceDisplayState display_state = enabled ? DISPLAY_ENABLED : DISPLAY_DISABLED;
     g_return_if_fail(channel != NULL);
     g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
     g_return_if_fail(id >= -1);
 
-    SpiceMainChannelPrivate *c = channel->priv;
+    GArray *monitor_configs = spice_session_get_monitor_configs(
+        spice_channel_get_session(SPICE_CHANNEL(channel)));
+
+    SpiceDisplayState display_state = enabled ? DISPLAY_ENABLED : DISPLAY_DISABLED;
 
     if (id == -1) {
+        SPICE_DEBUG("Updating all monitor configs' state to %s", enabled ? "enabled" : "disabled");
+
         gint i;
-        for (i = 0; i < G_N_ELEMENTS(c->display); i++) {
-            c->display[i].display_state = display_state;
+        for (i = 0; i < monitor_configs->len; i++) {
+            g_array_index(monitor_configs, SpiceMonitorConfig, i).display_state = display_state;
         }
     } else {
-        g_return_if_fail(id < G_N_ELEMENTS(c->display));
-        if (c->display[id].display_state == display_state)
+        int found = 0;
+        SpiceMonitorConfig *mc = NULL;
+        for (size_t i = 0; i < monitor_configs->len; ++i) {
+            mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+            if ((mc->channel_id + mc->monitor_id) == id) {
+                found = 1;
+                break;
+            }
+        }
+
+        if (!found) {
+            g_warning("Display ID %d not found while trying to %s the display (monitor config).",
+                      id, enabled ? "enable" : "disable");
             return;
-        c->display[id].display_state = display_state;
+        }
+
+        SPICE_DEBUG("Updating monitor config id: %d (channel_id: %u, monitor_id: %u) state to %s",
+                    id, mc->channel_id, mc->monitor_id, enabled ? "enabled" : "disabled");
+
+        mc->display_state = display_state;
     }
 
     if (update)
@@ -3016,7 +3047,7 @@ void spice_main_channel_update_display_enabled(SpiceMainChannel *channel, int id
 /**
  * spice_main_set_display_enabled:
  * @channel: a #SpiceMainChannel
- * @id: display ID (if -1: set all displays)
+ * @id: the display ID - assumed to be channel_id + monitor_id or equivalent, -1 to update all
  * @enabled: wether display @id is enabled
  *
  * When sending monitor configuration to agent guest, don't set
diff --git a/src/channel-main.h b/src/channel-main.h
index 530378d..bbc2fea 100644
--- a/src/channel-main.h
+++ b/src/channel-main.h
@@ -112,7 +112,7 @@ G_DEPRECATED_FOR(spice_main_channel_clipboard_selection_request)
 void spice_main_clipboard_request(SpiceMainChannel *channel, guint32 type);
 
 G_DEPRECATED_FOR(spice_main_channel_update_display)
-void spice_main_set_display(SpiceMainChannel *channel, int id,int x, int y, int width, int height);
+void spice_main_set_display(SpiceMainChannel *channel, int id, int x, int y, int width, int height);
 G_DEPRECATED_FOR(spice_main_update_display)
 void spice_main_update_display(SpiceMainChannel *channel, int id, int x, int y, int width,
                                int height, gboolean update);
diff --git a/src/map-file b/src/map-file
index cdb81c3..72ee2f3 100644
--- a/src/map-file
+++ b/src/map-file
@@ -120,9 +120,13 @@ spice_port_write_finish;
 spice_record_channel_get_type;
 spice_record_channel_send_data;
 spice_record_send_data;
+spice_session_add_monitor_config;
 spice_session_connect;
 spice_session_disconnect;
+spice_display_state_get_type;
+spice_session_find_monitor_config;
 spice_session_get_channels;
+spice_session_get_monitor_configs;
 spice_session_get_proxy_uri;
 spice_session_get_read_only;
 spice_session_get_type;
@@ -131,6 +135,7 @@ spice_session_is_for_migration;
 spice_session_migration_get_type;
 spice_session_new;
 spice_session_open_fd;
+spice_session_update_monitor_config;
 spice_session_verify_get_type;
 spice_set_session_option;
 spice_smartcard_channel_get_type;
diff --git a/src/spice-glib-sym-file b/src/spice-glib-sym-file
index b19844c..c186624 100644
--- a/src/spice-glib-sym-file
+++ b/src/spice-glib-sym-file
@@ -99,9 +99,13 @@ spice_port_write_finish
 spice_record_channel_get_type
 spice_record_channel_send_data
 spice_record_send_data
+spice_session_add_monitor_config
 spice_session_connect
 spice_session_disconnect
+spice_display_state_get_type
+spice_session_find_monitor_config
 spice_session_get_channels
+spice_session_get_monitor_configs
 spice_session_get_proxy_uri
 spice_session_get_read_only
 spice_session_get_type
@@ -110,6 +114,7 @@ spice_session_is_for_migration
 spice_session_migration_get_type
 spice_session_new
 spice_session_open_fd
+spice_session_update_monitor_config
 spice_session_verify_get_type
 spice_set_session_option
 spice_smartcard_channel_get_type
diff --git a/src/spice-session-priv.h b/src/spice-session-priv.h
index 03005aa..12b0764 100644
--- a/src/spice-session-priv.h
+++ b/src/spice-session-priv.h
@@ -100,6 +100,7 @@ void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel
 gboolean spice_session_set_migration_session(SpiceSession *session, SpiceSession *mig_session);
 SpiceAudio *spice_audio_get(SpiceSession *session, GMainContext *context);
 const gchar* spice_audio_data_mode_to_string(gint mode);
+
 G_END_DECLS
 
 #endif /* __SPICE_CLIENT_SESSION_PRIV_H__ */
diff --git a/src/spice-session.c b/src/spice-session.c
index 57acc63..c170110 100644
--- a/src/spice-session.c
+++ b/src/spice-session.c
@@ -90,6 +90,14 @@ struct _SpiceSessionPrivate {
     GStrv             secure_channels;
     gint              color_depth;
 
+    /* A list of monitor configs for all channels and monitors. It is filled up
+     * as display channels are created from their monitors_config messages. The
+     * client application then updates these through
+     * spice_main_channel_update_display{,_enabled} to enable/disable them and
+     * set the resolution.
+     */
+    GArray            *monitor_configs;
+
     int               connection_id;
     int               protocol;
     SpiceChannel      *cmain; /* weak reference */
@@ -294,6 +302,8 @@ static void spice_session_init(SpiceSession *session)
     s->glz_window = glz_decoder_window_new();
     update_proxy(session, NULL);
 
+    s->monitor_configs = g_array_new(FALSE, TRUE, sizeof(SpiceMonitorConfig));
+
     s->usb_manager = spice_usb_device_manager_get(session, &err);
     if (err != NULL) {
         SPICE_DEBUG("Could not initialize SpiceUsbDeviceManager - %s", err->message);
@@ -349,6 +359,8 @@ spice_session_dispose(GObject *gobject)
     g_clear_object(&s->proxy);
     g_clear_object(&s->webdav);
 
+    g_array_free(s->monitor_configs, TRUE);
+
     /* Chain up to the parent class */
     if (G_OBJECT_CLASS(spice_session_parent_class)->dispose)
         G_OBJECT_CLASS(spice_session_parent_class)->dispose(gobject);
@@ -2800,6 +2812,123 @@ gboolean spice_session_is_for_migration(SpiceSession *session)
     return session->priv->for_migration;
 }
 
+/**
+ * spice_session_get_monitor_configs:
+ * @session: a #SpiceSession
+ *
+ * Returns: a pointer to the array of SpiceMonitorConfigs
+ * Since: 0.36
+ **/
+GArray *spice_session_get_monitor_configs(SpiceSession *session)
+{
+    g_assert(session != NULL);
+
+    return session->priv->monitor_configs;
+}
+
+/**
+ * spice_session_find_monitor_config:
+ * @session: a #SpiceSession
+ * @channel_id: a channel ID
+ * @monitor_id: a monitor ID
+ *
+ * Looks up a monitor config which has the channel_id and monitor_id equal to
+ * those specified in aruments.
+ *
+ * Returns: a pointer to SpiceMonitorConfig if found, %NULL otherwise
+ * Since: 0.36
+ **/
+SpiceMonitorConfig *spice_session_find_monitor_config(SpiceSession *session,
+                                                      uint32_t channel_id,
+                                                      uint32_t monitor_id)
+{
+    GArray *monitor_configs = spice_session_get_monitor_configs(session);
+    g_assert(monitor_configs != NULL);
+
+    for (size_t i = 0; i < monitor_configs->len; ++i) {
+        SpiceMonitorConfig *d = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+        if (d->channel_id == channel_id && d->monitor_id == monitor_id) {
+            return d;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * spice_session_add_monitor_config:
+ * @session: a #SpiceSession
+ * @channel_id: a channel ID
+ * @monitor_id: a monitor ID
+ * @x: X coordinate of the monitor
+ * @y: Y coordinate of the monitor
+ * @width: width of the monitor
+ * @height: height of the monitor
+ *
+ * Appends a new #SpiceMonitorConfig to the end of monitor_configs array under
+ * the session and sets its attributes to those specified in arguments.
+ *
+ * Since: 0.36
+ **/
+void spice_session_add_monitor_config(SpiceSession *session, uint32_t channel_id, uint32_t monitor_id,
+                                      int x, int y, int width, int height)
+{
+    GArray *monitor_configs = spice_session_get_monitor_configs(session);
+    g_assert(monitor_configs != NULL);
+
+    g_return_if_fail(x >= 0);
+    g_return_if_fail(y >= 0);
+    g_return_if_fail(width >= 0);
+    g_return_if_fail(height >= 0);
+
+    SpiceMonitorConfig mc = {
+        .channel_id = channel_id,
+        .monitor_id = monitor_id,
+        .x = x,
+        .y = y,
+        .width = width,
+        .height = height,
+        .display_state = DISPLAY_DISABLED
+    };
+
+    SPICE_DEBUG("Adding new monitor_config idx=%u +%d+%d:%dx%d",
+                monitor_configs->len, x, y, width, height);
+
+    g_array_append_val(monitor_configs, mc);
+}
+
+/**
+ * spice_session_update_monitor_config:
+ * @session: a #SpiceSession
+ * @channel_id: a channel ID
+ * @monitor_id: a monitor ID
+ * @x: X coordinate of the monitor
+ * @y: Y coordinate of the monitor
+ * @width: width of the monitor
+ * @height: height of the monitor
+ *
+ * Looks up #SpiceMonitorConfig with channel_id and monitor_id equal to those
+ * in arguments in the session's monitor_configs array and sets its x, y, width
+ * and height to those specified in arguments.
+ *
+ * Since: 0.36
+ **/
+void spice_session_update_monitor_config(SpiceSession *session, uint32_t  channel_id, uint32_t monitor_id,
+                                         int x, int y, int width, int height)
+{
+    SpiceMonitorConfig *mc = spice_session_find_monitor_config(session, channel_id, monitor_id);
+
+    g_return_if_fail(mc != NULL);
+
+    SPICE_DEBUG("Updating monitor config channel_id: %u, monitor_id: %u, +%d+%d-%dx%d",
+                channel_id, monitor_id, x, y, width, height);
+
+    mc->x = x;
+    mc->y = y;
+    mc->width = width;
+    mc->height = height;
+}
+
 G_GNUC_INTERNAL
 void spice_session_set_main_channel(SpiceSession *session, SpiceChannel *channel)
 {
diff --git a/src/spice-session.h b/src/spice-session.h
index cfe02b1..6d97ab2 100644
--- a/src/spice-session.h
+++ b/src/spice-session.h
@@ -23,6 +23,8 @@
 #endif
 
 #include <glib-object.h>
+#include <stdint.h>
+
 #include "spice-types.h"
 #include "spice-uri.h"
 #include "spice-glib-enums.h"
@@ -103,6 +105,22 @@ struct _SpiceSessionClass
     gchar _spice_reserved[SPICE_RESERVED_PADDING];
 };
 
+typedef enum {
+    DISPLAY_UNDEFINED,
+    DISPLAY_DISABLED,
+    DISPLAY_ENABLED,
+} SpiceDisplayState;
+
+typedef struct {
+    uint32_t                channel_id;
+    uint32_t                monitor_id;
+    int                     x;
+    int                     y;
+    int                     width;
+    int                     height;
+    SpiceDisplayState       display_state;
+} SpiceMonitorConfig;
+
 GType spice_session_get_type(void);
 
 SpiceSession *spice_session_new(void);
@@ -115,6 +133,18 @@ gboolean spice_session_get_read_only(SpiceSession *session);
 SpiceURI *spice_session_get_proxy_uri(SpiceSession *session);
 gboolean spice_session_is_for_migration(SpiceSession *session);
 
+GArray *spice_session_get_monitor_configs(SpiceSession *session);
+
+SpiceMonitorConfig *spice_session_find_monitor_config(SpiceSession *session,
+                                                      uint32_t channel_id,
+                                                      uint32_t monitor_id);
+
+void spice_session_add_monitor_config(SpiceSession *session, uint32_t channel_id, uint32_t display_id,
+                                      int x, int y, int width, int height);
+
+void spice_session_update_monitor_config(SpiceSession *session, uint32_t  channel_id, uint32_t monitor_id,
+                                         int x, int y, int width, int height);
+
 G_END_DECLS
 
 #endif /* __SPICE_CLIENT_SESSION_H__ */
-- 
2.17.1

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux Virtualization]     [Linux Virtualization]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]