Update to libxcb 1.8.1. Tested by krw@, mpi@, shadchin@

This commit is contained in:
matthieu
2012-03-27 19:14:20 +00:00
parent bfe2e894a1
commit 1f3df99ce6
37 changed files with 5451 additions and 693 deletions

View File

@@ -58,6 +58,9 @@ endif
if BUILD_XINPUT
pkgconfig_DATA += xcb-xinput.pc
endif
if BUILD_XKB
pkgconfig_DATA += xcb-xkb.pc
endif
if BUILD_XPRINT
pkgconfig_DATA += xcb-xprint.pc
endif

55
dist/libxcb/NEWS vendored
View File

@@ -1,3 +1,58 @@
Release 1.8.1 (2012-03-09)
==========================
- Fix a busy loop on BSD and Mac OS
- Bump xcb-proto requirement
- Fallback to TCP if no protocol is specified and the UNIX connection fails
- Update use of error_connection under WIN32 to _xcb_conn_ret_error()
- Fix build of xcb_auth.c with XDMCP on WIN32
- Revert "Fix include order with Xdmcp on WIN32"
- darwin: Use read(2) rather than recv(2)
- Add xkb_internals and xkb_issues to EXTRA_DIST.
Release 1.8 (2012-01-11)
========================
- xcb_disconnect: call shutdown() to force a disconnect
- Use special path to sockets when running under Solaris Trusted Extensions
- Remove unused DECnet code
- Add #include <sys/socket.h> to xcb_conn.c
- Make launchd code in xcb_util.c match surrounding code indent levels
- If protocol is "unix", use a Unix domain socket, not TCP
- Added more error states and removed global error_connection
- Handle XGE events with the "send event" flag
- added xcb_sumof() with restriction to uint8_t
- xkb: updated configure.ac/Makefile.am
- xkb: added pkg config file
- special case 'intermixed variable and fixed size fields': fixed reply side, needs testing
- added accessors for special cases
- Add support for building with Python 3
- Insert, not append explicit xcbgen dir python path
- xcb_request_check: Sync even if an event was read for this sequence.
- _xcb_conn_wait: Shut down the connection on unexpected poll() events.
- xcb_send_request: Send all requests using a common internal send_request.
- xcb_request_check: Hold the I/O lock while deciding to sync.
- xcb_discard_reply: Simplify by re-using poll_for_reply helper.
- xcb_in: Use 64-bit sequence numbers internally everywhere.
- Enable AM_SILENT_RULES on automake 1.11 or newer.
- Factor reader_list management out of wait_for_reply.
- Dequeue readers that can't receive any new responses.
- Delete the old c-client.xsl.
- Keep ALIGNOF definition out of the public namespace.
- darwin: Don't use poll() when expected to run on darwin10 and prior
- Add Win32
- Allow disconnecting connections that are in error state.
- Make xcb_take_socket keep flushing until idle
- Support pre-IPv6 systems (without getaddrinfo)
- Drop AI_ADDRCONFIG when resolving TCP addresses
- xcb_auth: Fix memory leak in _xcb_get_auth_info.
- Don't emit out-of-module sizeof definitions
- Clean up a couple of warnings in xprint
- Prevent reply waiters from being blocked.
- Prevent theoretical double free and leak on get_peer_sock_name.
- Introduce a variant of xcb_poll_for_event for examining event queue.
- xcb_take_socket: Document sequence wrap requirements
- Compute alignment correctly
- Fix a dead-lock due to xcb_poll_for_reply
Release 1.7 (2010-08-13)
========================
- Always wake up readers after writing

View File

@@ -3,18 +3,20 @@
AC_PREREQ(2.57)
AC_INIT([libxcb],
1.7,
1.8.1,
[xcb@lists.freedesktop.org])
AC_CONFIG_SRCDIR([xcb.pc.in])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AM_PATH_PYTHON([2.5])
AM_PATH_PYTHON([2.6])
PKG_CHECK_MODULES(CHECK, [check >= 0.9.4], [HAVE_CHECK=yes], [HAVE_CHECK=no])
AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes)
AC_CONFIG_HEADERS([src/config.h])
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
AC_PROG_CC
@@ -32,7 +34,7 @@ fi
AC_SUBST(HTML_CHECK_RESULT)
# Checks for pkg-config packages
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.6)
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.7)
NEEDED="pthread-stubs xau >= 0.99.2"
PKG_CHECK_MODULES(NEEDED, $NEEDED)
@@ -72,12 +74,21 @@ AC_HEADER_STDC
AC_SEARCH_LIBS(getaddrinfo, socket)
AC_SEARCH_LIBS(connect, socket)
have_win32="no"
lt_enable_auto_import=""
case $host_os in
mingw*)
have_win32="yes"
lt_enable_auto_import="-Wl,--enable-auto-import"
;;
linux*)
AC_DEFINE([HAVE_ABSTRACT_SOCKETS], 1, [Define if your platform supports abstract sockets])
;;
esac
AC_SUBST(lt_enable_auto_import)
AM_CONDITIONAL([XCB_HAVE_WIN32], [test "x${have_win32}" = "xyes"])
dnl define buffer queue size
AC_ARG_WITH([queue-size],
AC_HELP_STRING([--with-queue-size=SIZE],
@@ -95,6 +106,10 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
#include <sys/un.h>
])
dnl check for support for Solaris Trusted Extensions
AC_CHECK_HEADERS([tsol/label.h])
AC_CHECK_FUNCS([is_system_labeled])
xcbincludedir='${includedir}/xcb'
AC_SUBST(xcbincludedir)
@@ -120,9 +135,26 @@ AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
XCB_CHECK_DOXYGEN()
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
case $host_os in
# darwin has poll() but can't be used to poll character devices (atleast through SnowLeopard)
darwin*) ;;
# darwin through Snow Leopard has poll() but can't be used to poll character devices.
darwin@<:@789@:>@*|darwin10*) ;;
darwin*)
_ac_xorg_macosx_version_min=""
if echo $CPPFLAGS $CFLAGS | grep -q mmacosx-version-min ; then
_ac_xorg_macosx_version_min=`echo $CPPFLAGS $CFLAGS | sed 's/^.*-mmacosx-version-min=\(@<:@^ @:>@*\).*$/\1/'`
else
_ac_xorg_macosx_version_min=$MACOSX_DEPLOYMENT_TARGET
fi
case $_ac_xorg_macosx_version_min in
10.@<:@0123456@:>@|10.@<:@0123456@:>@.*) ;;
*)
AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
;;
esac
unset _ac_xorg_macosx_version_min
;;
*)
AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
;;
@@ -146,6 +178,7 @@ XCB_EXTENSION(XFixes, "yes")
XCB_EXTENSION(XFree86-DRI, "yes")
XCB_EXTENSION(Xinerama, "yes")
XCB_EXTENSION(XInput, "no")
XCB_EXTENSION(XKB, "no")
XCB_EXTENSION(Xprint, "yes")
XCB_EXTENSION(SELinux, "no")
XCB_EXTENSION(XTest, "yes")
@@ -189,6 +222,7 @@ xcb-xf86dri.pc
xcb-xfixes.pc
xcb-xinerama.pc
xcb-xinput.pc
xcb-xkb.pc
xcb-xprint.pc
xcb-xselinux.pc
xcb-xtest.pc
@@ -232,6 +266,7 @@ echo " Xfixes..............: ${BUILD_XFIXES}"
echo " Xfree86-dri.........: ${BUILD_XFREE86_DRI}"
echo " xinerama............: ${BUILD_XINERAMA}"
echo " xinput..............: ${BUILD_XINPUT}"
echo " xkb.................: ${BUILD_XKB}"
echo " xprint..............: ${BUILD_XPRINT}"
echo " xtest...............: ${BUILD_XTEST}"
echo " xv..................: ${BUILD_XV}"

