xcb_io.c revision 57f47464
11ab64890Smrg/* Copyright (C) 2003-2006 Jamey Sharp, Josh Triplett 21ab64890Smrg * This file is licensed under the MIT license. See the file COPYING. */ 31ab64890Smrg 4b4ee4795Smrg#ifdef HAVE_CONFIG_H 5b4ee4795Smrg#include <config.h> 6b4ee4795Smrg#endif 7b4ee4795Smrg 81ab64890Smrg#include "Xlibint.h" 91ab64890Smrg#include "locking.h" 1061b2299dSmrg#include "Xprivate.h" 111ab64890Smrg#include "Xxcbint.h" 121ab64890Smrg#include <xcb/xcbext.h> 131ab64890Smrg 141ab64890Smrg#include <assert.h> 1588de56ccSmrg#ifdef HAVE_INTTYPES_H 1661b2299dSmrg#include <inttypes.h> 1788de56ccSmrg#endif 1861b2299dSmrg#include <stdint.h> 191ab64890Smrg#include <stdlib.h> 201ab64890Smrg#include <string.h> 21b4ee4795Smrg#ifdef HAVE_SYS_SELECT_H 22b4ee4795Smrg#include <sys/select.h> 23b4ee4795Smrg#endif 241ab64890Smrg 2561b2299dSmrgstatic void return_socket(void *closure) 2661b2299dSmrg{ 2761b2299dSmrg Display *dpy = closure; 2888de56ccSmrg InternalLockDisplay(dpy, /* don't skip user locks */ 0); 2961b2299dSmrg _XSend(dpy, NULL, 0); 3061b2299dSmrg dpy->bufmax = dpy->buffer; 3161b2299dSmrg UnlockDisplay(dpy); 3261b2299dSmrg} 3361b2299dSmrg 3461b2299dSmrgstatic void require_socket(Display *dpy) 3561b2299dSmrg{ 3661b2299dSmrg if(dpy->bufmax == dpy->buffer) 3761b2299dSmrg { 3861b2299dSmrg uint64_t sent; 3961b2299dSmrg int flags = 0; 4061b2299dSmrg /* if we don't own the event queue, we have to ask XCB 4161b2299dSmrg * to set our errors aside for us. */ 4261b2299dSmrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 4361b2299dSmrg flags = XCB_REQUEST_CHECKED; 4461b2299dSmrg if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy, 4561b2299dSmrg flags, &sent)) 4661b2299dSmrg _XIOError(dpy); 4761b2299dSmrg /* Xlib uses unsigned long for sequence numbers. XCB 4861b2299dSmrg * uses 64-bit internally, but currently exposes an 4961b2299dSmrg * unsigned int API. If these differ, Xlib cannot track 5061b2299dSmrg * the full 64-bit sequence number if 32-bit wrap 5161b2299dSmrg * happens while Xlib does not own the socket. A 5261b2299dSmrg * complete fix would be to make XCB's public API use 5361b2299dSmrg * 64-bit sequence numbers. */ 5461b2299dSmrg assert(!(sizeof(unsigned long) > sizeof(unsigned int) 5561b2299dSmrg && dpy->xcb->event_owner == XlibOwnsEventQueue 5661b2299dSmrg && (sent - dpy->last_request_read >= (UINT64_C(1) << 32)))); 5761b2299dSmrg dpy->xcb->last_flushed = dpy->request = sent; 5861b2299dSmrg dpy->bufmax = dpy->xcb->real_bufmax; 5961b2299dSmrg } 6061b2299dSmrg} 6161b2299dSmrg 621ab64890Smrg/* Call internal connection callbacks for any fds that are currently 631ab64890Smrg * ready to read. This function will not block unless one of the 641ab64890Smrg * callbacks blocks. 651ab64890Smrg * 661ab64890Smrg * This code borrowed from _XWaitForReadable. Inverse call tree: 671ab64890Smrg * _XRead 681ab64890Smrg * _XWaitForWritable 691ab64890Smrg * _XFlush 701ab64890Smrg * _XSend 711ab64890Smrg * _XEventsQueued 721ab64890Smrg * _XReadEvents 731ab64890Smrg * _XRead[0-9]+ 741ab64890Smrg * _XAllocIDs 751ab64890Smrg * _XReply 761ab64890Smrg * _XEatData 771ab64890Smrg * _XReadPad 781ab64890Smrg */ 791ab64890Smrgstatic void check_internal_connections(Display *dpy) 801ab64890Smrg{ 8161b2299dSmrg struct _XConnectionInfo *ilist; 821ab64890Smrg fd_set r_mask; 831ab64890Smrg struct timeval tv; 841ab64890Smrg int result; 851ab64890Smrg int highest_fd = -1; 861ab64890Smrg 871ab64890Smrg if(dpy->flags & XlibDisplayProcConni || !dpy->im_fd_info) 881ab64890Smrg return; 891ab64890Smrg 901ab64890Smrg FD_ZERO(&r_mask); 911ab64890Smrg for(ilist = dpy->im_fd_info; ilist; ilist = ilist->next) 921ab64890Smrg { 931ab64890Smrg assert(ilist->fd >= 0); 941ab64890Smrg FD_SET(ilist->fd, &r_mask); 951ab64890Smrg if(ilist->fd > highest_fd) 961ab64890Smrg highest_fd = ilist->fd; 971ab64890Smrg } 981ab64890Smrg assert(highest_fd >= 0); 991ab64890Smrg 1001ab64890Smrg tv.tv_sec = 0; 1011ab64890Smrg tv.tv_usec = 0; 1021ab64890Smrg result = select(highest_fd + 1, &r_mask, NULL, NULL, &tv); 1031ab64890Smrg 1041ab64890Smrg if(result == -1) 1051ab64890Smrg { 1061ab64890Smrg if(errno == EINTR) 1071ab64890Smrg return; 1081ab64890Smrg _XIOError(dpy); 1091ab64890Smrg } 1101ab64890Smrg 1111ab64890Smrg for(ilist = dpy->im_fd_info; result && ilist; ilist = ilist->next) 1121ab64890Smrg if(FD_ISSET(ilist->fd, &r_mask)) 1131ab64890Smrg { 1141ab64890Smrg _XProcessInternalConnection(dpy, ilist); 1151ab64890Smrg --result; 1161ab64890Smrg } 1171ab64890Smrg} 1181ab64890Smrg 11988de56ccSmrgstatic PendingRequest *append_pending_request(Display *dpy, unsigned long sequence) 1201ab64890Smrg{ 12188de56ccSmrg PendingRequest *node = malloc(sizeof(PendingRequest)); 12288de56ccSmrg assert(node); 12388de56ccSmrg node->next = NULL; 12488de56ccSmrg node->sequence = sequence; 12588de56ccSmrg node->reply_waiter = 0; 12688de56ccSmrg if(dpy->xcb->pending_requests_tail) 1271ab64890Smrg { 12888de56ccSmrg assert(XLIB_SEQUENCE_COMPARE(dpy->xcb->pending_requests_tail->sequence, <, node->sequence)); 12988de56ccSmrg assert(dpy->xcb->pending_requests_tail->next == NULL); 13088de56ccSmrg dpy->xcb->pending_requests_tail->next = node; 1311ab64890Smrg } 13288de56ccSmrg else 13388de56ccSmrg dpy->xcb->pending_requests = node; 13488de56ccSmrg dpy->xcb->pending_requests_tail = node; 13588de56ccSmrg return node; 1361ab64890Smrg} 1371ab64890Smrg 13888de56ccSmrgstatic void dequeue_pending_request(Display *dpy, PendingRequest *req) 1391ab64890Smrg{ 14088de56ccSmrg assert(req == dpy->xcb->pending_requests); 14188de56ccSmrg dpy->xcb->pending_requests = req->next; 14288de56ccSmrg if(!dpy->xcb->pending_requests) 1431ab64890Smrg { 14488de56ccSmrg assert(req == dpy->xcb->pending_requests_tail); 14588de56ccSmrg dpy->xcb->pending_requests_tail = NULL; 1461ab64890Smrg } 1471ab64890Smrg else 14888de56ccSmrg assert(XLIB_SEQUENCE_COMPARE(req->sequence, <, dpy->xcb->pending_requests->sequence)); 14988de56ccSmrg free(req); 15088de56ccSmrg} 15188de56ccSmrg 15288de56ccSmrgstatic int handle_error(Display *dpy, xError *err, Bool in_XReply) 15388de56ccSmrg{ 15488de56ccSmrg _XExtension *ext; 15588de56ccSmrg int ret_code; 15688de56ccSmrg /* Oddly, Xlib only allows extensions to suppress errors when 15788de56ccSmrg * those errors were seen by _XReply. */ 15888de56ccSmrg if(in_XReply) 15988de56ccSmrg /* 16088de56ccSmrg * we better see if there is an extension who may 16188de56ccSmrg * want to suppress the error. 16288de56ccSmrg */ 16388de56ccSmrg for(ext = dpy->ext_procs; ext; ext = ext->next) 16488de56ccSmrg if(ext->error && (*ext->error)(dpy, err, &ext->codes, &ret_code)) 16588de56ccSmrg return ret_code; 16688de56ccSmrg _XError(dpy, err); 16788de56ccSmrg return 0; 1681ab64890Smrg} 1691ab64890Smrg 17061b2299dSmrg/* Widen a 32-bit sequence number into a native-word-size (unsigned long) 17161b2299dSmrg * sequence number. Treating the comparison as a 1 and shifting it avoids a 17261b2299dSmrg * conditional branch, and shifting by 16 twice avoids a compiler warning when 17361b2299dSmrg * sizeof(unsigned long) == 4. */ 17461b2299dSmrgstatic void widen(unsigned long *wide, unsigned int narrow) 17561b2299dSmrg{ 17661b2299dSmrg unsigned long new = (*wide & ~0xFFFFFFFFUL) | narrow; 17761b2299dSmrg *wide = new + ((unsigned long) (new < *wide) << 16 << 16); 17861b2299dSmrg} 17961b2299dSmrg 18088de56ccSmrg/* Thread-safety rules: 18188de56ccSmrg * 18288de56ccSmrg * At most one thread can be reading from XCB's event queue at a time. 18388de56ccSmrg * If you are not the current event-reading thread and you need to find 18488de56ccSmrg * out if an event is available, you must wait. 18588de56ccSmrg * 18688de56ccSmrg * The same rule applies for reading replies. 18788de56ccSmrg * 18888de56ccSmrg * A single thread cannot be both the the event-reading and the 18988de56ccSmrg * reply-reading thread at the same time. 19088de56ccSmrg * 19188de56ccSmrg * We always look at both the current event and the first pending reply 19288de56ccSmrg * to decide which to process next. 19388de56ccSmrg * 19488de56ccSmrg * We always process all responses in sequence-number order, which may 19588de56ccSmrg * mean waiting for another thread (either the event_waiter or the 19688de56ccSmrg * reply_waiter) to handle an earlier response before we can process or 19788de56ccSmrg * return a later one. If so, we wait on the corresponding condition 19888de56ccSmrg * variable for that thread to process the response and wake us up. 19988de56ccSmrg */ 2001ab64890Smrg 20188de56ccSmrgstatic xcb_generic_reply_t *poll_for_event(Display *dpy) 20288de56ccSmrg{ 20388de56ccSmrg /* Make sure the Display's sequence numbers are valid */ 20461b2299dSmrg require_socket(dpy); 20561b2299dSmrg 20688de56ccSmrg /* Precondition: This thread can safely get events from XCB. */ 20788de56ccSmrg assert(dpy->xcb->event_owner == XlibOwnsEventQueue && !dpy->xcb->event_waiter); 20888de56ccSmrg 20988de56ccSmrg if(!dpy->xcb->next_event) 21088de56ccSmrg dpy->xcb->next_event = xcb_poll_for_event(dpy->xcb->connection); 21188de56ccSmrg 21288de56ccSmrg if(dpy->xcb->next_event) 2131ab64890Smrg { 2141ab64890Smrg PendingRequest *req = dpy->xcb->pending_requests; 21588de56ccSmrg xcb_generic_event_t *event = dpy->xcb->next_event; 21661b2299dSmrg unsigned long event_sequence = dpy->last_request_read; 21788de56ccSmrg widen(&event_sequence, event->full_sequence); 21888de56ccSmrg if(!req || XLIB_SEQUENCE_COMPARE(event_sequence, <, req->sequence) 21988de56ccSmrg || (event->response_type != X_Error && event_sequence == req->sequence)) 2201ab64890Smrg { 22188de56ccSmrg assert(XLIB_SEQUENCE_COMPARE(event_sequence, <=, dpy->request)); 22261b2299dSmrg dpy->last_request_read = event_sequence; 22388de56ccSmrg dpy->xcb->next_event = NULL; 22488de56ccSmrg return (xcb_generic_reply_t *) event; 2251ab64890Smrg } 22688de56ccSmrg } 22788de56ccSmrg return NULL; 22888de56ccSmrg} 22988de56ccSmrg 23088de56ccSmrgstatic xcb_generic_reply_t *poll_for_response(Display *dpy) 23188de56ccSmrg{ 23288de56ccSmrg void *response; 23388de56ccSmrg xcb_generic_error_t *error; 23488de56ccSmrg PendingRequest *req; 23588de56ccSmrg while(!(response = poll_for_event(dpy)) && 23688de56ccSmrg (req = dpy->xcb->pending_requests) && 23788de56ccSmrg !req->reply_waiter && 23888de56ccSmrg xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &response, &error)) 23988de56ccSmrg { 24088de56ccSmrg assert(XLIB_SEQUENCE_COMPARE(req->sequence, <=, dpy->request)); 24188de56ccSmrg dpy->last_request_read = req->sequence; 242e9fcaa8aSmrg if(response) 243e9fcaa8aSmrg break; 244e9fcaa8aSmrg dequeue_pending_request(dpy, req); 24588de56ccSmrg if(error) 24688de56ccSmrg return (xcb_generic_reply_t *) error; 24788de56ccSmrg } 24888de56ccSmrg return response; 24988de56ccSmrg} 25088de56ccSmrg 25188de56ccSmrgstatic void handle_response(Display *dpy, xcb_generic_reply_t *response, Bool in_XReply) 25288de56ccSmrg{ 25388de56ccSmrg _XAsyncHandler *async, *next; 25488de56ccSmrg switch(response->response_type) 25588de56ccSmrg { 25688de56ccSmrg case X_Reply: 25788de56ccSmrg for(async = dpy->async_handlers; async; async = next) 2581ab64890Smrg { 25988de56ccSmrg next = async->next; 26088de56ccSmrg if(async->handler(dpy, (xReply *) response, (char *) response, sizeof(xReply) + (response->length << 2), async->data)) 26188de56ccSmrg break; 2621ab64890Smrg } 26388de56ccSmrg break; 26488de56ccSmrg 26588de56ccSmrg case X_Error: 26688de56ccSmrg handle_error(dpy, (xError *) response, in_XReply); 26788de56ccSmrg break; 26888de56ccSmrg 26988de56ccSmrg default: /* event */ 27088de56ccSmrg /* GenericEvents may be > 32 bytes. In this case, the 27188de56ccSmrg * event struct is trailed by the additional bytes. the 27288de56ccSmrg * xcb_generic_event_t struct uses 4 bytes for internal 27388de56ccSmrg * numbering, so we need to shift the trailing data to 27488de56ccSmrg * be after the first 32 bytes. */ 27588de56ccSmrg if(response->response_type == GenericEvent && ((xcb_ge_event_t *) response)->length) 2761ab64890Smrg { 27788de56ccSmrg xcb_ge_event_t *event = (xcb_ge_event_t *) response; 27888de56ccSmrg memmove(&event->full_sequence, &event[1], event->length * 4); 2791ab64890Smrg } 28088de56ccSmrg _XEnq(dpy, (xEvent *) response); 28188de56ccSmrg break; 2821ab64890Smrg } 28388de56ccSmrg free(response); 2841ab64890Smrg} 2851ab64890Smrg 2861ab64890Smrgint _XEventsQueued(Display *dpy, int mode) 2871ab64890Smrg{ 28888de56ccSmrg xcb_generic_reply_t *response; 2891ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2901ab64890Smrg return 0; 2911ab64890Smrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 2921ab64890Smrg return 0; 2931ab64890Smrg 2941ab64890Smrg if(mode == QueuedAfterFlush) 29561b2299dSmrg _XSend(dpy, NULL, 0); 2961ab64890Smrg else 2971ab64890Smrg check_internal_connections(dpy); 29888de56ccSmrg 29988de56ccSmrg /* If another thread is blocked waiting for events, then we must 30088de56ccSmrg * let that thread pick up the next event. Since it blocked, we 30188de56ccSmrg * can reasonably claim there are no new events right now. */ 30288de56ccSmrg if(!dpy->xcb->event_waiter) 30388de56ccSmrg { 30488de56ccSmrg while((response = poll_for_response(dpy))) 30588de56ccSmrg handle_response(dpy, response, False); 30688de56ccSmrg if(xcb_connection_has_error(dpy->xcb->connection)) 30788de56ccSmrg _XIOError(dpy); 30888de56ccSmrg } 3091ab64890Smrg return dpy->qlen; 3101ab64890Smrg} 3111ab64890Smrg 3121ab64890Smrg/* _XReadEvents - Flush the output queue, 3131ab64890Smrg * then read as many events as possible (but at least 1) and enqueue them 3141ab64890Smrg */ 3151ab64890Smrgvoid _XReadEvents(Display *dpy) 3161ab64890Smrg{ 31788de56ccSmrg xcb_generic_reply_t *response; 31888de56ccSmrg unsigned long serial; 31988de56ccSmrg 3201ab64890Smrg if(dpy->flags & XlibDisplayIOError) 3211ab64890Smrg return; 32261b2299dSmrg _XSend(dpy, NULL, 0); 3231ab64890Smrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 3241ab64890Smrg return; 3251ab64890Smrg check_internal_connections(dpy); 32688de56ccSmrg 32788de56ccSmrg serial = dpy->next_event_serial_num; 32888de56ccSmrg while(serial == dpy->next_event_serial_num || dpy->qlen == 0) 32988de56ccSmrg { 33088de56ccSmrg if(dpy->xcb->event_waiter) 33188de56ccSmrg { 33288de56ccSmrg ConditionWait(dpy, dpy->xcb->event_notify); 33388de56ccSmrg /* Maybe the other thread got us an event. */ 33488de56ccSmrg continue; 33588de56ccSmrg } 33688de56ccSmrg 33788de56ccSmrg if(!dpy->xcb->next_event) 33888de56ccSmrg { 33988de56ccSmrg xcb_generic_event_t *event; 34088de56ccSmrg dpy->xcb->event_waiter = 1; 34188de56ccSmrg UnlockDisplay(dpy); 34288de56ccSmrg event = xcb_wait_for_event(dpy->xcb->connection); 34357f47464Smrg /* It appears that classic Xlib respected user 34457f47464Smrg * locks when waking up after waiting for 34557f47464Smrg * events. However, if this thread did not have 34657f47464Smrg * any user locks, and another thread takes a 34757f47464Smrg * user lock and tries to read events, then we'd 34857f47464Smrg * deadlock. So we'll choose to let the thread 34957f47464Smrg * that got in first consume events, despite the 35057f47464Smrg * later thread's user locks. */ 35157f47464Smrg InternalLockDisplay(dpy, /* ignore user locks */ 1); 35288de56ccSmrg dpy->xcb->event_waiter = 0; 35388de56ccSmrg ConditionBroadcast(dpy, dpy->xcb->event_notify); 35488de56ccSmrg if(!event) 35588de56ccSmrg _XIOError(dpy); 35688de56ccSmrg dpy->xcb->next_event = event; 35788de56ccSmrg } 35888de56ccSmrg 35988de56ccSmrg /* We've established most of the conditions for 36088de56ccSmrg * poll_for_response to return non-NULL. The exceptions 36188de56ccSmrg * are connection shutdown, and finding that another 36288de56ccSmrg * thread is waiting for the next reply we'd like to 36388de56ccSmrg * process. */ 36488de56ccSmrg 36588de56ccSmrg response = poll_for_response(dpy); 36688de56ccSmrg if(response) 36788de56ccSmrg handle_response(dpy, response, False); 36888de56ccSmrg else if(dpy->xcb->pending_requests->reply_waiter) 36988de56ccSmrg { /* need braces around ConditionWait */ 37088de56ccSmrg ConditionWait(dpy, dpy->xcb->reply_notify); 37188de56ccSmrg } 37288de56ccSmrg else 37388de56ccSmrg _XIOError(dpy); 37488de56ccSmrg } 37588de56ccSmrg 37688de56ccSmrg /* The preceding loop established that there is no 37788de56ccSmrg * event_waiter--unless we just called ConditionWait because of 37888de56ccSmrg * a reply_waiter, in which case another thread may have become 37988de56ccSmrg * the event_waiter while we slept unlocked. */ 38088de56ccSmrg if(!dpy->xcb->event_waiter) 38188de56ccSmrg while((response = poll_for_response(dpy))) 38288de56ccSmrg handle_response(dpy, response, False); 38388de56ccSmrg if(xcb_connection_has_error(dpy->xcb->connection)) 38488de56ccSmrg _XIOError(dpy); 3851ab64890Smrg} 3861ab64890Smrg 3871ab64890Smrg/* 3881ab64890Smrg * _XSend - Flush the buffer and send the client data. 32 bit word aligned 3891ab64890Smrg * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. 3901ab64890Smrg * 3911ab64890Smrg * Note that the connection must not be read from once the data currently 3921ab64890Smrg * in the buffer has been written. 3931ab64890Smrg */ 3941ab64890Smrgvoid _XSend(Display *dpy, const char *data, long size) 3951ab64890Smrg{ 39661b2299dSmrg static const xReq dummy_request; 39761b2299dSmrg static char const pad[3]; 39861b2299dSmrg struct iovec vec[3]; 39961b2299dSmrg uint64_t requests; 40061b2299dSmrg _XExtension *ext; 4011ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 4021ab64890Smrg if(dpy->flags & XlibDisplayIOError) 4031ab64890Smrg return; 4041ab64890Smrg 40561b2299dSmrg if(dpy->bufptr == dpy->buffer && !size) 40661b2299dSmrg return; 4071ab64890Smrg 40861b2299dSmrg /* iff we asked XCB to set aside errors, we must pick those up 40961b2299dSmrg * eventually. iff there are async handlers, we may have just 41061b2299dSmrg * issued requests that will generate replies. in either case, 41161b2299dSmrg * we need to remember to check later. */ 41261b2299dSmrg if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers) 41361b2299dSmrg { 4142e9c7c8cSmrg uint64_t sequence; 41588de56ccSmrg for(sequence = dpy->xcb->last_flushed + 1; sequence <= dpy->request; ++sequence) 41688de56ccSmrg append_pending_request(dpy, sequence); 41761b2299dSmrg } 41861b2299dSmrg requests = dpy->request - dpy->xcb->last_flushed; 41961b2299dSmrg dpy->xcb->last_flushed = dpy->request; 4201ab64890Smrg 42161b2299dSmrg vec[0].iov_base = dpy->buffer; 42261b2299dSmrg vec[0].iov_len = dpy->bufptr - dpy->buffer; 42361b2299dSmrg vec[1].iov_base = (caddr_t) data; 42461b2299dSmrg vec[1].iov_len = size; 42561b2299dSmrg vec[2].iov_base = (caddr_t) pad; 42661b2299dSmrg vec[2].iov_len = -size & 3; 42761b2299dSmrg 42861b2299dSmrg for(ext = dpy->flushes; ext; ext = ext->next_flush) 42961b2299dSmrg { 43061b2299dSmrg int i; 43161b2299dSmrg for(i = 0; i < 3; ++i) 43261b2299dSmrg if(vec[i].iov_len) 43361b2299dSmrg ext->before_flush(dpy, &ext->codes, vec[i].iov_base, vec[i].iov_len); 43461b2299dSmrg } 4351ab64890Smrg 43661b2299dSmrg if(xcb_writev(c, vec, 3, requests) < 0) 43761b2299dSmrg _XIOError(dpy); 43861b2299dSmrg dpy->bufptr = dpy->buffer; 43961b2299dSmrg dpy->last_req = (char *) &dummy_request; 4401ab64890Smrg 4411ab64890Smrg check_internal_connections(dpy); 4421ab64890Smrg 44361b2299dSmrg _XSetSeqSyncFunction(dpy); 4441ab64890Smrg} 4451ab64890Smrg 4461ab64890Smrg/* 4471ab64890Smrg * _XFlush - Flush the X request buffer. If the buffer is empty, no 4481ab64890Smrg * action is taken. 4491ab64890Smrg */ 4501ab64890Smrgvoid _XFlush(Display *dpy) 4511ab64890Smrg{ 45261b2299dSmrg require_socket(dpy); 45361b2299dSmrg _XSend(dpy, NULL, 0); 4541ab64890Smrg 4551ab64890Smrg _XEventsQueued(dpy, QueuedAfterReading); 4561ab64890Smrg} 4571ab64890Smrg 45861b2299dSmrgstatic const XID inval_id = ~0UL; 45961b2299dSmrg 46088de56ccSmrgvoid _XIDHandler(Display *dpy) 4611ab64890Smrg{ 46288de56ccSmrg if (dpy->xcb->next_xid == inval_id) 46388de56ccSmrg _XAllocIDs(dpy, &dpy->xcb->next_xid, 1); 4641ab64890Smrg} 4651ab64890Smrg 4661ab64890Smrg/* _XAllocID - resource ID allocation routine. */ 4671ab64890SmrgXID _XAllocID(Display *dpy) 4681ab64890Smrg{ 4691ab64890Smrg XID ret = dpy->xcb->next_xid; 47061b2299dSmrg assert (ret != inval_id); 47161b2299dSmrg dpy->xcb->next_xid = inval_id; 47261b2299dSmrg _XSetPrivSyncFunction(dpy); 4731ab64890Smrg return ret; 4741ab64890Smrg} 4751ab64890Smrg 4761ab64890Smrg/* _XAllocIDs - multiple resource ID allocation routine. */ 4771ab64890Smrgvoid _XAllocIDs(Display *dpy, XID *ids, int count) 4781ab64890Smrg{ 4791ab64890Smrg int i; 48061b2299dSmrg#ifdef XTHREADS 48161b2299dSmrg if (dpy->lock) 48261b2299dSmrg (*dpy->lock->user_lock_display)(dpy); 48361b2299dSmrg UnlockDisplay(dpy); 48461b2299dSmrg#endif 4851ab64890Smrg for (i = 0; i < count; i++) 4861ab64890Smrg ids[i] = xcb_generate_id(dpy->xcb->connection); 48761b2299dSmrg#ifdef XTHREADS 48888de56ccSmrg InternalLockDisplay(dpy, /* don't skip user locks */ 0); 48961b2299dSmrg if (dpy->lock) 49061b2299dSmrg (*dpy->lock->user_unlock_display)(dpy); 49161b2299dSmrg#endif 4921ab64890Smrg} 4931ab64890Smrg 4941ab64890Smrgstatic void _XFreeReplyData(Display *dpy, Bool force) 4951ab64890Smrg{ 4961ab64890Smrg if(!force && dpy->xcb->reply_consumed < dpy->xcb->reply_length) 4971ab64890Smrg return; 4981ab64890Smrg free(dpy->xcb->reply_data); 49961b2299dSmrg dpy->xcb->reply_data = NULL; 5001ab64890Smrg} 5011ab64890Smrg 5021ab64890Smrg/* 5031ab64890Smrg * _XReply - Wait for a reply packet and copy its contents into the 5041ab64890Smrg * specified rep. 5051ab64890Smrg * extra: number of 32-bit words expected after the reply 5061ab64890Smrg * discard: should I discard data following "extra" words? 5071ab64890Smrg */ 5081ab64890SmrgStatus _XReply(Display *dpy, xReply *rep, int extra, Bool discard) 5091ab64890Smrg{ 5101ab64890Smrg xcb_generic_error_t *error; 5111ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 5121ab64890Smrg char *reply; 5131ab64890Smrg PendingRequest *current; 5141ab64890Smrg 5151ab64890Smrg assert(!dpy->xcb->reply_data); 5161ab64890Smrg 5171ab64890Smrg if(dpy->flags & XlibDisplayIOError) 5181ab64890Smrg return 0; 5191ab64890Smrg 52061b2299dSmrg _XSend(dpy, NULL, 0); 52188de56ccSmrg if(dpy->xcb->pending_requests_tail && dpy->xcb->pending_requests_tail->sequence == dpy->request) 52288de56ccSmrg current = dpy->xcb->pending_requests_tail; 52388de56ccSmrg else 52488de56ccSmrg current = append_pending_request(dpy, dpy->request); 52588de56ccSmrg /* Don't let any other thread get this reply. */ 52688de56ccSmrg current->reply_waiter = 1; 52788de56ccSmrg 52888de56ccSmrg while(1) 52988de56ccSmrg { 53088de56ccSmrg PendingRequest *req = dpy->xcb->pending_requests; 53188de56ccSmrg xcb_generic_reply_t *response; 5321ab64890Smrg 53388de56ccSmrg if(req != current && req->reply_waiter) 53488de56ccSmrg { 53588de56ccSmrg ConditionWait(dpy, dpy->xcb->reply_notify); 53688de56ccSmrg /* Another thread got this reply. */ 53788de56ccSmrg continue; 53888de56ccSmrg } 53988de56ccSmrg req->reply_waiter = 1; 54088de56ccSmrg UnlockDisplay(dpy); 54188de56ccSmrg response = xcb_wait_for_reply(c, req->sequence, &error); 54257f47464Smrg /* Any user locks on another thread must have been taken 54357f47464Smrg * while we slept in xcb_wait_for_reply. Classic Xlib 54457f47464Smrg * ignored those user locks in this case, so we do too. */ 54557f47464Smrg InternalLockDisplay(dpy, /* ignore user locks */ 1); 54688de56ccSmrg 54788de56ccSmrg /* We have the response we're looking for. Now, before 54888de56ccSmrg * letting anyone else process this sequence number, we 54988de56ccSmrg * need to process any events that should have come 55088de56ccSmrg * earlier. */ 55188de56ccSmrg 55288de56ccSmrg if(dpy->xcb->event_owner == XlibOwnsEventQueue) 55388de56ccSmrg { 55488de56ccSmrg xcb_generic_reply_t *event; 55588de56ccSmrg /* If some thread is already waiting for events, 55688de56ccSmrg * it will get the first one. That thread must 55788de56ccSmrg * process that event before we can continue. */ 55888de56ccSmrg /* FIXME: That event might be after this reply, 55988de56ccSmrg * and might never even come--or there might be 56088de56ccSmrg * multiple threads trying to get events. */ 56188de56ccSmrg while(dpy->xcb->event_waiter) 56288de56ccSmrg { /* need braces around ConditionWait */ 56388de56ccSmrg ConditionWait(dpy, dpy->xcb->event_notify); 56488de56ccSmrg } 56588de56ccSmrg while((event = poll_for_event(dpy))) 56688de56ccSmrg handle_response(dpy, event, True); 56788de56ccSmrg } 56888de56ccSmrg 56988de56ccSmrg req->reply_waiter = 0; 57088de56ccSmrg ConditionBroadcast(dpy, dpy->xcb->reply_notify); 57188de56ccSmrg assert(XLIB_SEQUENCE_COMPARE(req->sequence, <=, dpy->request)); 57288de56ccSmrg dpy->last_request_read = req->sequence; 57388de56ccSmrg if(!response) 57488de56ccSmrg dequeue_pending_request(dpy, req); 57588de56ccSmrg 57688de56ccSmrg if(req == current) 57788de56ccSmrg { 57888de56ccSmrg reply = (char *) response; 57988de56ccSmrg break; 58088de56ccSmrg } 58188de56ccSmrg 58288de56ccSmrg if(error) 58388de56ccSmrg handle_response(dpy, (xcb_generic_reply_t *) error, True); 58488de56ccSmrg else if(response) 58588de56ccSmrg handle_response(dpy, response, True); 58688de56ccSmrg } 5871ab64890Smrg check_internal_connections(dpy); 58888de56ccSmrg 58988de56ccSmrg if(dpy->xcb->next_event && dpy->xcb->next_event->response_type == X_Error) 59088de56ccSmrg { 59188de56ccSmrg xcb_generic_event_t *event = dpy->xcb->next_event; 59288de56ccSmrg unsigned long event_sequence = dpy->last_request_read; 59388de56ccSmrg widen(&event_sequence, event->full_sequence); 59461234c2cSmrg if(event_sequence == dpy->last_request_read) 59588de56ccSmrg { 59688de56ccSmrg error = (xcb_generic_error_t *) event; 59788de56ccSmrg dpy->xcb->next_event = NULL; 59888de56ccSmrg } 59988de56ccSmrg } 6001ab64890Smrg 6011ab64890Smrg if(error) 6021ab64890Smrg { 6031ab64890Smrg int ret_code; 6041ab64890Smrg 6051ab64890Smrg /* Xlib is evil and assumes that even errors will be 6061ab64890Smrg * copied into rep. */ 6071ab64890Smrg memcpy(rep, error, 32); 6081ab64890Smrg 6091ab64890Smrg /* do not die on "no such font", "can't allocate", 6101ab64890Smrg "can't grab" failures */ 61188de56ccSmrg switch(error->error_code) 6121ab64890Smrg { 6131ab64890Smrg case BadName: 61488de56ccSmrg switch(error->major_code) 6151ab64890Smrg { 6161ab64890Smrg case X_LookupColor: 6171ab64890Smrg case X_AllocNamedColor: 61861b2299dSmrg free(error); 6191ab64890Smrg return 0; 6201ab64890Smrg } 6211ab64890Smrg break; 6221ab64890Smrg case BadFont: 62388de56ccSmrg if(error->major_code == X_QueryFont) { 62461b2299dSmrg free(error); 6251ab64890Smrg return 0; 62661b2299dSmrg } 6271ab64890Smrg break; 6281ab64890Smrg case BadAlloc: 6291ab64890Smrg case BadAccess: 63061b2299dSmrg free(error); 6311ab64890Smrg return 0; 6321ab64890Smrg } 6331ab64890Smrg 63488de56ccSmrg ret_code = handle_error(dpy, (xError *) error, True); 63561b2299dSmrg free(error); 63688de56ccSmrg return ret_code; 6371ab64890Smrg } 6381ab64890Smrg 6391ab64890Smrg /* it's not an error, but we don't have a reply, so it's an I/O 6401ab64890Smrg * error. */ 6411ab64890Smrg if(!reply) 6421ab64890Smrg { 6431ab64890Smrg _XIOError(dpy); 6441ab64890Smrg return 0; 6451ab64890Smrg } 6461ab64890Smrg 6471ab64890Smrg /* there's no error and we have a reply. */ 6481ab64890Smrg dpy->xcb->reply_data = reply; 6491ab64890Smrg dpy->xcb->reply_consumed = sizeof(xReply) + (extra * 4); 6501ab64890Smrg dpy->xcb->reply_length = sizeof(xReply); 6511ab64890Smrg if(dpy->xcb->reply_data[0] == 1) 6521ab64890Smrg dpy->xcb->reply_length += (((xcb_generic_reply_t *) dpy->xcb->reply_data)->length * 4); 6531ab64890Smrg 6541ab64890Smrg /* error: Xlib asks too much. give them what we can anyway. */ 6551ab64890Smrg if(dpy->xcb->reply_length < dpy->xcb->reply_consumed) 6561ab64890Smrg dpy->xcb->reply_consumed = dpy->xcb->reply_length; 6571ab64890Smrg 6581ab64890Smrg memcpy(rep, dpy->xcb->reply_data, dpy->xcb->reply_consumed); 6591ab64890Smrg _XFreeReplyData(dpy, discard); 6601ab64890Smrg return 1; 6611ab64890Smrg} 6621ab64890Smrg 6631ab64890Smrgint _XRead(Display *dpy, char *data, long size) 6641ab64890Smrg{ 6651ab64890Smrg assert(size >= 0); 6661ab64890Smrg if(size == 0) 6671ab64890Smrg return 0; 66861b2299dSmrg assert(dpy->xcb->reply_data != NULL); 6691ab64890Smrg assert(dpy->xcb->reply_consumed + size <= dpy->xcb->reply_length); 6701ab64890Smrg memcpy(data, dpy->xcb->reply_data + dpy->xcb->reply_consumed, size); 6711ab64890Smrg dpy->xcb->reply_consumed += size; 6721ab64890Smrg _XFreeReplyData(dpy, False); 6731ab64890Smrg return 0; 6741ab64890Smrg} 6751ab64890Smrg 6761ab64890Smrg/* 6771ab64890Smrg * _XReadPad - Read bytes from the socket taking into account incomplete 6781ab64890Smrg * reads. If the number of bytes is not 0 mod 4, read additional pad 6791ab64890Smrg * bytes. 6801ab64890Smrg */ 6811ab64890Smrgvoid _XReadPad(Display *dpy, char *data, long size) 6821ab64890Smrg{ 6831ab64890Smrg _XRead(dpy, data, size); 6841ab64890Smrg dpy->xcb->reply_consumed += -size & 3; 6851ab64890Smrg _XFreeReplyData(dpy, False); 6861ab64890Smrg} 6871ab64890Smrg 6881ab64890Smrg/* Read and discard "n" 8-bit bytes of data */ 6891ab64890Smrgvoid _XEatData(Display *dpy, unsigned long n) 6901ab64890Smrg{ 6911ab64890Smrg dpy->xcb->reply_consumed += n; 6921ab64890Smrg _XFreeReplyData(dpy, False); 6931ab64890Smrg} 694