1 /* Copyright (C) 2003-2006 Jamey Sharp, Josh Triplett
2 * This file is licensed under the MIT license. See the file COPYING. */
12 #include <xcb/xcbext.h>
15 #ifdef HAVE_INTTYPES_H
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
26 #define xcb_fail_assert(_message, _var) { \
27 unsigned int _var = 1; \
28 fprintf(stderr, "[xcb] Aborting, sorry about that.\n"); \
32 #define throw_thread_fail_assert(_message, _var) { \
33 fprintf(stderr, "[xcb] " _message "\n"); \
34 fprintf(stderr, "[xcb] Most likely this is a multi-threaded client " \
35 "and XInitThreads has not been called\n"); \
36 xcb_fail_assert(_message, _var); \
39 /* XXX: It would probably be most useful if we stored the last-processed
40 * request, so we could find the offender from the message. */
41 #define throw_extlib_fail_assert(_message, _var) { \
42 fprintf(stderr, "[xcb] " _message "\n"); \
43 fprintf(stderr, "[xcb] This is most likely caused by a broken X " \
44 "extension library\n"); \
45 xcb_fail_assert(_message, _var); \
48 static void return_socket(void *closure)
50 Display *dpy = closure;
51 InternalLockDisplay(dpy, /* don't skip user locks */ 0);
53 dpy->bufmax = dpy->buffer;
57 static void require_socket(Display *dpy)
59 if(dpy->bufmax == dpy->buffer)
63 /* if we don't own the event queue, we have to ask XCB
64 * to set our errors aside for us. */
65 if(dpy->xcb->event_owner != XlibOwnsEventQueue)
66 flags = XCB_REQUEST_CHECKED;
67 if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy,
70 /* Xlib uses unsigned long for sequence numbers. XCB
71 * uses 64-bit internally, but currently exposes an
72 * unsigned int API. If these differ, Xlib cannot track
73 * the full 64-bit sequence number if 32-bit wrap
74 * happens while Xlib does not own the socket. A
75 * complete fix would be to make XCB's public API use
76 * 64-bit sequence numbers. */
77 if (sizeof(unsigned long) > sizeof(unsigned int) &&
78 dpy->xcb->event_owner == XlibOwnsEventQueue &&
79 (sent - dpy->last_request_read >= (UINT64_C(1) << 32))) {
80 throw_thread_fail_assert("Sequence number wrapped "
81 "beyond 32 bits while Xlib "
82 "did not own the socket",
83 xcb_xlib_seq_number_wrapped);
85 dpy->xcb->last_flushed = dpy->request = sent;
86 dpy->bufmax = dpy->xcb->real_bufmax;
90 /* Call internal connection callbacks for any fds that are currently
91 * ready to read. This function will not block unless one of the
94 * This code borrowed from _XWaitForReadable. Inverse call tree:
107 static void check_internal_connections(Display *dpy)
109 struct _XConnectionInfo *ilist;
115 if(dpy->flags & XlibDisplayProcConni || !dpy->im_fd_info)
119 for(ilist = dpy->im_fd_info; ilist; ilist = ilist->next)
121 assert(ilist->fd >= 0);
122 FD_SET(ilist->fd, &r_mask);
123 if(ilist->fd > highest_fd)
124 highest_fd = ilist->fd;
126 assert(highest_fd >= 0);
130 result = select(highest_fd + 1, &r_mask, NULL, NULL, &tv);
139 for(ilist = dpy->im_fd_info; result && ilist; ilist = ilist->next)
140 if(FD_ISSET(ilist->fd, &r_mask))
142 _XProcessInternalConnection(dpy, ilist);
147 static PendingRequest *append_pending_request(Display *dpy, unsigned long sequence)
149 PendingRequest *node = malloc(sizeof(PendingRequest));
152 node->sequence = sequence;
153 node->reply_waiter = 0;
154 if(dpy->xcb->pending_requests_tail)
156 if (XLIB_SEQUENCE_COMPARE(dpy->xcb->pending_requests_tail->sequence,
158 throw_thread_fail_assert("Unknown sequence number "
159 "while appending request",
160 xcb_xlib_unknown_seq_number);
161 if (dpy->xcb->pending_requests_tail->next != NULL)
162 throw_thread_fail_assert("Unknown request in queue "
163 "while appending request",
164 xcb_xlib_unknown_req_pending);
165 dpy->xcb->pending_requests_tail->next = node;
168 dpy->xcb->pending_requests = node;
169 dpy->xcb->pending_requests_tail = node;
173 static void dequeue_pending_request(Display *dpy, PendingRequest *req)
175 if (req != dpy->xcb->pending_requests)
176 throw_thread_fail_assert("Unknown request in queue while "
178 xcb_xlib_unknown_req_in_deq);
180 dpy->xcb->pending_requests = req->next;
181 if(!dpy->xcb->pending_requests)
183 if (req != dpy->xcb->pending_requests_tail)
184 throw_thread_fail_assert("Unknown request in queue "
186 xcb_xlib_unknown_req_in_deq);
187 dpy->xcb->pending_requests_tail = NULL;
189 else if (XLIB_SEQUENCE_COMPARE(req->sequence, >=,
190 dpy->xcb->pending_requests->sequence))
191 throw_thread_fail_assert("Unknown sequence number while "
193 xcb_xlib_threads_sequence_lost);
198 static int handle_error(Display *dpy, xError *err, Bool in_XReply)
202 /* Oddly, Xlib only allows extensions to suppress errors when
203 * those errors were seen by _XReply. */
206 * we better see if there is an extension who may
207 * want to suppress the error.
209 for(ext = dpy->ext_procs; ext; ext = ext->next)
210 if(ext->error && (*ext->error)(dpy, err, &ext->codes, &ret_code))
216 /* Widen a 32-bit sequence number into a native-word-size (unsigned long)
217 * sequence number. Treating the comparison as a 1 and shifting it avoids a
218 * conditional branch, and shifting by 16 twice avoids a compiler warning when
219 * sizeof(unsigned long) == 4. */
220 static void widen(unsigned long *wide, unsigned int narrow)
222 unsigned long new = (*wide & ~0xFFFFFFFFUL) | narrow;
223 *wide = new + ((unsigned long) (new < *wide) << 16 << 16);
226 /* Thread-safety rules:
228 * At most one thread can be reading from XCB's event queue at a time.
229 * If you are not the current event-reading thread and you need to find
230 * out if an event is available, you must wait.
232 * The same rule applies for reading replies.
234 * A single thread cannot be both the the event-reading and the
235 * reply-reading thread at the same time.
237 * We always look at both the current event and the first pending reply
238 * to decide which to process next.
240 * We always process all responses in sequence-number order, which may
241 * mean waiting for another thread (either the event_waiter or the
242 * reply_waiter) to handle an earlier response before we can process or
243 * return a later one. If so, we wait on the corresponding condition
244 * variable for that thread to process the response and wake us up.
247 static xcb_generic_reply_t *poll_for_event(Display *dpy)
249 /* Make sure the Display's sequence numbers are valid */
252 /* Precondition: This thread can safely get events from XCB. */
253 assert(dpy->xcb->event_owner == XlibOwnsEventQueue && !dpy->xcb->event_waiter);
255 if(!dpy->xcb->next_event)
256 dpy->xcb->next_event = xcb_poll_for_event(dpy->xcb->connection);
258 if(dpy->xcb->next_event)
260 PendingRequest *req = dpy->xcb->pending_requests;
261 xcb_generic_event_t *event = dpy->xcb->next_event;
262 unsigned long event_sequence = dpy->last_request_read;
263 widen(&event_sequence, event->full_sequence);
264 if(!req || XLIB_SEQUENCE_COMPARE(event_sequence, <, req->sequence)
265 || (event->response_type != X_Error && event_sequence == req->sequence))
267 if (XLIB_SEQUENCE_COMPARE(event_sequence, >,
270 throw_thread_fail_assert("Unknown sequence "
273 xcb_xlib_threads_sequence_lost);
275 dpy->last_request_read = event_sequence;
276 dpy->xcb->next_event = NULL;
277 return (xcb_generic_reply_t *) event;
283 static xcb_generic_reply_t *poll_for_response(Display *dpy)
286 xcb_generic_error_t *error;
288 while(!(response = poll_for_event(dpy)) &&
289 (req = dpy->xcb->pending_requests) &&
290 !req->reply_waiter &&
291 xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &response, &error))
293 if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy->request))
295 throw_thread_fail_assert("Unknown sequence number "
296 "while awaiting reply",
297 xcb_xlib_threads_sequence_lost);
299 dpy->last_request_read = req->sequence;
302 dequeue_pending_request(dpy, req);
304 return (xcb_generic_reply_t *) error;
309 static void handle_response(Display *dpy, xcb_generic_reply_t *response, Bool in_XReply)
311 _XAsyncHandler *async, *next;
312 switch(response->response_type)
315 for(async = dpy->async_handlers; async; async = next)
318 if(async->handler(dpy, (xReply *) response, (char *) response, sizeof(xReply) + (response->length << 2), async->data))
324 handle_error(dpy, (xError *) response, in_XReply);
328 /* GenericEvents may be > 32 bytes. In this case, the
329 * event struct is trailed by the additional bytes. the
330 * xcb_generic_event_t struct uses 4 bytes for internal
331 * numbering, so we need to shift the trailing data to
332 * be after the first 32 bytes. */
333 if(response->response_type == GenericEvent && ((xcb_ge_event_t *) response)->length)
335 xcb_ge_event_t *event = (xcb_ge_event_t *) response;
336 memmove(&event->full_sequence, &event[1], event->length * 4);
338 _XEnq(dpy, (xEvent *) response);
344 int _XEventsQueued(Display *dpy, int mode)
346 xcb_generic_reply_t *response;
347 if(dpy->flags & XlibDisplayIOError)
349 if(dpy->xcb->event_owner != XlibOwnsEventQueue)
352 if(mode == QueuedAfterFlush)
353 _XSend(dpy, NULL, 0);
355 check_internal_connections(dpy);
357 /* If another thread is blocked waiting for events, then we must
358 * let that thread pick up the next event. Since it blocked, we
359 * can reasonably claim there are no new events right now. */
360 if(!dpy->xcb->event_waiter)
362 while((response = poll_for_response(dpy)))
363 handle_response(dpy, response, False);
364 if(xcb_connection_has_error(dpy->xcb->connection))
370 /* _XReadEvents - Flush the output queue,
371 * then read as many events as possible (but at least 1) and enqueue them
373 void _XReadEvents(Display *dpy)
375 xcb_generic_reply_t *response;
376 unsigned long serial;
378 if(dpy->flags & XlibDisplayIOError)
380 _XSend(dpy, NULL, 0);
381 if(dpy->xcb->event_owner != XlibOwnsEventQueue)
383 check_internal_connections(dpy);
385 serial = dpy->next_event_serial_num;
386 while(serial == dpy->next_event_serial_num || dpy->qlen == 0)
388 if(dpy->xcb->event_waiter)
390 ConditionWait(dpy, dpy->xcb->event_notify);
391 /* Maybe the other thread got us an event. */
395 if(!dpy->xcb->next_event)
397 xcb_generic_event_t *event;
398 dpy->xcb->event_waiter = 1;
400 event = xcb_wait_for_event(dpy->xcb->connection);
401 /* It appears that classic Xlib respected user
402 * locks when waking up after waiting for
403 * events. However, if this thread did not have
404 * any user locks, and another thread takes a
405 * user lock and tries to read events, then we'd
406 * deadlock. So we'll choose to let the thread
407 * that got in first consume events, despite the
408 * later thread's user locks. */
409 InternalLockDisplay(dpy, /* ignore user locks */ 1);
410 dpy->xcb->event_waiter = 0;
411 ConditionBroadcast(dpy, dpy->xcb->event_notify);
414 dpy->xcb->next_event = event;
417 /* We've established most of the conditions for
418 * poll_for_response to return non-NULL. The exceptions
419 * are connection shutdown, and finding that another
420 * thread is waiting for the next reply we'd like to
423 response = poll_for_response(dpy);
425 handle_response(dpy, response, False);
426 else if(dpy->xcb->pending_requests->reply_waiter)
427 { /* need braces around ConditionWait */
428 ConditionWait(dpy, dpy->xcb->reply_notify);
434 /* The preceding loop established that there is no
435 * event_waiter--unless we just called ConditionWait because of
436 * a reply_waiter, in which case another thread may have become
437 * the event_waiter while we slept unlocked. */
438 if(!dpy->xcb->event_waiter)
439 while((response = poll_for_response(dpy)))
440 handle_response(dpy, response, False);
441 if(xcb_connection_has_error(dpy->xcb->connection))
446 * _XSend - Flush the buffer and send the client data. 32 bit word aligned
447 * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
449 * Note that the connection must not be read from once the data currently
450 * in the buffer has been written.
452 void _XSend(Display *dpy, const char *data, long size)
454 static const xReq dummy_request;
455 static char const pad[3];
459 xcb_connection_t *c = dpy->xcb->connection;
460 if(dpy->flags & XlibDisplayIOError)
463 if(dpy->bufptr == dpy->buffer && !size)
466 /* iff we asked XCB to set aside errors, we must pick those up
467 * eventually. iff there are async handlers, we may have just
468 * issued requests that will generate replies. in either case,
469 * we need to remember to check later. */
470 if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers)
473 for(sequence = dpy->xcb->last_flushed + 1; sequence <= dpy->request; ++sequence)
474 append_pending_request(dpy, sequence);
476 requests = dpy->request - dpy->xcb->last_flushed;
477 dpy->xcb->last_flushed = dpy->request;
479 vec[0].iov_base = dpy->buffer;
480 vec[0].iov_len = dpy->bufptr - dpy->buffer;
481 vec[1].iov_base = (char *)data;
482 vec[1].iov_len = size;
483 vec[2].iov_base = (char *)pad;
484 vec[2].iov_len = -size & 3;
486 for(ext = dpy->flushes; ext; ext = ext->next_flush)
489 for(i = 0; i < 3; ++i)
491 ext->before_flush(dpy, &ext->codes, vec[i].iov_base, vec[i].iov_len);
494 if(xcb_writev(c, vec, 3, requests) < 0)
496 dpy->bufptr = dpy->buffer;
497 dpy->last_req = (char *) &dummy_request;
499 check_internal_connections(dpy);
501 _XSetSeqSyncFunction(dpy);
505 * _XFlush - Flush the X request buffer. If the buffer is empty, no
508 void _XFlush(Display *dpy)
511 _XSend(dpy, NULL, 0);
513 _XEventsQueued(dpy, QueuedAfterReading);
516 static const XID inval_id = ~0UL;
518 void _XIDHandler(Display *dpy)
520 if (dpy->xcb->next_xid == inval_id)
521 _XAllocIDs(dpy, &dpy->xcb->next_xid, 1);
524 /* _XAllocID - resource ID allocation routine. */
525 XID _XAllocID(Display *dpy)
527 XID ret = dpy->xcb->next_xid;
528 assert (ret != inval_id);
529 dpy->xcb->next_xid = inval_id;
530 _XSetPrivSyncFunction(dpy);
534 /* _XAllocIDs - multiple resource ID allocation routine. */
535 void _XAllocIDs(Display *dpy, XID *ids, int count)
540 (*dpy->lock->user_lock_display)(dpy);
543 for (i = 0; i < count; i++)
544 ids[i] = xcb_generate_id(dpy->xcb->connection);
546 InternalLockDisplay(dpy, /* don't skip user locks */ 0);
548 (*dpy->lock->user_unlock_display)(dpy);
552 static void _XFreeReplyData(Display *dpy, Bool force)
554 if(!force && dpy->xcb->reply_consumed < dpy->xcb->reply_length)
556 free(dpy->xcb->reply_data);
557 dpy->xcb->reply_data = NULL;
561 * _XReply - Wait for a reply packet and copy its contents into the
563 * extra: number of 32-bit words expected after the reply
564 * discard: should I discard data following "extra" words?
566 Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
568 xcb_generic_error_t *error;
569 xcb_connection_t *c = dpy->xcb->connection;
571 PendingRequest *current;
573 if (dpy->xcb->reply_data)
574 throw_extlib_fail_assert("Extra reply data still left in queue",
575 xcb_xlib_extra_reply_data_left);
577 if(dpy->flags & XlibDisplayIOError)
580 _XSend(dpy, NULL, 0);
581 if(dpy->xcb->pending_requests_tail && dpy->xcb->pending_requests_tail->sequence == dpy->request)
582 current = dpy->xcb->pending_requests_tail;
584 current = append_pending_request(dpy, dpy->request);
585 /* Don't let any other thread get this reply. */
586 current->reply_waiter = 1;
590 PendingRequest *req = dpy->xcb->pending_requests;
591 xcb_generic_reply_t *response;
593 if(req != current && req->reply_waiter)
595 ConditionWait(dpy, dpy->xcb->reply_notify);
596 /* Another thread got this reply. */
599 req->reply_waiter = 1;
601 response = xcb_wait_for_reply(c, req->sequence, &error);
602 /* Any user locks on another thread must have been taken
603 * while we slept in xcb_wait_for_reply. Classic Xlib
604 * ignored those user locks in this case, so we do too. */
605 InternalLockDisplay(dpy, /* ignore user locks */ 1);
607 /* We have the response we're looking for. Now, before
608 * letting anyone else process this sequence number, we
609 * need to process any events that should have come
612 if(dpy->xcb->event_owner == XlibOwnsEventQueue)
614 xcb_generic_reply_t *event;
615 /* If some thread is already waiting for events,
616 * it will get the first one. That thread must
617 * process that event before we can continue. */
618 /* FIXME: That event might be after this reply,
619 * and might never even come--or there might be
620 * multiple threads trying to get events. */
621 while(dpy->xcb->event_waiter)
622 { /* need braces around ConditionWait */
623 ConditionWait(dpy, dpy->xcb->event_notify);
625 while((event = poll_for_event(dpy)))
626 handle_response(dpy, event, True);
629 req->reply_waiter = 0;
630 ConditionBroadcast(dpy, dpy->xcb->reply_notify);
631 if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy->request)) {
632 throw_thread_fail_assert("Unknown sequence number "
633 "while processing reply",
634 xcb_xlib_threads_sequence_lost);
636 dpy->last_request_read = req->sequence;
638 dequeue_pending_request(dpy, req);
642 reply = (char *) response;
647 handle_response(dpy, (xcb_generic_reply_t *) error, True);
649 handle_response(dpy, response, True);
651 check_internal_connections(dpy);
653 if(dpy->xcb->next_event && dpy->xcb->next_event->response_type == X_Error)
655 xcb_generic_event_t *event = dpy->xcb->next_event;
656 unsigned long event_sequence = dpy->last_request_read;
657 widen(&event_sequence, event->full_sequence);
658 if(event_sequence == dpy->last_request_read)
660 error = (xcb_generic_error_t *) event;
661 dpy->xcb->next_event = NULL;
669 /* Xlib is evil and assumes that even errors will be
670 * copied into rep. */
671 memcpy(rep, error, 32);
673 /* do not die on "no such font", "can't allocate",
674 "can't grab" failures */
675 switch(error->error_code)
678 switch(error->major_code)
681 case X_AllocNamedColor:
687 if(error->major_code == X_QueryFont) {
698 ret_code = handle_error(dpy, (xError *) error, True);
703 /* it's not an error, but we don't have a reply, so it's an I/O
711 /* there's no error and we have a reply. */
712 dpy->xcb->reply_data = reply;
713 dpy->xcb->reply_consumed = sizeof(xReply) + (extra * 4);
714 dpy->xcb->reply_length = sizeof(xReply);
715 if(dpy->xcb->reply_data[0] == 1)
716 dpy->xcb->reply_length += (((xcb_generic_reply_t *) dpy->xcb->reply_data)->length * 4);
718 /* error: Xlib asks too much. give them what we can anyway. */
719 if(dpy->xcb->reply_length < dpy->xcb->reply_consumed)
720 dpy->xcb->reply_consumed = dpy->xcb->reply_length;
722 memcpy(rep, dpy->xcb->reply_data, dpy->xcb->reply_consumed);
723 _XFreeReplyData(dpy, discard);
727 int _XRead(Display *dpy, char *data, long size)
732 if(dpy->xcb->reply_data == NULL ||
733 dpy->xcb->reply_consumed + size > dpy->xcb->reply_length)
734 throw_extlib_fail_assert("Too much data requested from _XRead",
735 xcb_xlib_too_much_data_requested);
736 memcpy(data, dpy->xcb->reply_data + dpy->xcb->reply_consumed, size);
737 dpy->xcb->reply_consumed += size;
738 _XFreeReplyData(dpy, False);
743 * _XReadPad - Read bytes from the socket taking into account incomplete
744 * reads. If the number of bytes is not 0 mod 4, read additional pad
747 void _XReadPad(Display *dpy, char *data, long size)
749 _XRead(dpy, data, size);
750 dpy->xcb->reply_consumed += -size & 3;
751 _XFreeReplyData(dpy, False);
754 /* Read and discard "n" 8-bit bytes of data */
755 void _XEatData(Display *dpy, unsigned long n)
757 dpy->xcb->reply_consumed += n;
758 _XFreeReplyData(dpy, False);