View File

@@ -2,7 +2,9 @@
EXTRA_DIST = \
tutorial/index.html \
tutorial/xcb.css \
xcb.doxygen.in
xcb.doxygen.in \
xkb_internals \
xkb_issues
docdirs = $(srcdir)/tutorial

49
dist/libxcb/doc/xkb_internals vendored Normal file
View File

@@ -0,0 +1,49 @@
XKB introduces several uncommon data structures:
- switch allows conditional inclusion of fields
- several complex objects intermix variable and fixed size fields
- lists with a variable number of variable size objects
To handle these objects, a number of new functions is generated:
- _serialize() turns a structured object into a byte stream,
(re)ordering or including fields according to the protocol
- _unserialize() rewrites data from a buffer into a structured object
- _unpack() expands a buffer representing a switch object into
a special structured type, all flags needed to resolve the switch
expression have to given as parameters
- _sizeof() calculates the size of a serialized object, often by calling
_unserialize()/_unpack() internally
The new structured data type for switch is special as it contains fixed
and variable size fields. Variable size fields can be accessed via pointers.
If switch appears in a request, an additional set of request helpers is
generated with the suffix _aux or _aux_(un)checked. While the 'common'
request functions require that switch has been serialized before, the _aux
variants take the structured data type. They are especially designed to
replace certain functions in xcb-util/aux.
Accessors for switch members need two parameters, where the first is usually
a pointer to the respective request or reply structure, while the second
is a pointer to the unpacked switch data structure.
Functions from the serialize family that take a double pointer can allocate
memory on their own, which is useful if the size of a buffer has to be
calculated depending on the data within. These functions call malloc() when
the double pointer is given as the address of a pointer that has been
initialized to 0. It is the responsibility of the user to free any allocated
memory.
Intermixed variable and fixed size fields are an important special case in XKB.
The current implementation resolves the issue by reordering the fields before
sending them on the wire as well as before returning a reply. That means that
these objects look like 'common' XCB data types and they can be accessed as such
(i.e. fixed size fields directly via the structured type and variable size fields
via accessors/iterators).
In case a list with variable size elements needs to be accessed, it is necessary
to use iterators. The iterator functions take care of determining the actual
object size for each element automatically.
A small and preliminary set of auxiliary functions is available in xkb_util.c
in the check_xkb module.

38
dist/libxcb/doc/xkb_issues vendored Normal file
View File

@@ -0,0 +1,38 @@
There are a number of problematic special cases in XKB. The issues
mentioned here are at most partly resolved.
1. The are several XxxDoodad structures defined in xkb.xml. They are used
in a few lists, but in a rather special way:
The struct "CommonDoodad" is supposed to be a rather generic data type,
combining the most basic Doodad fields that are common in all these structures.
All Doodads are encapsulated in a union type simply called "Doodad".
Now this union is used in subsequent list definitions, aiming at a kind of
'polymorphism': From inspection of the protocol and Xlib, the Doodads are to
be discriminated based on their type field.
However the special meaning of the type field is not encoded in the protocol.
Furthermore the TextDoodad and the LogoDoodad are variable size types due to
some fields of type CountedString16, thereby turning the union into a
possibly variable size type as well.
However, for lists with variable size elements, special sizeof functions are
required. These cannot be autogenerated as it cannot be referred which
Doodad type to use for the union.
Therefore, the Doodad type structures are unsupported at the moment.
2. There are still some bugs in xkb.xml: Either certain fields are missing
that are required by the protocol, or Xlib simply has another understanding
of the protocol.
3. The interface for accessors should be reviewed.
4. Currently some bitcases carry 'name' attributes. These could be avoided if
the data within would consist of a singe struct field only.
5. switch could get a 'fixed_size' attribute, so when rewriting valueparam to switch,
an uint32_t * pointer could be used instead of void *.
6. The automatic inclusion of padding requires some complicated coding in the
generator. This is errorprone and could be avoided if all padding is explicitly
given in the protocol definition. For variable size fields that require padding,
the pad tag could get a 'fieldref' attribute. That way padding could be handled
a lot easier in the autogenerator.

View File

@@ -18,7 +18,7 @@ nodist_libxcb_la_SOURCES = xproto.c bigreq.c xc_misc.c
# * If you add an interface, increment current and age and set revision to 0.
# * If you change or remove an interface, increment current and set revision
# and age to 0.
libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined
libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined @lt_enable_auto_import@
XCB_LIBS = libxcb.la
@@ -27,7 +27,7 @@ XCB_LIBS = libxcb.la
EXTSOURCES += composite.c
if BUILD_COMPOSITE
lib_LTLIBRARIES += libxcb-composite.la
libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_composite_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_composite_la_SOURCES = composite.c composite.h
endif
@@ -35,7 +35,7 @@ endif
EXTSOURCES += damage.c
if BUILD_DAMAGE
lib_LTLIBRARIES += libxcb-damage.la
libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_damage_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_damage_la_SOURCES = damage.c damage.h
endif
@@ -43,7 +43,7 @@ endif
EXTSOURCES += dpms.c
if BUILD_DPMS
lib_LTLIBRARIES += libxcb-dpms.la
libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_dpms_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_dpms_la_SOURCES = dpms.c dpms.h
endif
@@ -51,7 +51,7 @@ endif
EXTSOURCES += dri2.c
if BUILD_DRI2
lib_LTLIBRARIES += libxcb-dri2.la
libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_dri2_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h
endif
@@ -59,7 +59,7 @@ endif
EXTSOURCES += glx.c
if BUILD_GLX
lib_LTLIBRARIES += libxcb-glx.la
libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_glx_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_glx_la_SOURCES = glx.c glx.h
endif
@@ -67,7 +67,7 @@ endif
EXTSOURCES += randr.c
if BUILD_RANDR
lib_LTLIBRARIES += libxcb-randr.la
libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined
libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined @lt_enable_auto_import@
libxcb_randr_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_randr_la_SOURCES = randr.c randr.h
endif
@@ -75,7 +75,7 @@ endif
EXTSOURCES += record.c
if BUILD_RECORD
lib_LTLIBRARIES += libxcb-record.la
libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_record_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_record_la_SOURCES = record.c record.h
endif
@@ -83,7 +83,7 @@ endif
EXTSOURCES += render.c
if BUILD_RENDER
lib_LTLIBRARIES += libxcb-render.la
libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_render_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_render_la_SOURCES = render.c render.h
endif
@@ -91,7 +91,7 @@ endif
EXTSOURCES += res.c
if BUILD_RESOURCE
lib_LTLIBRARIES += libxcb-res.la
libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_res_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_res_la_SOURCES = res.c res.h
endif
@@ -99,7 +99,7 @@ endif
EXTSOURCES += screensaver.c
if BUILD_SCREENSAVER
lib_LTLIBRARIES += libxcb-screensaver.la
libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_screensaver_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_screensaver_la_SOURCES = screensaver.c screensaver.h
endif
@@ -107,7 +107,7 @@ endif
EXTSOURCES += shape.c
if BUILD_SHAPE
lib_LTLIBRARIES += libxcb-shape.la
libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_shape_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_shape_la_SOURCES = shape.c shape.h
endif
@@ -115,7 +115,7 @@ endif
EXTSOURCES += shm.c
if BUILD_SHM
lib_LTLIBRARIES += libxcb-shm.la
libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_shm_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_shm_la_SOURCES = shm.c shm.h
endif
@@ -123,7 +123,7 @@ endif
EXTSOURCES += sync.c
if BUILD_SYNC
lib_LTLIBRARIES += libxcb-sync.la
libxcb_sync_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_sync_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_sync_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_sync_la_SOURCES = sync.c sync.h
endif
@@ -131,7 +131,7 @@ endif
EXTSOURCES += xevie.c
if BUILD_XEVIE
lib_LTLIBRARIES += libxcb-xevie.la
libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xevie_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xevie_la_SOURCES = xevie.c xevie.h
endif
@@ -139,7 +139,7 @@ endif
EXTSOURCES += xf86dri.c
if BUILD_XFREE86_DRI
lib_LTLIBRARIES += libxcb-xf86dri.la
libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xf86dri_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xf86dri_la_SOURCES = xf86dri.c xf86dri.h
endif
@@ -147,7 +147,7 @@ endif
EXTSOURCES += xfixes.c
if BUILD_XFIXES
lib_LTLIBRARIES += libxcb-xfixes.la
libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xfixes_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xfixes_la_SOURCES = xfixes.c xfixes.h
endif
@@ -155,7 +155,7 @@ endif
EXTSOURCES += xinerama.c
if BUILD_XINERAMA
lib_LTLIBRARIES += libxcb-xinerama.la
libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xinerama_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xinerama_la_SOURCES = xinerama.c xinerama.h
endif
@@ -163,15 +163,23 @@ endif
EXTSOURCES += xinput.c
if BUILD_XINPUT
lib_LTLIBRARIES += libxcb-xinput.la
libxcb_xinput_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xinput_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xinput_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xinput_la_SOURCES = xinput.c xinput.h
endif
EXTSOURCES += xkb.c
if BUILD_XKB
lib_LTLIBRARIES += libxcb-xkb.la
libxcb_xkb_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xkb_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xkb_la_SOURCES = xkb.c xkb.h
endif
EXTSOURCES += xprint.c
if BUILD_XPRINT
lib_LTLIBRARIES += libxcb-xprint.la
libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xprint_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xprint_la_SOURCES = xprint.c xprint.h
endif
@@ -179,7 +187,7 @@ endif
EXTSOURCES += xselinux.c
if BUILD_SELINUX
lib_LTLIBRARIES += libxcb-xselinux.la
libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xselinux_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xselinux_la_SOURCES = xselinux.c xselinux.h
endif
@@ -187,7 +195,7 @@ endif
EXTSOURCES += xtest.c
if BUILD_XTEST
lib_LTLIBRARIES += libxcb-xtest.la
libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xtest_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xtest_la_SOURCES = xtest.c xtest.h
endif
@@ -195,7 +203,7 @@ endif
EXTSOURCES += xv.c
if BUILD_XV
lib_LTLIBRARIES += libxcb-xv.la
libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xv_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xv_la_SOURCES = xv.c xv.h
endif
@@ -203,7 +211,7 @@ endif
EXTSOURCES += xvmc.c
if BUILD_XVMC
lib_LTLIBRARIES += libxcb-xvmc.la
libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined
libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_xvmc_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_xvmc_la_SOURCES = xvmc.c xvmc.h
endif
@@ -211,6 +219,9 @@ endif
EXTHEADERS=$(EXTSOURCES:.c=.h)
xcbinclude_HEADERS = xcb.h xcbext.h
if XCB_HAVE_WIN32
xcbinclude_HEADERS += xcb_windefs.h
endif
nodist_xcbinclude_HEADERS = $(EXTHEADERS)
noinst_HEADERS = xcbint.h

File diff suppressed because it is too large Load Diff

44
dist/libxcb/src/xcb.h vendored
View File

@@ -35,7 +35,11 @@
#include <stdint.h>
#endif
#ifndef _WIN32
#include <sys/uio.h>
#else
#include "xcb_windefs.h"
#endif
#include <pthread.h>
@@ -65,6 +69,21 @@ extern "C" {
/** X_TCP_PORT + display number = server port for TCP transport */
#define X_TCP_PORT 6000
/** xcb connection errors because of socket, pipe and other stream errors. */
#define XCB_CONN_ERROR 1
/** xcb connection shutdown because of extension not sppported */
#define XCB_CONN_CLOSED_EXT_NOTSUPPORTED 2
/** malloc(), calloc() and realloc() error upon failure, for eg ENOMEM */
#define XCB_CONN_CLOSED_MEM_INSUFFICIENT 3
/** Connection closed, exceeding request length that server accepts. */
#define XCB_CONN_CLOSED_REQ_LEN_EXCEED 4
/** Connection closed, error during parsing display string. */
#define XCB_CONN_CLOSED_PARSE_ERR 5
#define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
/* Opaque structures */
@@ -267,6 +286,22 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c);
*/
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c);
/**
* @brief Returns the next event without reading from the connection.
* @param c: The connection to the X server.
* @return The next already queued event from the server.
*
* This is a version of xcb_poll_for_event that only examines the
* event queue for new events. The function doesn't try to read new
* events from the connection if no queued events are found.
*
* This function is useful for callers that know in advance that all
* interesting events have already been read from the connection. For
* example, callers might use xcb_wait_for_reply and be interested
* only of events that preceded a specific reply.
*/
xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c);
/**
* @brief Return the error for a request, or NULL if none can ever arrive.
* @param c: The connection to the X server.
@@ -376,15 +411,18 @@ int xcb_get_file_descriptor(xcb_connection_t *c);
/**
* @brief Test whether the connection has shut down due to a fatal error.
* @param c: The connection.
* @return 1 if the connection is in an error state; 0 otherwise.
* @return > 0 if the connection is in an error state; 0 otherwise.
*
* Some errors that occur in the context of an xcb_connection_t
* are unrecoverable. When such an error occurs, the
* connection is shut down and further operations on the
* xcb_connection_t have no effect.
*
* @todo Other functions should document the conditions in
* which they shut down the connection.
* @return XCB_CONN_ERROR, because of socket errors, pipe errors or other stream errors.
* @return XCB_CONN_CLOSED_EXT_NOTSUPPORTED, when extension not supported.
* @return XCB_CONN_CLOSED_MEM_INSUFFICIENT, when memory not available.
* @return XCB_CONN_CLOSED_REQ_LEN_EXCEED, exceeding request length that server accepts.
* @return XCB_CONN_CLOSED_PARSE_ERR, error during parsing display string.
*/
int xcb_connection_has_error(xcb_connection_t *c);

View File

@@ -25,15 +25,35 @@
/* Authorization systems for the X protocol. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <X11/Xauth.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef __INTERIX
/* _don't_ ask. interix has INADDR_LOOPBACK in here. */
#include <rpc/types.h>
#endif
#ifdef _WIN32
#ifdef HASXDMAUTH
/* We must include the wrapped windows.h before any system header which includes
it unwrapped, to avoid conflicts with types defined in X headers */
#include <X11/Xwindows.h>
#endif
#include "xcb_windefs.h"
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#endif /* _WIN32 */
#include "xcb.h"
#include "xcbint.h"
@@ -256,7 +276,7 @@ static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
{
socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
socklen_t actual_socknamelen = socknamelen;
struct sockaddr *sockname = malloc(socknamelen), *new_sockname = NULL;
struct sockaddr *sockname = malloc(socknamelen);
if (sockname == NULL)
return NULL;
@@ -269,14 +289,17 @@ static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
if (actual_socknamelen > socknamelen)
{
struct sockaddr *new_sockname = NULL;
socknamelen = actual_socknamelen;
if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL ||
socket_func(fd, new_sockname, &actual_socknamelen) == -1 ||
actual_socknamelen > socknamelen)
if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL)
goto sock_or_realloc_error;
sockname = new_sockname;
if (socket_func(fd, sockname, &actual_socknamelen) == -1 ||
actual_socknamelen > socknamelen)
goto sock_or_realloc_error;
}
return sockname;
@@ -322,10 +345,15 @@ int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display)
if (!info->namelen)
goto no_auth; /* out of memory */
if (!gotsockname && (sockname = get_peer_sock_name(getsockname, fd)) == NULL)
if (!gotsockname)
{
free(info->name);
goto no_auth; /* can only authenticate sockets */
free(sockname);
if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
{
free(info->name);
goto no_auth; /* can only authenticate sockets */
}
}
ret = compute_auth(info, authptr, sockname);

View File

@@ -26,13 +26,10 @@
/* Connection management: the core of XCB. */
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
@@ -40,20 +37,45 @@
#include "xcbint.h"
#if USE_POLL
#include <poll.h>
#else
#elif !defined _WIN32
#include <sys/select.h>
#endif
#ifdef _WIN32
#include "xcb_windefs.h"
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif /* _WIN32 */
/* SHUT_RDWR is fairly recent and is not available on all platforms */
#if !defined(SHUT_RDWR)
#define SHUT_RDWR 2
#endif
typedef struct {
uint8_t status;
uint8_t pad0[5];
uint16_t length;
} xcb_setup_generic_t;
const int error_connection = 1;
static const int xcb_con_error = XCB_CONN_ERROR;
static const int xcb_con_closed_mem_er = XCB_CONN_CLOSED_MEM_INSUFFICIENT;
static const int xcb_con_closed_parse_er = XCB_CONN_CLOSED_PARSE_ERR;
static int set_fd_flags(const int fd)
{
/* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */
#ifdef _WIN32
u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */
int ret = 0;
ret = ioctlsocket(fd, FIONBIO, &iMode);
if(ret != 0)
return 0;
return 1;
#else
int flags = fcntl(fd, F_GETFL, 0);
if(flags == -1)
return 0;
@@ -63,6 +85,7 @@ static int set_fd_flags(const int fd)
if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
return 0;
return 1;
#endif /* _WIN32 */
}
static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
@@ -155,12 +178,40 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
{
int n;
assert(!c->out.queue_len);
#ifdef _WIN32
int i = 0;
int ret = 0,err = 0;
struct iovec *vec;
n = 0;
/* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from
an iovec would require more work and I'm not sure of the benefit....works for now */
vec = *vector;
while(i < *count)
{
ret = send(c->fd,vec->iov_base,vec->iov_len,0);
if(ret == SOCKET_ERROR)
{
err = WSAGetLastError();
if(err == WSAEWOULDBLOCK)
{
return 1;
}
}
n += ret;
*vec++;
i++;
}
#else
n = writev(c->fd, *vector, *count);
if(n < 0 && errno == EAGAIN)
return 1;
#endif /* _WIN32 */
if(n <= 0)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
return 0;
}
@@ -209,18 +260,20 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
{
xcb_connection_t* c;
#ifndef _WIN32
#ifndef USE_POLL
if(fd >= FD_SETSIZE) /* would overflow in FD_SET */
{
close(fd);
return (xcb_connection_t *) &error_connection;
return _xcb_conn_ret_error(XCB_CONN_ERROR);
}
#endif
#endif /* !_WIN32*/
c = calloc(1, sizeof(xcb_connection_t));
if(!c) {
close(fd);
return (xcb_connection_t *) &error_connection;
return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ;
}
c->fd = fd;
@@ -237,7 +290,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
))
{
xcb_disconnect(c);
return (xcb_connection_t *) &error_connection;
return _xcb_conn_ret_error(XCB_CONN_ERROR);
}
return c;
@@ -245,7 +298,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
void xcb_disconnect(xcb_connection_t *c)
{
if(c == (xcb_connection_t *) &error_connection)
if(c->has_error)
return;
free(c->setup);
@@ -262,13 +315,42 @@ void xcb_disconnect(xcb_connection_t *c)
_xcb_xid_destroy(c);
free(c);
#ifdef _WIN32
WSACleanup();
#endif
}
/* Private interface */
void _xcb_conn_shutdown(xcb_connection_t *c)
void _xcb_conn_shutdown(xcb_connection_t *c, int err)
{
c->has_error = 1;
c->has_error = err;
}
/* Return connection error state.
* To make thread-safe, I need a seperate static
* variable for every possible error.
*/
xcb_connection_t *_xcb_conn_ret_error(int err)
{
switch(err)
{
case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
{
return (xcb_connection_t *) &xcb_con_closed_mem_er;
}
case XCB_CONN_CLOSED_PARSE_ERR:
{
return (xcb_connection_t *) &xcb_con_closed_parse_er;
}
case XCB_CONN_ERROR:
default:
{
return (xcb_connection_t *) &xcb_con_error;
}
}
}
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
@@ -329,7 +411,7 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
} while (ret == -1 && errno == EINTR);
if(ret < 0)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
ret = 0;
}
pthread_mutex_lock(&c->iolock);

View File

@@ -37,9 +37,15 @@
#include "xcbint.h"
#if USE_POLL
#include <poll.h>
#else
#include <sys/select.h>
#endif
#ifndef _WIN32
#include <sys/select.h>
#include <sys/socket.h>
#endif
#ifdef _WIN32
#include "xcb_windefs.h"
#endif /* _WIN32 */
#define XCB_ERROR 0
#define XCB_REPLY 1
@@ -64,11 +70,22 @@ typedef struct pending_reply {
} pending_reply;
typedef struct reader_list {
unsigned int request;
uint64_t request;
pthread_cond_t *data;
struct reader_list *next;
} reader_list;
static void remove_finished_readers(reader_list **prev_reader, uint64_t completed)
{
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, completed))
{
/* If you don't have what you're looking for now, you never
* will. Wake up and leave me alone. */
pthread_cond_signal((*prev_reader)->data);
*prev_reader = (*prev_reader)->next;
}
}
static int read_packet(xcb_connection_t *c)
{
xcb_generic_reply_t genrep;
@@ -119,6 +136,8 @@ static int read_packet(xcb_connection_t *c)
if(genrep.response_type == XCB_ERROR)
c->in.request_completed = c->in.request_read;
remove_finished_readers(&c->in.readers, c->in.request_completed);
}
if(genrep.response_type == XCB_ERROR || genrep.response_type == XCB_REPLY)
@@ -143,14 +162,14 @@ static int read_packet(xcb_connection_t *c)
}
/* XGE events may have sizes > 32 */
if (genrep.response_type == XCB_XGE_EVENT)
if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT)
eventlength = genrep.length * 4;
buf = malloc(length + eventlength +
(genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)));
if(!buf)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
return 0;
}
@@ -183,11 +202,10 @@ static int read_packet(xcb_connection_t *c)
if( genrep.response_type == XCB_REPLY ||
(genrep.response_type == XCB_ERROR && pend && (pend->flags & XCB_REQUEST_CHECKED)))
{
reader_list *reader;
struct reply_list *cur = malloc(sizeof(struct reply_list));
if(!cur)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
free(buf);
return 0;
}
@@ -195,17 +213,8 @@ static int read_packet(xcb_connection_t *c)
cur->next = 0;
*c->in.current_reply_tail = cur;
c->in.current_reply_tail = &cur->next;
for(reader = c->in.readers;
reader &&
XCB_SEQUENCE_COMPARE_32(reader->request, <=, c->in.request_read);
reader = reader->next)
{
if(XCB_SEQUENCE_COMPARE_32(reader->request, ==, c->in.request_read))
{
pthread_cond_signal(reader->data);
break;
}
}
if(c->in.readers && c->in.readers->request == c->in.request_read)
pthread_cond_signal(c->in.readers->data);
return 1;
}
@@ -213,7 +222,7 @@ static int read_packet(xcb_connection_t *c)
event = malloc(sizeof(struct event_list));
if(!event)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
free(buf);
return 0;
}
@@ -255,10 +264,14 @@ static int read_block(const int fd, void *buf, const ssize_t len)
int done = 0;
while(done < len)
{
int ret = read(fd, ((char *) buf) + done, len - done);
int ret = recv(fd, ((char *) buf) + done, len - done, 0);
if(ret > 0)
done += ret;
#ifndef _WIN32
if(ret < 0 && errno == EAGAIN)
#else
if(ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
#endif /* !_Win32 */
{
#if USE_POLL
struct pollfd pfd;
@@ -272,10 +285,13 @@ static int read_block(const int fd, void *buf, const ssize_t len)
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
/* Initializing errno here makes sure that for Win32 this loop will execute only once */
errno = 0;
do {
ret = select(fd + 1, &fds, 0, 0, 0);
} while (ret == -1 && errno == EINTR);
#endif
#endif /* USE_POLL */
}
if(ret <= 0)
return ret;
@@ -283,7 +299,7 @@ static int read_block(const int fd, void *buf, const ssize_t len)
return len;
}
static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error)
static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error)
{
struct reply_list *head;
@@ -292,7 +308,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
head = 0;
/* We've read requests past the one we want, so if it has replies we have
* them all and they're in the replies map. */
else if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
else if(XCB_SEQUENCE_COMPARE(request, <, c->in.request_read))
{
head = _xcb_map_remove(c->in.replies, request);
if(head && head->next)
@@ -300,7 +316,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
}
/* We're currently processing the responses to the request we want, and we
* have a reply ready to return. So just return it without blocking. */
else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
else if(request == c->in.request_read && c->in.current_reply)
{
head = c->in.current_reply;
c->in.current_reply = head->next;
@@ -309,7 +325,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
}
/* We know this request can't have any more replies, and we've already
* established it doesn't have a reply now. Don't bother blocking. */
else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_completed))
else if(request == c->in.request_completed)
head = 0;
/* We may have more replies on the way for this request: block until we're
* sure. */
@@ -338,61 +354,70 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
return 1;
}
static void insert_reader(reader_list **prev_reader, reader_list *reader, uint64_t request, pthread_cond_t *cond)
{
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request))
prev_reader = &(*prev_reader)->next;
reader->request = request;
reader->data = cond;
reader->next = *prev_reader;
*prev_reader = reader;
}
static void remove_reader(reader_list **prev_reader, reader_list *reader)
{
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, reader->request))
if(*prev_reader == reader)
{
*prev_reader = (*prev_reader)->next;
break;
}
}
static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e)
{
void *ret = 0;
/* If this request has not been written yet, write it. */
if(c->out.return_socket || _xcb_out_flush_to(c, request))
{
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
reader_list reader;
insert_reader(&c->in.readers, &reader, request, &cond);
while(!poll_for_reply(c, request, &ret, e))
if(!_xcb_conn_wait(c, &cond, 0, 0))
break;
remove_reader(&c->in.readers, &reader);
pthread_cond_destroy(&cond);
}
_xcb_in_wake_up_next_reader(c);
return ret;
}
static uint64_t widen(xcb_connection_t *c, unsigned int request)
{
uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
if(widened_request > c->out.request)
widened_request -= UINT64_C(1) << 32;
return widened_request;
}
/* Public interface */
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
{
uint64_t widened_request;
void *ret = 0;
void *ret;
if(e)
*e = 0;
if(c->has_error)
return 0;
pthread_mutex_lock(&c->iolock);
widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
if(widened_request > c->out.request)
widened_request -= UINT64_C(1) << 32;
/* If this request has not been written yet, write it. */
if(c->out.return_socket || _xcb_out_flush_to(c, widened_request))
{
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
reader_list reader;
reader_list **prev_reader;
for(prev_reader = &c->in.readers;
*prev_reader &&
XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
prev_reader = &(*prev_reader)->next)
{
/* empty */;
}
reader.request = request;
reader.data = &cond;
reader.next = *prev_reader;
*prev_reader = &reader;
while(!poll_for_reply(c, request, &ret, e))
if(!_xcb_conn_wait(c, &cond, 0, 0))
break;
for(prev_reader = &c->in.readers;
*prev_reader &&
XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
prev_reader = &(*prev_reader)->next)
{
if(*prev_reader == &reader)
{
*prev_reader = (*prev_reader)->next;
break;
}
}
pthread_cond_destroy(&cond);
}
_xcb_in_wake_up_next_reader(c);
ret = wait_for_reply(c, widen(c, request), e);
pthread_mutex_unlock(&c->iolock);
return ret;
}
@@ -403,7 +428,7 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
pend = malloc(sizeof(*pend));
if(!pend)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
return;
}
@@ -418,66 +443,27 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
c->in.pending_replies_tail = &pend->next;
}
static void discard_reply(xcb_connection_t *c, unsigned int request)
static void discard_reply(xcb_connection_t *c, uint64_t request)
{
pending_reply *pend = 0;
void *reply;
pending_reply **prev_pend;
uint64_t widened_request;
/* We've read requests past the one we want, so if it has replies we have
* them all and they're in the replies map. */
if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
{
struct reply_list *head;
head = _xcb_map_remove(c->in.replies, request);
while (head)
{
struct reply_list *next = head->next;
free(head->reply);
free(head);
head = next;
}
/* Free any replies or errors that we've already read. Stop if
* xcb_wait_for_reply would block or we've run out of replies. */
while(poll_for_reply(c, request, &reply, 0) && reply)
free(reply);
/* If we've proven there are no more responses coming, we're done. */
if(XCB_SEQUENCE_COMPARE(request, <=, c->in.request_completed))
return;
}
/* We're currently processing the responses to the request we want, and we
* have a reply ready to return. Free it, and mark the pend to free any further
* replies. */
if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
{
struct reply_list *head;
head = c->in.current_reply;
c->in.current_reply = NULL;
c->in.current_reply_tail = &c->in.current_reply;
while (head)
{
struct reply_list *next = head->next;
free(head->reply);
free(head);
head = next;
}
pend = c->in.pending_replies;
if(pend &&
!(XCB_SEQUENCE_COMPARE(pend->first_request, <=, c->in.request_read) &&
(pend->workaround == WORKAROUND_EXTERNAL_SOCKET_OWNER ||
XCB_SEQUENCE_COMPARE(c->in.request_read, <=, pend->last_request))))
pend = 0;
if(pend)
pend->flags |= XCB_REQUEST_DISCARD_REPLY;
else
insert_pending_discard(c, &c->in.pending_replies, c->in.request_read);
return;
}
/* Walk the list of pending requests. Mark the first match for deletion. */
for(prev_pend = &c->in.pending_replies; *prev_pend; prev_pend = &(*prev_pend)->next)
{
if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, >, request))
if(XCB_SEQUENCE_COMPARE((*prev_pend)->first_request, >, request))
break;
if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, ==, request))
if((*prev_pend)->first_request == request)
{
/* Pending reply found. Mark for discard: */
(*prev_pend)->flags |= XCB_REQUEST_DISCARD_REPLY;
@@ -486,11 +472,7 @@ static void discard_reply(xcb_connection_t *c, unsigned int request)
}
/* Pending reply not found (likely due to _unchecked request). Create one: */
widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
if(widened_request > c->out.request)
widened_request -= UINT64_C(1) << 32;
insert_pending_discard(c, prev_pend, widened_request);
insert_pending_discard(c, prev_pend, request);
}
void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
@@ -503,7 +485,7 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
return;
pthread_mutex_lock(&c->iolock);
discard_reply(c, sequence);
discard_reply(c, widen(c, sequence));
pthread_mutex_unlock(&c->iolock);
}
@@ -519,7 +501,7 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply,
}
assert(reply != 0);
pthread_mutex_lock(&c->iolock);
ret = poll_for_reply(c, request, reply, error);
ret = poll_for_reply(c, widen(c, request), reply, error);
pthread_mutex_unlock(&c->iolock);
return ret;
}
@@ -540,7 +522,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
return ret;
}
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
static xcb_generic_event_t *poll_for_next_event(xcb_connection_t *c, int queued)
{
xcb_generic_event_t *ret = 0;
if(!c->has_error)
@@ -548,30 +530,41 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
pthread_mutex_lock(&c->iolock);
/* FIXME: follow X meets Z architecture changes. */
ret = get_event(c);
if(!ret && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
if(!ret && !queued && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
ret = get_event(c);
pthread_mutex_unlock(&c->iolock);
}
return ret;
}
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
{
return poll_for_next_event(c, 0);
}
xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c)
{
return poll_for_next_event(c, 1);
}
xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
{
/* FIXME: this could hold the lock to avoid syncing unnecessarily, but
* that would require factoring the locking out of xcb_get_input_focus,
* xcb_get_input_focus_reply, and xcb_wait_for_reply. */
xcb_generic_error_t *ret;
uint64_t request;
xcb_generic_error_t *ret = 0;
void *reply;
if(c->has_error)
return 0;
if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected)
&& XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
pthread_mutex_lock(&c->iolock);
request = widen(c, cookie.sequence);
if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected)
&& XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed))
{
free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret));
assert(!ret);
_xcb_out_send_sync(c);
_xcb_out_flush_to(c, c->out.request);
}
reply = xcb_wait_for_reply(c, cookie.sequence, &ret);
reply = wait_for_reply(c, request, &ret);
assert(!reply);
pthread_mutex_unlock(&c->iolock);
return ret;
}
@@ -635,7 +628,7 @@ int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds
assert(workaround != WORKAROUND_NONE || flags != 0);
if(!pend)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
return 0;
}
pend->first_request = pend->last_request = request;
@@ -663,14 +656,18 @@ void _xcb_in_replies_done(xcb_connection_t *c)
int _xcb_in_read(xcb_connection_t *c)
{
int n = read(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len);
int n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len, 0);
if(n > 0)
c->in.queue_len += n;
while(read_packet(c))
/* empty */;
#ifndef _WIN32
if((n > 0) || (n < 0 && errno == EAGAIN))
#else
if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK))
#endif /* !_WIN32 */
return 1;
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
return 0;
}
@@ -689,7 +686,7 @@ int _xcb_in_read_block(xcb_connection_t *c, void *buf, int len)
int ret = read_block(c->fd, (char *) buf + done, len - done);
if(ret <= 0)
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
return ret;
}
}

View File

@@ -35,8 +35,17 @@
#include "xcbint.h"
#include "bigreq.h"
static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
static inline void send_request(xcb_connection_t *c, int isvoid, enum workarounds workaround, int flags, struct iovec *vector, int count)
{
if(c->has_error)
return;
++c->out.request;
if(!isvoid)
c->in.request_expected = c->out.request;
if(workaround != WORKAROUND_NONE || flags != 0)
_xcb_in_expect_reply(c, c->out.request, workaround, flags);
while(count && c->out.queue_len + vector[0].iov_len <= sizeof(c->out.queue))
{
memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len);
@@ -46,13 +55,29 @@ static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
++vector, --count;
}
if(!count)
return 1;
return;
--vector, ++count;
vector[0].iov_base = c->out.queue;
vector[0].iov_len = c->out.queue_len;
c->out.queue_len = 0;
return _xcb_out_send(c, vector, count);
_xcb_out_send(c, vector, count);
}
static void send_sync(xcb_connection_t *c)
{
static const union {
struct {
uint8_t major;
uint8_t pad;
uint16_t len;
} fields;
uint32_t packet;
} sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
struct iovec vector[2];
vector[1].iov_base = (char *) &sync_req;
vector[1].iov_len = sizeof(sync_req);
send_request(c, 0, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY, vector + 1, 1);
}
static void get_socket_back(xcb_connection_t *c)
@@ -123,16 +148,8 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
{
static const union {
struct {
uint8_t major;
uint8_t pad;
uint16_t len;
} fields;
uint32_t packet;
} sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
uint64_t request;
uint32_t prefix[3] = { 0 };
uint32_t prefix[2];
int veclen = req->count;
enum workarounds workaround = WORKAROUND_NONE;
@@ -156,7 +173,7 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
if(!(extension && extension->present))
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED);
return 0;
}
((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
@@ -186,14 +203,22 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
}
else if(longlen > xcb_get_maximum_request_length(c))
{
_xcb_conn_shutdown(c);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_REQ_LEN_EXCEED);
return 0; /* server can't take this; maybe need BIGREQUESTS? */
}
/* set the length field. */
((uint16_t *) vector[0].iov_base)[1] = shortlen;
if(!shortlen)
prefix[2] = ++longlen;
{
prefix[0] = ((uint32_t *) vector[0].iov_base)[0];
prefix[1] = ++longlen;
vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1;
vector[0].iov_len -= sizeof(uint32_t);
--vector, ++veclen;
vector[0].iov_base = prefix;
vector[0].iov_len = sizeof(prefix);
}
}
flags &= ~XCB_REQUEST_RAW;
@@ -212,45 +237,21 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
pthread_cond_wait(&c->out.cond, &c->iolock);
get_socket_back(c);
request = ++c->out.request;
/* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
* a reply.
* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
* a reply. */
if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2)
send_sync(c);
/* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
* applications see sequence 0 as that is used to indicate
* an error in sending the request */
while((req->isvoid &&
c->out.request == c->in.request_expected + (1 << 16) - 1) ||
request == 0)
{
prefix[0] = sync_req.packet;
_xcb_in_expect_reply(c, request, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY);
c->in.request_expected = c->out.request;
request = ++c->out.request;
}
if((unsigned int) (c->out.request + 1) == 0)
send_sync(c);
if(workaround != WORKAROUND_NONE || flags != 0)
_xcb_in_expect_reply(c, request, workaround, flags);
if(!req->isvoid)
c->in.request_expected = c->out.request;
if(prefix[0] || prefix[2])
{
--vector, ++veclen;
if(prefix[2])
{
prefix[1] = ((uint32_t *) vector[1].iov_base)[0];
vector[1].iov_base = (uint32_t *) vector[1].iov_base + 1;
vector[1].iov_len -= sizeof(uint32_t);
}
vector[0].iov_len = sizeof(uint32_t) * ((prefix[0] ? 1 : 0) + (prefix[2] ? 2 : 0));
vector[0].iov_base = prefix + !prefix[0];
}
if(!write_block(c, vector, veclen))
{
_xcb_conn_shutdown(c);
request = 0;
}
/* The above send_sync calls could drop the I/O lock, but this
* thread will still exclude any other thread that tries to write,
* so the sequence number postconditions still hold. */
send_request(c, req->isvoid, workaround, flags, vector, veclen);
request = c->has_error ? 0 : c->out.request;
pthread_mutex_unlock(&c->iolock);
return request;
}
@@ -262,7 +263,13 @@ int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), v
return 0;
pthread_mutex_lock(&c->iolock);
get_socket_back(c);
ret = _xcb_out_flush_to(c, c->out.request);
/* _xcb_out_flush may drop the iolock allowing other threads to
* write requests, so keep flushing until we're done
*/
do
ret = _xcb_out_flush_to(c, c->out.request);
while (ret && c->out.request != c->out.request_written);
if(ret)
{
c->out.return_socket = return_socket;
@@ -342,6 +349,15 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
return ret;
}
void _xcb_out_send_sync(xcb_connection_t *c)
{
/* wait for other writing threads to get out of my way. */
while(c->out.writing)
pthread_cond_wait(&c->out.cond, &c->iolock);
get_socket_back(c);
send_sync(c);
}
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
{
assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));

