A hash table of (channel_id, monitor_id) -> (guest_output_id) that is meant to store the guest_output_ids of the streamed channels' monitors. Signed-off-by: Lukáš Hrázký <lhrazky@xxxxxxxxxx> --- server/reds-private.h | 6 +++++ server/reds.c | 61 +++++++++++++++++++++++++++++++++++++++++++ server/reds.h | 5 ++++ 3 files changed, 72 insertions(+) diff --git a/server/reds-private.h b/server/reds-private.h index 920edc5c..a4828fec 100644 --- a/server/reds-private.h +++ b/server/reds-private.h @@ -123,6 +123,12 @@ struct RedsState { * client, being passed to the guest */ SpiceBuffer client_monitors_config; + /* A map of (channel_id, monitor_id) -> guest_output_id. (channel_id, + * monitor_id) is a unique identifier of a monitor. However, that ID has no + * meaning in the guest context. for cases the guest monitor ID (called + * output ID) is available, it is stored in this hash table. + */ + GHashTable *monitors_guest_output_id; int mm_time_enabled; uint32_t mm_time_latency; diff --git a/server/reds.c b/server/reds.c index 85043a88..d4356807 100644 --- a/server/reds.c +++ b/server/reds.c @@ -262,6 +262,11 @@ typedef struct __attribute__ ((__packed__)) VDInternalBuf { u; } VDInternalBuf; +typedef struct MonitorKey { + uint32_t channel_id; + uint32_t monitor_id; +} MonitorKey; + SPICE_DECLARE_TYPE(RedCharDeviceVDIPort, red_char_device_vdi_port, CHAR_DEVICE_VDIPORT); #define RED_TYPE_CHAR_DEVICE_VDIPORT red_char_device_vdi_port_get_type() @@ -621,6 +626,36 @@ bool reds_config_get_playback_compression(RedsState *reds) return reds->config->playback_compression; } +void reds_store_monitor_guest_output_id(RedsState *reds, uint32_t channel_id, + uint32_t monitor_id, uint32_t guest_output_id) +{ + MonitorKey *key = g_malloc(sizeof(MonitorKey)); + + key->channel_id = channel_id; + key->monitor_id = monitor_id; + + g_hash_table_insert(reds->monitors_guest_output_id, key, GUINT_TO_POINTER(guest_output_id)); +} + +bool reds_get_monitor_guest_output_id(RedsState *reds, uint32_t channel_id, + uint32_t monitor_id, uint32_t *guest_output_id) +{ + MonitorKey key = { + .channel_id = channel_id, + .monitor_id = monitor_id + }; + + gpointer value; + gboolean has_key = g_hash_table_lookup_extended(reds->monitors_guest_output_id, &key, NULL, &value); + + if (!has_key) { + return FALSE; + } + + *guest_output_id = GPOINTER_TO_INT(value); + return TRUE; +} + SpiceMouseMode reds_get_mouse_mode(RedsState *reds) { return reds->mouse_mode; @@ -3354,6 +3389,24 @@ SPICE_GNUC_VISIBLE int spice_server_remove_interface(SpiceBaseInstance *sin) return 0; } +static guint monitor_key_hash(gconstpointer key) +{ + const MonitorKey *monitor_key = (const MonitorKey*) key; + return g_int_hash(&monitor_key->channel_id) ^ g_int_hash(&monitor_key->monitor_id); +} + +static gboolean monitor_key_equal(gconstpointer a, gconstpointer b) +{ + const MonitorKey *mka = (const MonitorKey*) a; + const MonitorKey *mkb = (const MonitorKey*) b; + return mka->channel_id == mkb->channel_id && mka->monitor_id == mkb->monitor_id; +} + +static void monitor_key_destroy(gpointer key) +{ + g_free(key); +} + static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface) { spice_debug("starting %s", VERSION); @@ -3404,6 +3457,11 @@ static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface) spice_buffer_free(&reds->client_monitors_config); + reds->monitors_guest_output_id = g_hash_table_new_full(&monitor_key_hash, + &monitor_key_equal, + &monitor_key_destroy, + NULL); + reds->allow_multiple_clients = getenv(SPICE_DEBUG_ALLOW_MC_ENV) != NULL; if (reds->allow_multiple_clients) { spice_warning("spice: allowing multiple client connections"); @@ -3697,6 +3755,9 @@ SPICE_GNUC_VISIBLE void spice_server_destroy(SpiceServer *reds) reds->channels = NULL; spice_buffer_free(&reds->client_monitors_config); + + g_hash_table_destroy(reds->monitors_guest_output_id); + red_record_unref(reds->record); reds_cleanup(reds); #ifdef RED_STATISTICS diff --git a/server/reds.h b/server/reds.h index 9f17a5ec..1f10c4b3 100644 --- a/server/reds.h +++ b/server/reds.h @@ -50,6 +50,11 @@ gboolean reds_config_get_agent_mouse(const RedsState *reds); // used by inputs_c int reds_has_vdagent(RedsState *reds); // used by inputs channel bool reds_config_get_playback_compression(RedsState *reds); // used by playback channel +void reds_store_monitor_guest_output_id(RedsState *reds, uint32_t channel_id, + uint32_t monitor_id, uint32_t guest_output_id); +bool reds_get_monitor_guest_output_id(RedsState *reds, uint32_t channel_id, + uint32_t monitor_id, uint32_t *guest_output_id); + void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState *mouse_state); // used by inputs_channel GArray* reds_get_renderers(RedsState *reds); -- 2.18.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel