Import libX11 1.1.1 from X.Org 7.2RC3

This commit is contained in:
matthieu 2006-12-16 16:39:39 +00:00
parent 48b7839b9e
commit 7a183623da
11 changed files with 373 additions and 61 deletions

View File

@ -1,3 +1,128 @@
commit f637a5b03164263a3af2e644cf655e52b015f1bb
Author: Ross Combs <rocombs@cs.nmsu.edu>
Date: Sat Nov 25 14:45:17 2006 -0800
Debian bug #354315: Clarify return value in XGetWindowAttributes man page
This man page does not discuss the actual return values of the
function, but says they are of type "Status". One might assume
that this means you could compare it with the "Success" macro.
One would be wrong.
The X functions seem to have two three types representing status.
If it is an "int" there are a number of error codes or "Success"
which can be compared against. If it is a bool, the result can be
compared with "True" or "False". If the return type is "Status" it
appears that the return type is either 0 or 1. Unfortunately the
value for Success is zero, so it is important to distinguish
between the first two types of return values and the third;
otherwise the conditional will be inverted.
XGetWindowAttributes() is one of the functions which returns zero
for failure. The man page should make this clear.
commit c6a0b0f18ed1242eeb908f5cf767ab8381edd456
Author: Jamey Sharp <jamey@minilop.net>
Date: Sat Nov 25 14:23:45 2006 -0800
Bug #9154: Always process an event for _XReadEvents, even if an error occurs
Previously, process_responses (in the wait_for_first_event case called
from _XReadEvents) considered any return from xcb_wait_for_event
sufficient to think it had processed an event. If xcb_wait_for_event
returned an error, and no more events occurred before process_responses
called xcb_poll_for_event, process_responses would try to return with
dpy->head NULL, and would fail an assertion for the _XReadEvents
postcondition. Now, process_responses continues using xcb_wait_for_event
until it gets an event.
commit d56e78acce9b2aa1dd1bf172afedaa3bccd5e1c8
Author: Tilman Sauerbeck <tilman@code-monkey.de>
Date: Sat Nov 25 05:29:31 2006 -0800
Bug #9153: Fix access to freed memory.
The fix for bug #8622 introduced a smaller bug where _XReply would
read memory shortly after freeing it. This patch caches the needed
value in a stack-allocated variable before the heap-allocated memory
is freed.
commit 934ca763bbc0dd7ae460469bfc000ba101602bcc
Author: Josh Triplett <josh@freedesktop.org>
Date: Fri Nov 24 19:57:58 2006 -0800
libx11 doesn't use inputproto in public headers; don't require it in x11.pc
Based on a Debian patch.
commit 4255997ef2d92740d51f6e63e9eabcfa089683f0
Author: Josh Triplett <josh@freedesktop.org>
Date: Thu Nov 23 07:19:32 2006 -0800
Release libX11 1.1
commit a1168e11ec9377307c51a7271faec3bf88a63a66
Author: Jamey Sharp <jamey@minilop.net>
Date: Tue Nov 21 17:52:34 2006 -0800
Add note in man-page that XListFontsWithInfo is not thread-safe.
_XReply drops the Display lock, so the value of dpy->request may change
before _XReply is called again.
I discovered this by inspection a year or two ago. I'm pretty confident
in the claim, and nobody has come up with an argument for why it's safe
despite appearances.
commit 67abe024268c6b1fdee516e5d3a046ccffd7e80a
Author: Jamey Sharp <jamey@minilop.net>
Date: Sat Nov 18 15:39:26 2006 -0800
Bug #8622: Fix response processing order for threaded apps
Previously, process_responses (the common code for _XReply,
_XReadEvents, and _XEventsQueued) took the current request sequence
number as an argument, and did some highly complicated processing to
attempt to process responses in order across threads. This didn't
actually work.
Now, process_responses handles responses in order, by adding condition
variables to the list of outstanding requests in
dpy->xcb->pending_requests, and blocking on them when those requests
should get processed to allow _XReply to process them; if actually
called from _XReply, it returns when _XReply's request should get
processed. _XReply broadcasts on the condition variable after it has
read its reply and re-acquired the display lock.
Another great commit brought to you by Jamey Sharp, Josh Triplett, the
Gobby collaborative text editor, conspy, and ridiculous amounts of SSH
forwarding.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
commit 941f02ede63baa46f93ed8abccebe76fb29c0789
Author: Lars Knoll <lars@trolltech.com>
Date: Wed Nov 8 12:17:41 2006 -0800
Don't hold the display lock around callbacks to the application.
This fixes an XCB locking assertion failure, particularly with emacs.
commit e494ecaac1ec8a22bd9a85f800fca74d02e9d358
Author: Diego 'Flameeyes' Pettenò <flameeyes@gentoo.org>
Date: Tue Nov 7 09:32:00 2006 -0800
Add xcb-xlib dependency to x11.pc when built against XCB.
commit 2302008a3793eb4df8ede777d54fe06505c47eaf
Author: Eric Anholt <eric@anholt.net>
Date: Mon Nov 6 17:11:42 2006 -0800
XCB: Allocate the right amount of memory for dpy->lock_fns.
Fixes a crash I was experiencing on startup of anything using gdk.
commit 5f860655be88108b03ccd97470a0814819254bf0
Author: Jamey Sharp <jamey@minilop.net>
Date: Thu Nov 2 17:55:31 2006 -0800

