diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2016-10-12 08:32:04 +0200 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2016-10-12 08:32:04 +0200 |
commit | 051d521f6e20761ba6831cecd91883da960fa931 (patch) | |
tree | b28abba7818115d2fed80eb360a79a0f9183948e /nx-X11/lib/X11/XlibInt.c | |
parent | 6dce607bad8711dd06a5a7b69ad1930386b4123b (diff) | |
parent | b8de7bf654929c823080b211aeac56cd213f5a32 (diff) | |
download | nx-libs-051d521f6e20761ba6831cecd91883da960fa931.tar.gz nx-libs-051d521f6e20761ba6831cecd91883da960fa931.tar.bz2 nx-libs-051d521f6e20761ba6831cecd91883da960fa931.zip |
Merge branch 'uli42-pr/upgrade_libX11' into 3.6.x
Attributes GH PR #214: https://github.com/ArcticaProject/nx-libs/pull/214
Fixes ArcticaProject/nx-libs#157.
Diffstat (limited to 'nx-X11/lib/X11/XlibInt.c')
-rw-r--r-- | nx-X11/lib/X11/XlibInt.c | 644 |
1 files changed, 434 insertions, 210 deletions
diff --git a/nx-X11/lib/X11/XlibInt.c b/nx-X11/lib/X11/XlibInt.c index 67483d3af..7ca1d0d01 100644 --- a/nx-X11/lib/X11/XlibInt.c +++ b/nx-X11/lib/X11/XlibInt.c @@ -63,9 +63,13 @@ from The Open Group. #include <config.h> #endif #include "Xlibint.h" +#include "Xprivate.h" #include <nx-X11/Xpoll.h> +#if !USE_XCB #include <nx-X11/Xtrans/Xtrans.h> #include <nx-X11/extensions/xcmiscstr.h> +#endif /* !USE_XCB */ +#include <assert.h> #include <stdio.h> #ifdef WIN32 #include <direct.h> @@ -97,6 +101,7 @@ xthread_t (*_Xthread_self_fn)(void) = NULL; #define XThread_Self() ((*_Xthread_self_fn)()) +#if !USE_XCB #define UnlockNextReplyReader(d) if ((d)->lock) \ (*(d)->lock->pop_reader)((d),&(d)->lock->reply_awaiters,&(d)->lock->reply_awaiters_tail) @@ -104,24 +109,16 @@ xthread_t (*_Xthread_self_fn)(void) = NULL; (*(d)->lock->push_reader)(d,&(d)->lock->reply_awaiters_tail) : NULL) #define QueueEventReaderLock(d) ((d)->lock ? \ (*(d)->lock->push_reader)(d,&(d)->lock->event_awaiters_tail) : NULL) - -#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) -#define InternalLockDisplay(d,wskip) if ((d)->lock) \ - (*(d)->lock->internal_lock_display)(d,wskip,__FILE__,__LINE__) -#else -#define InternalLockDisplay(d,wskip) if ((d)->lock) \ - (*(d)->lock->internal_lock_display)(d,wskip) -#endif +#endif /* !USE_XCB */ #else /* XTHREADS else */ -#define UnlockNextReplyReader(d) +#if !USE_XCB +#define UnlockNextReplyReader(d) #define UnlockNextEventReader(d) -#define InternalLockDisplay(d,wskip) +#endif /* !USE_XCB */ -#endif /* XTHREADS else */ - -#include <nx/NX.h> +#endif /* XTHREADS else */ #ifdef NX_TRANS_SOCKET @@ -142,9 +139,7 @@ static struct timeval retry; */ #ifdef NX_TRANS_CHANGE - extern int _X11TransSocketCongestionChange(XtransConnInfo, int *); - #endif #endif /* #ifdef NX_TRANS_SOCKET */ @@ -178,11 +173,7 @@ extern int _X11TransSocketCongestionChange(XtransConnInfo, int *); #define ECHECK(err) (errno == err) #define ESET(val) #else -#ifdef ISC -#define ECHECK(err) ((errno == err) || ETEST()) -#else #define ECHECK(err) (errno == err) -#endif #define ESET(val) errno = val #endif #endif @@ -200,11 +191,15 @@ extern int _X11TransSocketCongestionChange(XtransConnInfo, int *); #endif #ifdef __UNIXOS2__ +#if !USE_XCB #define select(n,r,w,x,t) os2ClientSelect(n,r,w,x,t) +#endif /* !USE_XCB */ #include <limits.h> #define MAX_PATH _POSIX_PATH_MAX #endif +#if !USE_XCB + #define STARTITERATE(tpvar,type,start,endcond) \ for (tpvar = (type *) (start); endcond; ) #define ITERPTR(tpvar) (char *)tpvar @@ -212,6 +207,7 @@ extern int _X11TransSocketCongestionChange(XtransConnInfo, int *); #define INCITERPTR(tpvar,type) tpvar++ #define ENDITERATE + typedef union { xReply rep; char buf[BUFSIZE]; @@ -223,12 +219,7 @@ static char *_XAsyncReply( char *buf, register int *lenp, Bool discard); - -static void _XProcessInternalConnection( - Display *dpy, - struct _XConnectionInfo *conn_info); - -#define SEQLIMIT (65535 - (BUFSIZE / SIZEOF(xReq)) - 10) +#endif /* !USE_XCB */ /* * The following routines are internal routines used by Xlib for protocol @@ -243,11 +234,12 @@ static void _XProcessInternalConnection( * perform any operations (directly or indirectly) on the DISPLAY. * * Routines declared with a return type of 'Status' return 0 on failure, - * and non 0 on success. Routines with no declared return type don't + * and non 0 on success. Routines with no declared return type don't * return anything. Whenever possible routines that create objects return * the object they have created. */ +#if !USE_XCB static xReq _dummy_request = { 0, 0, 0 }; @@ -369,16 +361,13 @@ _XWaitForWritable( #endif int nfound; -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) +#ifdef NX_TRANS_SOCKET +#if defined(NX_TRANS_CHANGE) int congestion; #endif - -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { return; } - #endif #ifdef USE_POLL @@ -409,7 +398,7 @@ _XWaitForWritable( XXX - what if cv is NULL and someone else comes along after us while we are waiting? */ - + if (!dpy->lock || (!dpy->lock->event_awaiters && (!dpy->lock->reply_awaiters || @@ -456,18 +445,17 @@ _XWaitForWritable( FD_SET(dpy->fd, &w_mask); #endif #endif /* #ifdef NX_TRANS_SOCKET */ - UnlockDisplay(dpy); #ifdef USE_POLL #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XWaitForWritable: Calling poll().\n"); #endif nfound = poll (&filedes, 1, -1); -#else +#else /* USE_POLL */ #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XWaitForWritable: Calling select() after [%ld] ms.\n", NXTransTime()); -#endif +#endif /* defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) */ #ifdef NX_TRANS_SOCKET /* * Give a chance to the callback to detect @@ -482,9 +470,9 @@ _XWaitForWritable( } else { nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); } -#else +#else /* NX_TRANS_SOCKET */ nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); -#endif +#endif /* NX_TRANS_SOCKET */ #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XWaitForWritable: Out of select() with [%d] after [%ld] ms.\n", nfound, NXTransTime()); @@ -504,37 +492,36 @@ _XWaitForWritable( fprintf(stderr, "_XWaitForWritable: Descriptor [%d] has become writable.\n\n", dpy->fd); } -#endif -#endif +#endif /* defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) */ +#endif /* USE_POLL */ InternalLockDisplay(dpy, cv != NULL); +#ifdef NX_TRANS_SOCKET #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) if (_NXDisplayCongestionFunction != NULL && _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { (*_NXDisplayCongestionFunction)(dpy, congestion); } -#endif - -#ifdef NX_TRANS_SOCKET +#endif /* defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) */ if (nfound <= 0) { - if ((nfound == -1 && !ECHECK(EINTR)) || + if ((nfound == -1 && !(ECHECK(EINTR) || ETEST())) || (_NXDisplayErrorFunction != NULL && (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { _XIOError(dpy); return; } } -#else - if (nfound < 0 && !ECHECK(EINTR)) +#else /* NX_TRANS_SOCKET */ + if (nfound < 0 && !(ECHECK(EINTR) || ETEST())) _XIOError(dpy); -#endif +#endif /* NX_TRANS_SOCKET */ } while (nfound <= 0); if ( #ifdef USE_POLL filedes.revents & POLLIN -#else +#else /* USE_POLL */ FD_ISSET(dpy->fd, &r_mask) -#endif +#endif /* USE_POLL */ ) { _XAlignedBuffer buf; @@ -550,9 +537,9 @@ _XWaitForWritable( return; } -#else +#else /* NX_TRANS_SOCKET */ _XIOError(dpy); -#endif +#endif /* NX_TRANS_SOCKET */ len = pend; /* must read at least one xEvent; if none is pending, then @@ -563,7 +550,7 @@ _XWaitForWritable( #endif ) len = SIZEOF(xReply); - + /* but we won't read more than the max buffer size */ if (len > BUFSIZE) len = BUFSIZE; @@ -609,6 +596,7 @@ _XWaitForWritable( } } } +#endif /* !USE_XCB */ #define POLLFD_CACHE_SIZE 5 @@ -666,6 +654,7 @@ void _XPollfdCacheDel( #endif } +#if !USE_XCB /* returns True iff there is an event in the queue newer than serial_num */ static Bool @@ -694,7 +683,7 @@ _XWaitForReadable( { int result; int fd = dpy->fd; - struct _XConnectionInfo *ilist; + struct _XConnectionInfo *ilist; register int saved_event_serial = 0; int in_read_events = 0; register Bool did_proc_conni = False; @@ -730,9 +719,9 @@ _XWaitForReadable( } else { filedes = (struct pollfd *)dpy->filedes; } -#else +#else /* USE_POLL */ FD_ZERO(&r_mask); -#endif +#endif /* USE_POLL */ for (;;) { #ifndef USE_POLL FD_SET(fd, &r_mask); @@ -742,7 +731,7 @@ _XWaitForReadable( if (ilist->fd > highest_fd) highest_fd = ilist->fd; } -#endif +#endif /* USE_POLL */ UnlockDisplay(dpy); #ifdef USE_POLL #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) @@ -751,7 +740,7 @@ _XWaitForReadable( result = poll(filedes, (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length, -1); -#else +#else /* USE_POLL */ #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XWaitForReadable: Calling select().\n"); #endif @@ -777,10 +766,10 @@ _XWaitForReadable( } else { result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); } -#else +#else /* NX_TRANS_SOCKET */ result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); -#endif -#endif +#endif /* NX_TRANS_SOCKET */ +#endif /* USE_POLL */ #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XWaitForReadable: Out of select with result [%d] and errno [%d].\n", result, (result < 0 ? errno : 0)); @@ -794,7 +783,7 @@ _XWaitForReadable( #endif #ifdef NX_TRANS_SOCKET if (result <= 0) { - if ((result == -1 && !ECHECK(EINTR)) || + if ((result == -1 && !(ECHECK(EINTR) || ETEST())) || (_NXDisplayErrorFunction != NULL && (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { _XIOError(dpy); @@ -803,7 +792,7 @@ _XWaitForReadable( continue; } #else - if (result == -1 && !ECHECK(EINTR)) _XIOError(dpy); + if (result == -1 && !(ECHECK(EINTR) || ETEST())) _XIOError(dpy); if (result <= 0) continue; #endif @@ -856,9 +845,32 @@ _XWaitForReadable( #endif return 0; } +#endif /* !USE_XCB */ + +static int sync_hazard(Display *dpy) +{ + unsigned long span = dpy->request - dpy->last_request_read; + unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10); + return span >= 65535 - hazard - 10; +} static -int _XSeqSyncFunction( +void sync_while_locked(Display *dpy) +{ +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); +#endif + UnlockDisplay(dpy); + SyncHandle(); + InternalLockDisplay(dpy, /* don't skip user locks */ 0); +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_unlock_display)(dpy); +#endif +} + +void _XSeqSyncFunction( register Display *dpy) { xGetInputFocusReply rep; @@ -868,30 +880,62 @@ int _XSeqSyncFunction( #ifdef NX_TRANS_DEBUG fprintf(stderr, "_XSeqSyncFunction: Going to synchronize the display.\n"); #endif + if (dpy->flags & XlibDisplayIOError) { #ifdef NX_TRANS_DEBUG fprintf(stderr, "_XSeqSyncFunction: Returning 0 with I/O error detected.\n"); #endif - return 0; + return; } -#endif - - LockDisplay(dpy); - if ((dpy->request - dpy->last_request_read) >= (BUFSIZE / SIZEOF(xReq))) { +#endif /* NX_TRANS_SOCKET */ + if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) { GetEmptyReq(GetInputFocus, req); (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); - } - /* could get XID handler while waiting for reply in MT env */ - if (dpy->synchandler == _XSeqSyncFunction) { - dpy->synchandler = dpy->savedsynchandler; - dpy->flags &= ~XlibDisplayPrivSync; - } - UnlockDisplay(dpy); - SyncHandle(); + sync_while_locked(dpy); + } else if (sync_hazard(dpy)) + _XSetPrivSyncFunction(dpy); +} + +/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */ +static int +_XPrivSyncFunction (Display *dpy) +{ +#if XTHREADS + assert(!dpy->lock_fns); +#endif + assert(dpy->synchandler == _XPrivSyncFunction); + assert((dpy->flags & XlibDisplayPrivSync) != 0); + dpy->synchandler = dpy->savedsynchandler; + dpy->savedsynchandler = NULL; + dpy->flags &= ~XlibDisplayPrivSync; + if(dpy->synchandler) + dpy->synchandler(dpy); + _XIDHandler(dpy); + _XSeqSyncFunction(dpy); return 0; } +void _XSetPrivSyncFunction(Display *dpy) +{ +#ifdef XTHREADS + if (dpy->lock_fns) + return; +#endif + if (!(dpy->flags & XlibDisplayPrivSync)) { + dpy->savedsynchandler = dpy->synchandler; + dpy->synchandler = _XPrivSyncFunction; + dpy->flags |= XlibDisplayPrivSync; + } +} + +void _XSetSeqSyncFunction(Display *dpy) +{ + if (sync_hazard(dpy)) + _XSetPrivSyncFunction (dpy); +} + +#if !USE_XCB #ifdef XTHREADS static void _XFlushInt( register Display *dpy, @@ -936,7 +980,7 @@ static void _XFlushInt( #endif /* This fix resets the bufptr to the front of the buffer so * additional appends to the bufptr will not corrupt memory. Since - * the server is down, these appends are no-op's anyway but + * the server is down, these appends are no-op's anyway but * callers of _XFlush() are not verifying this before they call it. */ if (dpy->flags & XlibDisplayIOError) @@ -1015,7 +1059,7 @@ static void _XFlushInt( #endif #ifdef ESZTEST } else if (ESZTEST()) { - if (todo > 1) + if (todo > 1) todo >>= 1; else { _XWaitForWritable(dpy @@ -1046,12 +1090,7 @@ static void _XFlushInt( #endif } dpy->last_req = (char *)&_dummy_request; - if ((dpy->request - dpy->last_request_read) >= SEQLIMIT && - !(dpy->flags & XlibDisplayPrivSync)) { - dpy->savedsynchandler = dpy->synchandler; - dpy->synchandler = _XSeqSyncFunction; - dpy->flags |= XlibDisplayPrivSync; - } + _XSetSeqSyncFunction(dpy); dpy->bufptr = dpy->buffer; #ifdef XTHREADS dpy->flags &= ~XlibDisplayWriting; @@ -1192,7 +1231,7 @@ _XEventsQueued( } #ifdef NX_TRANS_SOCKET if (result <= 0) { - if ((result == -1 && !ECHECK(EINTR)) || + if ((result == -1 && !(ECHECK(EINTR) || ETEST())) || (_NXDisplayErrorFunction != NULL && (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { _XIOError(dpy); @@ -1200,9 +1239,9 @@ _XEventsQueued( } } #else - else if (result < 0 && !ECHECK(EINTR)) - _XIOError(dpy); + else if (result < 0 && !(ECHECK(EINTR) || ETEST())) #endif + _XIOError(dpy); } } #endif /* XCONN_CHECK_FREQ */ @@ -1214,7 +1253,6 @@ _XEventsQueued( { UnlockNextEventReader(dpy); } - #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XEventsQueued: Returning [%d].\n", dpy->qlen); #endif @@ -1233,7 +1271,7 @@ _XEventsQueued( #endif /* XTHREADS*/ { read_buf = buf.buf; - + if (len < SIZEOF(xReply) #ifdef XTHREADS || dpy->async_handlers @@ -1249,7 +1287,7 @@ _XEventsQueued( #endif (void) _XRead (dpy, read_buf, (long) len); - + #ifdef NX_TRANS_SOCKET if (_XGetIOError(dpy)) { return(dpy->qlen); @@ -1353,15 +1391,12 @@ void _XReadEvents( #endif /* XTHREADS */ /* find out how much data can be read */ if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) -#ifdef NX_TRANS_SOCKET { _XIOError(dpy); - +#ifdef NX_TRANS_SOCKET return; - } -#else - _XIOError(dpy); #endif + } len = pend; /* must read at least one xEvent; if none is pending, then @@ -1462,12 +1497,22 @@ void _XReadEvents( RESETITERPTR(rep,xReply, _XAsyncReply (dpy, rep, ITERPTR(rep), &len, True)); - pend = len; + pend = len; } else { if (rep->generic.type == X_Error) _XError (dpy, (xError *) rep); else /* must be an event packet */ - _XEnq (dpy, (xEvent *)rep); + { + if (rep->generic.type == GenericEvent) + { + int evlen; + evlen = (rep->generic.length << 2); + if (_XRead(dpy, &read_buf[len], evlen) == -2) + goto got_event; /* XXX: aargh! */ + } + + _XEnq (dpy, (xEvent *)rep); + } INCITERPTR(rep,xReply); len -= SIZEOF(xReply); } @@ -1477,7 +1522,7 @@ void _XReadEvents( UnlockNextEventReader(dpy); } -/* +/* * _XRead - Read bytes from the socket taking into account incomplete * reads. This routine may have to be reworked if int < long. */ @@ -1577,6 +1622,7 @@ int _XRead( #endif /* XTHREADS*/ return 0; } +#endif /* !USE_XCB */ #ifdef LONG64 void _XRead32( @@ -1599,6 +1645,8 @@ void _XRead32( #endif /* LONG64 */ + +#if !USE_XCB /* * _XReadPad - Read bytes from the socket taking into account incomplete * reads. If the number of bytes is not 0 mod 4, read additional pad @@ -1622,7 +1670,7 @@ void _XReadPad( if ((dpy->flags & XlibDisplayIOError) || size == 0) return; iov[0].iov_len = (int)size; iov[0].iov_base = data; - /* + /* * The following hack is used to provide 32 bit long-word * aligned padding. The [1] vector is of length 0, 1, 2, or 3, * whatever is needed. @@ -1683,7 +1731,7 @@ void _XReadPad( _XIOError(dpy); #endif } - + else /* bytes_read is less than 0; presumably -1 */ { /* If it's a system call interrupt, it's not an error. */ #ifdef NX_TRANS_SOCKET @@ -1820,7 +1868,7 @@ _XSend ( InsertIOV (dpy->buffer, dbufsize) InsertIOV ((char *)data, size) InsertIOV ((char *)pad, padsize) - + ESET(0); if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) { #ifdef NX_TRANS_SOCKET @@ -1853,7 +1901,7 @@ _XSend ( #endif #ifdef ESZTEST } else if (ESZTEST()) { - if (todo > 1) + if (todo > 1) todo >>= 1; else { _XWaitForWritable(dpy @@ -1882,12 +1930,7 @@ _XSend ( #endif } dpy->last_req = (char *) & _dummy_request; - if ((dpy->request - dpy->last_request_read) >= SEQLIMIT && - !(dpy->flags & XlibDisplayPrivSync)) { - dpy->savedsynchandler = dpy->synchandler; - dpy->synchandler = _XSeqSyncFunction; - dpy->flags |= XlibDisplayPrivSync; - } + _XSetSeqSyncFunction(dpy); dpy->bufptr = dpy->buffer; #ifdef XTHREADS dpy->flags &= ~XlibDisplayWriting; @@ -1925,35 +1968,30 @@ _XGetMiscCode( } } -static int +void _XIDHandler( register Display *dpy) { xXCMiscGetXIDRangeReply grep; register xXCMiscGetXIDRangeReq *greq; - LockDisplay(dpy); - _XGetMiscCode(dpy); - if (dpy->xcmisc_opcode > 0) { - GetReq(XCMiscGetXIDRange, greq); - greq->reqType = dpy->xcmisc_opcode; - greq->miscReqType = X_XCMiscGetXIDRange; - if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) { - dpy->resource_id = ((grep.start_id - dpy->resource_base) >> - dpy->resource_shift); - dpy->resource_max = dpy->resource_id; - if (grep.count > 5) - dpy->resource_max += grep.count - 6; - dpy->resource_max <<= dpy->resource_shift; + if (dpy->resource_max == dpy->resource_mask + 1) { + _XGetMiscCode(dpy); + if (dpy->xcmisc_opcode > 0) { + GetReq(XCMiscGetXIDRange, greq); + greq->reqType = dpy->xcmisc_opcode; + greq->miscReqType = X_XCMiscGetXIDRange; + if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) { + dpy->resource_id = ((grep.start_id - dpy->resource_base) >> + dpy->resource_shift); + dpy->resource_max = dpy->resource_id; + if (grep.count > 5) + dpy->resource_max += grep.count - 6; + dpy->resource_max <<= dpy->resource_shift; + } + sync_while_locked(dpy); } } - if (dpy->flags & XlibDisplayPrivSync) { - dpy->synchandler = dpy->savedsynchandler; - dpy->flags &= ~XlibDisplayPrivSync; - } - UnlockDisplay(dpy); - SyncHandle(); - return 0; } /* @@ -1966,11 +2004,7 @@ XID _XAllocID( id = dpy->resource_id << dpy->resource_shift; if (id >= dpy->resource_max) { - if (!(dpy->flags & XlibDisplayPrivSync)) { - dpy->savedsynchandler = dpy->synchandler; - dpy->flags |= XlibDisplayPrivSync; - } - dpy->synchandler = _XIDHandler; + _XSetPrivSyncFunction(dpy); dpy->resource_max = dpy->resource_mask + 1; } if (id <= dpy->resource_mask) { @@ -2026,11 +2060,7 @@ void _XAllocIDs( dpy->resource_id = id; } if (id >= dpy->resource_max) { - if (!(dpy->flags & XlibDisplayPrivSync)) { - dpy->savedsynchandler = dpy->synchandler; - dpy->flags |= XlibDisplayPrivSync; - } - dpy->synchandler = _XIDHandler; + _XSetPrivSyncFunction(dpy); dpy->resource_max = dpy->resource_mask + 1; } } @@ -2038,6 +2068,7 @@ void _XAllocIDs( for (i = grep.count; i < count; i++) ids[i] = XAllocID(dpy); } +#endif /* !USE_XCB */ /* * The hard part about this is that we only get 16 bits from a reply. @@ -2070,31 +2101,20 @@ _XSetLastRequestRead( if (newseq < lastseq) { newseq += 0x10000; if (newseq > dpy->request) { - #ifdef NX_TRANS_SOCKET - if (_NXLostSequenceFunction != NULL) { (*_NXLostSequenceFunction)(dpy, newseq, dpy->request, (unsigned int) rep->type); } else +#endif /* #ifdef NX_TRANS_SOCKET */ { (void) fprintf (stderr, "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", newseq, dpy->request, (unsigned int) rep->type); } - -#else /* #ifdef NX_TRANS_SOCKET */ - - (void) fprintf (stderr, - "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", - newseq, dpy->request, - (unsigned int) rep->type); - -#endif /* #ifdef NX_TRANS_SOCKET */ - newseq -= 0x10000; } } @@ -2103,6 +2123,7 @@ _XSetLastRequestRead( return(newseq); } +#if !USE_XCB /* * _XReply - Wait for a reply packet and copy its contents into the * specified rep. Meanwhile we must handle error and event packets that @@ -2181,7 +2202,6 @@ _XReply ( #ifdef NX_TRANS_TEST fprintf(stderr, "_XReply: Requesting a flush of the NX transport.\n"); #endif - NXTransFlush(dpy->fd); #endif @@ -2212,9 +2232,9 @@ _XReply ( } if (extra <= rep->generic.length) { if (extra > 0) - /* + /* * Read the extra data into storage immediately - * following the GenericReply structure. + * following the GenericReply structure. */ (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), ((long)extra) << 2); @@ -2239,9 +2259,9 @@ _XReply ( #endif return 1; } - /* + /* *if we get here, then extra > rep->generic.length--meaning we - * read a reply that's shorter than we expected. This is an + * read a reply that's shorter than we expected. This is an * error, but we still need to figure out how to handle it... */ (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), @@ -2290,12 +2310,12 @@ _XReply ( UnlockNextReplyReader(dpy); return (0); } - /* + /* * we better see if there is an extension who may * want to suppress the error. */ for (ext = dpy->ext_procs; !ret && ext; ext = ext->next) { - if (ext->error) + if (ext->error) ret = (*ext->error)(dpy, err, &ext->codes, &ret_code); } if (!ret) { @@ -2324,7 +2344,7 @@ _XReply ( } #endif } -} +} static char * _XAsyncReply( @@ -2355,7 +2375,7 @@ _XAsyncReply( *lenp = 0; return buf; } - + for (async = dpy->async_handlers; async; async = next) { next = async->next; if ((consumed = (*async->handler)(dpy, rep, buf, *lenp, async->data))) @@ -2364,7 +2384,7 @@ _XAsyncReply( if (!consumed) { if (!discard) return buf; - (void) fprintf(stderr, + (void) fprintf(stderr, "Xlib: unexpected async reply (sequence 0x%lx)!\n", dpy->last_request_read); #ifdef XTHREADS @@ -2415,6 +2435,7 @@ _XAsyncReply( } return nbuf; } +#endif /* !USE_XCB */ /* * Support for internal connections, such as an IM might use. @@ -2456,7 +2477,6 @@ _XRegisterInternalConnection( #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XRegisterInternalConnection: Got called.\n"); #endif - new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo)); if (!new_conni) return 0; @@ -2507,7 +2527,6 @@ _XUnregisterInternalConnection( #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "_XUnregisterInternalConnection: Got called.\n"); #endif - for (prev = &dpy->im_fd_info; (info_list = *prev); prev = &info_list->next) { if (info_list->fd == fd) { @@ -2550,7 +2569,6 @@ XInternalConnectionNumbers( #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "XInternalConnectionNumbers: Got called.\n"); #endif - LockDisplay(dpy); count = 0; for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) @@ -2572,12 +2590,12 @@ XInternalConnectionNumbers( return 1; } -static void _XProcessInternalConnection( +void _XProcessInternalConnection( Display *dpy, struct _XConnectionInfo *conn_info) { dpy->flags |= XlibDisplayProcConni; -#ifdef XTHREADS +#if defined(XTHREADS) && !USE_XCB if (dpy->lock) { /* check cache to avoid call to thread_self */ if (xthread_have_id(dpy->lock->reading_thread)) @@ -2585,14 +2603,14 @@ static void _XProcessInternalConnection( else dpy->lock->conni_thread = XThread_Self(); } -#endif /* XTHREADS */ +#endif /* XTHREADS && !USE_XCB */ UnlockDisplay(dpy); (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data); LockDisplay(dpy); -#ifdef XTHREADS +#if defined(XTHREADS) && !USE_XCB if (dpy->lock) xthread_clear_id(dpy->lock->conni_thread); -#endif /* XTHREADS */ +#endif /* XTHREADS && !USE_XCB */ dpy->flags &= ~XlibDisplayProcConni; } @@ -2644,7 +2662,6 @@ XAddConnectionWatch( #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "XAddConnectionWatch: Got called.\n"); #endif - LockDisplay(dpy); /* allocate new watch data */ @@ -2688,7 +2705,7 @@ XAddConnectionWatch( * Unregister a callback registered by XAddConnectionWatch. * Both callback and client_data must match what was passed to * XAddConnectionWatch. - */ + */ void XRemoveConnectionWatch( Display* dpy, @@ -2704,7 +2721,6 @@ XRemoveConnectionWatch( #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) fprintf(stderr, "XRemoveConnectionWatch: Got called.\n"); #endif - LockDisplay(dpy); for (watch=dpy->conn_watchers; watch; watch=watch->next) { if (watch->fn == callback && watch->client_data == client_data) { @@ -2733,6 +2749,7 @@ XRemoveConnectionWatch( /* end of internal connections support */ +#if !USE_XCB /* Read and discard "n" 8-bit bytes of data */ void _XEatData( @@ -2766,7 +2783,7 @@ void _XEatData( lib. This workaround had been implemented temporarily in a couple of X libs, see e.g. https://lists.x.org/archives/xorg-devel/2013-July/036763.html. */ -#include <X11/Xmd.h> /* for LONG64 on 64-bit platforms */ +#include <nx-X11/Xmd.h> /* for LONG64 on 64-bit platforms */ #include <limits.h> void _XEatDataWords(Display *dpy, unsigned long n) @@ -2777,6 +2794,129 @@ void _XEatDataWords(Display *dpy, unsigned long n) #endif _XEatData (dpy, n << 2); } +#endif /* !USE_XCB */ + +/* Cookie jar implementation + dpy->cookiejar is a linked list. _XEnq receives the events but leaves + them in the normal EQ. _XStoreEvent returns the cookie event (minus + data pointer) and adds it to the cookiejar. _XDeq just removes + the entry like any other event but resets the data pointer for + cookie events (to avoid double-free, the memory is re-used by Xlib). + + _XFetchEventCookie (called from XGetEventData) removes a cookie from the + jar. _XFreeEventCookies removes all unclaimed cookies from the jar + (called by XNextEvent). + + _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the + normal EQ. + */ + +#include "utlist.h" +struct stored_event { + XGenericEventCookie ev; + struct stored_event *prev; + struct stored_event *next; +}; + +Bool +_XIsEventCookie(Display *dpy, XEvent *ev) +{ + return (ev->xcookie.type == GenericEvent && + dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); +} + +/** + * Free all events in the event list. + */ +void +_XFreeEventCookies(Display *dpy) +{ + struct stored_event **head, *e, *tmp; + + if (!dpy->cookiejar) + return; + + head = (struct stored_event**)&dpy->cookiejar; + + DL_FOREACH_SAFE(*head, e, tmp) { + XFree(e->ev.data); + XFree(e); + if (dpy->cookiejar == e) + dpy->cookiejar = NULL; + } +} + +/** + * Add an event to the display's event list. This event must be freed on the + * next call to XNextEvent(). + */ +void +_XStoreEventCookie(Display *dpy, XEvent *event) +{ + XGenericEventCookie* cookie = &event->xcookie; + struct stored_event **head, *add; + + if (!_XIsEventCookie(dpy, event)) + return; + + head = (struct stored_event**)(&dpy->cookiejar); + + add = Xmalloc(sizeof(struct stored_event)); + if (!add) { + ESET(ENOMEM); + _XIOError(dpy); + } + add->ev = *cookie; + DL_APPEND(*head, add); + cookie->data = NULL; /* don't return data yet, must be claimed */ +} + +/** + * Return the event with the given cookie and remove it from the list. + */ +Bool +_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) +{ + Bool ret = False; + struct stored_event **head, *event; + head = (struct stored_event**)&dpy->cookiejar; + + if (!_XIsEventCookie(dpy, (XEvent*)ev)) + return ret; + + DL_FOREACH(*head, event) { + if (event->ev.cookie == ev->cookie && + event->ev.extension == ev->extension && + event->ev.evtype == ev->evtype) { + *ev = event->ev; + DL_DELETE(*head, event); + Xfree(event); + ret = True; + break; + } + } + + return ret; +} + +Bool +_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) +{ + Bool ret = False; + int extension; + + if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) + return ret; + + extension = in->extension & 0x7F; + + if (!dpy->generic_event_copy_vec[extension]) + return ret; + + ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); + out->cookie = ret ? ++dpy->next_cookie : 0; + return ret; +} /* @@ -2789,12 +2929,13 @@ void _XEnq( register xEvent *event) { register _XQEvent *qelt; + int type, extension; if ((qelt = dpy->qfree)) { /* If dpy->qfree is non-NULL do this, else malloc a new one. */ dpy->qfree = qelt->next; } - else if ((qelt = + else if ((qelt = (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { /* Malloc call failed! */ ESET(ENOMEM); @@ -2807,12 +2948,33 @@ void _XEnq( #endif } qelt->next = NULL; - /* go call through display to find proper event reformatter */ - if ((*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) { + + type = event->u.u.type & 0177; + extension = ((xGenericEvent*)event)->extension; + /* If an extension has registerd a generic_event_vec handler, then + * it can handle event cookies. Otherwise, proceed with the normal + * event handlers. + * + * If the generic_event_vec is called, qelt->event is a event cookie + * with the data pointer and the "free" pointer set. Data pointer is + * some memory allocated by the extension. + */ + if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { + XGenericEventCookie *cookie = &qelt->event.xcookie; + (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); + cookie->cookie = ++dpy->next_cookie; + + qelt->qserial_num = dpy->next_event_serial_num++; + if (dpy->tail) dpy->tail->next = qelt; + else dpy->head = qelt; + + dpy->tail = qelt; + dpy->qlen++; + } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { qelt->qserial_num = dpy->next_event_serial_num++; if (dpy->tail) dpy->tail->next = qelt; else dpy->head = qelt; - + dpy->tail = qelt; dpy->qlen++; } else { @@ -2842,6 +3004,13 @@ void _XDeq( qelt->next = dpy->qfree; dpy->qfree = qelt; dpy->qlen--; + + if (_XIsEventCookie(dpy, &qelt->event)) { + XGenericEventCookie* cookie = &qelt->event.xcookie; + /* dpy->qfree is re-used, reset memory to avoid double free on + * _XFreeDisplayStructure */ + cookie->data = NULL; + } } /* @@ -2856,13 +3025,41 @@ _XUnknownWireEvent( register xEvent *event) /* wire protocol event */ { #ifdef notdef - (void) fprintf(stderr, + (void) fprintf(stderr, "Xlib: unhandled wire event! event number = %d, display = %x\n.", event->u.u.type, dpy); #endif return(False); } +Bool +_XUnknownWireEventCookie( + Display *dpy, /* pointer to display structure */ + XGenericEventCookie *re, /* pointer to where event should be reformatted */ + xEvent *event) /* wire protocol event */ +{ +#ifdef notdef + fprintf(stderr, + "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", + ((xGenericEvent*)event)->extension, dpy); +#endif + return(False); +} + +Bool +_XUnknownCopyEventCookie( + Display *dpy, /* pointer to display structure */ + XGenericEventCookie *in, /* source */ + XGenericEventCookie *out) /* destination */ +{ +#ifdef notdef + fprintf(stderr, + "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", + in->extension, dpy); +#endif + return(False); +} + /*ARGSUSED*/ Status _XUnknownNativeEvent( @@ -2871,7 +3068,7 @@ _XUnknownNativeEvent( register xEvent *event) /* wire protocol event */ { #ifdef notdef - (void) fprintf(stderr, + (void) fprintf(stderr, "Xlib: unhandled native event! event number = %d, display = %x\n.", re->type, dpy); #endif @@ -2892,7 +3089,7 @@ _XWireToEvent( (xGenericReply *)event); ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); ((XAnyEvent *)re)->display = dpy; - + /* Ignore the leading bit of the event type since it is set when a client sends an event rather than the server. */ @@ -2961,7 +3158,7 @@ _XWireToEvent( ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); ev->state = event->u.enterLeave.state; ev->mode = event->u.enterLeave.mode; - ev->same_screen = (event->u.enterLeave.flags & + ev->same_screen = (event->u.enterLeave.flags & ELFlagSameScreen) && True; ev->focus = (event->u.enterLeave.flags & ELFlagFocus) && True; @@ -3199,14 +3396,14 @@ _XWireToEvent( case ClientMessage: { register int i; - register XClientMessageEvent *ev + register XClientMessageEvent *ev = (XClientMessageEvent *) re; ev->window = event->u.clientMessage.window; ev->format = event->u.u.detail; switch (ev->format) { - case 8: + case 8: ev->message_type = event->u.clientMessage.u.b.type; - for (i = 0; i < 20; i++) + for (i = 0; i < 20; i++) ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; break; case 16: @@ -3252,7 +3449,7 @@ _XWireToEvent( /* - * _XDefaultIOError - Default fatal system error reporting routine. Called + * _XDefaultIOError - Default fatal system error reporting routine. Called * when an X internal system error is encountered. */ int _XDefaultIOError( @@ -3263,7 +3460,7 @@ int _XDefaultIOError( "X connection to %s broken (explicit kill or server shutdown).\r\n", DisplayString (dpy)); } else { - (void) fprintf (stderr, + (void) fprintf (stderr, "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", #ifdef WIN32 WSAGetLastError(), strerror(WSAGetLastError()), @@ -3271,7 +3468,7 @@ int _XDefaultIOError( errno, strerror (errno), #endif DisplayString (dpy)); - (void) fprintf (stderr, + (void) fprintf (stderr, " after %lu requests (%lu known processed) with %d events remaining.\r\n", NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), QLength(dpy)); @@ -3299,7 +3496,6 @@ int _XDefaultIOError( #else exit(1); #endif /* #ifdef NX_TRANS_SOCKET */ - return(0); /* dummy - function should never return */ } @@ -3312,13 +3508,13 @@ static int _XPrintDefaultError( char buffer[BUFSIZ]; char mesg[BUFSIZ]; char number[32]; - char *mtype = "XlibMessage"; + const char *mtype = "XlibMessage"; register _XExtension *ext = (_XExtension *)NULL; _XExtension *bext = (_XExtension *)NULL; XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); (void) fprintf(fp, "%s: %s\n ", mesg, buffer); - XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", mesg, BUFSIZ); (void) fprintf(fp, mesg, event->request_code); if (event->request_code < 128) { @@ -3351,7 +3547,7 @@ static int _XPrintDefaultError( /* kludge, try to find the extension that caused it */ buffer[0] = '\0'; for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_string) + if (ext->error_string) (*ext->error_string)(dpy, event->error_code, &ext->codes, buffer, BUFSIZ); if (buffer[0]) { @@ -3362,7 +3558,7 @@ static int _XPrintDefaultError( ext->codes.first_error < (int)event->error_code && (!bext || ext->codes.first_error > bext->codes.first_error)) bext = ext; - } + } if (bext) sprintf(buffer, "%s.%d", bext->name, event->error_code - bext->codes.first_error); @@ -3402,7 +3598,7 @@ static int _XPrintDefaultError( (void) fprintf(fp, mesg, event->resourceid); fputs("\n", fp); } - XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", mesg, BUFSIZ); fputs(" ", fp); (void) fprintf(fp, mesg, event->serial); @@ -3425,10 +3621,7 @@ int _XDefaultError( } /*ARGSUSED*/ -Bool _XDefaultWireError(display, he, we) - Display *display; - XErrorEvent *he; - xError *we; +Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) { return True; } @@ -3440,7 +3633,7 @@ int _XError ( Display *dpy, register xError *rep) { - /* + /* * X_Error packet encountered! We need to unpack the error before * giving it to the user. */ @@ -3467,23 +3660,23 @@ int _XError ( return 0; if (_XErrorFunction != NULL) { int rtn_val; -#ifdef XTHREADS +#if defined(XTHREADS) && !USE_XCB if (dpy->lock) (*dpy->lock->user_lock_display)(dpy); UnlockDisplay(dpy); -#endif /* XTHREADS */ +#endif /* XTHREADS && !USE_XCB */ rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ -#ifdef XTHREADS +#if defined(XTHREADS) && !USE_XCB LockDisplay(dpy); if (dpy->lock) (*dpy->lock->user_unlock_display)(dpy); -#endif /* XTHREADS */ +#endif /* XTHREADS && !USE_XCB */ return rtn_val; } else { return _XDefaultError(dpy, (XErrorEvent *)&event); } } - + /* * _XIOError - call user connection error handler and exit */ @@ -3496,6 +3689,16 @@ _XIOError ( errno = WSAGetLastError(); #endif + /* This assumes that the thread calling exit will call any atexit handlers. + * If this does not hold, then an alternate solution would involve + * registering an atexit handler to take over the lock, which would only + * assume that the same thread calls all the atexit handlers. */ +#ifdef XTHREADS + if (dpy->lock) + (*dpy->lock->user_lock_display)(dpy); +#endif + UnlockDisplay(dpy); + if (_XIOErrorFunction != NULL) (*_XIOErrorFunction)(dpy); else @@ -3688,6 +3891,7 @@ _XData32( #endif /* LONG64 */ + /* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. * Otherwise, Xau will not be able to find your cookies in the Xauthority file. * @@ -3696,9 +3900,13 @@ _XData32( * and so, you may be better off using gethostname (if it exists). */ -#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) +#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) #define NEED_UTSNAME #include <sys/utsname.h> +#else +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #endif /* @@ -3738,9 +3946,7 @@ int _XGetHostname ( * _XScreenOfWindow - get the Screen of a given window */ -Screen *_XScreenOfWindow (dpy, w) - Display *dpy; - Window w; +Screen *_XScreenOfWindow(Display *dpy, Window w) { register int i; Window root; @@ -3749,7 +3955,7 @@ Screen *_XScreenOfWindow (dpy, w) if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, &bw, &depth) == False) { - return None; + return NULL; } for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ if (root == RootWindow (dpy, i)) { @@ -3770,8 +3976,6 @@ void *_XGetRequest(Display *dpy, CARD8 type, size_t len) { xReq *req; - WORD64ALIGN - if (dpy->bufptr + len > dpy->bufmax) _XFlush(dpy); @@ -3854,7 +4058,7 @@ static int AccessFile (path, pathbuf, len_pathbuf, pathret) return 1; } -#ifndef __UNIXOS2__ +#ifndef __UNIXOS2__ /* one last place to look */ drive = getenv ("HOMEDRIVE"); if (drive) { @@ -3912,6 +4116,26 @@ int _XOpenFile(path, flags) return ret; } +int _XOpenFileMode(path, flags, mode) + _Xconst char* path; + int flags; + mode_t mode; +{ + char buf[MAX_PATH]; + char* bufp = NULL; + int ret = -1; + UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); + + if (AccessFile (path, buf, MAX_PATH, &bufp)) + ret = open (bufp, flags, mode); + + (void) SetErrorMode (olderror); + + if (bufp != buf) Xfree (bufp); + + return ret; +} + void* _XFopenFile(path, mode) _Xconst char* path; _Xconst char* mode; |