[Spice-devel] [RFC PATCH spice-gtk v2 17/20] Send SpiceMsgcMainMonitorsConfig instead of VDAgentMonitorsConfig
Lukáš Hrázký
lhrazky at redhat.com
Thu Aug 16 16:26:46 UTC 2018
TODO This patch does not use a capability to send the old version of the
monitors config message (the VDAgentMonitorsConfig one) in case of an
old server.
Sends the SpiceMsgcMainMonitorsConfig as the monitors_config message,
which contains the unique (channel_id, monitor_id) identification pair
to identify the monitors_configs with. The message is meant for the
server only, which needs to translate the ID pair to a guest_output_id
in case it needs to send the monitors_config to the vd_agent.
Signed-off-by: Lukáš Hrázký <lhrazky at redhat.com>
---
src/channel-main.c | 183 +++++++++++++++++++++++++++++----------
subprojects/spice-common | 2 +-
2 files changed, 137 insertions(+), 48 deletions(-)
diff --git a/src/channel-main.c b/src/channel-main.c
index 44137b9..cff9595 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -1054,6 +1054,53 @@ static void monitors_align(VDAgentMonConfig *monitors, int nmonitors)
g_free(sorted_monitors);
}
+static int monitors_cmp_smh(const void *p1, const void *p2, gpointer user_data)
+{
+ const SpiceMainHead *m1 = p1;
+ const SpiceMainHead *m2 = p2;
+ double d1 = sqrt(m1->x * m1->x + m1->y * m1->y);
+ double d2 = sqrt(m2->x * m2->x + m2->y * m2->y);
+ int diff = d1 - d2;
+
+ return diff == 0 ? (char*)p1 - (char*)p2 : diff;
+}
+
+static void monitors_align_smh(SpiceMainHead *monitors, int nmonitors)
+{
+ gint i, j, x = 0;
+ guint32 used = 0;
+ SpiceMainHead *sorted_monitors;
+
+ if (nmonitors == 0)
+ return;
+
+ /* sort by distance from origin */
+ sorted_monitors = g_memdup(monitors, nmonitors * sizeof(SpiceMainHead));
+ g_qsort_with_data(sorted_monitors, nmonitors, sizeof(SpiceMainHead), monitors_cmp_smh, NULL);
+
+ /* super-KISS ltr alignment, feel free to improve */
+ for (i = 0; i < nmonitors; i++) {
+ /* Find where this monitor is in the sorted order */
+ for (j = 0; j < nmonitors; j++) {
+ /* Avoid using the same entry twice, this happens with older
+ virt-viewer versions which always set x and y to 0 */
+ if (used & (1 << j))
+ continue;
+ if (memcmp(&monitors[j], &sorted_monitors[i],
+ sizeof(SpiceMainHead)) == 0)
+ break;
+ }
+ used |= 1 << j;
+ monitors[j].x = x;
+ monitors[j].y = 0;
+ x += monitors[j].width;
+ if (monitors[j].width || monitors[j].height)
+ SPICE_DEBUG("#%d +%u+%u-%ux%u", j, monitors[j].x, monitors[j].y,
+ monitors[j].width, monitors[j].height);
+ }
+ g_free(sorted_monitors);
+}
+
#define agent_msg_queue(Channel, Type, Size, Data) \
agent_msg_queue_many((Channel), (Type), (Data), (Size), NULL)
@@ -1087,69 +1134,111 @@ gboolean spice_main_send_monitor_config(SpiceMainChannel *channel)
**/
gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
{
- SpiceMainChannelPrivate *c;
- VDAgentMonitorsConfig *mon;
- int i, j, monitors;
- size_t size;
-
g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
- c = channel->priv;
+
+ SpiceMainChannelPrivate *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 = monitor_configs->len;
- } else {
- monitors = 0;
+ if (false /* TODO add capability for the old version of the message in this if branch */) {
+ VDAgentMonitorsConfig *mon;
+ int i, j, monitors;
+ size_t size;
+
+ if (spice_main_channel_agent_test_capability(channel, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
+ monitors = monitor_configs->len;
+ } else {
+ monitors = 0;
+ for (i = 0; i < monitor_configs->len; i++) {
+ if (g_array_index(monitor_configs, SpiceMonitorConfig, i).enabled) {
+ monitors += 1;
+ }
+ }
+ }
+
+ size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) * monitors;
+ mon = g_malloc0(size);
+
+ mon->num_of_monitors = monitors;
+ if (c->disable_display_position == FALSE ||
+ c->disable_display_align == FALSE)
+ mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+
+ CHANNEL_DEBUG(channel, "Sending new monitors config to the vd_agent:");
+ j = 0;
for (i = 0; i < monitor_configs->len; i++) {
- if (g_array_index(monitor_configs, SpiceMonitorConfig, i).enabled) {
- monitors += 1;
+ SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+ if (!mc->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 = 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,
+ mon->monitors[j].depth);
+ j++;
}
- }
- size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) * monitors;
- mon = g_malloc0(size);
+ if (c->disable_display_align == FALSE)
+ monitors_align(mon->monitors, mon->num_of_monitors);
- mon->num_of_monitors = monitors;
- if (c->disable_display_position == FALSE ||
- c->disable_display_align == FALSE)
- mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+ agent_msg_queue(channel, VD_AGENT_MONITORS_CONFIG, size, mon);
+ g_free(mon);
- CHANNEL_DEBUG(channel, "sending new monitors config to guest");
- j = 0;
- for (i = 0; i < monitor_configs->len; i++) {
- SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
- if (!mc->enabled) {
- if (spice_main_channel_agent_test_capability(channel,
- VD_AGENT_CAP_SPARSE_MONITORS_CONFIG))
- j++;
- continue;
+ spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
+ if (c->timer_id != 0) {
+ g_source_remove(c->timer_id);
+ c->timer_id = 0;
}
- mon->monitors[j].depth = c->display_color_depth ? c->display_color_depth : 32;
- 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,
- mon->monitors[j].depth);
- j++;
- }
+ } else {
+ size_t size = sizeof(SpiceMsgcMainMonitorsConfig) + sizeof(SpiceMainHead) * monitor_configs->len;
+ SpiceMsgcMainMonitorsConfig *msg = g_malloc0(size);
- if (c->disable_display_align == FALSE)
- monitors_align(mon->monitors, mon->num_of_monitors);
+ msg->count = monitor_configs->len;
- agent_msg_queue(channel, VD_AGENT_MONITORS_CONFIG, size, mon);
- g_free(mon);
+ if (c->disable_display_position == FALSE ||
+ c->disable_display_align == FALSE) {
+ msg->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+ }
- spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
- if (c->timer_id != 0) {
- g_source_remove(c->timer_id);
- c->timer_id = 0;
+ CHANNEL_DEBUG(channel, "Sending new monitors config to the server:");
+
+ for (size_t i = 0; i < monitor_configs->len; i++) {
+ SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+
+ msg->heads[i].channel_id = mc->channel_id;
+ msg->heads[i].monitor_id = mc->monitor_id;
+ msg->heads[i].depth = c->display_color_depth ? c->display_color_depth : 32;
+ msg->heads[i].width = mc->width;
+ msg->heads[i].height = mc->height;
+ msg->heads[i].x = mc->x;
+ msg->heads[i].y = mc->y;
+
+ CHANNEL_DEBUG(channel, " monitor channel_id %u, monitor_id %u: %ux%u+%u+%u @ %u bpp",
+ msg->heads[i].channel_id, msg->heads[i].monitor_id,
+ msg->heads[i].width, msg->heads[i].height,
+ msg->heads[i].x, msg->heads[i].y,
+ msg->heads[i].depth);
+ }
+
+ if (c->disable_display_align == FALSE) {
+ monitors_align_smh(msg->heads, msg->count);
+ }
+
+ SpiceMsgOut *out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_MONITORS_CONFIG);
+ out->marshallers->msgc_main_monitors_config(out->marshaller, msg);
+ spice_msg_out_send(out);
+
+ g_free(msg);
}
return TRUE;
diff --git a/subprojects/spice-common b/subprojects/spice-common
index f82a6c5..0af835f 160000
--- a/subprojects/spice-common
+++ b/subprojects/spice-common
@@ -1 +1 @@
-Subproject commit f82a6c5349a9a71485910bd3a57fe588c49d74f8
+Subproject commit 0af835f10e4dd51773dbeeb784fda4364b745874
--
2.18.0
More information about the Spice-devel
mailing list