View File

@ -1,3 +1,57 @@
Version 1.1.1 - 2006-11-30
The "xcompmgr is hard, let's go releasing" release
* Fix Bug #9154 and friends, to unbreak xcompmgr:
Always process an event for _XReadEvents, even if an error occurs.
Previously, process_responses (in the wait_for_first_event case called
from _XReadEvents) considered any return from xcb_wait_for_event
sufficient to think it had processed an event. If xcb_wait_for_event
returned an error, and no more events occurred before process_responses
called xcb_poll_for_event, process_responses would try to return with
dpy->head NULL, and would fail an assertion for the _XReadEvents
postcondition. Now, process_responses continues using xcb_wait_for_event
until it gets an event.
* Bug #9153: Fix access to freed memory.
The fix for bug #8622 introduced a smaller bug where _XReply would
read memory shortly after freeing it. This patch caches the needed
value in a stack-allocated variable before the heap-allocated memory
is freed.
* libx11 doesn't use inputproto in public headers; don't require it in x11.pc.
Based on a Debian patch.
* Debian bug #354315: Clarify return value in XGetWindowAttributes man page.
Patch by Debian user Ross Combs.
Version 1.1 - 2006-11-23
* Add note in man-page that XListFontsWithInfo is not thread-safe. _XReply
drops the Display lock, so the value of dpy->request may change before
_XReply is called again. Jamey Sharp discovered this by inspection a few
years ago.
* Fix Bug #8622, by fixing the response processing order for threaded apps.
process_responses (the common code for _XReply, _XReadEvents, and
_XEventsQueued) now handles responses in order, by adding condition variables
to the list of outstanding requests in dpy->xcb->pending_requests, and
blocking on them when those requests should get processed, to allow _XReply
to process them; if actually called from _XReply, it returns when _XReply's
request should get processed. _XReply broadcasts on its condition variable
after it has read its reply and re-acquired the display lock.
* Don't hold the display lock around callbacks to the application. This avoids
recursive locking of the display lock (which triggers an XCB locking
assertion), particularly with emacs.
* Add xcb-xlib dependency to x11.pc when built against XCB.
* Allocate the right amount of memory for dpy->lock_fns. Fixes a crash on
startup with gdk.
Version 1.1 RC2 - 2006-11-02
Benno Schulenberg:

87
lib/libX11/config.sub vendored
View File

@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2005-07-08'
timestamp='2006-07-02'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@ -119,8 +120,9 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@ -171,6 +173,10 @@ case $os in
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@ -187,6 +193,10 @@ case $os in
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@ -231,7 +241,7 @@ case $basic_machine in
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
@ -239,7 +249,8 @@ case $basic_machine in
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@ -257,18 +268,19 @@ case $basic_machine in
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| ms1 \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b \
| strongarm \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
@ -276,9 +288,6 @@ case $basic_machine in
| z8k)
basic_machine=$basic_machine-unknown
;;
m32c)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
@ -286,6 +295,9 @@ case $basic_machine in
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@ -305,7 +317,7 @@ case $basic_machine in
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
@ -316,7 +328,7 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| m32r-* | m32rle-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@ -336,19 +348,20 @@ case $basic_machine in
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| ms1-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
@ -359,8 +372,6 @@ case $basic_machine in
| ymp-* \
| z8k-*)
;;
m32c-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
@ -696,6 +707,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
mvs)
basic_machine=i370-ibm
os=-mvs
@ -803,6 +817,12 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
@ -859,6 +879,10 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@ -1101,7 +1125,7 @@ case $basic_machine in
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
@ -1174,21 +1198,23 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku*)
| -skyos* | -haiku* | -rdos* | -toppers*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@ -1340,6 +1366,9 @@ else
# system, and we'll never get to this point.
case $basic_machine in
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
@ -1349,9 +1378,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20

