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