This patch is useful for people working with XWayland, where the X11
connection must be opened from a file descriptor.
>From c5e4bf50a722670e0ac1b05509834874251c0c9c Mon Sep 17 00:00:00 2001
From: Mike Blumenkrantz <[email protected]>
Date: Wed, 27 May 2015 08:37:05 -0400
Subject: [PATCH] add XCBGetXDisplay

a method for creating a Display object from an xcb connection

Signed-off-by: Mike Blumenkrantz <[email protected]>
---
 include/X11/Xlib-xcb.h |   1 +
 src/x11_xcb.c          | 562 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 563 insertions(+)

diff --git a/include/X11/Xlib-xcb.h b/include/X11/Xlib-xcb.h
index a21e2be..240a25c 100644
--- a/include/X11/Xlib-xcb.h
+++ b/include/X11/Xlib-xcb.h
@@ -11,6 +11,7 @@
 _XFUNCPROTOBEGIN
 
 xcb_connection_t *XGetXCBConnection(Display *dpy);
+Display *XCBGetXDisplay(xcb_connection_t *c);
 
 enum XEventQueueOwner { XlibOwnsEventQueue = 0, XCBOwnsEventQueue };
 void XSetEventQueueOwner(Display *dpy, enum XEventQueueOwner owner);
diff --git a/src/x11_xcb.c b/src/x11_xcb.c
index 3ddf403..0dabf6d 100644
--- a/src/x11_xcb.c
+++ b/src/x11_xcb.c
@@ -1,9 +1,78 @@
 /* Copyright (C) 2003,2006 Jamey Sharp, Josh Triplett
  * This file is licensed under the MIT license. See the file COPYING. */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 #include "Xlibint.h"
 #include "Xxcbint.h"
 
+#include <X11/Xatom.h>
+#include <X11/Xresource.h>
+#include <stdio.h>
+#include "Xintconn.h"
+
+#ifdef XKB
+#include "XKBlib.h"
+#endif /* XKB */
+
+#ifdef XTHREADS
+#include "locking.h"
+int  (*_XInitDisplayLock_fn)(Display *dpy) = NULL;
+void (*_XFreeDisplayLock_fn)(Display *dpy) = NULL;
+
+#define InitDisplayLock(d)	(_XInitDisplayLock_fn ? (*_XInitDisplayLock_fn)(d) : Success)
+#define FreeDisplayLock(d)	if (_XFreeDisplayLock_fn) (*_XFreeDisplayLock_fn)(d)
+#else
+#define InitDisplayLock(dis) Success
+#define FreeDisplayLock(dis)
+#endif /* XTHREADS */
+
+static xReq _dummy_request = {
+	0, 0, 0
+};
+
+/* OutOfMemory is called if malloc fails.  XOpenDisplay returns NULL
+   after this returns. */
+
+static void OutOfMemory(Display *dpy)
+{
+    if(dpy->xcb->connection)
+	xcb_disconnect(dpy->xcb->connection);
+    _XFreeDisplayStructure (dpy);
+}
+
+
+static int _XCBConnectX(Display *dpy, _Xconst char *display, int *screenp, xcb_connection_t *c)
+{
+	char *host;
+	int n = 0;
+
+	dpy->fd = -1;
+
+	dpy->xcb = Xcalloc(1, sizeof(_X11XCBPrivate));
+	if(!dpy->xcb)
+		return 0;
+
+	if(!xcb_parse_display(display, &host, &n, screenp))
+		return 0;
+	/* host and n are unused, but xcb_parse_display requires them */
+	free(host);
+
+	dpy->fd = xcb_get_file_descriptor(c);
+
+	dpy->xcb->connection = c;
+	dpy->xcb->next_xid = xcb_generate_id(dpy->xcb->connection);
+
+	dpy->xcb->event_notify = xcondition_malloc();
+	dpy->xcb->reply_notify = xcondition_malloc();
+	if (!dpy->xcb->event_notify || !dpy->xcb->reply_notify)
+		return 0;
+	xcondition_init(dpy->xcb->event_notify);
+	xcondition_init(dpy->xcb->reply_notify);
+	return !xcb_connection_has_error(c);
+}
+
 xcb_connection_t *XGetXCBConnection(Display *dpy)
 {
 	return dpy->xcb->connection;
@@ -13,3 +82,496 @@ void XSetEventQueueOwner(Display *dpy, enum XEventQueueOwner owner)
 {
 	dpy->xcb->event_owner = owner;
 }
+
+Display *XCBGetXDisplay(xcb_connection_t *c)
+{
+	register Display *dpy;		/* New Display object being created. */
+	register int i;
+	int j, k;			/* random iterator indexes */
+	char *display_name;		/* pointer to display name */
+	char *setup = NULL;		/* memory allocated at startup */
+	int iscreen;			/* screen number */
+	xConnSetupPrefix prefix;	/* prefix information */
+	int vendorlen;			/* length of vendor string */
+	union {
+		xConnSetup *setup;
+		char *failure;
+		char *vendor;
+		xPixmapFormat *sf;
+		xWindowRoot *rp;
+		xDepth *dp;
+		xVisualType *vp;
+	} u;				/* proto data returned from server */
+	long setuplength;	/* number of bytes in setup message */
+	long usedbytes = 0;     /* number of bytes we have processed */
+	unsigned long mask;
+	long int conn_buf_size;
+	char *xlib_buffer_size;
+
+	if ((display_name = getenv("DISPLAY")) == NULL) {
+		/* Oops! No DISPLAY environment variable - error. */
+		return(NULL);
+	}
+
+	/*
+	 * Set the default error handlers.  This allows the global variables to
+	 * default to NULL for use with shared libraries.
+	 */
+	if (_XErrorFunction == NULL) (void) XSetErrorHandler (NULL);
+	if (_XIOErrorFunction == NULL) (void) XSetIOErrorHandler (NULL);
+
+	/*
+	 * Attempt to allocate a display structure. Return NULL if allocation fails.
+	 */
+	if ((dpy = Xcalloc(1, sizeof(Display))) == NULL) {
+		return(NULL);
+	}
+
+	if ((dpy->display_name = strdup(display_name)) == NULL) {
+		OutOfMemory(dpy);
+		return(NULL);
+	}
+
+/*
+ * Call the Connect routine to set up the transport connection object.
+ * If 0 is returned, the connection failed.
+ */
+
+	if(!_XCBConnectX(dpy, display_name, &iscreen, c)) {
+		OutOfMemory(dpy);
+		return NULL;
+	}
+
+	/* Initialize as much of the display structure as we can.
+	 * Initialize pointers to NULL so that XFreeDisplayStructure will
+	 * work if we run out of memory before we finish initializing.
+	 */
+	dpy->keysyms		= (KeySym *) NULL;
+	dpy->modifiermap	= NULL;
+	dpy->lock_meaning	= NoSymbol;
+	dpy->keysyms_per_keycode = 0;
+	dpy->xdefaults		= (char *)NULL;
+	dpy->scratch_length	= 0L;
+	dpy->scratch_buffer	= NULL;
+	dpy->key_bindings	= NULL;
+	dpy->ext_procs		= (_XExtension *)NULL;
+	dpy->ext_data		= (XExtData *)NULL;
+	dpy->ext_number 	= 0;
+	dpy->event_vec[X_Error] = _XUnknownWireEvent;
+	dpy->event_vec[X_Reply] = _XUnknownWireEvent;
+	dpy->wire_vec[X_Error]  = _XUnknownNativeEvent;
+	dpy->wire_vec[X_Reply]  = _XUnknownNativeEvent;
+	for (i = KeyPress; i < LASTEvent; i++) {
+	    dpy->event_vec[i] 	= _XWireToEvent;
+	    dpy->wire_vec[i] 	= NULL;
+	}
+	for (i = LASTEvent; i < 128; i++) {
+	    dpy->event_vec[i] 	= _XUnknownWireEvent;
+	    dpy->wire_vec[i] 	= _XUnknownNativeEvent;
+	}
+	dpy->resource_id	= 0;
+	dpy->db 		= (struct _XrmHashBucketRec *)NULL;
+	dpy->cursor_font	= None;
+	dpy->flags		= 0;
+	dpy->async_handlers	= NULL;
+	dpy->screens		= NULL;
+	dpy->vendor		= NULL;
+	dpy->buffer		= NULL;
+	dpy->atoms		= NULL;
+	dpy->error_vec		= NULL;
+	dpy->context_db		= NULL;
+	dpy->free_funcs		= NULL;
+	dpy->pixmap_format	= NULL;
+	dpy->cms.clientCmaps	= NULL;
+	dpy->cms.defaultCCCs	= NULL;
+	dpy->cms.perVisualIntensityMaps = NULL;
+	dpy->im_filters		= NULL;
+ 	dpy->bigreq_size	= 0;
+	dpy->lock		= NULL;
+	dpy->lock_fns		= NULL;
+	dpy->qfree		= NULL;
+	dpy->next_event_serial_num = 1;
+	dpy->im_fd_info		= NULL;
+	dpy->im_fd_length	= 0;
+	dpy->conn_watchers	= NULL;
+	dpy->watcher_count	= 0;
+	dpy->filedes		= NULL;
+	dpy->flushes		= NULL;
+	dpy->xcmisc_opcode	= 0;
+	dpy->xkb_info		= NULL;
+
+	/*
+	 * Setup other information in this display structure.
+	 */
+	dpy->vnumber = X_PROTOCOL;
+	dpy->resource_alloc = _XAllocID;
+	dpy->idlist_alloc = _XAllocIDs;
+	dpy->synchandler = NULL;
+	dpy->savedsynchandler = NULL;
+	dpy->request = 0;
+	dpy->last_request_read = 0;
+	dpy->default_screen = iscreen;  /* Value returned by ConnectDisplay */
+	dpy->last_req = (char *)&_dummy_request;
+
+	/* Initialize the display lock */
+	if (InitDisplayLock(dpy) != 0) {
+	        OutOfMemory (dpy);
+		return(NULL);
+	}
+
+	if (!_XPollfdCacheInit(dpy)) {
+	        OutOfMemory (dpy);
+		return(NULL);
+	}
+
+	/* Set up the output buffers. */
+#ifndef XLIBDEFAULTBUFSIZE
+#define XLIBDEFAULTBUFSIZE 16384 /* 16k */
+#endif
+#ifndef XLIBMINBUFSIZE
+#define XLIBMINBUFSIZE BUFSIZE /* old default buffer size */
+#endif
+	xlib_buffer_size = getenv("XLIBBUFFERSIZE");
+
+#ifdef __sun /* Backwards compatibility for old Solaris libX11 name */
+	if (xlib_buffer_size == NULL)
+	    xlib_buffer_size = getenv("XSUNBUFFERSIZE");
+#endif
+
+	if (xlib_buffer_size == NULL)
+	    conn_buf_size = XLIBDEFAULTBUFSIZE;
+	else
+	    conn_buf_size = 1024 * strtol(xlib_buffer_size, NULL, 10);
+	if (conn_buf_size < XLIBMINBUFSIZE)
+	    conn_buf_size = XLIBMINBUFSIZE;
+
+	if ((dpy->bufptr = dpy->buffer = Xcalloc(1, conn_buf_size)) == NULL) {
+	    OutOfMemory (dpy);
+	    return(NULL);
+	}
+	dpy->xcb->real_bufmax = dpy->buffer + conn_buf_size;
+	dpy->bufmax = dpy->buffer;
+
+	/* Set up the input event queue and input event queue parameters. */
+	dpy->head = dpy->tail = NULL;
+	dpy->qlen = 0;
+
+	/* Set up free-function record */
+	if ((dpy->free_funcs = Xcalloc(1, sizeof(_XFreeFuncRec))) == NULL) {
+	    OutOfMemory (dpy);
+	    return(NULL);
+	}
+
+	{
+		const struct xcb_setup_t *xcbsetup = xcb_get_setup(dpy->xcb->connection);
+		memcpy(&prefix, xcbsetup, sizeof(prefix));
+		setuplength = prefix.length << 2;
+		setup = (char *) xcbsetup;
+		setup += SIZEOF(xConnSetupPrefix);
+		u.setup = (xConnSetup *) setup;
+	}
+
+	/*
+	 * Check if the reply was long enough to get any information out of it.
+	 */
+	usedbytes = sz_xConnSetup;
+	if (setuplength < usedbytes ) {
+	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
+	    OutOfMemory(dpy);
+	    return (NULL);
+	}
+
+	/*
+	 * We succeeded at authorization, so let us move the data into
+	 * the display structure.
+	 */
+	dpy->proto_major_version= prefix.majorVersion;
+	dpy->proto_minor_version= prefix.minorVersion;
+	dpy->release 		= u.setup->release;
+	dpy->resource_base	= u.setup->ridBase;
+	dpy->resource_mask	= u.setup->ridMask;
+	dpy->min_keycode	= u.setup->minKeyCode;
+	dpy->max_keycode	= u.setup->maxKeyCode;
+	dpy->motion_buffer	= u.setup->motionBufferSize;
+	dpy->nformats		= u.setup->numFormats;
+	dpy->nscreens		= u.setup->numRoots;
+	dpy->byte_order		= u.setup->imageByteOrder;
+	dpy->bitmap_unit	= u.setup->bitmapScanlineUnit;
+	dpy->bitmap_pad		= u.setup->bitmapScanlinePad;
+	dpy->bitmap_bit_order   = u.setup->bitmapBitOrder;
+	dpy->max_request_size	= u.setup->maxRequestSize;
+	mask = dpy->resource_mask;
+	dpy->resource_shift	= 0;
+	if (!mask)
+	{
+	    fprintf (stderr, "Xlib: connection to \"%s\" invalid setup\n",
+		     dpy->display_name);
+	    OutOfMemory(dpy);
+	    return (NULL);
+	}
+
+	while (!(mask & 1)) {
+	    dpy->resource_shift++;
+	    mask = mask >> 1;
+	}
+	dpy->resource_max = (dpy->resource_mask >> dpy->resource_shift) - 5;
+	/*
+	 * now extract the vendor string...  String must be null terminated,
+	 * padded to multiple of 4 bytes.
+	 */
+	/* Check for a sane vendor string length */
+	if (u.setup->nbytesVendor > 256) {
+	    OutOfMemory(dpy);
+	    return (NULL);
+	}
+
+	dpy->vendor = Xmalloc(u.setup->nbytesVendor + 1);
+	if (dpy->vendor == NULL) {
+	    OutOfMemory(dpy);
+	    return (NULL);
+	}
+	vendorlen = u.setup->nbytesVendor;
+
+	/*
+	 * validate setup length
+	 */
+	usedbytes += (vendorlen + 3) & ~3;
+	if (setuplength < usedbytes) {
+	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
+	    OutOfMemory(dpy);
+	    return (NULL);
+	}
+
+ 	u.setup = (xConnSetup *) (((char *) u.setup) + sz_xConnSetup);
+  	(void) strncpy(dpy->vendor, u.vendor, vendorlen);
+	dpy->vendor[vendorlen] = '\0';
+ 	vendorlen = (vendorlen + 3) & ~3;	/* round up */
+	u.vendor += vendorlen;
+
+	/*
+	 * Now iterate down setup information.....
+	 */
+	dpy->pixmap_format = Xcalloc(dpy->nformats, sizeof(ScreenFormat));
+	if (dpy->pixmap_format == NULL) {
+	        OutOfMemory (dpy);
+		return(NULL);
+	}
+	/*
+	 * First decode the Z axis Screen format information.
+	 */
+	usedbytes += dpy->nformats * sz_xPixmapFormat;
+
+	if (setuplength < usedbytes) {
+	    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
+	    OutOfMemory (dpy);
+	    return(NULL);
+	}
+
+	for (i = 0; i < dpy->nformats; i++) {
+	    register ScreenFormat *fmt = &dpy->pixmap_format[i];
+	    fmt->depth = u.sf->depth;
+	    fmt->bits_per_pixel = u.sf->bitsPerPixel;
+	    fmt->scanline_pad = u.sf->scanLinePad;
+	    fmt->ext_data = NULL;
+	    u.sf = (xPixmapFormat *) (((char *) u.sf) + sz_xPixmapFormat);
+	}
+
+	/*
+	 * next the Screen structures.
+	 */
+	dpy->screens = Xcalloc(dpy->nscreens, sizeof(Screen));
+	if (dpy->screens == NULL) {
+	        OutOfMemory (dpy);
+		return(NULL);
+	}
+
+	/*
+	 * Now go deal with each screen structure.
+	 */
+	for (i = 0; i < dpy->nscreens; i++) {
+	    register Screen *sp = &dpy->screens[i];
+	    VisualID root_visualID;
+
+	    usedbytes += sz_xWindowRoot;
+	    if (setuplength < usedbytes) {
+		fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
+		OutOfMemory (dpy);
+		return(NULL);
+	    }
+
+	    root_visualID = u.rp->rootVisualID;
+	    sp->display	    = dpy;
+	    sp->root 	    = u.rp->windowId;
+	    sp->cmap 	    = u.rp->defaultColormap;
+	    sp->white_pixel = u.rp->whitePixel;
+	    sp->black_pixel = u.rp->blackPixel;
+	    sp->root_input_mask = u.rp->currentInputMask;
+	    sp->width	    = u.rp->pixWidth;
+	    sp->height	    = u.rp->pixHeight;
+	    sp->mwidth	    = u.rp->mmWidth;
+	    sp->mheight	    = u.rp->mmHeight;
+	    sp->min_maps    = u.rp->minInstalledMaps;
+	    sp->max_maps    = u.rp->maxInstalledMaps;
+	    sp->backing_store= u.rp->backingStore;
+	    sp->save_unders = u.rp->saveUnders;
+	    sp->root_depth  = u.rp->rootDepth;
+	    sp->ndepths	    = u.rp->nDepths;
+	    sp->ext_data   = NULL;
+	    u.rp = (xWindowRoot *) (((char *) u.rp) + sz_xWindowRoot);
+	/*
+	 * lets set up the depth structures.
+	 */
+	    sp->depths = Xcalloc(sp->ndepths, sizeof(Depth));
+	    if (sp->depths == NULL) {
+		OutOfMemory (dpy);
+		return(NULL);
+	    }
+	    /*
+	     * for all depths on this screen.
+	     */
+	    for (j = 0; j < sp->ndepths; j++) {
+		Depth *dp = &sp->depths[j];
+
+		usedbytes += sz_xDepth;
+		if (setuplength < usedbytes) {
+		    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
+		    OutOfMemory (dpy);
+		    return(NULL);
+		}
+
+		dp->depth = u.dp->depth;
+		dp->nvisuals = u.dp->nVisuals;
+		u.dp = (xDepth *) (((char *) u.dp) + sz_xDepth);
+		if (dp->nvisuals > 0) {
+		    dp->visuals = Xcalloc(dp->nvisuals, sizeof(Visual));
+		    if (dp->visuals == NULL) {
+			OutOfMemory (dpy);
+			return(NULL);
+		    }
+		    for (k = 0; k < dp->nvisuals; k++) {
+			register Visual *vp = &dp->visuals[k];
+
+			usedbytes += sz_xVisualType;
+			if (setuplength < usedbytes) {
+			    fprintf (stderr, "Xlib: Broken initial reply: Too short (%ld)\n", setuplength);
+			    OutOfMemory (dpy);
+			    return(NULL);
+			}
+
+			vp->visualid	= u.vp->visualID;
+			vp->class	= u.vp->class;
+			vp->bits_per_rgb= u.vp->bitsPerRGB;
+			vp->map_entries	= u.vp->colormapEntries;
+			vp->red_mask	= u.vp->redMask;
+			vp->green_mask	= u.vp->greenMask;
+			vp->blue_mask	= u.vp->blueMask;
+			vp->ext_data	= NULL;
+			u.vp = (xVisualType *) (((char *) u.vp) +
+						sz_xVisualType);
+		    }
+		    if (dp->depth == 32 && getenv ("XLIB_SKIP_ARGB_VISUALS"))
+		    {
+			Xfree (dp->visuals);
+			dp->visuals = NULL;
+			dp->nvisuals = 0;
+		    }
+		} else {
+		    dp->visuals = (Visual *) NULL;
+		}
+	    }
+	    sp->root_visual = _XVIDtoVisual(dpy, root_visualID);
+	}
+
+	if(usedbytes != setuplength){
+	    /* Sanity check, shouldn't happen. */
+	    fprintf(stderr, "Xlib: Did not parse entire setup message: "
+	                    "parsed: %ld, message: %ld\n",
+		    usedbytes, setuplength);
+	    OutOfMemory(dpy);
+	    return(NULL);
+	}
+
+	/*
+	 * Now start talking to the server to setup all other information...
+	 */
+
+/*
+ * Make sure default screen is legal.
+ */
+	if (iscreen >= dpy->nscreens) {
+	    OutOfMemory(dpy);
+	    return(NULL);
+	}
+
+	/*
+	 * get availability of large requests
+	 */
+	dpy->bigreq_size = xcb_get_maximum_request_length(dpy->xcb->connection);
+	if(dpy->bigreq_size <= dpy->max_request_size)
+		dpy->bigreq_size = 0;
+
+	/*
+	 * Set up other stuff clients are always going to use.
+	 */
+	for (i = 0; i < dpy->nscreens; i++) {
+	    register Screen *sp = &dpy->screens[i];
+	    XGCValues values;
+	    values.foreground = sp->black_pixel;
+	    values.background = sp->white_pixel;
+	    if ((sp->default_gc = XCreateGC (dpy, sp->root,
+					     GCForeground|GCBackground,
+					     &values)) == NULL) {
+		OutOfMemory(dpy);
+		return (NULL);
+	    }
+	}
+	/*
+	 * call into synchronization routine so that all programs can be
+	 * forced synchronous
+	 */
+	(void) XSynchronize(dpy, _Xdebug);
+
+	/*
+	 * get the resource manager database off the root window.
+	 */
+	LockDisplay(dpy);
+	{
+	    xGetPropertyReply reply;
+	    xGetPropertyReq *req;
+
+	    GetReq (GetProperty, req);
+	    req->window = RootWindow(dpy, 0);
+	    req->property = XA_RESOURCE_MANAGER;
+	    req->type = XA_STRING;
+	    req->delete = False;
+	    req->longOffset = 0;
+	    req->longLength = 100000000L;
+
+	    if (_XReply (dpy, (xReply *) &reply, 0, xFalse)) {
+		if (reply.format == 8 && reply.propertyType == XA_STRING &&
+		    (reply.nItems + 1 > 0) &&
+		    (reply.nItems <= req->longLength * 4) &&
+		    (dpy->xdefaults = Xmalloc (reply.nItems + 1))) {
+		    _XReadPad (dpy, dpy->xdefaults, reply.nItems);
+		    dpy->xdefaults[reply.nItems] = '\0';
+		}
+		else if (reply.propertyType != None)
+		    _XEatDataWords(dpy, reply.length);
+	    }
+	}
+	UnlockDisplay(dpy);
+
+#ifdef MOTIFBC
+	{
+	    extern Display *_XHeadOfDisplayList;
+	    _XHeadOfDisplayList = dpy;
+	}
+#endif
+#ifdef XKB
+	XkbUseExtension(dpy,NULL,NULL);
+#endif
+	/*
+	 * and return successfully
+	 */
+ 	return(dpy);
+}
-- 
2.4.0

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to