View File

@ -3,7 +3,7 @@
AC_PREREQ(2.57)
AC_INIT([libX11],
1.0.99.2,
1.1.1,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
libX11)
AC_CONFIG_SRCDIR([Makefile.am])
@ -40,10 +40,12 @@ no)
;;
*)
X11_REQUIRES="xcb-xlib >= 0.9.92"
X11_EXTRA_DEPS="xcb-xlib"
xdmauth="no" # XCB handles all auth
AC_DEFINE(USE_XCB, 1, [Use XCB for low-level protocol implementation])
;;
esac
AC_SUBST(X11_EXTRA_DEPS)
PKG_CHECK_MODULES(X11, xextproto xtrans $X11_REQUIRES)
dnl Issue an error if xtrans.m4 was not found and XTRANS_CONNECTION_FLAGS macro
@ -292,8 +294,8 @@ AM_CONDITIONAL(MANPAGES, [ test x$LIBMAN '!=' xno ])
AM_CONDITIONAL(XKB, [ test x$XKB = xyes ])
if test x"$XKB" = "xyes"; then
XKBPROTO_REQUIRES="kbproto inputproto"
PKG_CHECK_MODULES(XKBPROTO, $XKBPROTO_REQUIRES)
XKBPROTO_REQUIRES="kbproto"
PKG_CHECK_MODULES(XKBPROTO, kbproto inputproto)
AC_DEFINE(XKB,1,[Use XKB])
X11_CFLAGS="$X11_CFLAGS $XKBPROTO_CFLAGS"
X11_LIBS="$X11_LIBS $XKBPROTO_LIBS"

View File

@ -193,7 +193,8 @@ The
.ZN XGetWindowAttributes
function returns the current attributes for the specified window to an
.ZN XWindowAttributes
structure.
structure. It returns a nonzero status on success; otherwise, it returns a
zero status.
.LP
.ZN XGetWindowAttributes
can generate
@ -210,6 +211,8 @@ border width, and depth.
These are described in the argument list.
It is legal to pass to this function a window whose class is
.ZN InputOnly .
It returns a nonzero status on success; otherwise, it returns a
zero status.
.SH STRUCTURES
The
.ZN XWindowAttributes

View File

@ -253,6 +253,12 @@ is passed, the structure is freed,
but the font is not closed; use
.ZN XUnloadFont
to close the font.
.LP
Note that
.ZN XListFontsWithInfo
is not thread-safe. If other threads make X requests on the same
.ZN Display ,
then this function's behavior is undefined.
.SH "SEE ALSO"
XLoadFont(3X11),
XSetFontPath(3X11)

View File

@ -96,9 +96,9 @@ XFilterEvent(ev, window)
if (win == p->window) {
if ((mask & p->event_mask) ||
(ev->type >= p->start_type && ev->type <= p->end_type)) {
UnlockDisplay(ev->xany.display);
ret = (*(p->filter))(ev->xany.display, p->window, ev,
p->client_data);
UnlockDisplay(ev->xany.display);
return(ret);
}
}

View File

@ -7,6 +7,7 @@
#include <assert.h>
#include <X11/Xlibint.h>
#include <X11/Xlib-xcb.h>
#include "locking.h" /* really just want X11/Xthreads.h but can't have it. */
#define XCB_SEQUENCE_COMPARE(a,op,b) ((int) ((a) - (b)) op 0)
#define assert_sequence_less(a,b) assert(XCB_SEQUENCE_COMPARE((a), <=, (b)))
@ -14,6 +15,8 @@
typedef struct PendingRequest PendingRequest;
struct PendingRequest {
PendingRequest *next;
xcondition_rec condition;
int waiters; /* Number of threads waiting; -1 if no wait needed */
unsigned int sequence;
};

View File

@ -2,6 +2,7 @@
* This file is licensed under the MIT license. See the file COPYING. */
#include "Xlibint.h"
#include "locking.h"
#include "Xxcbint.h"
#include <xcb/xcbext.h>
#include <xcb/xcbxlib.h>
@ -67,6 +68,15 @@ static void check_internal_connections(Display *dpy)
}
}
static void condition_wait(Display *dpy, xcondition_t cv)
{
_XPutXCBBuffer(dpy);
xcb_xlib_unlock(dpy->xcb->connection);
ConditionWait(dpy, cv);
xcb_xlib_lock(dpy->xcb->connection);
_XGetXCBBuffer(dpy);
}
static void handle_event(Display *dpy, xcb_generic_event_t *e)
{
if(!e)
@ -92,7 +102,22 @@ static void call_handlers(Display *dpy, xcb_generic_reply_t *buf)
_XError(dpy, (xError *) buf);
}
static void process_responses(Display *dpy, int wait_for_first_event, xcb_generic_error_t **current_error, unsigned long current_request)
static xcb_generic_event_t * wait_or_poll_for_event(Display *dpy, int wait)
{
xcb_connection_t *c = dpy->xcb->connection;
xcb_generic_event_t *event;
if(wait && !dpy->head)
{
UnlockDisplay(dpy);
event = xcb_wait_for_event(c);
LockDisplay(dpy);
}
else
event = xcb_poll_for_event(c);
return event;
}
static void process_responses(Display *dpy, int wait_for_first_event, xcb_generic_error_t **current_error, unsigned int current_request)
{
void *reply;
xcb_generic_event_t *event = dpy->xcb->next_event;
@ -100,22 +125,13 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi
PendingRequest *req;
xcb_connection_t *c = dpy->xcb->connection;
if(!event && dpy->xcb->event_owner == XlibOwnsEventQueue)
{
if(wait_for_first_event)
{
UnlockDisplay(dpy);
event = xcb_wait_for_event(c);
LockDisplay(dpy);
}
else
event = xcb_poll_for_event(c);
}
event = wait_or_poll_for_event(dpy, wait_for_first_event);
while(1)
{
req = dpy->xcb->pending_requests;
if(event && XCB_SEQUENCE_COMPARE(event->full_sequence, <=, current_request)
&& (!req || XCB_SEQUENCE_COMPARE(event->full_sequence, <=, req->sequence)))
assert(!(req && current_request && !XCB_SEQUENCE_COMPARE(req->sequence, <=, current_request)));
if(event && (!req || XCB_SEQUENCE_COMPARE(event->full_sequence, <=, req->sequence)))
{
if(current_error && event->response_type == 0 && event->full_sequence == current_request)
{
@ -124,12 +140,27 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi
break;
}
handle_event(dpy, event);
event = xcb_poll_for_event(c);
event = wait_or_poll_for_event(dpy, wait_for_first_event);
}
else if(req && XCB_SEQUENCE_COMPARE(req->sequence, <, current_request)
&& xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &reply, &error))
else if(req && req->waiters != -1)
{
if(req->sequence == current_request)
break;
if(!current_request && !(wait_for_first_event && !dpy->head))
break;
dpy->xcb->next_event = event;
req->waiters++;
assert(req->waiters > 0);
condition_wait(dpy, &req->condition);
if(--req->waiters == 0)
free(req);
event = dpy->xcb->next_event;
}
else if(req && xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &reply, &error))
{
dpy->xcb->pending_requests = req->next;
if(!dpy->xcb->pending_requests)
dpy->xcb->pending_requests_tail = &dpy->xcb->pending_requests;
if(!reply)
reply = error;
if(reply)
@ -143,8 +174,6 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi
else
break;
}
if(!dpy->xcb->pending_requests)
dpy->xcb->pending_requests_tail = &dpy->xcb->pending_requests;
dpy->xcb->next_event = event;
@ -152,6 +181,7 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi
_XIOError(dpy);
assert_sequence_less(dpy->last_request_read, dpy->request);
assert(!wait_for_first_event || dpy->head);
}
int _XEventsQueued(Display *dpy, int mode)
@ -163,7 +193,7 @@ int _XEventsQueued(Display *dpy, int mode)
_XSend(dpy, 0, 0);
else
check_internal_connections(dpy);
process_responses(dpy, 0, 0, dpy->request);
process_responses(dpy, 0, 0, 0);
return dpy->qlen;
}
@ -176,7 +206,7 @@ void _XReadEvents(Display *dpy)
if(dpy->xcb->event_owner != XlibOwnsEventQueue)
return;
check_internal_connections(dpy);
process_responses(dpy, 1, 0, dpy->request);
process_responses(dpy, 1, 0, 0);
}
/*
@ -272,6 +302,44 @@ static void _XFreeReplyData(Display *dpy, Bool force)
dpy->xcb->reply_data = 0;
}
static PendingRequest * insert_pending_request(Display *dpy)
{
PendingRequest **cur = &dpy->xcb->pending_requests;
while(*cur && XCB_SEQUENCE_COMPARE((*cur)->sequence, <, dpy->request))
cur = &((*cur)->next);
if(*cur && (*cur)->sequence == dpy->request)
{
/* Replacing an existing PendingRequest should only happen once,
when calling _XReply, and the replaced PendingRequest must
not have a condition set. */
assert((*cur)->waiters == -1);
}
else
{
PendingRequest *node = malloc(sizeof(PendingRequest));
assert(node);
node->next = *cur;
node->sequence = dpy->request;
if(cur == dpy->xcb->pending_requests_tail)
dpy->xcb->pending_requests_tail = &(node->next);
*cur = node;
}
(*cur)->waiters = 0;
xcondition_init(&((*cur)->condition));
return *cur;
}
static void remove_pending_request(Display *dpy, PendingRequest *node)
{
PendingRequest **cur = &dpy->xcb->pending_requests;
while(*cur && *cur != node)
cur = &((*cur)->next);
if(*cur == node)
*cur = node->next;
if(!dpy->xcb->pending_requests)
dpy->xcb->pending_requests_tail = &dpy->xcb->pending_requests;
}
/*
* _XReply - Wait for a reply packet and copy its contents into the
* specified rep.
@ -282,17 +350,38 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
{
xcb_generic_error_t *error;
xcb_connection_t *c = dpy->xcb->connection;
unsigned long request = dpy->request;
char *reply;
PendingRequest *current;
unsigned int current_sequence;
assert(!dpy->xcb->reply_data);
UnlockDisplay(dpy);
reply = xcb_wait_for_reply(c, request, &error);
/* Internals of UnlockDisplay done by hand here, so that we can
insert_pending_request *after* we _XPutXCBBuffer, but before we
unlock the display. */
_XPutXCBBuffer(dpy);
current = insert_pending_request(dpy);
xcb_xlib_unlock(dpy->xcb->connection);
if(dpy->xcb->lock_fns.unlock_display)
dpy->xcb->lock_fns.unlock_display(dpy);
reply = xcb_wait_for_reply(c, current->sequence, &error);
LockDisplay(dpy);
check_internal_connections(dpy);
process_responses(dpy, 0, &error, request);
process_responses(dpy, 0, &error, current->sequence);
current_sequence = current->sequence;
remove_pending_request(dpy, current);
if(current->waiters)
{ /* The ConditionBroadcast macro contains an if; braces needed here. */
ConditionBroadcast(dpy, &current->condition);
}
else
{
free(current);
current = NULL;
}
if(error)
{
@ -347,7 +436,7 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
return 0;
}
dpy->last_request_read = request;
dpy->last_request_read = current_sequence;
/* there's no error and we have a reply. */
dpy->xcb->reply_data = reply;

View File

@ -38,7 +38,7 @@ static void _XCBUnlockDisplay(Display *dpy)
int _XCBInitDisplayLock(Display *dpy)
{
if(!dpy->lock_fns && !(dpy->lock_fns = Xcalloc(1, sizeof(dpy->lock_fns))))
if(!dpy->lock_fns && !(dpy->lock_fns = Xcalloc(1, sizeof(*dpy->lock_fns))))
return 0;
dpy->xcb->lock_fns.lock_display = dpy->lock_fns->lock_display;
dpy->lock_fns->lock_display = _XCBLockDisplay;
@ -146,6 +146,7 @@ static inline int issue_complete_request(Display *dpy, int veclen, struct iovec
PendingRequest *req = malloc(sizeof(PendingRequest));
assert(req);
req->next = 0;
req->waiters = -1;
req->sequence = sequence;
*dpy->xcb->pending_requests_tail = req;
dpy->xcb->pending_requests_tail = &req->next;

View File

@ -9,7 +9,7 @@ Name: X11
Description: X Library
Version: @PACKAGE_VERSION@
Requires: xproto @XKBPROTO_REQUIRES@
Requires.private: xau xdmcp
Requires.private: xau xdmcp @X11_EXTRA_DEPS@
Cflags: -I${includedir} @XTHREAD_CFLAGS@
Libs: -L${libdir} -lX11
Libs.private: @XTHREADLIB@