diff options
author | Jamey Sharp <jamey@minilop.net> | 2007-06-03 20:59:12 -0700 |
---|---|---|
committer | Jamey Sharp <jamey@minilop.net> | 2007-06-03 20:59:12 -0700 |
commit | 582ca690ea4f3ffd2b94826c4db97229bd3c7238 (patch) | |
tree | 8263b220bad861792cf145801cc0a9ef705a7053 /src/xcb_io.c | |
parent | e2c1d788d1fe7bd2d34756493951552441e59b8c (diff) |
Xlib/XCB: Fix _XReadEvents to always enqueue a new event, even if an error occurs
Commit c337f9de7cfd89f983f83956b7457a274dd412f3 broke the invariant that
_XReadEvents always enqueues at least one event even if an error occurred,
because the one call to xcb_wait_for_event would then return an error, not an
event, and nothing else ensured that process_responses would obtain an event.
Fix this by reverting most of c337f9de7cfd89f983f83956b7457a274dd412f3 and
f417570735aac865eb6b576d1ea76b5bfcd8573b and implementing the correct fix. In
process_responses, wait_for_first_event now serves as a flag, cleared when
actually handling an event.
Commit by Josh Triplett and Jamey Sharp.
Diffstat (limited to 'src/xcb_io.c')
-rw-r--r-- | src/xcb_io.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/src/xcb_io.c b/src/xcb_io.c index c0b2c1f0..afab7ac7 100644 --- a/src/xcb_io.c +++ b/src/xcb_io.c @@ -102,6 +102,21 @@ static void call_handlers(Display *dpy, xcb_generic_reply_t *buf) _XError(dpy, (xError *) buf); } +static xcb_generic_event_t * wait_or_poll_for_event(Display *dpy, int wait) +{ + xcb_connection_t *c = dpy->xcb->connection; + xcb_generic_event_t *event; + if(wait) + { + UnlockDisplay(dpy); + event = xcb_wait_for_event(c); + LockDisplay(dpy); + } + else + event = xcb_poll_for_event(c); + return event; +} + static void process_responses(Display *dpy, int wait_for_first_event, xcb_generic_error_t **current_error, unsigned int current_request) { void *reply; @@ -109,16 +124,7 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi xcb_generic_error_t *error; xcb_connection_t *c = dpy->xcb->connection; if(!event && dpy->xcb->event_owner == XlibOwnsEventQueue) - { - if(wait_for_first_event) - { - UnlockDisplay(dpy); - event = xcb_wait_for_event(c); - LockDisplay(dpy); - } - else - event = xcb_poll_for_event(c); - } + event = wait_or_poll_for_event(dpy, wait_for_first_event); while(1) { @@ -126,20 +132,25 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi assert(!(req && current_request && !XCB_SEQUENCE_COMPARE(req->sequence, <=, current_request))); if(event && (!req || XCB_SEQUENCE_COMPARE(event->full_sequence, <=, req->sequence))) { - if(current_error && event->response_type == 0 && event->full_sequence == current_request) + if(current_error && event->response_type == X_Error + && event->full_sequence == current_request) { + /* This can only occur when called from + * _XReply, which doesn't need a new event. */ *current_error = (xcb_generic_error_t *) event; event = 0; break; } + if(event->response_type != X_Error) + wait_for_first_event = 0; handle_event(dpy, event); - event = xcb_poll_for_event(c); + event = wait_or_poll_for_event(dpy, wait_for_first_event); } else if(req && req->waiters != -1) { if(req->sequence == current_request) break; - if(!current_request && !(wait_for_first_event && !dpy->head)) + if(!current_request && !wait_for_first_event) break; dpy->xcb->next_event = event; req->waiters++; @@ -176,7 +187,7 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi _XIOError(dpy); assert_sequence_less(dpy->last_request_read, dpy->request); - assert(!wait_for_first_event || dpy->head); + assert(!wait_for_first_event); } int _XEventsQueued(Display *dpy, int mode) |