summaryrefslogtreecommitdiff
path: root/src/xcb_io.c
diff options
context:
space:
mode:
authorJamey Sharp <jamey@minilop.net>2007-06-03 20:59:12 -0700
committerJamey Sharp <jamey@minilop.net>2007-06-03 20:59:12 -0700
commit582ca690ea4f3ffd2b94826c4db97229bd3c7238 (patch)
tree8263b220bad861792cf145801cc0a9ef705a7053 /src/xcb_io.c
parente2c1d788d1fe7bd2d34756493951552441e59b8c (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.c39
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)