[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freedesktop-xlibs-commit
Subject:    [xlibs-commit] X11/src/xcl display.c,NONE,1.1 io.c,NONE,1.1
From:       Jamey Sharp <xlibs-commit () pdx ! freedesktop ! org>
Date:       2003-11-28 10:49:46
Message-ID: E1APgC2-000056-A9 () pdx ! freedesktop ! org
[Download RAW message or body]

Committed by: jamey

Update of /cvs/xlibs/X11/src/xcl
In directory pdx:/tmp/cvs-serv32471/src/xcl

Added Files:
	display.c io.c 
Log Message:
A better-tested version of XCL is now available as a configure-time option.
Unlike the version that was on the XCL branch, this removes no code from CVS;
but when --with-xcb is given to configure, the old code is simply not compiled.
The new code is isolated in the xcl subdirectory.

Note that this version of XCL requires the XCB version with the pre_sendrequest
tag. Versions newer than that have API changes that XCL needs to track, but I
wanted to commit the conditional compile patches first.


--- NEW FILE: display.c ---
/* Copyright (C) 2003 Jamey Sharp.
 * This file is licensed under the MIT license. See the file COPYING. */

#include "Xlibint.h"
#include "xclint.h"
#include <X11/Xatom.h>
#include <X11/Xresource.h>
#include <stdio.h>

void _XFreeDisplayStructure(Display *dpy);

static XCBAuthInfo xauth;

static void *alloc_copy(const void *src, size_t *dstn, size_t n)
{
	void *dst;
	if(n <= 0)
	{
		*dstn = 0;
		return 0;
	}
	dst = Xmalloc(n);
	if(!dst)
		return 0;
	memcpy(dst, src, n);
	*dstn = n;
	return dst;
}

void XSetAuthorization(char *name, int namelen, char *data, int datalen)
{
	_XLockMutex(_Xglobal_lock);
	Xfree(xauth.name);
	Xfree(xauth.data);

	/* if either of these allocs fail, _XConnectXCB won't use this auth
	 * data, so we don't need to check it here. */
	xauth.name = alloc_copy(name, &xauth.namelen, namelen);
	xauth.data = alloc_copy(data, &xauth.datalen, datalen);

#if 0 /* but, for the paranoid among us: */
	if((namelen > 0 && !xauth.name) || (datalen > 0 && !xauth.data))
	{
		Xfree(xauth.name);
		Xfree(xauth.data);
		xauth.name = xauth.data = 0;
		xauth.namelen = xauth.datalen = 0;
	}
#endif

	_XUnlockMutex(_Xglobal_lock);
}

static int _XAsyncReplyHandler(Display *dpy, XCBGenericRep *buf)
{
	_XAsyncHandler *async, *next;
	_XSetLastRequestRead(dpy, (xGenericReply *) buf);
	for(async = dpy->async_handlers; async; async = next)
	{
		next = async->next;
		if(async->handler(dpy, (xReply *) buf, (char *) buf, sizeof(xReply) + (buf->length << 2), async->data))
			return 1;
	}
	return 0;
}

int _XConnectXCB(Display *dpy, _Xconst char *display, char **fullnamep, int *screenp)
{
	char *host;
	int n = 0;
	int use_global;
	XCBAuthInfo auth;
	XCBConnection *c;

	dpy->xcl = Xcalloc(1, sizeof(XCLPrivate));
	if(!dpy->xcl)
		return 0;

	dpy->fd = -1;
	if(XCBParseDisplay(display, &host, &n, screenp))
	{
		int len;
		dpy->fd = XCBOpen(host, n);
		len = strlen(host) + (1 + 20 + 1 + 20 + 1);
		*fullnamep = Xmalloc(len);
		snprintf(*fullnamep, len, "%s:%d.%d", host, n, *screenp);
	}
	free(host);

	if(dpy->fd == -1)
		return 0;

	_XLockMutex(_Xglobal_lock);
	use_global = xauth.name && xauth.data;
	if(use_global)
		auth = xauth;
	_XUnlockMutex(_Xglobal_lock);

	if(!use_global)
		XCBGetAuthInfo(dpy->fd, XCBNextNonce(), &auth);
	c = XCBConnect(dpy->fd, &auth);
	if(!use_global)
	{
		free(auth.name);
		free(auth.data);
	}

	XCBSetUnexpectedReplyHandler(c, (XCBUnexpectedReplyFunc) _XAsyncReplyHandler, dpy);
	dpy->xcl->connection = c;
	return c != 0;
}

static int init_pixmap_formats(Display *dpy, XCBConnection *c)
{
	int i;
	ScreenFormat *fmtdst;
	FORMAT *fmtsrc;
	dpy->nformats = XCBConnSetupSuccessRepPixmapFormatsLength(c->setup);

	/* Now iterate down setup information... */
	fmtdst = Xmalloc(dpy->nformats * sizeof(ScreenFormat));
	if(!fmtdst)
		return 0;
	dpy->pixmap_format = fmtdst;
	fmtsrc = XCBConnSetupSuccessRepPixmapFormats(c->setup);

	/* First decode the Z axis Screen format information. */
	for(i = dpy->nformats; i; --i, ++fmtsrc, ++fmtdst)
	{
		fmtdst->depth = fmtsrc->depth;
		fmtdst->bits_per_pixel = fmtsrc->bits_per_pixel;
		fmtdst->scanline_pad = fmtsrc->scanline_pad;
		fmtdst->ext_data = NULL;
	}
	return 1;
}

static int init_visuals(int len, VISUALTYPE *vpsrc, Visual **dst)
{
	Visual *vpdst;

	*dst = vpdst = Xmalloc(len * sizeof(Visual));
	if(!vpdst)
		return 0;

	for(; len; --len, ++vpsrc, ++vpdst)
	{
		vpdst->visualid		= vpsrc->visual_id.id;
		vpdst->class		= vpsrc->class;
		vpdst->bits_per_rgb	= vpsrc->bits_per_rgb_value;
		vpdst->map_entries	= vpsrc->colormap_entries;
		vpdst->red_mask		= vpsrc->red_mask;
		vpdst->green_mask	= vpsrc->green_mask;
		vpdst->blue_mask	= vpsrc->blue_mask;
		vpdst->ext_data		= NULL;
	}
	return 1;
}

static int init_depths(DEPTHIter dpsrc, Depth **dst)
{
	Depth *dpdst;

	*dst = dpdst = Xmalloc(dpsrc.rem * sizeof(Depth));
	if(!dpdst)
		return 0;

	/* for all depths on this screen. */
	for(; dpsrc.rem; DEPTHNext(&dpsrc), ++dpdst)
	{
		dpdst->depth		= dpsrc.data->depth;
		dpdst->nvisuals		= DEPTHVisualsLength(dpsrc.data);

		if(!init_visuals(dpdst->nvisuals, DEPTHVisuals(dpsrc.data), &dpdst->visuals))
			return 0;
	}
	return 1;
}

static int init_screens(Display *dpy, XCBConnection *c)
{
	Screen *spdst;
	XGCValues values;
	SCREENIter spsrc = XCBConnSetupSuccessRepRoots(c->setup);

	dpy->nscreens = spsrc.rem;

	spdst = Xmalloc(spsrc.rem * sizeof(Screen));
	if(!spdst)
		return 0;
	dpy->screens = spdst;

	/* Now go deal with each screen structure. */
	for(; spsrc.rem; SCREENNext(&spsrc), ++spdst)
	{
		spdst->display		= dpy;
		spdst->root 		= spsrc.data->root.xid;
		spdst->cmap 		= spsrc.data->default_colormap.xid;
		spdst->white_pixel	= spsrc.data->white_pixel;
		values.background	= spdst->white_pixel;
		spdst->black_pixel	= spsrc.data->black_pixel;
		values.foreground	= spdst->black_pixel;
		spdst->root_input_mask	= spsrc.data->current_input_masks;
		spdst->width		= spsrc.data->width_in_pixels;
		spdst->height		= spsrc.data->height_in_pixels;
		spdst->mwidth		= spsrc.data->width_in_millimeters;
		spdst->mheight		= spsrc.data->height_in_millimeters;
		spdst->min_maps		= spsrc.data->min_installed_maps;
		spdst->max_maps		= spsrc.data->max_installed_maps;
		spdst->backing_store	= spsrc.data->backing_stores;
		spdst->save_unders	= spsrc.data->save_unders;
		spdst->root_depth	= spsrc.data->root_depth;
		spdst->ndepths		= spsrc.data->allowed_depths_len;
		spdst->ext_data		= NULL;

		if(!init_depths(SCREENAllowedDepths(spsrc.data), &spdst->depths))
			return 0;

		spdst->root_visual = _XVIDtoVisual(dpy, spsrc.data->root_visual.id);

		/* Set up other stuff clients are always going to use. */
		spdst->default_gc = XCreateGC(dpy, spdst->root, GCForeground|GCBackground, &values);
		if(!spdst->default_gc)
			return 0;
	}
	return 1;
}

int _XConnectSetupXCB(Display *dpy)
{
	XCBConnection *c = dpy->xcl->connection;

	dpy->request = c->seqnum;

	dpy->proto_major_version	= c->setup->protocol_major_version;
	dpy->proto_minor_version	= c->setup->protocol_minor_version;
	dpy->release 			= c->setup->release_number;
	dpy->resource_base		= c->setup->resource_id_base;
	dpy->resource_mask		= c->setup->resource_id_mask;
	dpy->min_keycode		= c->setup->min_keycode.id;
	dpy->max_keycode		= c->setup->max_keycode.id;
	dpy->motion_buffer		= c->setup->motion_buffer_size;
	dpy->byte_order			= c->setup->image_byte_order;
	dpy->bitmap_unit		= c->setup->bitmap_format_scanline_unit;
	dpy->bitmap_pad			= c->setup->bitmap_format_scanline_pad;
	dpy->bitmap_bit_order		= c->setup->bitmap_format_bit_order;
	dpy->max_request_size		= c->setup->maximum_request_length;
	dpy->resource_shift		= 0;

	{
	    unsigned long mask;
	    for (mask = dpy->resource_mask; !(mask & 1); mask >>= 1)
		++dpy->resource_shift;
	}
	dpy->resource_max = (dpy->resource_mask >> dpy->resource_shift) - 5;

	{
		int len = XCBConnSetupSuccessRepVendorLength(c->setup);
		dpy->vendor = Xmalloc(len + 1);
		if(!dpy->vendor)
			return 0;
		memcpy(dpy->vendor, XCBConnSetupSuccessRepVendor(c->setup), len);
		dpy->vendor[len] = '\0';
	}

	if(!init_pixmap_formats(dpy, c))
		return 0;

	if(!init_screens(dpy, c))
		return 0;

	dpy->bigreq_size = XCBMaximumRequestLength(c);
	if(dpy->bigreq_size <= dpy->max_request_size)
		dpy->bigreq_size = 0;

	return 1;
}

--- NEW FILE: io.c ---
/* Copyright (C) 2003 Jamey Sharp.
 * This file is licensed under the MIT license. See the file COPYING. */

#include "Xlibint.h"
#include "xclint.h"
#include <X11/XCB/xcbint.h>

#include <assert.h>
#include <stdlib.h>
#include <string.h>

static void handle_event(Display *dpy, XCBGenericEvent *e)
{
	if(!e)
		_XIOError(dpy);
	if(e->response_type == X_Error)
		_XError(dpy, (xError *) e);
	else
		_XEnq(dpy, (xEvent *) e);
	free(e);
}

int _XEventsQueued(Display *dpy, int mode)
{
	XCBConnection *c = XCBConnectionOfDisplay(dpy);
	int ret;
	if(mode == QueuedAfterFlush)
		_XFlush(dpy);
	while((ret = XCBEventQueueLength(c)) > 0)
		handle_event(dpy, XCBWaitEvent(c));
	if(ret < 0)
		_XIOError(dpy);
	return dpy->qlen;
}

/* _XReadEvents - Flush the output queue,
 * then read as many events as possible (but at least 1) and enqueue them
 */
void _XReadEvents(Display *dpy)
{
	_XFlush(dpy);
	handle_event(dpy, XCBWaitEvent(XCBConnectionOfDisplay(dpy)));
	_XEventsQueued(dpy, QueuedAfterReading);
}

/*
 * _XSend - Flush the buffer and send the client data. 32 bit word aligned
 * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
 */
void _XSend(Display *dpy, const char *data, long size)
{
	static char const pad[3];
	static const xReq _dummy_request;

	struct iovec iov[2];
	_XExtension *ext;
	int count = 0;

	if(dpy->bufptr != dpy->buffer)
	{
		iov[count].iov_base = (caddr_t) dpy->buffer;
		iov[count].iov_len = dpy->bufptr - dpy->buffer;
		++count;
	}
	if(data && size)
	{
		iov[count].iov_base = (caddr_t) data;
		iov[count].iov_len = size;
		++count;
	}

	for (ext = dpy->flushes; ext; ext = ext->next_flush) {
		int i;
		for(i = 0; i < count; ++i)
		{
			ext->before_flush(dpy, &ext->codes, iov[i].iov_base, iov[i].iov_len);
			if((iov[i].iov_len & 3) != 0)
				ext->before_flush(dpy, &ext->codes, pad, XCB_PAD(iov[i].iov_len));
		}
	}

	if(XCBLockWrite(XCBConnectionOfDisplay(dpy), iov, count) < 0)
		_XIOError(dpy);
	if(XCBFlush(XCBConnectionOfDisplay(dpy)) < 0)
		_XIOError(dpy);

	dpy->last_req = (char *) & _dummy_request;
	dpy->bufptr = dpy->buffer;
}

/*
 * _XFlush - Flush the X request buffer.  If the buffer is empty, no
 * action is taken.
 */
void _XFlush(Display *dpy)
{
	_XSend(dpy, 0, 0);

	_XEventsQueued(dpy, QueuedAfterReading);
}

/* _XAllocID - resource ID allocation routine. */
XID _XAllocID(Display *dpy)
{
	return XCBGenerateID(XCBConnectionOfDisplay(dpy));
}

/* _XAllocIDs - multiple resource ID allocation routine. */
void _XAllocIDs(Display *dpy, XID *ids, int count)
{
	int i;
	for (i = 0; i < count; i++)
		ids[i] = XAllocID(dpy);
}

/*
 * The hard part about this is that we only get 16 bits from a reply.
 * We have three values that will march along, with the following invariant:
 *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
 * We have to keep
 *	dpy->request - dpy->last_request_read < 2^16
 * or else we won't know for sure what value to use in events.  We do this
 * by forcing syncs when we get close.
 */
unsigned long _XSetLastRequestRead(Display *dpy, xGenericReply *rep)
{
	unsigned long newseq;
	unsigned int xcb_seqnum = XCBConnectionOfDisplay(dpy)->seqnum_read;

	/*
	 * KeymapNotify has no sequence number, but is always guaranteed
	 * to immediately follow another event, except when generated via
	 * SendEvent (hmmm).
	 */
	if ((rep->type & 0x7f) == KeymapNotify)
		return(dpy->last_request_read);

	newseq = (xcb_seqnum & ~((unsigned long)0xffff)) | rep->sequenceNumber;

	if (newseq > xcb_seqnum)
		newseq -= 0x10000;
	assert(newseq <= dpy->request);

	dpy->last_request_read = newseq;
	return(newseq);
}

static void _XFreeReplyData(Display *dpy, Bool force)
{
	if(!force && dpy->xcl->reply_consumed < dpy->xcl->reply_length)
		return;
	free(dpy->xcl->reply_data);
	dpy->xcl->reply_data = 0;
}

/*
 * _XReply - Wait for a reply packet and copy its contents into the
 * specified rep.
 * extra: number of 32-bit words expected after the reply
 * discard: should I discard data following "extra" words?
 */
Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
{
	XCBGenericError *error;
	XCBConnection *c = XCBConnectionOfDisplay(dpy);

	free(dpy->xcl->reply_data);
	XCBAddReplyData(c, dpy->request);
	_XFlush(dpy);

	dpy->xcl->reply_data = XCBWaitSeqnum(c, dpy->request, &error);
	dpy->last_request_read = dpy->request;

	if(!dpy->xcl->reply_data)
	{
		_XExtension *ext;
		xError *err = (xError *) error;
		int ret_code;

		if(!error)
		{
			_XIOError(dpy);
			return 0;
		}

		/* do not die on "no such font", "can't allocate",
		   "can't grab" failures */
		switch(err->errorCode)
		{
			case BadName:
				switch(err->majorCode)
				{
					case X_LookupColor:
					case X_AllocNamedColor:
						return 0;
				}
				break;
			case BadFont:
				if(err->majorCode == X_QueryFont)
					return 0;
				break;
			case BadAlloc:
			case BadAccess:
				return 0;
		}

		/* 
		 * we better see if there is an extension who may
		 * want to suppress the error.
		 */
		for(ext = dpy->ext_procs; ext; ext = ext->next)
			if(ext->error && ext->error(dpy, err, &ext->codes, &ret_code))
				return ret_code;

		_XError(dpy, (xError *) error);
		return 0;
	}

	dpy->xcl->reply_consumed = sizeof(xReply) + (extra * 4);
	dpy->xcl->reply_length = sizeof(xReply) + (((XCBGenericRep *) dpy->xcl->reply_data)->length * 4);

	/* error: Xlib asks too much. give them what we can anyway. */
	if(dpy->xcl->reply_length < dpy->xcl->reply_consumed)
		dpy->xcl->reply_consumed = dpy->xcl->reply_length;

	memcpy(rep, dpy->xcl->reply_data, dpy->xcl->reply_consumed);
	_XFreeReplyData(dpy, discard);
	return 1;
}

int _XRead(Display *dpy, char *data, long size)
{
	assert(size >= 0);
	if(size == 0)
		return 0;
	assert(dpy->xcl->reply_data != 0);
	assert(dpy->xcl->reply_consumed + size <= dpy->xcl->reply_length);
	memcpy(data, dpy->xcl->reply_data + dpy->xcl->reply_consumed, size);
	dpy->xcl->reply_consumed += size;
	_XFreeReplyData(dpy, False);
	return 0;
}

/*
 * _XReadPad - Read bytes from the socket taking into account incomplete
 * reads.  If the number of bytes is not 0 mod 4, read additional pad
 * bytes.
 */
void _XReadPad(Display *dpy, char *data, long size)
{
	_XRead(dpy, data, size);
	dpy->xcl->reply_consumed += XCB_PAD(size);
	_XFreeReplyData(dpy, False);
}

/* Read and discard "n" 8-bit bytes of data */
void _XEatData(Display *dpy, unsigned long n)
{
	dpy->xcl->reply_consumed += n;
	_XFreeReplyData(dpy, False);
}



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic