> > This patch causes my v0.30-9-g17a6b8a vintage spice-gtk client stop > having a cursor in an Xspice session. > > The spice-html5 client cursor continues to work fine. > > I've bisected it, but not really explored further; if there are > easy/obvious things for me to check, let me know. > > Cheers, > > Jeremy > Hi Jeremy, do you have some logs? Hope they can shed some light. Frediano > On 11/02/2015 03:56 AM, Frediano Ziglio wrote: > > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > > > --- > > server/cursor-channel.c | 24 +++++++++++- > > server/cursor-channel.h | 18 ++------- > > server/red_channel.c | 12 ++++++ > > server/red_channel.h | 6 +++ > > server/red_worker.c | 98 > > ++++++++++++++++++++++--------------------------- > > server/red_worker.h | 5 +++ > > 6 files changed, 92 insertions(+), 71 deletions(-) > > > > diff --git a/server/cursor-channel.c b/server/cursor-channel.c > > index 6a1fcea..3ae7756 100644 > > --- a/server/cursor-channel.c > > +++ b/server/cursor-channel.c > > @@ -19,6 +19,21 @@ > > #include "common/generated_server_marshallers.h" > > #include "cursor-channel.h" > > > > +struct CursorChannel { > > + CommonChannel common; // Must be the first thing > > + > > + CursorItem *item; > > + int cursor_visible; > > + SpicePoint16 cursor_position; > > + uint16_t cursor_trail_length; > > + uint16_t cursor_trail_frequency; > > + uint32_t mouse_mode; > > + > > +#ifdef RED_STATISTICS > > + StatNodeRef stat; > > +#endif > > +}; > > + > > #define RCC_TO_CCC(rcc) SPICE_CONTAINEROF((rcc), CursorChannelClient, > > common.base) > > > > #define CLIENT_CURSOR_CACHE > > @@ -372,7 +387,7 @@ CursorChannel* cursor_channel_new(RedWorker *worker) > > }; > > > > spice_info("create cursor channel"); > > - channel = red_worker_new_channel(worker, sizeof(CursorChannel), > > + channel = red_worker_new_channel(worker, sizeof(CursorChannel), > > "cursor_channel", > > SPICE_CHANNEL_CURSOR, 0, > > &cbs, > > red_channel_client_handle_message); > > > > @@ -480,3 +495,10 @@ void cursor_channel_reset(CursorChannel *cursor) > > } > > } > > } > > + > > +void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode) > > +{ > > + spice_return_if_fail(cursor); > > + > > + cursor->mouse_mode = mode; > > +} > > diff --git a/server/cursor-channel.h b/server/cursor-channel.h > > index 1639cf9..d5e5b13 100644 > > --- a/server/cursor-channel.h > > +++ b/server/cursor-channel.h > > @@ -38,6 +38,8 @@ enum { > > PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE, > > }; > > > > +typedef struct CursorChannel CursorChannel; > > + > > typedef struct CursorItem { > > QXLInstance *qxl; > > uint32_t group_id; > > @@ -67,21 +69,6 @@ typedef struct CursorChannelClient { > > uint32_t cursor_cache_items; > > } CursorChannelClient; > > > > -typedef struct CursorChannel { > > - CommonChannel common; // Must be the first thing > > - > > - CursorItem *item; > > - int cursor_visible; > > - SpicePoint16 cursor_position; > > - uint16_t cursor_trail_length; > > - uint16_t cursor_trail_frequency; > > - uint32_t mouse_mode; > > - > > -#ifdef RED_STATISTICS > > - StatNodeRef stat; > > -#endif > > -} CursorChannel; > > - > > G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); > > > > CursorChannel* cursor_channel_new (RedWorker *worker); > > @@ -89,6 +76,7 @@ void cursor_channel_disconnect > > (CursorChannel *cursor_channel); > > void cursor_channel_reset (CursorChannel *cursor); > > void cursor_channel_process_cmd (CursorChannel *cursor, > > RedCursorCmd *cursor_cmd, > > uint32_t group_id); > > +void cursor_channel_set_mouse_mode(CursorChannel *cursor, > > uint32_t mode); > > > > CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor, > > RedClient *client, > > RedsStream *stream, > > diff --git a/server/red_channel.c b/server/red_channel.c > > index 34aa9dc..7330ae2 100644 > > --- a/server/red_channel.c > > +++ b/server/red_channel.c > > @@ -1151,9 +1151,21 @@ RedChannel *red_channel_create_parser(int size, > > } > > channel->incoming_cb.handle_parsed = > > (handle_parsed_proc)handle_parsed; > > channel->incoming_cb.parser = parser; > > + > > return channel; > > } > > > > +void red_channel_set_stat_node(RedChannel *channel, StatNodeRef stat) > > +{ > > + spice_return_if_fail(channel != NULL); > > + spice_return_if_fail(channel->stat == 0); > > + > > +#ifdef RED_STATISTICS > > + channel->stat = stat; > > + channel->out_bytes_counter = stat_add_counter(stat, "out_bytes", > > TRUE); > > +#endif > > +} > > + > > void red_channel_register_client_cbs(RedChannel *channel, ClientCbs > > *client_cbs) > > { > > spice_assert(client_cbs->connect || channel->type == > > SPICE_CHANNEL_MAIN); > > diff --git a/server/red_channel.h b/server/red_channel.h > > index 1f1538e..201a4d2 100644 > > --- a/server/red_channel.h > > +++ b/server/red_channel.h > > @@ -32,6 +32,7 @@ > > #include "red_common.h" > > #include "demarshallers.h" > > #include "reds_stream.h" > > +#include "stat.h" > > > > #define MAX_SEND_BUFS 1000 > > #define CLIENT_ACK_WINDOW 20 > > @@ -127,6 +128,7 @@ typedef struct OutgoingHandler { > > > > /* Red Channel interface */ > > > > +typedef struct RedsStream RedsStream; > > typedef struct RedChannel RedChannel; > > typedef struct RedChannelClient RedChannelClient; > > typedef struct RedClient RedClient; > > @@ -335,10 +337,13 @@ struct RedChannel { > > // TODO: when different channel_clients are in different threads from > > Channel -> need to protect! > > pthread_t thread_id; > > #ifdef RED_STATISTICS > > + StatNodeRef stat; > > uint64_t *out_bytes_counter; > > #endif > > }; > > > > +#define RED_CHANNEL(Channel) ((RedChannel *)(Channel)) > > + > > /* > > * When an error occurs over a channel, we treat it as a warning > > * for spice-server and shutdown the channel. > > @@ -370,6 +375,7 @@ RedChannel *red_channel_create_parser(int size, > > channel_handle_parsed_proc handle_parsed, > > ChannelCbs *channel_cbs, > > uint32_t migration_flags); > > +void red_channel_set_stat_node(RedChannel *channel, StatNodeRef stat); > > > > void red_channel_register_client_cbs(RedChannel *channel, ClientCbs > > *client_cbs); > > // caps are freed when the channel is destroyed > > diff --git a/server/red_worker.c b/server/red_worker.c > > index 868de94..a99da27 100644 > > --- a/server/red_worker.c > > +++ b/server/red_worker.c > > @@ -390,7 +390,6 @@ struct DisplayChannel { > > RedCompressBuf *free_compress_bufs; > > > > #ifdef RED_STATISTICS > > - StatNodeRef stat; > > uint64_t *cache_hits_counter; > > uint64_t *add_to_cache_counter; > > uint64_t *non_cache_counter; > > @@ -1034,8 +1033,8 @@ static int display_is_connected(RedWorker *worker) > > > > static int cursor_is_connected(RedWorker *worker) > > { > > - return (worker->cursor_channel && red_channel_is_connected( > > - &worker->cursor_channel->common.base)); > > + return worker->cursor_channel && > > + red_channel_is_connected(RED_CHANNEL(worker->cursor_channel)); > > } > > > > static void put_drawable_pipe_item(DrawablePipeItem *dpi) > > @@ -1294,7 +1293,7 @@ static inline void red_destroy_surface_item(RedWorker > > *worker, > > return; > > } > > dcc->surface_client_created[surface_id] = FALSE; > > - channel = &worker->display_channel->common.base; > > + channel = RED_CHANNEL(worker->display_channel); > > destroy = get_surface_destroy_item(channel, surface_id); > > red_channel_client_pipe_add(&dcc->common.base, &destroy->pipe_item); > > } > > @@ -2991,7 +2990,7 @@ static inline int red_current_add_equal(RedWorker > > *worker, DrawItem *item, TreeI > > > > /* sending the drawable to clients that already received > > * (or will receive) other_drawable */ > > - worker_ring_item = > > ring_get_head(&worker->display_channel->common.base.clients); > > + worker_ring_item = > > ring_get_head(&RED_CHANNEL(worker->display_channel)->clients); > > dpi_ring_item = ring_get_head(&other_drawable->pipes); > > /* dpi contains a sublist of dcc's, ordered the same */ > > while (worker_ring_item) { > > @@ -3000,7 +2999,7 @@ static inline int red_current_add_equal(RedWorker > > *worker, DrawItem *item, TreeI > > dpi = SPICE_CONTAINEROF(dpi_ring_item, DrawablePipeItem, > > base); > > while (worker_ring_item && (!dpi || dcc != dpi->dcc)) { > > red_pipe_add_drawable(dcc, drawable); > > - worker_ring_item = > > ring_next(&worker->display_channel->common.base.clients, > > + worker_ring_item = > > ring_next(&RED_CHANNEL(worker->display_channel)->clients, > > worker_ring_item); > > dcc = SPICE_CONTAINEROF(worker_ring_item, > > DisplayChannelClient, > > common.base.channel_link); > > @@ -3010,7 +3009,7 @@ static inline int red_current_add_equal(RedWorker > > *worker, DrawItem *item, TreeI > > dpi_ring_item = ring_next(&other_drawable->pipes, > > dpi_ring_item); > > } > > if (worker_ring_item) { > > - worker_ring_item = > > ring_next(&worker->display_channel->common.base.clients, > > + worker_ring_item = > > ring_next(&RED_CHANNEL(worker->display_channel)->clients, > > worker_ring_item); > > } > > } > > @@ -4144,7 +4143,7 @@ static int red_process_cursor(RedWorker *worker, > > uint32_t max_pipe_size, int *ri > > > > *ring_is_empty = FALSE; > > while (!cursor_is_connected(worker) || > > - red_channel_min_pipe_size(&worker->cursor_channel->common.base) > > <= max_pipe_size) { > > + red_channel_min_pipe_size(RED_CHANNEL(worker->cursor_channel)) > > <= max_pipe_size) { > > if (!worker->qxl->st->qif->get_cursor_command(worker->qxl, > > &ext_cmd)) { > > *ring_is_empty = TRUE; > > if (worker->cursor_poll_tries < CMD_RING_POLL_RETRIES) { > > @@ -4206,7 +4205,7 @@ static int red_process_commands(RedWorker *worker, > > uint32_t max_pipe_size, int * > > *ring_is_empty = FALSE; > > while (!display_is_connected(worker) || > > // TODO: change to average pipe size? > > - > > red_channel_min_pipe_size(&worker->display_channel->common.base) > > <= max_pipe_size) { > > + red_channel_min_pipe_size(RED_CHANNEL(worker->display_channel)) > > <= max_pipe_size) { > > if (!worker->qxl->st->qif->get_command(worker->qxl, &ext_cmd)) { > > *ring_is_empty = TRUE;; > > if (worker->display_poll_tries < CMD_RING_POLL_RETRIES) { > > @@ -4351,7 +4350,7 @@ static ImageItem > > *red_add_surface_area_image(DisplayChannelClient *dcc, int surf > > { > > DisplayChannel *display_channel = DCC_TO_DC(dcc); > > RedWorker *worker = display_channel->common.worker; > > - RedChannel *channel = &display_channel->common.base; > > + RedChannel *channel = RED_CHANNEL(display_channel); > > RedSurface *surface = &worker->surfaces[surface_id]; > > SpiceCanvas *canvas = surface->context.canvas; > > ImageItem *item; > > @@ -4530,7 +4529,7 @@ static void > > red_display_reset_compress_buf(DisplayChannelClient *dcc) > > > > static void red_display_destroy_compress_bufs(DisplayChannel > > *display_channel) > > { > > - > > spice_assert(!red_channel_is_connected(&display_channel->common.base)); > > + spice_assert(!red_channel_is_connected(RED_CHANNEL(display_channel))); > > while (display_channel->free_compress_bufs) { > > RedCompressBuf *buf = display_channel->free_compress_bufs; > > display_channel->free_compress_bufs = buf->next; > > @@ -4719,7 +4718,7 @@ static void > > red_display_clear_glz_drawables(DisplayChannel *display_channel) > > if (!display_channel) { > > return; > > } > > - DCC_FOREACH_SAFE(link, next, dcc, &display_channel->common.base) { > > + DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel)) { > > red_display_client_clear_glz_drawables(dcc); > > } > > } > > @@ -8359,10 +8358,10 @@ static void > > display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item > > static inline void red_push(RedWorker *worker) > > { > > if (worker->cursor_channel) { > > - red_channel_push(&worker->cursor_channel->common.base); > > + red_channel_push(RED_CHANNEL(worker->cursor_channel)); > > } > > if (worker->display_channel) { > > - red_channel_push(&worker->display_channel->common.base); > > + red_channel_push(RED_CHANNEL(worker->display_channel)); > > } > > } > > > > @@ -8728,7 +8727,7 @@ static inline void red_create_surface(RedWorker > > *worker, uint32_t surface_id, ui > > > > static inline void flush_display_commands(RedWorker *worker) > > { > > - RedChannel *display_red_channel = > > &worker->display_channel->common.base; > > + RedChannel *display_red_channel = > > RED_CHANNEL(worker->display_channel); > > > > for (;;) { > > uint64_t end_time; > > @@ -8740,7 +8739,7 @@ static inline void flush_display_commands(RedWorker > > *worker) > > } > > > > while (red_process_commands(worker, MAX_PIPE_SIZE, > > &ring_is_empty)) { > > - red_channel_push(&worker->display_channel->common.base); > > + red_channel_push(RED_CHANNEL(worker->display_channel)); > > } > > > > if (ring_is_empty) { > > @@ -8749,7 +8748,7 @@ static inline void flush_display_commands(RedWorker > > *worker) > > end_time = red_get_monotonic_time() + DISPLAY_CLIENT_TIMEOUT; > > int sleep_count = 0; > > for (;;) { > > - red_channel_push(&worker->display_channel->common.base); > > + red_channel_push(RED_CHANNEL(worker->display_channel)); > > if (!display_is_connected(worker) || > > red_channel_max_pipe_size(display_red_channel) <= > > MAX_PIPE_SIZE) { > > break; > > @@ -8772,7 +8771,7 @@ static inline void flush_display_commands(RedWorker > > *worker) > > > > static inline void flush_cursor_commands(RedWorker *worker) > > { > > - RedChannel *cursor_red_channel = &worker->cursor_channel->common.base; > > + RedChannel *cursor_red_channel = RED_CHANNEL(worker->cursor_channel); > > > > for (;;) { > > uint64_t end_time; > > @@ -8784,7 +8783,7 @@ static inline void flush_cursor_commands(RedWorker > > *worker) > > } > > > > while (red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty)) > > { > > - red_channel_push(&worker->cursor_channel->common.base); > > + red_channel_push(RED_CHANNEL(worker->cursor_channel)); > > } > > > > if (ring_is_empty) { > > @@ -8793,7 +8792,7 @@ static inline void flush_cursor_commands(RedWorker > > *worker) > > end_time = red_get_monotonic_time() + DISPLAY_CLIENT_TIMEOUT; > > int sleep_count = 0; > > for (;;) { > > - red_channel_push(&worker->cursor_channel->common.base); > > + red_channel_push(RED_CHANNEL(worker->cursor_channel)); > > if (!cursor_is_connected(worker) > > || red_channel_min_pipe_size(cursor_red_channel) <= > > || MAX_PIPE_SIZE) { > > break; > > @@ -9062,7 +9061,7 @@ static int > > display_channel_handle_migrate_glz_dictionary(DisplayChannelClient *d > > static int display_channel_handle_migrate_mark(RedChannelClient *rcc) > > { > > DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, > > DisplayChannel, common.base); > > - RedChannel *channel = &display_channel->common.base; > > + RedChannel *channel = RED_CHANNEL(display_channel); > > > > red_channel_pipes_add_type(channel, PIPE_ITEM_TYPE_MIGRATE_DATA); > > return TRUE; > > @@ -9446,6 +9445,7 @@ CommonChannelClient > > *common_channel_new_client(CommonChannel *common, > > > > > > RedChannel *red_worker_new_channel(RedWorker *worker, int size, > > + const char *name, > > uint32_t channel_type, int > > migration_flags, > > ChannelCbs *channel_cbs, > > channel_handle_parsed_proc > > handle_parsed) > > @@ -9470,16 +9470,12 @@ RedChannel *red_worker_new_channel(RedWorker > > *worker, int size, > > handle_parsed, > > channel_cbs, > > migration_flags); > > + spice_return_val_if_fail(channel, NULL); > > + red_channel_set_stat_node(channel, stat_add_node(worker->stat, name, > > TRUE)); > > + > > common = (CommonChannel *)channel; > > - if (!channel) { > > - goto error; > > - } > > common->worker = worker; > > return channel; > > - > > -error: > > - free(channel); > > - return NULL; > > } > > > > static void display_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem > > *item) > > @@ -9633,7 +9629,7 @@ static void display_channel_create(RedWorker *worker, > > int migrate) > > > > spice_info("create display channel"); > > if (!(worker->display_channel = (DisplayChannel > > *)red_worker_new_channel( > > - worker, sizeof(*display_channel), > > + worker, sizeof(*display_channel), "display_channel", > > SPICE_CHANNEL_DISPLAY, > > SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, > > &cbs, display_channel_handle_message))) { > > @@ -9642,14 +9638,12 @@ static void display_channel_create(RedWorker > > *worker, int migrate) > > } > > display_channel = worker->display_channel; > > #ifdef RED_STATISTICS > > - display_channel->stat = stat_add_node(worker->stat, "display_channel", > > TRUE); > > - display_channel->common.base.out_bytes_counter = > > stat_add_counter(display_channel->stat, > > - > > "out_bytes", > > TRUE); > > - display_channel->cache_hits_counter = > > stat_add_counter(display_channel->stat, > > + RedChannel *channel = RED_CHANNEL(display_channel); > > + display_channel->cache_hits_counter = stat_add_counter(channel->stat, > > "cache_hits", > > TRUE); > > - display_channel->add_to_cache_counter = > > stat_add_counter(display_channel->stat, > > + display_channel->add_to_cache_counter = > > stat_add_counter(channel->stat, > > "add_to_cache", > > TRUE); > > - display_channel->non_cache_counter = > > stat_add_counter(display_channel->stat, > > + display_channel->non_cache_counter = stat_add_counter(channel->stat, > > "non_cache", > > TRUE); > > #endif > > stat_compress_init(&display_channel->lz_stat, lz_stat_name); > > @@ -9692,14 +9686,14 @@ static void guest_set_client_capabilities(RedWorker > > *worker) > > return; > > } > > if ((worker->display_channel == NULL) || > > - (worker->display_channel->common.base.clients_num == 0)) { > > + (RED_CHANNEL(worker->display_channel)->clients_num == 0)) { > > worker->qxl->st->qif->set_client_capabilities(worker->qxl, FALSE, > > caps); > > } else { > > // Take least common denominator > > for (i = 0 ; i < sizeof(caps_available) / > > sizeof(caps_available[0]); ++i) { > > SET_CAP(caps, caps_available[i]); > > } > > - DCC_FOREACH_SAFE(link, next, dcc, > > &worker->display_channel->common.base) { > > + DCC_FOREACH_SAFE(link, next, dcc, > > RED_CHANNEL(worker->display_channel)) { > > rcc = (RedChannelClient *)dcc; > > for (i = 0 ; i < sizeof(caps_available) / > > sizeof(caps_available[0]); ++i) { > > if (!red_channel_client_test_remote_cap(rcc, > > caps_available[i])) > > @@ -9783,17 +9777,13 @@ static void red_connect_cursor(RedWorker *worker, > > RedClient *client, RedsStream > > common_caps, num_common_caps, > > caps, num_caps); > > spice_return_if_fail(ccc != NULL); > > -#ifdef RED_STATISTICS > > - channel->stat = stat_add_node(worker->stat, "cursor_channel", TRUE); > > - channel->common.base.out_bytes_counter = > > stat_add_counter(channel->stat, "out_bytes", TRUE); > > -#endif > > > > RedChannelClient *rcc = &ccc->common.base; > > red_channel_client_ack_zero_messages_window(rcc); > > red_channel_client_push_set_ack(rcc); > > // TODO: why do we check for context.canvas? defer this to after > > display cc is connected > > // and test it's canvas? this is just a test to see if there is an > > active renderer? > > - if (worker->surfaces[0].context.canvas && > > !channel->common.during_target_migrate) { > > + if (worker->surfaces[0].context.canvas && > > !COMMON_CHANNEL(channel)->during_target_migrate) { > > red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_CURSOR_INIT); > > } > > } > > @@ -9971,9 +9961,9 @@ static inline void dev_destroy_surfaces(RedWorker > > *worker) > > spice_assert(ring_is_empty(&worker->streams)); > > > > if (display_is_connected(worker)) { > > - red_channel_pipes_add_type(&worker->display_channel->common.base, > > + red_channel_pipes_add_type(RED_CHANNEL(worker->display_channel), > > PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE); > > - red_pipes_add_verb(&worker->display_channel->common.base, > > + red_pipes_add_verb(RED_CHANNEL(worker->display_channel), > > SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL); > > } > > > > @@ -10138,8 +10128,8 @@ static void dev_create_primary_surface(RedWorker > > *worker, uint32_t surface_id, > > } > > > > if (cursor_is_connected(worker) > > - && !worker->cursor_channel->common.during_target_migrate) { > > - red_channel_pipes_add_type(&worker->cursor_channel->common.base, > > + && !COMMON_CHANNEL(worker->cursor_channel)->during_target_migrate) > > { > > + red_channel_pipes_add_type(RED_CHANNEL(worker->cursor_channel), > > PIPE_ITEM_TYPE_CURSOR_INIT); > > } > > } > > @@ -10236,14 +10226,14 @@ void handle_dev_stop(void *opaque, void *payload) > > * purge the pipe, send destroy_all_surfaces > > * to the client (there is no such message right now), and start > > * from scratch on the destination side */ > > - if (!red_channel_wait_all_sent(&worker->display_channel->common.base, > > + if (!red_channel_wait_all_sent(RED_CHANNEL(worker->display_channel), > > DISPLAY_CLIENT_TIMEOUT)) { > > - red_channel_apply_clients(&worker->display_channel->common.base, > > + red_channel_apply_clients(RED_CHANNEL(worker->display_channel), > > red_channel_client_disconnect_if_pending_send); > > } > > - if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, > > + if (!red_channel_wait_all_sent(RED_CHANNEL(worker->cursor_channel), > > DISPLAY_CLIENT_TIMEOUT)) { > > - red_channel_apply_clients(&worker->cursor_channel->common.base, > > + red_channel_apply_clients(RED_CHANNEL(worker->cursor_channel), > > red_channel_client_disconnect_if_pending_send); > > } > > } > > @@ -10285,7 +10275,7 @@ void handle_dev_start(void *opaque, void *payload) > > > > spice_assert(!worker->running); > > if (worker->cursor_channel) { > > - worker->cursor_channel->common.during_target_migrate = FALSE; > > + COMMON_CHANNEL(worker->cursor_channel)->during_target_migrate = > > FALSE; > > } > > if (worker->display_channel) { > > worker->display_channel->common.during_target_migrate = FALSE; > > @@ -10492,7 +10482,7 @@ void handle_dev_cursor_channel_create(void *opaque, > > void *payload) > > spice_warning("cursor channel already created"); > > } > > > > - red_channel = &worker->cursor_channel->common.base; > > + red_channel = RED_CHANNEL(worker->cursor_channel); > > send_data(worker->channel, &red_channel, sizeof(RedChannel *)); > > } > > > > @@ -10609,9 +10599,7 @@ void handle_dev_set_mouse_mode(void *opaque, void > > *payload) > > RedWorker *worker = opaque; > > > > spice_info("mouse mode %u", msg->mode); > > - spice_return_if_fail(worker->cursor_channel); > > - > > - worker->cursor_channel->mouse_mode = msg->mode; > > + cursor_channel_set_mouse_mode(worker->cursor_channel, msg->mode); > > } > > > > void handle_dev_add_memslot_async(void *opaque, void *payload) > > diff --git a/server/red_worker.h b/server/red_worker.h > > index df52abd..0a3d7c6 100644 > > --- a/server/red_worker.h > > +++ b/server/red_worker.h > > @@ -27,6 +27,7 @@ typedef struct RedWorker RedWorker; > > > > typedef struct CommonChannelClient { > > RedChannelClient base; > > + > > uint32_t id; > > struct RedWorker *worker; > > int is_low_bandwidth; > > @@ -37,6 +38,7 @@ typedef struct CommonChannelClient { > > #define CHANNEL_RECEIVE_BUF_SIZE 1024 > > typedef struct CommonChannel { > > RedChannel base; // Must be the first thing > > + > > struct RedWorker *worker; > > uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE]; > > uint32_t id_alloc; // bitfield. TODO - use this instead of shift > > scheme. > > @@ -47,6 +49,8 @@ typedef struct CommonChannel { > > of the primary surface) */ > > } CommonChannel; > > > > +#define COMMON_CHANNEL(Channel) ((CommonChannel*)(Channel)) > > + > > enum { > > PIPE_ITEM_TYPE_VERB = PIPE_ITEM_TYPE_CHANNEL_BASE, > > PIPE_ITEM_TYPE_INVAL_ONE, > > @@ -103,6 +107,7 @@ bool red_worker_run(RedWorker *worker); > > QXLInstance* red_worker_get_qxl(RedWorker *worker); > > > > RedChannel *red_worker_new_channel(RedWorker *worker, int size, > > + const char *name, > > uint32_t channel_type, int > > migration_flags, > > ChannelCbs *channel_cbs, > > channel_handle_parsed_proc > > handle_parsed); > > > > _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel