xcb_io.c revision b4ee4795
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> 1561b2299dSmrg#include <inttypes.h> 1661b2299dSmrg#include <stdint.h> 171ab64890Smrg#include <stdlib.h> 181ab64890Smrg#include <string.h> 19b4ee4795Smrg#ifdef HAVE_SYS_SELECT_H 20b4ee4795Smrg#include <sys/select.h> 21b4ee4795Smrg#endif 221ab64890Smrg 2361b2299dSmrgstatic void return_socket(void *closure) 2461b2299dSmrg{ 2561b2299dSmrg Display *dpy = closure; 2661b2299dSmrg LockDisplay(dpy); 2761b2299dSmrg _XSend(dpy, NULL, 0); 2861b2299dSmrg dpy->bufmax = dpy->buffer; 2961b2299dSmrg UnlockDisplay(dpy); 3061b2299dSmrg} 3161b2299dSmrg 3261b2299dSmrgstatic void require_socket(Display *dpy) 3361b2299dSmrg{ 3461b2299dSmrg if(dpy->bufmax == dpy->buffer) 3561b2299dSmrg { 3661b2299dSmrg uint64_t sent; 3761b2299dSmrg int flags = 0; 3861b2299dSmrg /* if we don't own the event queue, we have to ask XCB 3961b2299dSmrg * to set our errors aside for us. */ 4061b2299dSmrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 4161b2299dSmrg flags = XCB_REQUEST_CHECKED; 4261b2299dSmrg if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy, 4361b2299dSmrg flags, &sent)) 4461b2299dSmrg _XIOError(dpy); 4561b2299dSmrg /* Xlib uses unsigned long for sequence numbers. XCB 4661b2299dSmrg * uses 64-bit internally, but currently exposes an 4761b2299dSmrg * unsigned int API. If these differ, Xlib cannot track 4861b2299dSmrg * the full 64-bit sequence number if 32-bit wrap 4961b2299dSmrg * happens while Xlib does not own the socket. A 5061b2299dSmrg * complete fix would be to make XCB's public API use 5161b2299dSmrg * 64-bit sequence numbers. */ 5261b2299dSmrg assert(!(sizeof(unsigned long) > sizeof(unsigned int) 5361b2299dSmrg && dpy->xcb->event_owner == XlibOwnsEventQueue 5461b2299dSmrg && (sent - dpy->last_request_read >= (UINT64_C(1) << 32)))); 5561b2299dSmrg dpy->xcb->last_flushed = dpy->request = sent; 5661b2299dSmrg dpy->bufmax = dpy->xcb->real_bufmax; 5761b2299dSmrg } 5861b2299dSmrg} 5961b2299dSmrg 601ab64890Smrg/* Call internal connection callbacks for any fds that are currently 611ab64890Smrg * ready to read. This function will not block unless one of the 621ab64890Smrg * callbacks blocks. 631ab64890Smrg * 641ab64890Smrg * This code borrowed from _XWaitForReadable. Inverse call tree: 651ab64890Smrg * _XRead 661ab64890Smrg * _XWaitForWritable 671ab64890Smrg * _XFlush 681ab64890Smrg * _XSend 691ab64890Smrg * _XEventsQueued 701ab64890Smrg * _XReadEvents 711ab64890Smrg * _XRead[0-9]+ 721ab64890Smrg * _XAllocIDs 731ab64890Smrg * _XReply 741ab64890Smrg * _XEatData 751ab64890Smrg * _XReadPad 761ab64890Smrg */ 771ab64890Smrgstatic void check_internal_connections(Display *dpy) 781ab64890Smrg{ 7961b2299dSmrg struct _XConnectionInfo *ilist; 801ab64890Smrg fd_set r_mask; 811ab64890Smrg struct timeval tv; 821ab64890Smrg int result; 831ab64890Smrg int highest_fd = -1; 841ab64890Smrg 851ab64890Smrg if(dpy->flags & XlibDisplayProcConni || !dpy->im_fd_info) 861ab64890Smrg return; 871ab64890Smrg 881ab64890Smrg FD_ZERO(&r_mask); 891ab64890Smrg for(ilist = dpy->im_fd_info; ilist; ilist = ilist->next) 901ab64890Smrg { 911ab64890Smrg assert(ilist->fd >= 0); 921ab64890Smrg FD_SET(ilist->fd, &r_mask); 931ab64890Smrg if(ilist->fd > highest_fd) 941ab64890Smrg highest_fd = ilist->fd; 951ab64890Smrg } 961ab64890Smrg assert(highest_fd >= 0); 971ab64890Smrg 981ab64890Smrg tv.tv_sec = 0; 991ab64890Smrg tv.tv_usec = 0; 1001ab64890Smrg result = select(highest_fd + 1, &r_mask, NULL, NULL, &tv); 1011ab64890Smrg 1021ab64890Smrg if(result == -1) 1031ab64890Smrg { 1041ab64890Smrg if(errno == EINTR) 1051ab64890Smrg return; 1061ab64890Smrg _XIOError(dpy); 1071ab64890Smrg } 1081ab64890Smrg 1091ab64890Smrg for(ilist = dpy->im_fd_info; result && ilist; ilist = ilist->next) 1101ab64890Smrg if(FD_ISSET(ilist->fd, &r_mask)) 1111ab64890Smrg { 1121ab64890Smrg _XProcessInternalConnection(dpy, ilist); 1131ab64890Smrg --result; 1141ab64890Smrg } 1151ab64890Smrg} 1161ab64890Smrg 1171ab64890Smrgstatic void call_handlers(Display *dpy, xcb_generic_reply_t *buf) 1181ab64890Smrg{ 1191ab64890Smrg _XAsyncHandler *async, *next; 1201ab64890Smrg for(async = dpy->async_handlers; async; async = next) 1211ab64890Smrg { 1221ab64890Smrg next = async->next; 1231ab64890Smrg if(async->handler(dpy, (xReply *) buf, (char *) buf, sizeof(xReply) + (buf->length << 2), async->data)) 1241ab64890Smrg return; 1251ab64890Smrg } 1261ab64890Smrg if(buf->response_type == 0) /* unhandled error */ 1271ab64890Smrg _XError(dpy, (xError *) buf); 1281ab64890Smrg} 1291ab64890Smrg 1301ab64890Smrgstatic xcb_generic_event_t * wait_or_poll_for_event(Display *dpy, int wait) 1311ab64890Smrg{ 1321ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 1331ab64890Smrg xcb_generic_event_t *event; 1341ab64890Smrg if(wait) 1351ab64890Smrg { 13661b2299dSmrg if(dpy->xcb->event_waiter) 13761b2299dSmrg { 13861b2299dSmrg ConditionWait(dpy, dpy->xcb->event_notify); 13961b2299dSmrg event = xcb_poll_for_event(c); 14061b2299dSmrg } 14161b2299dSmrg else 14261b2299dSmrg { 14361b2299dSmrg dpy->xcb->event_waiter = 1; 14461b2299dSmrg UnlockDisplay(dpy); 14561b2299dSmrg event = xcb_wait_for_event(c); 14661b2299dSmrg LockDisplay(dpy); 14761b2299dSmrg dpy->xcb->event_waiter = 0; 14861b2299dSmrg ConditionBroadcast(dpy, dpy->xcb->event_notify); 14961b2299dSmrg } 1501ab64890Smrg } 1511ab64890Smrg else 1521ab64890Smrg event = xcb_poll_for_event(c); 1531ab64890Smrg return event; 1541ab64890Smrg} 1551ab64890Smrg 15661b2299dSmrg/* Widen a 32-bit sequence number into a native-word-size (unsigned long) 15761b2299dSmrg * sequence number. Treating the comparison as a 1 and shifting it avoids a 15861b2299dSmrg * conditional branch, and shifting by 16 twice avoids a compiler warning when 15961b2299dSmrg * sizeof(unsigned long) == 4. */ 16061b2299dSmrgstatic void widen(unsigned long *wide, unsigned int narrow) 16161b2299dSmrg{ 16261b2299dSmrg unsigned long new = (*wide & ~0xFFFFFFFFUL) | narrow; 16361b2299dSmrg *wide = new + ((unsigned long) (new < *wide) << 16 << 16); 16461b2299dSmrg} 16561b2299dSmrg 16661b2299dSmrgstatic void process_responses(Display *dpy, int wait_for_first_event, xcb_generic_error_t **current_error, unsigned long current_request) 1671ab64890Smrg{ 1681ab64890Smrg void *reply; 1691ab64890Smrg xcb_generic_event_t *event = dpy->xcb->next_event; 1701ab64890Smrg xcb_generic_error_t *error; 1711ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 1721ab64890Smrg if(!event && dpy->xcb->event_owner == XlibOwnsEventQueue) 1731ab64890Smrg event = wait_or_poll_for_event(dpy, wait_for_first_event); 1741ab64890Smrg 17561b2299dSmrg require_socket(dpy); 17661b2299dSmrg 1771ab64890Smrg while(1) 1781ab64890Smrg { 1791ab64890Smrg PendingRequest *req = dpy->xcb->pending_requests; 18061b2299dSmrg unsigned long event_sequence = dpy->last_request_read; 18161b2299dSmrg if(event) 18261b2299dSmrg widen(&event_sequence, event->full_sequence); 18361b2299dSmrg assert(!(req && current_request && !XLIB_SEQUENCE_COMPARE(req->sequence, <=, current_request))); 18461b2299dSmrg if(event && (!req || XLIB_SEQUENCE_COMPARE(event_sequence, <=, req->sequence))) 1851ab64890Smrg { 18661b2299dSmrg dpy->last_request_read = event_sequence; 1871ab64890Smrg if(event->response_type != X_Error) 1881ab64890Smrg { 18961b2299dSmrg /* GenericEvents may be > 32 bytes. In this 19061b2299dSmrg * case, the event struct is trailed by the 19161b2299dSmrg * additional bytes. the xcb_generic_event_t 19261b2299dSmrg * struct uses 4 bytes for internal numbering, 19361b2299dSmrg * so we need to shift the trailing data to be 19461b2299dSmrg * after the first 32 bytes. */ 19561b2299dSmrg if (event->response_type == GenericEvent && 19661b2299dSmrg ((xcb_ge_event_t*)event)->length) 19761b2299dSmrg { 19861b2299dSmrg memmove(&event->full_sequence, 19961b2299dSmrg &event[1], 20061b2299dSmrg ((xcb_ge_event_t*)event)->length * 4); 20161b2299dSmrg } 2021ab64890Smrg _XEnq(dpy, (xEvent *) event); 2031ab64890Smrg wait_for_first_event = 0; 2041ab64890Smrg } 20561b2299dSmrg else if(current_error && event_sequence == current_request) 2061ab64890Smrg { 2071ab64890Smrg /* This can only occur when called from 2081ab64890Smrg * _XReply, which doesn't need a new event. */ 2091ab64890Smrg *current_error = (xcb_generic_error_t *) event; 21061b2299dSmrg event = NULL; 2111ab64890Smrg break; 2121ab64890Smrg } 2131ab64890Smrg else 2141ab64890Smrg _XError(dpy, (xError *) event); 2151ab64890Smrg free(event); 2161ab64890Smrg event = wait_or_poll_for_event(dpy, wait_for_first_event); 2171ab64890Smrg } 21861b2299dSmrg else if(req && req->sequence == current_request) 2191ab64890Smrg { 22061b2299dSmrg break; 2211ab64890Smrg } 2221ab64890Smrg else if(req && xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &reply, &error)) 2231ab64890Smrg { 2242e9c7c8cSmrg uint64_t sequence = req->sequence; 2251ab64890Smrg if(!reply) 2261ab64890Smrg { 2271ab64890Smrg dpy->xcb->pending_requests = req->next; 2281ab64890Smrg if(!dpy->xcb->pending_requests) 2291ab64890Smrg dpy->xcb->pending_requests_tail = &dpy->xcb->pending_requests; 2301ab64890Smrg free(req); 2311ab64890Smrg reply = error; 2321ab64890Smrg } 2331ab64890Smrg if(reply) 2341ab64890Smrg { 2351ab64890Smrg dpy->last_request_read = sequence; 2361ab64890Smrg call_handlers(dpy, reply); 2371ab64890Smrg free(reply); 2381ab64890Smrg } 2391ab64890Smrg } 2401ab64890Smrg else 2411ab64890Smrg break; 2421ab64890Smrg } 2431ab64890Smrg 2441ab64890Smrg dpy->xcb->next_event = event; 2451ab64890Smrg 2461ab64890Smrg if(xcb_connection_has_error(c)) 2471ab64890Smrg _XIOError(dpy); 2481ab64890Smrg 24961b2299dSmrg assert(XLIB_SEQUENCE_COMPARE(dpy->last_request_read, <=, dpy->request)); 2501ab64890Smrg} 2511ab64890Smrg 2521ab64890Smrgint _XEventsQueued(Display *dpy, int mode) 2531ab64890Smrg{ 2541ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2551ab64890Smrg return 0; 2561ab64890Smrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 2571ab64890Smrg return 0; 2581ab64890Smrg 2591ab64890Smrg if(mode == QueuedAfterFlush) 26061b2299dSmrg _XSend(dpy, NULL, 0); 2611ab64890Smrg else 2621ab64890Smrg check_internal_connections(dpy); 26361b2299dSmrg process_responses(dpy, 0, NULL, 0); 2641ab64890Smrg return dpy->qlen; 2651ab64890Smrg} 2661ab64890Smrg 2671ab64890Smrg/* _XReadEvents - Flush the output queue, 2681ab64890Smrg * then read as many events as possible (but at least 1) and enqueue them 2691ab64890Smrg */ 2701ab64890Smrgvoid _XReadEvents(Display *dpy) 2711ab64890Smrg{ 2721ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2731ab64890Smrg return; 27461b2299dSmrg _XSend(dpy, NULL, 0); 2751ab64890Smrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 2761ab64890Smrg return; 2771ab64890Smrg check_internal_connections(dpy); 27861b2299dSmrg do { 27961b2299dSmrg process_responses(dpy, 1, NULL, 0); 28061b2299dSmrg } while (dpy->qlen == 0); 2811ab64890Smrg} 2821ab64890Smrg 2831ab64890Smrg/* 2841ab64890Smrg * _XSend - Flush the buffer and send the client data. 32 bit word aligned 2851ab64890Smrg * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. 2861ab64890Smrg * 2871ab64890Smrg * Note that the connection must not be read from once the data currently 2881ab64890Smrg * in the buffer has been written. 2891ab64890Smrg */ 2901ab64890Smrgvoid _XSend(Display *dpy, const char *data, long size) 2911ab64890Smrg{ 29261b2299dSmrg static const xReq dummy_request; 29361b2299dSmrg static char const pad[3]; 29461b2299dSmrg struct iovec vec[3]; 29561b2299dSmrg uint64_t requests; 29661b2299dSmrg _XExtension *ext; 2971ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 2981ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2991ab64890Smrg return; 3001ab64890Smrg 30161b2299dSmrg if(dpy->bufptr == dpy->buffer && !size) 30261b2299dSmrg return; 3031ab64890Smrg 30461b2299dSmrg /* iff we asked XCB to set aside errors, we must pick those up 30561b2299dSmrg * eventually. iff there are async handlers, we may have just 30661b2299dSmrg * issued requests that will generate replies. in either case, 30761b2299dSmrg * we need to remember to check later. */ 30861b2299dSmrg if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers) 30961b2299dSmrg { 3102e9c7c8cSmrg uint64_t sequence; 31161b2299dSmrg for(sequence = dpy->xcb->last_flushed; sequence < dpy->request; ++sequence) 31261b2299dSmrg { 31361b2299dSmrg PendingRequest *req = malloc(sizeof(PendingRequest)); 31461b2299dSmrg assert(req); 31561b2299dSmrg req->next = NULL; 31661b2299dSmrg req->sequence = sequence; 31761b2299dSmrg *dpy->xcb->pending_requests_tail = req; 31861b2299dSmrg dpy->xcb->pending_requests_tail = &req->next; 31961b2299dSmrg } 32061b2299dSmrg } 32161b2299dSmrg requests = dpy->request - dpy->xcb->last_flushed; 32261b2299dSmrg dpy->xcb->last_flushed = dpy->request; 3231ab64890Smrg 32461b2299dSmrg vec[0].iov_base = dpy->buffer; 32561b2299dSmrg vec[0].iov_len = dpy->bufptr - dpy->buffer; 32661b2299dSmrg vec[1].iov_base = (caddr_t) data; 32761b2299dSmrg vec[1].iov_len = size; 32861b2299dSmrg vec[2].iov_base = (caddr_t) pad; 32961b2299dSmrg vec[2].iov_len = -size & 3; 33061b2299dSmrg 33161b2299dSmrg for(ext = dpy->flushes; ext; ext = ext->next_flush) 33261b2299dSmrg { 33361b2299dSmrg int i; 33461b2299dSmrg for(i = 0; i < 3; ++i) 33561b2299dSmrg if(vec[i].iov_len) 33661b2299dSmrg ext->before_flush(dpy, &ext->codes, vec[i].iov_base, vec[i].iov_len); 33761b2299dSmrg } 3381ab64890Smrg 33961b2299dSmrg if(xcb_writev(c, vec, 3, requests) < 0) 34061b2299dSmrg _XIOError(dpy); 34161b2299dSmrg dpy->bufptr = dpy->buffer; 34261b2299dSmrg dpy->last_req = (char *) &dummy_request; 3431ab64890Smrg 3441ab64890Smrg check_internal_connections(dpy); 3451ab64890Smrg 34661b2299dSmrg _XSetSeqSyncFunction(dpy); 3471ab64890Smrg} 3481ab64890Smrg 3491ab64890Smrg/* 3501ab64890Smrg * _XFlush - Flush the X request buffer. If the buffer is empty, no 3511ab64890Smrg * action is taken. 3521ab64890Smrg */ 3531ab64890Smrgvoid _XFlush(Display *dpy) 3541ab64890Smrg{ 35561b2299dSmrg require_socket(dpy); 35661b2299dSmrg _XSend(dpy, NULL, 0); 3571ab64890Smrg 3581ab64890Smrg _XEventsQueued(dpy, QueuedAfterReading); 3591ab64890Smrg} 3601ab64890Smrg 36161b2299dSmrgstatic const XID inval_id = ~0UL; 36261b2299dSmrg 36361b2299dSmrgint _XIDHandler(Display *dpy) 3641ab64890Smrg{ 36561b2299dSmrg XID next; 36661b2299dSmrg 36761b2299dSmrg if (dpy->xcb->next_xid != inval_id) 36861b2299dSmrg return 0; 36961b2299dSmrg 37061b2299dSmrg next = xcb_generate_id(dpy->xcb->connection); 3711ab64890Smrg LockDisplay(dpy); 3721ab64890Smrg dpy->xcb->next_xid = next; 37361b2299dSmrg#ifdef XTHREADS 37461b2299dSmrg if (dpy->lock) 37561b2299dSmrg (*dpy->lock->user_unlock_display)(dpy); 37661b2299dSmrg#endif 3771ab64890Smrg UnlockDisplay(dpy); 3781ab64890Smrg return 0; 3791ab64890Smrg} 3801ab64890Smrg 3811ab64890Smrg/* _XAllocID - resource ID allocation routine. */ 3821ab64890SmrgXID _XAllocID(Display *dpy) 3831ab64890Smrg{ 3841ab64890Smrg XID ret = dpy->xcb->next_xid; 38561b2299dSmrg assert (ret != inval_id); 38661b2299dSmrg#ifdef XTHREADS 38761b2299dSmrg if (dpy->lock) 38861b2299dSmrg (*dpy->lock->user_lock_display)(dpy); 38961b2299dSmrg#endif 39061b2299dSmrg dpy->xcb->next_xid = inval_id; 39161b2299dSmrg _XSetPrivSyncFunction(dpy); 3921ab64890Smrg return ret; 3931ab64890Smrg} 3941ab64890Smrg 3951ab64890Smrg/* _XAllocIDs - multiple resource ID allocation routine. */ 3961ab64890Smrgvoid _XAllocIDs(Display *dpy, XID *ids, int count) 3971ab64890Smrg{ 3981ab64890Smrg int i; 39961b2299dSmrg#ifdef XTHREADS 40061b2299dSmrg if (dpy->lock) 40161b2299dSmrg (*dpy->lock->user_lock_display)(dpy); 40261b2299dSmrg UnlockDisplay(dpy); 40361b2299dSmrg#endif 4041ab64890Smrg for (i = 0; i < count; i++) 4051ab64890Smrg ids[i] = xcb_generate_id(dpy->xcb->connection); 40661b2299dSmrg#ifdef XTHREADS 40761b2299dSmrg LockDisplay(dpy); 40861b2299dSmrg if (dpy->lock) 40961b2299dSmrg (*dpy->lock->user_unlock_display)(dpy); 41061b2299dSmrg#endif 4111ab64890Smrg} 4121ab64890Smrg 4131ab64890Smrgstatic void _XFreeReplyData(Display *dpy, Bool force) 4141ab64890Smrg{ 4151ab64890Smrg if(!force && dpy->xcb->reply_consumed < dpy->xcb->reply_length) 4161ab64890Smrg return; 4171ab64890Smrg free(dpy->xcb->reply_data); 41861b2299dSmrg dpy->xcb->reply_data = NULL; 4191ab64890Smrg} 4201ab64890Smrg 4211ab64890Smrgstatic PendingRequest * insert_pending_request(Display *dpy) 4221ab64890Smrg{ 4231ab64890Smrg PendingRequest **cur = &dpy->xcb->pending_requests; 42461b2299dSmrg while(*cur && XLIB_SEQUENCE_COMPARE((*cur)->sequence, <, dpy->request)) 4251ab64890Smrg cur = &((*cur)->next); 42661b2299dSmrg if(!*cur || (*cur)->sequence != dpy->request) 4271ab64890Smrg { 4281ab64890Smrg PendingRequest *node = malloc(sizeof(PendingRequest)); 4291ab64890Smrg assert(node); 4301ab64890Smrg node->next = *cur; 4311ab64890Smrg node->sequence = dpy->request; 4321ab64890Smrg if(cur == dpy->xcb->pending_requests_tail) 4331ab64890Smrg dpy->xcb->pending_requests_tail = &(node->next); 4341ab64890Smrg *cur = node; 4351ab64890Smrg } 4361ab64890Smrg return *cur; 4371ab64890Smrg} 4381ab64890Smrg 4391ab64890Smrg/* 4401ab64890Smrg * _XReply - Wait for a reply packet and copy its contents into the 4411ab64890Smrg * specified rep. 4421ab64890Smrg * extra: number of 32-bit words expected after the reply 4431ab64890Smrg * discard: should I discard data following "extra" words? 4441ab64890Smrg */ 4451ab64890SmrgStatus _XReply(Display *dpy, xReply *rep, int extra, Bool discard) 4461ab64890Smrg{ 4471ab64890Smrg xcb_generic_error_t *error; 4481ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 4491ab64890Smrg char *reply; 4501ab64890Smrg PendingRequest *current; 4511ab64890Smrg 4521ab64890Smrg assert(!dpy->xcb->reply_data); 4531ab64890Smrg 4541ab64890Smrg if(dpy->flags & XlibDisplayIOError) 4551ab64890Smrg return 0; 4561ab64890Smrg 45761b2299dSmrg _XSend(dpy, NULL, 0); 4581ab64890Smrg current = insert_pending_request(dpy); 45961b2299dSmrg /* FIXME: drop the Display lock while waiting? 46061b2299dSmrg * Complicates process_responses. */ 4611ab64890Smrg reply = xcb_wait_for_reply(c, current->sequence, &error); 4621ab64890Smrg 4631ab64890Smrg check_internal_connections(dpy); 4641ab64890Smrg process_responses(dpy, 0, &error, current->sequence); 4651ab64890Smrg 4661ab64890Smrg if(error) 4671ab64890Smrg { 4681ab64890Smrg _XExtension *ext; 4691ab64890Smrg xError *err = (xError *) error; 4701ab64890Smrg int ret_code; 4711ab64890Smrg 4721ab64890Smrg dpy->last_request_read = error->full_sequence; 4731ab64890Smrg 4741ab64890Smrg /* Xlib is evil and assumes that even errors will be 4751ab64890Smrg * copied into rep. */ 4761ab64890Smrg memcpy(rep, error, 32); 4771ab64890Smrg 4781ab64890Smrg /* do not die on "no such font", "can't allocate", 4791ab64890Smrg "can't grab" failures */ 4801ab64890Smrg switch(err->errorCode) 4811ab64890Smrg { 4821ab64890Smrg case BadName: 4831ab64890Smrg switch(err->majorCode) 4841ab64890Smrg { 4851ab64890Smrg case X_LookupColor: 4861ab64890Smrg case X_AllocNamedColor: 48761b2299dSmrg free(error); 4881ab64890Smrg return 0; 4891ab64890Smrg } 4901ab64890Smrg break; 4911ab64890Smrg case BadFont: 49261b2299dSmrg if(err->majorCode == X_QueryFont) { 49361b2299dSmrg free(error); 4941ab64890Smrg return 0; 49561b2299dSmrg } 4961ab64890Smrg break; 4971ab64890Smrg case BadAlloc: 4981ab64890Smrg case BadAccess: 49961b2299dSmrg free(error); 5001ab64890Smrg return 0; 5011ab64890Smrg } 5021ab64890Smrg 50361b2299dSmrg /* 5041ab64890Smrg * we better see if there is an extension who may 5051ab64890Smrg * want to suppress the error. 5061ab64890Smrg */ 5071ab64890Smrg for(ext = dpy->ext_procs; ext; ext = ext->next) 50861b2299dSmrg if(ext->error && ext->error(dpy, err, &ext->codes, &ret_code)) { 50961b2299dSmrg free(error); 5101ab64890Smrg return ret_code; 51161b2299dSmrg } 5121ab64890Smrg 51361b2299dSmrg _XError(dpy, err); 51461b2299dSmrg free(error); 5151ab64890Smrg return 0; 5161ab64890Smrg } 5171ab64890Smrg 5181ab64890Smrg /* it's not an error, but we don't have a reply, so it's an I/O 5191ab64890Smrg * error. */ 5201ab64890Smrg if(!reply) 5211ab64890Smrg { 5221ab64890Smrg _XIOError(dpy); 5231ab64890Smrg return 0; 5241ab64890Smrg } 5251ab64890Smrg 5261ab64890Smrg dpy->last_request_read = current->sequence; 5271ab64890Smrg 5281ab64890Smrg /* there's no error and we have a reply. */ 5291ab64890Smrg dpy->xcb->reply_data = reply; 5301ab64890Smrg dpy->xcb->reply_consumed = sizeof(xReply) + (extra * 4); 5311ab64890Smrg dpy->xcb->reply_length = sizeof(xReply); 5321ab64890Smrg if(dpy->xcb->reply_data[0] == 1) 5331ab64890Smrg dpy->xcb->reply_length += (((xcb_generic_reply_t *) dpy->xcb->reply_data)->length * 4); 5341ab64890Smrg 5351ab64890Smrg /* error: Xlib asks too much. give them what we can anyway. */ 5361ab64890Smrg if(dpy->xcb->reply_length < dpy->xcb->reply_consumed) 5371ab64890Smrg dpy->xcb->reply_consumed = dpy->xcb->reply_length; 5381ab64890Smrg 5391ab64890Smrg memcpy(rep, dpy->xcb->reply_data, dpy->xcb->reply_consumed); 5401ab64890Smrg _XFreeReplyData(dpy, discard); 5411ab64890Smrg return 1; 5421ab64890Smrg} 5431ab64890Smrg 5441ab64890Smrgint _XRead(Display *dpy, char *data, long size) 5451ab64890Smrg{ 5461ab64890Smrg assert(size >= 0); 5471ab64890Smrg if(size == 0) 5481ab64890Smrg return 0; 54961b2299dSmrg assert(dpy->xcb->reply_data != NULL); 5501ab64890Smrg assert(dpy->xcb->reply_consumed + size <= dpy->xcb->reply_length); 5511ab64890Smrg memcpy(data, dpy->xcb->reply_data + dpy->xcb->reply_consumed, size); 5521ab64890Smrg dpy->xcb->reply_consumed += size; 5531ab64890Smrg _XFreeReplyData(dpy, False); 5541ab64890Smrg return 0; 5551ab64890Smrg} 5561ab64890Smrg 5571ab64890Smrg/* 5581ab64890Smrg * _XReadPad - Read bytes from the socket taking into account incomplete 5591ab64890Smrg * reads. If the number of bytes is not 0 mod 4, read additional pad 5601ab64890Smrg * bytes. 5611ab64890Smrg */ 5621ab64890Smrgvoid _XReadPad(Display *dpy, char *data, long size) 5631ab64890Smrg{ 5641ab64890Smrg _XRead(dpy, data, size); 5651ab64890Smrg dpy->xcb->reply_consumed += -size & 3; 5661ab64890Smrg _XFreeReplyData(dpy, False); 5671ab64890Smrg} 5681ab64890Smrg 5691ab64890Smrg/* Read and discard "n" 8-bit bytes of data */ 5701ab64890Smrgvoid _XEatData(Display *dpy, unsigned long n) 5711ab64890Smrg{ 5721ab64890Smrg dpy->xcb->reply_consumed += n; 5731ab64890Smrg _XFreeReplyData(dpy, False); 5741ab64890Smrg} 575