View File

@@ -27,28 +27,36 @@
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <limits.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#ifdef DNETCONN
#include <netdnet/dnetdb.h>
#include <netdnet/dn.h>
#endif
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#ifdef _WIN32
#include "xcb_windefs.h"
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <netdb.h>
#endif /* _WIN32 */
#include "xcb.h"
#include "xcbext.h"
#include "xcbint.h"
/* must be after "xcbint.h" to get autoconf #defines */
#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
# include <tsol/label.h>
# include <sys/stat.h>
#endif
int xcb_popcount(uint32_t mask)
{
uint32_t y;
@@ -57,6 +65,16 @@ int xcb_popcount(uint32_t mask)
return ((y + (y >> 3)) & 030707070707) % 077;
}
int xcb_sumof(uint8_t *list, int len)
{
int i, s = 0;
for(i=0; i<len; i++) {
s += *list;
list++;
}
return s;
}
static int _xcb_parse_display(const char *name, char **host, char **protocol,
int *displayp, int *screenp)
{
@@ -137,10 +155,9 @@ int xcb_parse_display(const char *name, char **host, int *displayp,
}
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port);
#ifndef _WIN32
static int _xcb_open_unix(char *protocol, const char *file);
#ifdef DNETCONN
static int _xcb_open_decnet(const char *host, char *protocol, const unsigned short port);
#endif
#endif /* !WIN32 */
#ifdef HAVE_ABSTRACT_SOCKETS
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
#endif
@@ -155,36 +172,37 @@ static int _xcb_open(const char *host, char *protocol, const int display)
int actual_filelen;
#ifdef HAVE_LAUNCHD
if(strncmp(host, "/tmp/launch", 11) == 0) {
base = host;
host = "";
protocol = NULL;
}
#endif
if(*host || protocol)
{
#ifdef DNETCONN
/* DECnet displays have two colons, so _xcb_parse_display will have
left one at the end. However, an IPv6 address can end with *two*
colons, so only treat this as a DECnet display if host ends with
exactly one colon. */
char *colon = strchr(host, ':');
if(colon && *(colon+1) == '\0')
{
*colon = '\0';
return _xcb_open_decnet(host, protocol, display);
}
else
#endif
if (protocol
|| strcmp("unix",host)) { /* follow the old unix: rule */
/* display specifies TCP */
unsigned short port = X_TCP_PORT + display;
return _xcb_open_tcp(host, protocol, port);
}
if(strncmp(host, "/tmp/launch", 11) == 0) {
base = host;
host = "";
protocol = NULL;
}
#endif
/* If protocol or host is "unix", fall through to Unix socket code below */
if ((!protocol || (strcmp("unix",protocol) != 0)) &&
(*host != '\0') && (strcmp("unix",host) != 0))
{
/* display specifies TCP */
unsigned short port = X_TCP_PORT + display;
return _xcb_open_tcp(host, protocol, port);
}
#ifndef _WIN32
#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
/* Check special path for Unix sockets under Solaris Trusted Extensions */
if (is_system_labeled())
{
struct stat sbuf;
const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
char tsol_socket[PATH_MAX];
snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display);
if (stat(tsol_socket, &sbuf) == 0)
base = tsol_base;
}
#endif
filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
file = malloc(filelen);
@@ -217,7 +235,14 @@ static int _xcb_open(const char *host, char *protocol, const int display)
fd = _xcb_open_unix(protocol, file);
free(file);
if (fd < 0 && !protocol && *host == '\0') {
unsigned short port = X_TCP_PORT + display;
fd = _xcb_open_tcp(host, protocol, port);
}
return fd;
#endif /* !_WIN32 */
return -1; /* if control reaches here then something has gone wrong */
}
static int _xcb_socket(int family, int type, int proto)
@@ -230,59 +255,36 @@ static int _xcb_socket(int family, int type, int proto)
#endif
{
fd = socket(family, type, proto);
#ifndef _WIN32
if (fd >= 0)
fcntl(fd, F_SETFD, FD_CLOEXEC);
}
return fd;
}
#ifdef DNETCONN
static int _xcb_open_decnet(const char *host, const char *protocol, const unsigned short port)
{
int fd;
struct sockaddr_dn addr;
struct accessdata_dn accessdata;
struct nodeent *nodeaddr = getnodebyname(host);
if(!nodeaddr)
return -1;
if (protocol && strcmp("dnet",protocol))
return -1;
addr.sdn_family = AF_DECnet;
addr.sdn_add.a_len = nodeaddr->n_length;
memcpy(addr.sdn_add.a_addr, nodeaddr->n_addr, addr.sdn_add.a_len);
addr.sdn_objnamel = sprintf((char *)addr.sdn_objname, "X$X%d", port);
if(addr.sdn_objnamel < 0)
return -1;
addr.sdn_objnum = 0;
fd = _xcb_socket(PF_DECnet, SOCK_STREAM, 0);
if(fd == -1)
return -1;
memset(&accessdata, 0, sizeof(accessdata));
accessdata.acc_accl = sprintf((char*)accessdata.acc_acc, "%d", getuid());
if(accessdata.acc_accl < 0)
return -1;
setsockopt(fd, DNPROTO_NSP, SO_CONACCESS, &accessdata, sizeof(accessdata));
if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
close(fd);
return -1;
}
return fd;
}
#endif
}
return fd;
}
static int _xcb_do_connect(int fd, const struct sockaddr* addr, int addrlen) {
int on = 1;
if(fd < 0)
return -1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
return connect(fd, addr, addrlen);
}
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
{
int fd = -1;
#if HAVE_GETADDRINFO
struct addrinfo hints;
char service[6]; /* "65535" with the trailing '\0' */
struct addrinfo *results, *addr;
char *bracket;
#endif
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
#ifdef AF_INET6
@@ -294,10 +296,8 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
if (*host == '\0')
host = "localhost";
#if HAVE_GETADDRINFO
memset(&hints, 0, sizeof(hints));
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif
#ifdef AI_NUMERICSERV
hints.ai_flags |= AI_NUMERICSERV;
#endif
@@ -323,21 +323,45 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
for(addr = results; addr; addr = addr->ai_next)
{
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(fd >= 0) {
int on = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
break;
close(fd);
fd = -1;
}
if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
break;
close(fd);
fd = -1;
}
freeaddrinfo(results);
return fd;
#else
{
struct hostent* _h;
struct sockaddr_in _s;
struct in_addr ** _c;
if((_h = gethostbyname(host)) == NULL)
return -1;
_c = (struct in_addr**)_h->h_addr_list;
fd = -1;
while(*_c) {
_s.sin_family = AF_INET;
_s.sin_port = htons(port);
_s.sin_addr = *(*_c);
fd = _xcb_socket(_s.sin_family, SOCK_STREAM, 0);
if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0)
break;
close(fd);
fd = -1;
++_c;
}
return fd;
}
#endif
}
#ifndef _WIN32
static int _xcb_open_unix(char *protocol, const char *file)
{
int fd;
@@ -360,6 +384,7 @@ static int _xcb_open_unix(char *protocol, const char *file)
}
return fd;
}
#endif /* !_WIN32 */
#ifdef HAVE_ABSTRACT_SOCKETS
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
@@ -404,13 +429,24 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
if(!parsed) {
c = (xcb_connection_t *) &error_connection;
c = _xcb_conn_ret_error(XCB_CONN_CLOSED_PARSE_ERR);
goto out;
} else
} else {
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
c = _xcb_conn_ret_error(XCB_CONN_ERROR);
goto out;
}
#endif
fd = _xcb_open(host, protocol, display);
}
if(fd == -1) {
c = (xcb_connection_t *) &error_connection;
c = _xcb_conn_ret_error(XCB_CONN_ERROR);
#ifdef _WIN32
WSACleanup();
#endif
goto out;
}

