xcb_io.c revision 2e9c7c8c
11ab64890Smrg/* Copyright (C) 2003-2006 Jamey Sharp, Josh Triplett 21ab64890Smrg * This file is licensed under the MIT license. See the file COPYING. */ 31ab64890Smrg 41ab64890Smrg#include "Xlibint.h" 51ab64890Smrg#include "locking.h" 661b2299dSmrg#include "Xprivate.h" 71ab64890Smrg#include "Xxcbint.h" 81ab64890Smrg#include <xcb/xcbext.h> 91ab64890Smrg 101ab64890Smrg#include <assert.h> 1161b2299dSmrg#include <inttypes.h> 1261b2299dSmrg#include <stdint.h> 131ab64890Smrg#include <stdlib.h> 141ab64890Smrg#include <string.h> 151ab64890Smrg 1661b2299dSmrgstatic void return_socket(void *closure) 1761b2299dSmrg{ 1861b2299dSmrg Display *dpy = closure; 1961b2299dSmrg LockDisplay(dpy); 2061b2299dSmrg _XSend(dpy, NULL, 0); 2161b2299dSmrg dpy->bufmax = dpy->buffer; 2261b2299dSmrg UnlockDisplay(dpy); 2361b2299dSmrg} 2461b2299dSmrg 2561b2299dSmrgstatic void require_socket(Display *dpy) 2661b2299dSmrg{ 2761b2299dSmrg if(dpy->bufmax == dpy->buffer) 2861b2299dSmrg { 2961b2299dSmrg uint64_t sent; 3061b2299dSmrg int flags = 0; 3161b2299dSmrg /* if we don't own the event queue, we have to ask XCB 3261b2299dSmrg * to set our errors aside for us. */ 3361b2299dSmrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 3461b2299dSmrg flags = XCB_REQUEST_CHECKED; 3561b2299dSmrg if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy, 3661b2299dSmrg flags, &sent)) 3761b2299dSmrg _XIOError(dpy); 3861b2299dSmrg /* Xlib uses unsigned long for sequence numbers. XCB 3961b2299dSmrg * uses 64-bit internally, but currently exposes an 4061b2299dSmrg * unsigned int API. If these differ, Xlib cannot track 4161b2299dSmrg * the full 64-bit sequence number if 32-bit wrap 4261b2299dSmrg * happens while Xlib does not own the socket. A 4361b2299dSmrg * complete fix would be to make XCB's public API use 4461b2299dSmrg * 64-bit sequence numbers. */ 4561b2299dSmrg assert(!(sizeof(unsigned long) > sizeof(unsigned int) 4661b2299dSmrg && dpy->xcb->event_owner == XlibOwnsEventQueue 4761b2299dSmrg && (sent - dpy->last_request_read >= (UINT64_C(1) << 32)))); 4861b2299dSmrg dpy->xcb->last_flushed = dpy->request = sent; 4961b2299dSmrg dpy->bufmax = dpy->xcb->real_bufmax; 5061b2299dSmrg } 5161b2299dSmrg} 5261b2299dSmrg 531ab64890Smrg/* Call internal connection callbacks for any fds that are currently 541ab64890Smrg * ready to read. This function will not block unless one of the 551ab64890Smrg * callbacks blocks. 561ab64890Smrg * 571ab64890Smrg * This code borrowed from _XWaitForReadable. Inverse call tree: 581ab64890Smrg * _XRead 591ab64890Smrg * _XWaitForWritable 601ab64890Smrg * _XFlush 611ab64890Smrg * _XSend 621ab64890Smrg * _XEventsQueued 631ab64890Smrg * _XReadEvents 641ab64890Smrg * _XRead[0-9]+ 651ab64890Smrg * _XAllocIDs 661ab64890Smrg * _XReply 671ab64890Smrg * _XEatData 681ab64890Smrg * _XReadPad 691ab64890Smrg */ 701ab64890Smrgstatic void check_internal_connections(Display *dpy) 711ab64890Smrg{ 7261b2299dSmrg struct _XConnectionInfo *ilist; 731ab64890Smrg fd_set r_mask; 741ab64890Smrg struct timeval tv; 751ab64890Smrg int result; 761ab64890Smrg int highest_fd = -1; 771ab64890Smrg 781ab64890Smrg if(dpy->flags & XlibDisplayProcConni || !dpy->im_fd_info) 791ab64890Smrg return; 801ab64890Smrg 811ab64890Smrg FD_ZERO(&r_mask); 821ab64890Smrg for(ilist = dpy->im_fd_info; ilist; ilist = ilist->next) 831ab64890Smrg { 841ab64890Smrg assert(ilist->fd >= 0); 851ab64890Smrg FD_SET(ilist->fd, &r_mask); 861ab64890Smrg if(ilist->fd > highest_fd) 871ab64890Smrg highest_fd = ilist->fd; 881ab64890Smrg } 891ab64890Smrg assert(highest_fd >= 0); 901ab64890Smrg 911ab64890Smrg tv.tv_sec = 0; 921ab64890Smrg tv.tv_usec = 0; 931ab64890Smrg result = select(highest_fd + 1, &r_mask, NULL, NULL, &tv); 941ab64890Smrg 951ab64890Smrg if(result == -1) 961ab64890Smrg { 971ab64890Smrg if(errno == EINTR) 981ab64890Smrg return; 991ab64890Smrg _XIOError(dpy); 1001ab64890Smrg } 1011ab64890Smrg 1021ab64890Smrg for(ilist = dpy->im_fd_info; result && ilist; ilist = ilist->next) 1031ab64890Smrg if(FD_ISSET(ilist->fd, &r_mask)) 1041ab64890Smrg { 1051ab64890Smrg _XProcessInternalConnection(dpy, ilist); 1061ab64890Smrg --result; 1071ab64890Smrg } 1081ab64890Smrg} 1091ab64890Smrg 1101ab64890Smrgstatic void call_handlers(Display *dpy, xcb_generic_reply_t *buf) 1111ab64890Smrg{ 1121ab64890Smrg _XAsyncHandler *async, *next; 1131ab64890Smrg for(async = dpy->async_handlers; async; async = next) 1141ab64890Smrg { 1151ab64890Smrg next = async->next; 1161ab64890Smrg if(async->handler(dpy, (xReply *) buf, (char *) buf, sizeof(xReply) + (buf->length << 2), async->data)) 1171ab64890Smrg return; 1181ab64890Smrg } 1191ab64890Smrg if(buf->response_type == 0) /* unhandled error */ 1201ab64890Smrg _XError(dpy, (xError *) buf); 1211ab64890Smrg} 1221ab64890Smrg 1231ab64890Smrgstatic xcb_generic_event_t * wait_or_poll_for_event(Display *dpy, int wait) 1241ab64890Smrg{ 1251ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 1261ab64890Smrg xcb_generic_event_t *event; 1271ab64890Smrg if(wait) 1281ab64890Smrg { 12961b2299dSmrg if(dpy->xcb->event_waiter) 13061b2299dSmrg { 13161b2299dSmrg ConditionWait(dpy, dpy->xcb->event_notify); 13261b2299dSmrg event = xcb_poll_for_event(c); 13361b2299dSmrg } 13461b2299dSmrg else 13561b2299dSmrg { 13661b2299dSmrg dpy->xcb->event_waiter = 1; 13761b2299dSmrg UnlockDisplay(dpy); 13861b2299dSmrg event = xcb_wait_for_event(c); 13961b2299dSmrg LockDisplay(dpy); 14061b2299dSmrg dpy->xcb->event_waiter = 0; 14161b2299dSmrg ConditionBroadcast(dpy, dpy->xcb->event_notify); 14261b2299dSmrg } 1431ab64890Smrg } 1441ab64890Smrg else 1451ab64890Smrg event = xcb_poll_for_event(c); 1461ab64890Smrg return event; 1471ab64890Smrg} 1481ab64890Smrg 14961b2299dSmrg/* Widen a 32-bit sequence number into a native-word-size (unsigned long) 15061b2299dSmrg * sequence number. Treating the comparison as a 1 and shifting it avoids a 15161b2299dSmrg * conditional branch, and shifting by 16 twice avoids a compiler warning when 15261b2299dSmrg * sizeof(unsigned long) == 4. */ 15361b2299dSmrgstatic void widen(unsigned long *wide, unsigned int narrow) 15461b2299dSmrg{ 15561b2299dSmrg unsigned long new = (*wide & ~0xFFFFFFFFUL) | narrow; 15661b2299dSmrg *wide = new + ((unsigned long) (new < *wide) << 16 << 16); 15761b2299dSmrg} 15861b2299dSmrg 15961b2299dSmrgstatic void process_responses(Display *dpy, int wait_for_first_event, xcb_generic_error_t **current_error, unsigned long current_request) 1601ab64890Smrg{ 1611ab64890Smrg void *reply; 1621ab64890Smrg xcb_generic_event_t *event = dpy->xcb->next_event; 1631ab64890Smrg xcb_generic_error_t *error; 1641ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 1651ab64890Smrg if(!event && dpy->xcb->event_owner == XlibOwnsEventQueue) 1661ab64890Smrg event = wait_or_poll_for_event(dpy, wait_for_first_event); 1671ab64890Smrg 16861b2299dSmrg require_socket(dpy); 16961b2299dSmrg 1701ab64890Smrg while(1) 1711ab64890Smrg { 1721ab64890Smrg PendingRequest *req = dpy->xcb->pending_requests; 17361b2299dSmrg unsigned long event_sequence = dpy->last_request_read; 17461b2299dSmrg if(event) 17561b2299dSmrg widen(&event_sequence, event->full_sequence); 17661b2299dSmrg assert(!(req && current_request && !XLIB_SEQUENCE_COMPARE(req->sequence, <=, current_request))); 17761b2299dSmrg if(event && (!req || XLIB_SEQUENCE_COMPARE(event_sequence, <=, req->sequence))) 1781ab64890Smrg { 17961b2299dSmrg dpy->last_request_read = event_sequence; 1801ab64890Smrg if(event->response_type != X_Error) 1811ab64890Smrg { 18261b2299dSmrg /* GenericEvents may be > 32 bytes. In this 18361b2299dSmrg * case, the event struct is trailed by the 18461b2299dSmrg * additional bytes. the xcb_generic_event_t 18561b2299dSmrg * struct uses 4 bytes for internal numbering, 18661b2299dSmrg * so we need to shift the trailing data to be 18761b2299dSmrg * after the first 32 bytes. */ 18861b2299dSmrg if (event->response_type == GenericEvent && 18961b2299dSmrg ((xcb_ge_event_t*)event)->length) 19061b2299dSmrg { 19161b2299dSmrg memmove(&event->full_sequence, 19261b2299dSmrg &event[1], 19361b2299dSmrg ((xcb_ge_event_t*)event)->length * 4); 19461b2299dSmrg } 1951ab64890Smrg _XEnq(dpy, (xEvent *) event); 1961ab64890Smrg wait_for_first_event = 0; 1971ab64890Smrg } 19861b2299dSmrg else if(current_error && event_sequence == current_request) 1991ab64890Smrg { 2001ab64890Smrg /* This can only occur when called from 2011ab64890Smrg * _XReply, which doesn't need a new event. */ 2021ab64890Smrg *current_error = (xcb_generic_error_t *) event; 20361b2299dSmrg event = NULL; 2041ab64890Smrg break; 2051ab64890Smrg } 2061ab64890Smrg else 2071ab64890Smrg _XError(dpy, (xError *) event); 2081ab64890Smrg free(event); 2091ab64890Smrg event = wait_or_poll_for_event(dpy, wait_for_first_event); 2101ab64890Smrg } 21161b2299dSmrg else if(req && req->sequence == current_request) 2121ab64890Smrg { 21361b2299dSmrg break; 2141ab64890Smrg } 2151ab64890Smrg else if(req && xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &reply, &error)) 2161ab64890Smrg { 2172e9c7c8cSmrg uint64_t sequence = req->sequence; 2181ab64890Smrg if(!reply) 2191ab64890Smrg { 2201ab64890Smrg dpy->xcb->pending_requests = req->next; 2211ab64890Smrg if(!dpy->xcb->pending_requests) 2221ab64890Smrg dpy->xcb->pending_requests_tail = &dpy->xcb->pending_requests; 2231ab64890Smrg free(req); 2241ab64890Smrg reply = error; 2251ab64890Smrg } 2261ab64890Smrg if(reply) 2271ab64890Smrg { 2281ab64890Smrg dpy->last_request_read = sequence; 2291ab64890Smrg call_handlers(dpy, reply); 2301ab64890Smrg free(reply); 2311ab64890Smrg } 2321ab64890Smrg } 2331ab64890Smrg else 2341ab64890Smrg break; 2351ab64890Smrg } 2361ab64890Smrg 2371ab64890Smrg dpy->xcb->next_event = event; 2381ab64890Smrg 2391ab64890Smrg if(xcb_connection_has_error(c)) 2401ab64890Smrg _XIOError(dpy); 2411ab64890Smrg 24261b2299dSmrg assert(XLIB_SEQUENCE_COMPARE(dpy->last_request_read, <=, dpy->request)); 2431ab64890Smrg} 2441ab64890Smrg 2451ab64890Smrgint _XEventsQueued(Display *dpy, int mode) 2461ab64890Smrg{ 2471ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2481ab64890Smrg return 0; 2491ab64890Smrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 2501ab64890Smrg return 0; 2511ab64890Smrg 2521ab64890Smrg if(mode == QueuedAfterFlush) 25361b2299dSmrg _XSend(dpy, NULL, 0); 2541ab64890Smrg else 2551ab64890Smrg check_internal_connections(dpy); 25661b2299dSmrg process_responses(dpy, 0, NULL, 0); 2571ab64890Smrg return dpy->qlen; 2581ab64890Smrg} 2591ab64890Smrg 2601ab64890Smrg/* _XReadEvents - Flush the output queue, 2611ab64890Smrg * then read as many events as possible (but at least 1) and enqueue them 2621ab64890Smrg */ 2631ab64890Smrgvoid _XReadEvents(Display *dpy) 2641ab64890Smrg{ 2651ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2661ab64890Smrg return; 26761b2299dSmrg _XSend(dpy, NULL, 0); 2681ab64890Smrg if(dpy->xcb->event_owner != XlibOwnsEventQueue) 2691ab64890Smrg return; 2701ab64890Smrg check_internal_connections(dpy); 27161b2299dSmrg do { 27261b2299dSmrg process_responses(dpy, 1, NULL, 0); 27361b2299dSmrg } while (dpy->qlen == 0); 2741ab64890Smrg} 2751ab64890Smrg 2761ab64890Smrg/* 2771ab64890Smrg * _XSend - Flush the buffer and send the client data. 32 bit word aligned 2781ab64890Smrg * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. 2791ab64890Smrg * 2801ab64890Smrg * Note that the connection must not be read from once the data currently 2811ab64890Smrg * in the buffer has been written. 2821ab64890Smrg */ 2831ab64890Smrgvoid _XSend(Display *dpy, const char *data, long size) 2841ab64890Smrg{ 28561b2299dSmrg static const xReq dummy_request; 28661b2299dSmrg static char const pad[3]; 28761b2299dSmrg struct iovec vec[3]; 28861b2299dSmrg uint64_t requests; 28961b2299dSmrg _XExtension *ext; 2901ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 2911ab64890Smrg if(dpy->flags & XlibDisplayIOError) 2921ab64890Smrg return; 2931ab64890Smrg 29461b2299dSmrg if(dpy->bufptr == dpy->buffer && !size) 29561b2299dSmrg return; 2961ab64890Smrg 29761b2299dSmrg /* iff we asked XCB to set aside errors, we must pick those up 29861b2299dSmrg * eventually. iff there are async handlers, we may have just 29961b2299dSmrg * issued requests that will generate replies. in either case, 30061b2299dSmrg * we need to remember to check later. */ 30161b2299dSmrg if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers) 30261b2299dSmrg { 3032e9c7c8cSmrg uint64_t sequence; 30461b2299dSmrg for(sequence = dpy->xcb->last_flushed; sequence < dpy->request; ++sequence) 30561b2299dSmrg { 30661b2299dSmrg PendingRequest *req = malloc(sizeof(PendingRequest)); 30761b2299dSmrg assert(req); 30861b2299dSmrg req->next = NULL; 30961b2299dSmrg req->sequence = sequence; 31061b2299dSmrg *dpy->xcb->pending_requests_tail = req; 31161b2299dSmrg dpy->xcb->pending_requests_tail = &req->next; 31261b2299dSmrg } 31361b2299dSmrg } 31461b2299dSmrg requests = dpy->request - dpy->xcb->last_flushed; 31561b2299dSmrg dpy->xcb->last_flushed = dpy->request; 3161ab64890Smrg 31761b2299dSmrg vec[0].iov_base = dpy->buffer; 31861b2299dSmrg vec[0].iov_len = dpy->bufptr - dpy->buffer; 31961b2299dSmrg vec[1].iov_base = (caddr_t) data; 32061b2299dSmrg vec[1].iov_len = size; 32161b2299dSmrg vec[2].iov_base = (caddr_t) pad; 32261b2299dSmrg vec[2].iov_len = -size & 3; 32361b2299dSmrg 32461b2299dSmrg for(ext = dpy->flushes; ext; ext = ext->next_flush) 32561b2299dSmrg { 32661b2299dSmrg int i; 32761b2299dSmrg for(i = 0; i < 3; ++i) 32861b2299dSmrg if(vec[i].iov_len) 32961b2299dSmrg ext->before_flush(dpy, &ext->codes, vec[i].iov_base, vec[i].iov_len); 33061b2299dSmrg } 3311ab64890Smrg 33261b2299dSmrg if(xcb_writev(c, vec, 3, requests) < 0) 33361b2299dSmrg _XIOError(dpy); 33461b2299dSmrg dpy->bufptr = dpy->buffer; 33561b2299dSmrg dpy->last_req = (char *) &dummy_request; 3361ab64890Smrg 3371ab64890Smrg check_internal_connections(dpy); 3381ab64890Smrg 33961b2299dSmrg _XSetSeqSyncFunction(dpy); 3401ab64890Smrg} 3411ab64890Smrg 3421ab64890Smrg/* 3431ab64890Smrg * _XFlush - Flush the X request buffer. If the buffer is empty, no 3441ab64890Smrg * action is taken. 3451ab64890Smrg */ 3461ab64890Smrgvoid _XFlush(Display *dpy) 3471ab64890Smrg{ 34861b2299dSmrg require_socket(dpy); 34961b2299dSmrg _XSend(dpy, NULL, 0); 3501ab64890Smrg 3511ab64890Smrg _XEventsQueued(dpy, QueuedAfterReading); 3521ab64890Smrg} 3531ab64890Smrg 35461b2299dSmrgstatic const XID inval_id = ~0UL; 35561b2299dSmrg 35661b2299dSmrgint _XIDHandler(Display *dpy) 3571ab64890Smrg{ 35861b2299dSmrg XID next; 35961b2299dSmrg 36061b2299dSmrg if (dpy->xcb->next_xid != inval_id) 36161b2299dSmrg return 0; 36261b2299dSmrg 36361b2299dSmrg next = xcb_generate_id(dpy->xcb->connection); 3641ab64890Smrg LockDisplay(dpy); 3651ab64890Smrg dpy->xcb->next_xid = next; 36661b2299dSmrg#ifdef XTHREADS 36761b2299dSmrg if (dpy->lock) 36861b2299dSmrg (*dpy->lock->user_unlock_display)(dpy); 36961b2299dSmrg#endif 3701ab64890Smrg UnlockDisplay(dpy); 3711ab64890Smrg return 0; 3721ab64890Smrg} 3731ab64890Smrg 3741ab64890Smrg/* _XAllocID - resource ID allocation routine. */ 3751ab64890SmrgXID _XAllocID(Display *dpy) 3761ab64890Smrg{ 3771ab64890Smrg XID ret = dpy->xcb->next_xid; 37861b2299dSmrg assert (ret != inval_id); 37961b2299dSmrg#ifdef XTHREADS 38061b2299dSmrg if (dpy->lock) 38161b2299dSmrg (*dpy->lock->user_lock_display)(dpy); 38261b2299dSmrg#endif 38361b2299dSmrg dpy->xcb->next_xid = inval_id; 38461b2299dSmrg _XSetPrivSyncFunction(dpy); 3851ab64890Smrg return ret; 3861ab64890Smrg} 3871ab64890Smrg 3881ab64890Smrg/* _XAllocIDs - multiple resource ID allocation routine. */ 3891ab64890Smrgvoid _XAllocIDs(Display *dpy, XID *ids, int count) 3901ab64890Smrg{ 3911ab64890Smrg int i; 39261b2299dSmrg#ifdef XTHREADS 39361b2299dSmrg if (dpy->lock) 39461b2299dSmrg (*dpy->lock->user_lock_display)(dpy); 39561b2299dSmrg UnlockDisplay(dpy); 39661b2299dSmrg#endif 3971ab64890Smrg for (i = 0; i < count; i++) 3981ab64890Smrg ids[i] = xcb_generate_id(dpy->xcb->connection); 39961b2299dSmrg#ifdef XTHREADS 40061b2299dSmrg LockDisplay(dpy); 40161b2299dSmrg if (dpy->lock) 40261b2299dSmrg (*dpy->lock->user_unlock_display)(dpy); 40361b2299dSmrg#endif 4041ab64890Smrg} 4051ab64890Smrg 4061ab64890Smrgstatic void _XFreeReplyData(Display *dpy, Bool force) 4071ab64890Smrg{ 4081ab64890Smrg if(!force && dpy->xcb->reply_consumed < dpy->xcb->reply_length) 4091ab64890Smrg return; 4101ab64890Smrg free(dpy->xcb->reply_data); 41161b2299dSmrg dpy->xcb->reply_data = NULL; 4121ab64890Smrg} 4131ab64890Smrg 4141ab64890Smrgstatic PendingRequest * insert_pending_request(Display *dpy) 4151ab64890Smrg{ 4161ab64890Smrg PendingRequest **cur = &dpy->xcb->pending_requests; 41761b2299dSmrg while(*cur && XLIB_SEQUENCE_COMPARE((*cur)->sequence, <, dpy->request)) 4181ab64890Smrg cur = &((*cur)->next); 41961b2299dSmrg if(!*cur || (*cur)->sequence != dpy->request) 4201ab64890Smrg { 4211ab64890Smrg PendingRequest *node = malloc(sizeof(PendingRequest)); 4221ab64890Smrg assert(node); 4231ab64890Smrg node->next = *cur; 4241ab64890Smrg node->sequence = dpy->request; 4251ab64890Smrg if(cur == dpy->xcb->pending_requests_tail) 4261ab64890Smrg dpy->xcb->pending_requests_tail = &(node->next); 4271ab64890Smrg *cur = node; 4281ab64890Smrg } 4291ab64890Smrg return *cur; 4301ab64890Smrg} 4311ab64890Smrg 4321ab64890Smrg/* 4331ab64890Smrg * _XReply - Wait for a reply packet and copy its contents into the 4341ab64890Smrg * specified rep. 4351ab64890Smrg * extra: number of 32-bit words expected after the reply 4361ab64890Smrg * discard: should I discard data following "extra" words? 4371ab64890Smrg */ 4381ab64890SmrgStatus _XReply(Display *dpy, xReply *rep, int extra, Bool discard) 4391ab64890Smrg{ 4401ab64890Smrg xcb_generic_error_t *error; 4411ab64890Smrg xcb_connection_t *c = dpy->xcb->connection; 4421ab64890Smrg char *reply; 4431ab64890Smrg PendingRequest *current; 4441ab64890Smrg 4451ab64890Smrg assert(!dpy->xcb->reply_data); 4461ab64890Smrg 4471ab64890Smrg if(dpy->flags & XlibDisplayIOError) 4481ab64890Smrg return 0; 4491ab64890Smrg 45061b2299dSmrg _XSend(dpy, NULL, 0); 4511ab64890Smrg current = insert_pending_request(dpy); 45261b2299dSmrg /* FIXME: drop the Display lock while waiting? 45361b2299dSmrg * Complicates process_responses. */ 4541ab64890Smrg reply = xcb_wait_for_reply(c, current->sequence, &error); 4551ab64890Smrg 4561ab64890Smrg check_internal_connections(dpy); 4571ab64890Smrg process_responses(dpy, 0, &error, current->sequence); 4581ab64890Smrg 4591ab64890Smrg if(error) 4601ab64890Smrg { 4611ab64890Smrg _XExtension *ext; 4621ab64890Smrg xError *err = (xError *) error; 4631ab64890Smrg int ret_code; 4641ab64890Smrg 4651ab64890Smrg dpy->last_request_read = error->full_sequence; 4661ab64890Smrg 4671ab64890Smrg /* Xlib is evil and assumes that even errors will be 4681ab64890Smrg * copied into rep. */ 4691ab64890Smrg memcpy(rep, error, 32); 4701ab64890Smrg 4711ab64890Smrg /* do not die on "no such font", "can't allocate", 4721ab64890Smrg "can't grab" failures */ 4731ab64890Smrg switch(err->errorCode) 4741ab64890Smrg { 4751ab64890Smrg case BadName: 4761ab64890Smrg switch(err->majorCode) 4771ab64890Smrg { 4781ab64890Smrg case X_LookupColor: 4791ab64890Smrg case X_AllocNamedColor: 48061b2299dSmrg free(error); 4811ab64890Smrg return 0; 4821ab64890Smrg } 4831ab64890Smrg break; 4841ab64890Smrg case BadFont: 48561b2299dSmrg if(err->majorCode == X_QueryFont) { 48661b2299dSmrg free(error); 4871ab64890Smrg return 0; 48861b2299dSmrg } 4891ab64890Smrg break; 4901ab64890Smrg case BadAlloc: 4911ab64890Smrg case BadAccess: 49261b2299dSmrg free(error); 4931ab64890Smrg return 0; 4941ab64890Smrg } 4951ab64890Smrg 49661b2299dSmrg /* 4971ab64890Smrg * we better see if there is an extension who may 4981ab64890Smrg * want to suppress the error. 4991ab64890Smrg */ 5001ab64890Smrg for(ext = dpy->ext_procs; ext; ext = ext->next) 50161b2299dSmrg if(ext->error && ext->error(dpy, err, &ext->codes, &ret_code)) { 50261b2299dSmrg free(error); 5031ab64890Smrg return ret_code; 50461b2299dSmrg } 5051ab64890Smrg 50661b2299dSmrg _XError(dpy, err); 50761b2299dSmrg free(error); 5081ab64890Smrg return 0; 5091ab64890Smrg } 5101ab64890Smrg 5111ab64890Smrg /* it's not an error, but we don't have a reply, so it's an I/O 5121ab64890Smrg * error. */ 5131ab64890Smrg if(!reply) 5141ab64890Smrg { 5151ab64890Smrg _XIOError(dpy); 5161ab64890Smrg return 0; 5171ab64890Smrg } 5181ab64890Smrg 5191ab64890Smrg dpy->last_request_read = current->sequence; 5201ab64890Smrg 5211ab64890Smrg /* there's no error and we have a reply. */ 5221ab64890Smrg dpy->xcb->reply_data = reply; 5231ab64890Smrg dpy->xcb->reply_consumed = sizeof(xReply) + (extra * 4); 5241ab64890Smrg dpy->xcb->reply_length = sizeof(xReply); 5251ab64890Smrg if(dpy->xcb->reply_data[0] == 1) 5261ab64890Smrg dpy->xcb->reply_length += (((xcb_generic_reply_t *) dpy->xcb->reply_data)->length * 4); 5271ab64890Smrg 5281ab64890Smrg /* error: Xlib asks too much. give them what we can anyway. */ 5291ab64890Smrg if(dpy->xcb->reply_length < dpy->xcb->reply_consumed) 5301ab64890Smrg dpy->xcb->reply_consumed = dpy->xcb->reply_length; 5311ab64890Smrg 5321ab64890Smrg memcpy(rep, dpy->xcb->reply_data, dpy->xcb->reply_consumed); 5331ab64890Smrg _XFreeReplyData(dpy, discard); 5341ab64890Smrg return 1; 5351ab64890Smrg} 5361ab64890Smrg 5371ab64890Smrgint _XRead(Display *dpy, char *data, long size) 5381ab64890Smrg{ 5391ab64890Smrg assert(size >= 0); 5401ab64890Smrg if(size == 0) 5411ab64890Smrg return 0; 54261b2299dSmrg assert(dpy->xcb->reply_data != NULL); 5431ab64890Smrg assert(dpy->xcb->reply_consumed + size <= dpy->xcb->reply_length); 5441ab64890Smrg memcpy(data, dpy->xcb->reply_data + dpy->xcb->reply_consumed, size); 5451ab64890Smrg dpy->xcb->reply_consumed += size; 5461ab64890Smrg _XFreeReplyData(dpy, False); 5471ab64890Smrg return 0; 5481ab64890Smrg} 5491ab64890Smrg 5501ab64890Smrg/* 5511ab64890Smrg * _XReadPad - Read bytes from the socket taking into account incomplete 5521ab64890Smrg * reads. If the number of bytes is not 0 mod 4, read additional pad 5531ab64890Smrg * bytes. 5541ab64890Smrg */ 5551ab64890Smrgvoid _XReadPad(Display *dpy, char *data, long size) 5561ab64890Smrg{ 5571ab64890Smrg _XRead(dpy, data, size); 5581ab64890Smrg dpy->xcb->reply_consumed += -size & 3; 5591ab64890Smrg _XFreeReplyData(dpy, False); 5601ab64890Smrg} 5611ab64890Smrg 5621ab64890Smrg/* Read and discard "n" 8-bit bytes of data */ 5631ab64890Smrgvoid _XEatData(Display *dpy, unsigned long n) 5641ab64890Smrg{ 5651ab64890Smrg dpy->xcb->reply_consumed += n; 5661ab64890Smrg _XFreeReplyData(dpy, False); 5671ab64890Smrg} 568