diff options
-rw-r--r-- | src/xcb_in.c | 32 | ||||
-rw-r--r-- | src/xcbint.h | 1 |
2 files changed, 33 insertions, 0 deletions
diff --git a/src/xcb_in.c b/src/xcb_in.c index 322bed8..bab4bc7 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -97,6 +97,11 @@ typedef struct reader_list { struct reader_list *next; } reader_list; +typedef struct special_list { + xcb_special_event_t *se; + struct special_list *next; +} special_list; + static void remove_finished_readers(reader_list **prev_reader, uint64_t completed) { while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, completed)) @@ -475,6 +480,26 @@ static void remove_reader(reader_list **prev_reader, reader_list *reader) } } +static void insert_special(special_list **prev_special, special_list *special, xcb_special_event_t *se) +{ + special->se = se; + special->next = *prev_special; + *prev_special = special; +} + +static void remove_special(special_list **prev_special, special_list *special) +{ + while(*prev_special) + { + if(*prev_special == special) + { + *prev_special = (*prev_special)->next; + break; + } + prev_special = &(*prev_special)->next; + } +} + static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e) { void *ret = 0; @@ -750,17 +775,22 @@ xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c, xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c, xcb_special_event_t *se) { + special_list special; xcb_generic_event_t *event; if(c->has_error) return 0; pthread_mutex_lock(&c->iolock); + insert_special(&c->in.special_waiters, &special, se); + /* get_special_event returns 0 on empty list. */ while(!(event = get_special_event(c, se))) if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0)) break; + remove_special(&c->in.special_waiters, &special); + _xcb_in_wake_up_next_reader(c); pthread_mutex_unlock(&c->iolock); return event; @@ -889,6 +919,8 @@ void _xcb_in_wake_up_next_reader(xcb_connection_t *c) int pthreadret; if(c->in.readers) pthreadret = pthread_cond_signal(c->in.readers->data); + else if(c->in.special_waiters) + pthreadret = pthread_cond_signal(&c->in.special_waiters->se->special_event_cond); else pthreadret = pthread_cond_signal(&c->in.event_cond); assert(pthreadret == 0); diff --git a/src/xcbint.h b/src/xcbint.h index f89deba..acce646 100644 --- a/src/xcbint.h +++ b/src/xcbint.h @@ -142,6 +142,7 @@ typedef struct _xcb_in { struct event_list *events; struct event_list **events_tail; struct reader_list *readers; + struct special_list *special_waiters; struct pending_reply *pending_replies; struct pending_reply **pending_replies_tail; |