45
dist/libxcb/src/xcb_windefs.h vendored Normal file
View File

@@ -0,0 +1,45 @@
/* Copyright (C) 2009 Jatin Golani.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the names of the authors or their
* institutions shall not be used in advertising or otherwise to promote the
* sale, use or other dealings in this Software without prior written
* authorization from the authors.
*/
#ifndef _XCB_WINDEFS_H
#define _XCB_WINDEFS_H
#ifndef WINVER
#define WINVER 0x0501 /* required for getaddrinfo/freeaddrinfo defined only for WinXP and above */
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windef.h>
struct iovec {
void *iov_base; /* Pointer to data. */
int iov_len; /* Length of data. */
};
typedef unsigned int in_addr_t;
#endif /* xcb_windefs.h */

View File

@@ -65,15 +65,22 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
* request XCB sent. The caller of xcb_take_socket must supply a
* callback which XCB can call when it wants the write side of the
* socket back to make a request. This callback synchronizes with the
* external socket owner, flushes any output queues if appropriate, and
* then returns the sequence number of the last request sent over the
* socket. */
* external socket owner and flushes any output queues if appropriate.
* If you are sending requests which won't cause a reply, please note the
* comment for xcb_writev which explains some sequence number wrap issues.
* */
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent);
/* You must own the write-side of the socket (you've called
* xcb_take_socket, and haven't returned from return_socket yet) to call
* xcb_writev. Also, the iovec must have at least 1 byte of data in it.
* */
* You have to make sure that xcb can detect sequence number wraps correctly.
* This means that the first request you send after xcb_take_socket must cause a
* reply (e.g. just insert a GetInputFocus request). After every (1 << 16) - 1
* requests without a reply, you have to insert a request which will cause a
* reply. You can again use GetInputFocus for this. You do not have to wait for
* any of the GetInputFocus replies, but can instead handle them via
* xcb_discard_reply(). */
int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests);
@@ -86,6 +93,7 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply,
/* xcb_util.c */
int xcb_popcount(uint32_t mask);
int xcb_sumof(uint8_t *list, int len);
#ifdef __cplusplus
}

View File

@@ -54,7 +54,6 @@ enum lazy_reply_tag
#define XCB_PAD(i) (-(i) & 3)
#define XCB_SEQUENCE_COMPARE(a,op,b) ((int64_t) ((a) - (b)) op 0)
#define XCB_SEQUENCE_COMPARE_32(a,op,b) (((int) (a) - (int) (b)) op 0)
#ifndef offsetof
#define offsetof(type,member) ((size_t) &((type *)0)->member)
@@ -107,6 +106,7 @@ int _xcb_out_init(_xcb_out *out);
void _xcb_out_destroy(_xcb_out *out);
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count);
void _xcb_out_send_sync(xcb_connection_t *c);
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request);
@@ -193,7 +193,10 @@ struct xcb_connection_t {
_xcb_xid xid;
};
void _xcb_conn_shutdown(xcb_connection_t *c);
void _xcb_conn_shutdown(xcb_connection_t *c, int err);
xcb_connection_t *_xcb_conn_ret_error(int err);
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);

11
dist/libxcb/xcb-xkb.pc.in vendored Normal file
View File

@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: XCB XKB
Description: XCB Keyboard Extension (EXPERIMENTAL)
Version: @PACKAGE_VERSION@
Requires: xcb
Libs: -L${libdir} -lxcb-xkb
Cflags: -I${includedir}