sync code with last improvements from OpenBSD
This commit is contained in:
commit
88965415ff
26235 changed files with 29195616 additions and 0 deletions
269
dist/libxcb/src/Makefile.am
vendored
Normal file
269
dist/libxcb/src/Makefile.am
vendored
Normal file
|
@ -0,0 +1,269 @@
|
|||
lib_LTLIBRARIES = libxcb.la
|
||||
|
||||
EXTSOURCES = xproto.c \
|
||||
bigreq.c \
|
||||
xc_misc.c
|
||||
|
||||
AM_CFLAGS = $(BASE_CFLAGS) $(NEEDED_CFLAGS) $(XDMCP_CFLAGS)
|
||||
libxcb_la_LIBADD = $(NEEDED_LIBS) $(XDMCP_LIBS)
|
||||
libxcb_la_SOURCES = \
|
||||
xcb_conn.c xcb_out.c xcb_in.c xcb_ext.c xcb_xid.c \
|
||||
xcb_list.c xcb_util.c xcb_auth.c c_client.py
|
||||
nodist_libxcb_la_SOURCES = xproto.c bigreq.c xc_misc.c
|
||||
|
||||
# Explanation for -version-info:
|
||||
# -version-info current:revision:age
|
||||
# The library supports interface (current-age) to interface current.
|
||||
# * If you changed the source code at all, increment revision.
|
||||
# * 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 @lt_enable_auto_import@
|
||||
|
||||
XCB_LIBS = libxcb.la
|
||||
|
||||
# FIXME: find a way to autogenerate this from the XML files.
|
||||
|
||||
EXTSOURCES += composite.c
|
||||
if BUILD_COMPOSITE
|
||||
lib_LTLIBRARIES += libxcb-composite.la
|
||||
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
|
||||
|
||||
EXTSOURCES += damage.c
|
||||
if BUILD_DAMAGE
|
||||
lib_LTLIBRARIES += libxcb-damage.la
|
||||
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
|
||||
|
||||
EXTSOURCES += dpms.c
|
||||
if BUILD_DPMS
|
||||
lib_LTLIBRARIES += libxcb-dpms.la
|
||||
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
|
||||
|
||||
EXTSOURCES += dri2.c
|
||||
if BUILD_DRI2
|
||||
lib_LTLIBRARIES += libxcb-dri2.la
|
||||
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
|
||||
|
||||
EXTSOURCES += dri3.c
|
||||
if BUILD_DRI3
|
||||
lib_LTLIBRARIES += libxcb-dri3.la
|
||||
libxcb_dri3_la_LDFLAGS = -version-info 1:0:1 -no-undefined @lt_enable_auto_import@
|
||||
libxcb_dri3_la_LIBADD = $(XCB_LIBS)
|
||||
nodist_libxcb_dri3_la_SOURCES = dri3.c dri3.h
|
||||
endif
|
||||
|
||||
EXTSOURCES += present.c
|
||||
if BUILD_PRESENT
|
||||
lib_LTLIBRARIES += libxcb-present.la
|
||||
libxcb_present_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||
libxcb_present_la_LIBADD = $(XCB_LIBS)
|
||||
nodist_libxcb_present_la_SOURCES = present.c present.h
|
||||
endif
|
||||
|
||||
EXTSOURCES += glx.c
|
||||
if BUILD_GLX
|
||||
lib_LTLIBRARIES += libxcb-glx.la
|
||||
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
|
||||
|
||||
EXTSOURCES += randr.c
|
||||
if BUILD_RANDR
|
||||
lib_LTLIBRARIES += libxcb-randr.la
|
||||
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
|
||||
|
||||
EXTSOURCES += record.c
|
||||
if BUILD_RECORD
|
||||
lib_LTLIBRARIES += libxcb-record.la
|
||||
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
|
||||
|
||||
EXTSOURCES += render.c
|
||||
if BUILD_RENDER
|
||||
lib_LTLIBRARIES += libxcb-render.la
|
||||
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
|
||||
|
||||
EXTSOURCES += res.c
|
||||
if BUILD_RESOURCE
|
||||
lib_LTLIBRARIES += libxcb-res.la
|
||||
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
|
||||
|
||||
EXTSOURCES += screensaver.c
|
||||
if BUILD_SCREENSAVER
|
||||
lib_LTLIBRARIES += libxcb-screensaver.la
|
||||
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
|
||||
|
||||
EXTSOURCES += shape.c
|
||||
if BUILD_SHAPE
|
||||
lib_LTLIBRARIES += libxcb-shape.la
|
||||
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
|
||||
|
||||
EXTSOURCES += shm.c
|
||||
if BUILD_SHM
|
||||
lib_LTLIBRARIES += libxcb-shm.la
|
||||
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
|
||||
|
||||
EXTSOURCES += sync.c
|
||||
if BUILD_SYNC
|
||||
lib_LTLIBRARIES += libxcb-sync.la
|
||||
libxcb_sync_la_LDFLAGS = -version-info 1:0:0 -no-undefined @lt_enable_auto_import@
|
||||
libxcb_sync_la_LIBADD = $(XCB_LIBS)
|
||||
nodist_libxcb_sync_la_SOURCES = sync.c sync.h
|
||||
endif
|
||||
|
||||
EXTSOURCES += xevie.c
|
||||
if BUILD_XEVIE
|
||||
lib_LTLIBRARIES += libxcb-xevie.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xf86dri.c
|
||||
if BUILD_XFREE86_DRI
|
||||
lib_LTLIBRARIES += libxcb-xf86dri.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xfixes.c
|
||||
if BUILD_XFIXES
|
||||
lib_LTLIBRARIES += libxcb-xfixes.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xinerama.c
|
||||
if BUILD_XINERAMA
|
||||
lib_LTLIBRARIES += libxcb-xinerama.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xinput.c
|
||||
if BUILD_XINPUT
|
||||
lib_LTLIBRARIES += libxcb-xinput.la
|
||||
libxcb_xinput_la_LDFLAGS = -version-info 1:0:1 -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 1: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 @lt_enable_auto_import@
|
||||
libxcb_xprint_la_LIBADD = $(XCB_LIBS)
|
||||
nodist_libxcb_xprint_la_SOURCES = xprint.c xprint.h
|
||||
endif
|
||||
|
||||
EXTSOURCES += xselinux.c
|
||||
if BUILD_SELINUX
|
||||
lib_LTLIBRARIES += libxcb-xselinux.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xtest.c
|
||||
if BUILD_XTEST
|
||||
lib_LTLIBRARIES += libxcb-xtest.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xv.c
|
||||
if BUILD_XV
|
||||
lib_LTLIBRARIES += libxcb-xv.la
|
||||
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
|
||||
|
||||
EXTSOURCES += xvmc.c
|
||||
if BUILD_XVMC
|
||||
lib_LTLIBRARIES += libxcb-xvmc.la
|
||||
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
|
||||
|
||||
EXTSOURCES += ge.c
|
||||
if BUILD_GE
|
||||
lib_LTLIBRARIES += libxcb-ge.la
|
||||
libxcb_ge_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||
libxcb_ge_la_LIBADD = $(XCB_LIBS)
|
||||
nodist_libxcb_ge_la_SOURCES = ge.c ge.h
|
||||
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
|
||||
|
||||
BUILT_MAN_PAGES = man/xcb_*
|
||||
libmandir = $(LIB_MAN_DIR)
|
||||
libman_DATA = $(BUILT_MAN_PAGES)
|
||||
|
||||
BUILT_SOURCES = $(EXTSOURCES) $(BUILT_MAN_PAGES)
|
||||
CLEANFILES = $(EXTSOURCES) $(EXTHEADERS) $(BUILT_MAN_PAGES)
|
||||
|
||||
C_CLIENT_PY_EXTRA_ARGS =
|
||||
if XCB_SERVERSIDE_SUPPORT
|
||||
C_CLIENT_PY_EXTRA_ARGS += --server-side
|
||||
endif
|
||||
|
||||
$(EXTSOURCES): c_client.py $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml)
|
||||
$(AM_V_GEN)$(PYTHON) $(srcdir)/c_client.py -c "$(PACKAGE_STRING)" -l "$(XORG_MAN_PAGE)" \
|
||||
-s "$(LIB_MAN_SUFFIX)" -p $(XCBPROTO_XCBPYTHONDIR) \
|
||||
$(C_CLIENT_PY_EXTRA_ARGS) \
|
||||
$(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml)
|
||||
|
||||
$(BUILT_MAN_PAGES): $(EXTSOURCES)
|
1299
dist/libxcb/src/Makefile.in
vendored
Normal file
1299
dist/libxcb/src/Makefile.in
vendored
Normal file
File diff suppressed because it is too large
Load diff
3394
dist/libxcb/src/c_client.py
vendored
Normal file
3394
dist/libxcb/src/c_client.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
144
dist/libxcb/src/config.h.in
vendored
Normal file
144
dist/libxcb/src/config.h.in
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Defined if GCC supports the visibility feature */
|
||||
#undef GCC_HAS_VISIBILITY
|
||||
|
||||
/* Has Wraphelp.c needed for XDM AUTH protocols */
|
||||
#undef HASXDMAUTH
|
||||
|
||||
/* Define if your platform supports abstract sockets */
|
||||
#undef HAVE_ABSTRACT_SOCKETS
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* getaddrinfo() function is available */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `is_system_labeled' function. */
|
||||
#undef HAVE_IS_SYSTEM_LABELED
|
||||
|
||||
/* launchd support available */
|
||||
#undef HAVE_LAUNCHD
|
||||
|
||||
/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
|
||||
#undef HAVE_LIBWS2_32
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define if your platform supports sendmsg */
|
||||
#undef HAVE_SENDMSG
|
||||
|
||||
/* Have the sockaddr_un.sun_len member. */
|
||||
#undef HAVE_SOCKADDR_SUN_LEN
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <tsol/label.h> header file. */
|
||||
#undef HAVE_TSOL_LABEL_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if not provided by <limits.h> */
|
||||
#undef IOV_MAX
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Major version of this package */
|
||||
#undef PACKAGE_VERSION_MAJOR
|
||||
|
||||
/* Minor version of this package */
|
||||
#undef PACKAGE_VERSION_MINOR
|
||||
|
||||
/* Patch version of this package */
|
||||
#undef PACKAGE_VERSION_PATCHLEVEL
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* poll() function is available */
|
||||
#undef USE_POLL
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* XCB buffer queue size */
|
||||
#undef XCB_QUEUE_BUFFER_SIZE
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* Defined if needed to expose struct msghdr.msg_control */
|
||||
#undef _XOPEN_SOURCE
|
644
dist/libxcb/src/xcb.h
vendored
Normal file
644
dist/libxcb/src/xcb.h
vendored
Normal file
|
@ -0,0 +1,644 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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_H__
|
||||
#define __XCB_H__
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(__solaris__)
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#else
|
||||
#include "xcb_windefs.h"
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file xcb.h
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define XCB_PACKED __attribute__((__packed__))
|
||||
#else
|
||||
#define XCB_PACKED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup XCB_Core_API XCB Core API
|
||||
* @brief Core API of the XCB library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Pre-defined constants */
|
||||
|
||||
/** Current protocol version */
|
||||
#define X_PROTOCOL 11
|
||||
|
||||
/** Current minor version */
|
||||
#define X_PROTOCOL_REVISION 0
|
||||
|
||||
/** 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 supported */
|
||||
#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
|
||||
|
||||
/** Connection closed because the server does not have a screen matching the display. */
|
||||
#define XCB_CONN_CLOSED_INVALID_SCREEN 6
|
||||
|
||||
/** Connection closed because some FD passing operation failed */
|
||||
#define XCB_CONN_CLOSED_FDPASSING_FAILED 7
|
||||
|
||||
#define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
|
||||
|
||||
/* Opaque structures */
|
||||
|
||||
/**
|
||||
* @brief XCB Connection structure.
|
||||
*
|
||||
* A structure that contain all data that XCB needs to communicate with an X server.
|
||||
*/
|
||||
typedef struct xcb_connection_t xcb_connection_t; /**< Opaque structure containing all data that XCB needs to communicate with an X server. */
|
||||
|
||||
|
||||
/* Other types */
|
||||
|
||||
/**
|
||||
* @brief Generic iterator.
|
||||
*
|
||||
* A generic iterator structure.
|
||||
*/
|
||||
typedef struct {
|
||||
void *data; /**< Data of the current iterator */
|
||||
int rem; /**< remaining elements */
|
||||
int index; /**< index of the current iterator */
|
||||
} xcb_generic_iterator_t;
|
||||
|
||||
/**
|
||||
* @brief Generic reply.
|
||||
*
|
||||
* A generic reply structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t response_type; /**< Type of the response */
|
||||
uint8_t pad0; /**< Padding */
|
||||
uint16_t sequence; /**< Sequence number */
|
||||
uint32_t length; /**< Length of the response */
|
||||
} xcb_generic_reply_t;
|
||||
|
||||
/**
|
||||
* @brief Generic event.
|
||||
*
|
||||
* A generic event structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t response_type; /**< Type of the response */
|
||||
uint8_t pad0; /**< Padding */
|
||||
uint16_t sequence; /**< Sequence number */
|
||||
uint32_t pad[7]; /**< Padding */
|
||||
uint32_t full_sequence; /**< full sequence */
|
||||
} xcb_generic_event_t;
|
||||
|
||||
/**
|
||||
* @brief Raw Generic event.
|
||||
*
|
||||
* A generic event structure as used on the wire, i.e., without the full_sequence field
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t response_type; /**< Type of the response */
|
||||
uint8_t pad0; /**< Padding */
|
||||
uint16_t sequence; /**< Sequence number */
|
||||
uint32_t pad[7]; /**< Padding */
|
||||
} xcb_raw_generic_event_t;
|
||||
|
||||
/**
|
||||
* @brief GE event
|
||||
*
|
||||
* An event as sent by the XGE extension. The length field specifies the
|
||||
* number of 4-byte blocks trailing the struct.
|
||||
*
|
||||
* @deprecated Since some fields in this struct have unfortunate names, it is
|
||||
* recommended to use xcb_ge_generic_event_t instead.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t response_type; /**< Type of the response */
|
||||
uint8_t pad0; /**< Padding */
|
||||
uint16_t sequence; /**< Sequence number */
|
||||
uint32_t length;
|
||||
uint16_t event_type;
|
||||
uint16_t pad1;
|
||||
uint32_t pad[5]; /**< Padding */
|
||||
uint32_t full_sequence; /**< full sequence */
|
||||
} xcb_ge_event_t;
|
||||
|
||||
/**
|
||||
* @brief Generic error.
|
||||
*
|
||||
* A generic error structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t response_type; /**< Type of the response */
|
||||
uint8_t error_code; /**< Error code */
|
||||
uint16_t sequence; /**< Sequence number */
|
||||
uint32_t resource_id; /** < Resource ID for requests with side effects only */
|
||||
uint16_t minor_code; /** < Minor opcode of the failed request */
|
||||
uint8_t major_code; /** < Major opcode of the failed request */
|
||||
uint8_t pad0;
|
||||
uint32_t pad[5]; /**< Padding */
|
||||
uint32_t full_sequence; /**< full sequence */
|
||||
} xcb_generic_error_t;
|
||||
|
||||
/**
|
||||
* @brief Generic cookie.
|
||||
*
|
||||
* A generic cookie structure.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int sequence; /**< Sequence number */
|
||||
} xcb_void_cookie_t;
|
||||
|
||||
|
||||
/* Include the generated xproto header. */
|
||||
#include "xproto.h"
|
||||
|
||||
|
||||
/** XCB_NONE is the universal null resource or null atom parameter value for many core X requests */
|
||||
#define XCB_NONE 0L
|
||||
|
||||
/** XCB_COPY_FROM_PARENT can be used for many xcb_create_window parameters */
|
||||
#define XCB_COPY_FROM_PARENT 0L
|
||||
|
||||
/** XCB_CURRENT_TIME can be used in most requests that take an xcb_timestamp_t */
|
||||
#define XCB_CURRENT_TIME 0L
|
||||
|
||||
/** XCB_NO_SYMBOL fills in unused entries in xcb_keysym_t tables */
|
||||
#define XCB_NO_SYMBOL 0L
|
||||
|
||||
|
||||
/* xcb_auth.c */
|
||||
|
||||
/**
|
||||
* @brief Container for authorization information.
|
||||
*
|
||||
* A container for authorization information to be sent to the X server.
|
||||
*/
|
||||
typedef struct xcb_auth_info_t {
|
||||
int namelen; /**< Length of the string name (as returned by strlen). */
|
||||
char *name; /**< String containing the authentication protocol name, such as "MIT-MAGIC-COOKIE-1" or "XDM-AUTHORIZATION-1". */
|
||||
int datalen; /**< Length of the data member. */
|
||||
char *data; /**< Data interpreted in a protocol-specific manner. */
|
||||
} xcb_auth_info_t;
|
||||
|
||||
|
||||
/* xcb_out.c */
|
||||
|
||||
/**
|
||||
* @brief Forces any buffered output to be written to the server.
|
||||
* @param c The connection to the X server.
|
||||
* @return > @c 0 on success, <= @c 0 otherwise.
|
||||
*
|
||||
* Forces any buffered output to be written to the server. Blocks
|
||||
* until the write is complete.
|
||||
*/
|
||||
int xcb_flush(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Returns the maximum request length that this server accepts.
|
||||
* @param c The connection to the X server.
|
||||
* @return The maximum request length field.
|
||||
*
|
||||
* In the absence of the BIG-REQUESTS extension, returns the
|
||||
* maximum request length field from the connection setup data, which
|
||||
* may be as much as 65535. If the server supports BIG-REQUESTS, then
|
||||
* the maximum request length field from the reply to the
|
||||
* BigRequestsEnable request will be returned instead.
|
||||
*
|
||||
* Note that this length is measured in four-byte units, making the
|
||||
* theoretical maximum lengths roughly 256kB without BIG-REQUESTS and
|
||||
* 16GB with.
|
||||
*/
|
||||
uint32_t xcb_get_maximum_request_length(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Prefetch the maximum request length without blocking.
|
||||
* @param c The connection to the X server.
|
||||
*
|
||||
* Without blocking, does as much work as possible toward computing
|
||||
* the maximum request length accepted by the X server.
|
||||
*
|
||||
* Invoking this function may cause a call to xcb_big_requests_enable,
|
||||
* but will not block waiting for the reply.
|
||||
* xcb_get_maximum_request_length will return the prefetched data
|
||||
* after possibly blocking while the reply is retrieved.
|
||||
*
|
||||
* Note that in order for this function to be fully non-blocking, the
|
||||
* application must previously have called
|
||||
* xcb_prefetch_extension_data(c, &xcb_big_requests_id) and the reply
|
||||
* must have already arrived.
|
||||
*/
|
||||
void xcb_prefetch_maximum_request_length(xcb_connection_t *c);
|
||||
|
||||
|
||||
/* xcb_in.c */
|
||||
|
||||
/**
|
||||
* @brief Returns the next event or error from the server.
|
||||
* @param c The connection to the X server.
|
||||
* @return The next event from the server.
|
||||
*
|
||||
* Returns the next event or error from the server, or returns null in
|
||||
* the event of an I/O error. Blocks until either an event or error
|
||||
* arrive, or an I/O error occurs.
|
||||
*/
|
||||
xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Returns the next event or error from the server.
|
||||
* @param c The connection to the X server.
|
||||
* @return The next event from the server.
|
||||
*
|
||||
* Returns the next event or error from the server, if one is
|
||||
* available, or returns @c NULL otherwise. If no event is available, that
|
||||
* might be because an I/O error like connection close occurred while
|
||||
* attempting to read the next event, in which case the connection is
|
||||
* shut down when this function returns.
|
||||
*/
|
||||
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);
|
||||
|
||||
typedef struct xcb_special_event xcb_special_event_t;
|
||||
|
||||
/**
|
||||
* @brief Returns the next event from a special queue
|
||||
*/
|
||||
xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
|
||||
xcb_special_event_t *se);
|
||||
|
||||
/**
|
||||
* @brief Returns the next event from a special queue, blocking until one arrives
|
||||
*/
|
||||
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
|
||||
xcb_special_event_t *se);
|
||||
/**
|
||||
* @typedef typedef struct xcb_extension_t xcb_extension_t
|
||||
*/
|
||||
typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */
|
||||
|
||||
/**
|
||||
* @brief Listen for a special event
|
||||
*/
|
||||
xcb_special_event_t *xcb_register_for_special_xge(xcb_connection_t *c,
|
||||
xcb_extension_t *ext,
|
||||
uint32_t eid,
|
||||
uint32_t *stamp);
|
||||
|
||||
/**
|
||||
* @brief Stop listening for a special event
|
||||
*/
|
||||
void xcb_unregister_for_special_event(xcb_connection_t *c,
|
||||
xcb_special_event_t *se);
|
||||
|
||||
/**
|
||||
* @brief Return the error for a request, or NULL if none can ever arrive.
|
||||
* @param c The connection to the X server.
|
||||
* @param cookie The request cookie.
|
||||
* @return The error for the request, or NULL if none can ever arrive.
|
||||
*
|
||||
* The xcb_void_cookie_t cookie supplied to this function must have resulted
|
||||
* from a call to xcb_[request_name]_checked(). This function will block
|
||||
* until one of two conditions happens. If an error is received, it will be
|
||||
* returned. If a reply to a subsequent request has already arrived, no error
|
||||
* can arrive for this request, so this function will return NULL.
|
||||
*
|
||||
* Note that this function will perform a sync if needed to ensure that the
|
||||
* sequence number will advance beyond that provided in cookie; this is a
|
||||
* convenience to avoid races in determining whether the sync is needed.
|
||||
*/
|
||||
xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie);
|
||||
|
||||
/**
|
||||
* @brief Discards the reply for a request.
|
||||
* @param c The connection to the X server.
|
||||
* @param sequence The request sequence number from a cookie.
|
||||
*
|
||||
* Discards the reply for a request. Additionally, any error generated
|
||||
* by the request is also discarded (unless it was an _unchecked request
|
||||
* and the error has already arrived).
|
||||
*
|
||||
* This function will not block even if the reply is not yet available.
|
||||
*
|
||||
* Note that the sequence really does have to come from an xcb cookie;
|
||||
* this function is not designed to operate on socket-handoff replies.
|
||||
*/
|
||||
void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence);
|
||||
|
||||
/**
|
||||
* @brief Discards the reply for a request, given by a 64bit sequence number
|
||||
* @param c The connection to the X server.
|
||||
* @param sequence 64-bit sequence number as returned by xcb_send_request64().
|
||||
*
|
||||
* Discards the reply for a request. Additionally, any error generated
|
||||
* by the request is also discarded (unless it was an _unchecked request
|
||||
* and the error has already arrived).
|
||||
*
|
||||
* This function will not block even if the reply is not yet available.
|
||||
*
|
||||
* Note that the sequence really does have to come from xcb_send_request64();
|
||||
* the cookie sequence number is defined as "unsigned" int and therefore
|
||||
* not 64-bit on all platforms.
|
||||
* This function is not designed to operate on socket-handoff replies.
|
||||
*
|
||||
* Unlike its xcb_discard_reply() counterpart, the given sequence number is not
|
||||
* automatically "widened" to 64-bit.
|
||||
*/
|
||||
void xcb_discard_reply64(xcb_connection_t *c, uint64_t sequence);
|
||||
|
||||
/* xcb_ext.c */
|
||||
|
||||
/**
|
||||
* @brief Caches reply information from QueryExtension requests.
|
||||
* @param c The connection.
|
||||
* @param ext The extension data.
|
||||
* @return A pointer to the xcb_query_extension_reply_t for the extension.
|
||||
*
|
||||
* This function is the primary interface to the "extension cache",
|
||||
* which caches reply information from QueryExtension
|
||||
* requests. Invoking this function may cause a call to
|
||||
* xcb_query_extension to retrieve extension information from the
|
||||
* server, and may block until extension data is received from the
|
||||
* server.
|
||||
*
|
||||
* The result must not be freed. This storage is managed by the cache
|
||||
* itself.
|
||||
*/
|
||||
const struct xcb_query_extension_reply_t *xcb_get_extension_data(xcb_connection_t *c, xcb_extension_t *ext);
|
||||
|
||||
/**
|
||||
* @brief Prefetch of extension data into the extension cache
|
||||
* @param c The connection.
|
||||
* @param ext The extension data.
|
||||
*
|
||||
* This function allows a "prefetch" of extension data into the
|
||||
* extension cache. Invoking the function may cause a call to
|
||||
* xcb_query_extension, but will not block waiting for the
|
||||
* reply. xcb_get_extension_data will return the prefetched data after
|
||||
* possibly blocking while it is retrieved.
|
||||
*/
|
||||
void xcb_prefetch_extension_data(xcb_connection_t *c, xcb_extension_t *ext);
|
||||
|
||||
|
||||
/* xcb_conn.c */
|
||||
|
||||
/**
|
||||
* @brief Access the data returned by the server.
|
||||
* @param c The connection.
|
||||
* @return A pointer to an xcb_setup_t structure.
|
||||
*
|
||||
* Accessor for the data returned by the server when the xcb_connection_t
|
||||
* was initialized. This data includes
|
||||
* - the server's required format for images,
|
||||
* - a list of available visuals,
|
||||
* - a list of available screens,
|
||||
* - the server's maximum request length (in the absence of the
|
||||
* BIG-REQUESTS extension),
|
||||
* - and other assorted information.
|
||||
*
|
||||
* See the X protocol specification for more details.
|
||||
*
|
||||
* The result must not be freed.
|
||||
*/
|
||||
const struct xcb_setup_t *xcb_get_setup(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Access the file descriptor of the connection.
|
||||
* @param c The connection.
|
||||
* @return The file descriptor.
|
||||
*
|
||||
* Accessor for the file descriptor that was passed to the
|
||||
* xcb_connect_to_fd call that returned @p c.
|
||||
*/
|
||||
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 > 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, but memory will not be freed until
|
||||
* xcb_disconnect() is called on the xcb_connection_t.
|
||||
*
|
||||
* @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.
|
||||
* @return XCB_CONN_CLOSED_INVALID_SCREEN, because the server does not have a screen matching the display.
|
||||
*/
|
||||
int xcb_connection_has_error(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @brief Connects to the X server.
|
||||
* @param fd The file descriptor.
|
||||
* @param auth_info Authentication data.
|
||||
* @return A newly allocated xcb_connection_t structure.
|
||||
*
|
||||
* Connects to an X server, given the open socket @p fd and the
|
||||
* xcb_auth_info_t @p auth_info. The file descriptor @p fd is
|
||||
* bidirectionally connected to an X server. If the connection
|
||||
* should be unauthenticated, @p auth_info must be @c
|
||||
* NULL.
|
||||
*
|
||||
* Always returns a non-NULL pointer to a xcb_connection_t, even on failure.
|
||||
* Callers need to use xcb_connection_has_error() to check for failure.
|
||||
* When finished, use xcb_disconnect() to close the connection and free
|
||||
* the structure.
|
||||
*/
|
||||
xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info);
|
||||
|
||||
/**
|
||||
* @brief Closes the connection.
|
||||
* @param c The connection.
|
||||
*
|
||||
* Closes the file descriptor and frees all memory associated with the
|
||||
* connection @c c. If @p c is @c NULL, nothing is done.
|
||||
*/
|
||||
void xcb_disconnect(xcb_connection_t *c);
|
||||
|
||||
|
||||
/* xcb_util.c */
|
||||
|
||||
/**
|
||||
* @brief Parses a display string name in the form documented by X(7x).
|
||||
* @param name The name of the display.
|
||||
* @param host A pointer to a malloc'd copy of the hostname.
|
||||
* @param display A pointer to the display number.
|
||||
* @param screen A pointer to the screen number.
|
||||
* @return 0 on failure, non 0 otherwise.
|
||||
*
|
||||
* Parses the display string name @p display_name in the form
|
||||
* documented by X(7x). Has no side effects on failure. If
|
||||
* @p displayname is @c NULL or empty, it uses the environment
|
||||
* variable DISPLAY. @p hostp is a pointer to a newly allocated string
|
||||
* that contain the host name. @p displayp is set to the display
|
||||
* number and @p screenp to the preferred screen number. @p screenp
|
||||
* can be @c NULL. If @p displayname does not contain a screen number,
|
||||
* it is set to @c 0.
|
||||
*/
|
||||
int xcb_parse_display(const char *name, char **host, int *display, int *screen);
|
||||
|
||||
/**
|
||||
* @brief Connects to the X server.
|
||||
* @param displayname The name of the display.
|
||||
* @param screenp A pointer to a preferred screen number.
|
||||
* @return A newly allocated xcb_connection_t structure.
|
||||
*
|
||||
* Connects to the X server specified by @p displayname. If @p
|
||||
* displayname is @c NULL, uses the value of the DISPLAY environment
|
||||
* variable. If a particular screen on that server is preferred, the
|
||||
* int pointed to by @p screenp (if not @c NULL) will be set to that
|
||||
* screen; otherwise the screen will be set to 0.
|
||||
*
|
||||
* Always returns a non-NULL pointer to a xcb_connection_t, even on failure.
|
||||
* Callers need to use xcb_connection_has_error() to check for failure.
|
||||
* When finished, use xcb_disconnect() to close the connection and free
|
||||
* the structure.
|
||||
*/
|
||||
xcb_connection_t *xcb_connect(const char *displayname, int *screenp);
|
||||
|
||||
/**
|
||||
* @brief Connects to the X server, using an authorization information.
|
||||
* @param display The name of the display.
|
||||
* @param auth The authorization information.
|
||||
* @param screen A pointer to a preferred screen number.
|
||||
* @return A newly allocated xcb_connection_t structure.
|
||||
*
|
||||
* Connects to the X server specified by @p displayname, using the
|
||||
* authorization @p auth. If a particular screen on that server is
|
||||
* preferred, the int pointed to by @p screenp (if not @c NULL) will
|
||||
* be set to that screen; otherwise @p screenp will be set to 0.
|
||||
*
|
||||
* Always returns a non-NULL pointer to a xcb_connection_t, even on failure.
|
||||
* Callers need to use xcb_connection_has_error() to check for failure.
|
||||
* When finished, use xcb_disconnect() to close the connection and free
|
||||
* the structure.
|
||||
*/
|
||||
xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *display, xcb_auth_info_t *auth, int *screen);
|
||||
|
||||
|
||||
/* xcb_xid.c */
|
||||
|
||||
/**
|
||||
* @brief Allocates an XID for a new object.
|
||||
* @param c The connection.
|
||||
* @return A newly allocated XID, or -1 on failure.
|
||||
*
|
||||
* Allocates an XID for a new object. Typically used just prior to
|
||||
* various object creation functions, such as xcb_create_window.
|
||||
*/
|
||||
uint32_t xcb_generate_id(xcb_connection_t *c);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Obtain number of bytes read from the connection.
|
||||
* @param c The connection
|
||||
* @return Number of bytes read from the server.
|
||||
*
|
||||
* Returns cumulative number of bytes received from the connection.
|
||||
*
|
||||
* This retrieves the total number of bytes read from this connection,
|
||||
* to be used for diagnostic/monitoring/informative purposes.
|
||||
*/
|
||||
|
||||
uint64_t
|
||||
xcb_total_read(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Obtain number of bytes written to the connection.
|
||||
* @param c The connection
|
||||
* @return Number of bytes written to the server.
|
||||
*
|
||||
* Returns cumulative number of bytes sent to the connection.
|
||||
*
|
||||
* This retrieves the total number of bytes written to this connection,
|
||||
* to be used for diagnostic/monitoring/informative purposes.
|
||||
*/
|
||||
|
||||
uint64_t
|
||||
xcb_total_written(xcb_connection_t *c);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __XCB_H__ */
|
388
dist/libxcb/src/xcb_auth.c
vendored
Normal file
388
dist/libxcb/src/xcb_auth.c
vendored
Normal file
|
@ -0,0 +1,388 @@
|
|||
/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Authorization systems for the X protocol. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <X11/Xauth.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.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 <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/un.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "xcb.h"
|
||||
#include "xcbint.h"
|
||||
|
||||
#ifdef HASXDMAUTH
|
||||
#include <X11/Xdmcp.h>
|
||||
#endif
|
||||
|
||||
enum auth_protos {
|
||||
#ifdef HASXDMAUTH
|
||||
AUTH_XA1,
|
||||
#endif
|
||||
AUTH_MC1,
|
||||
N_AUTH_PROTOS
|
||||
};
|
||||
|
||||
#define AUTH_PROTO_XDM_AUTHORIZATION "XDM-AUTHORIZATION-1"
|
||||
#define AUTH_PROTO_MIT_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1"
|
||||
|
||||
static char *authnames[N_AUTH_PROTOS] = {
|
||||
#ifdef HASXDMAUTH
|
||||
AUTH_PROTO_XDM_AUTHORIZATION,
|
||||
#endif
|
||||
AUTH_PROTO_MIT_MAGIC_COOKIE,
|
||||
};
|
||||
|
||||
static int authnameslen[N_AUTH_PROTOS] = {
|
||||
#ifdef HASXDMAUTH
|
||||
sizeof(AUTH_PROTO_XDM_AUTHORIZATION) - 1,
|
||||
#endif
|
||||
sizeof(AUTH_PROTO_MIT_MAGIC_COOKIE) - 1,
|
||||
};
|
||||
|
||||
static size_t memdup(char **dst, void *src, size_t len)
|
||||
{
|
||||
if(len)
|
||||
*dst = malloc(len);
|
||||
else
|
||||
*dst = 0;
|
||||
if(!*dst)
|
||||
return 0;
|
||||
memcpy(*dst, src, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int authname_match(enum auth_protos kind, char *name, size_t namelen)
|
||||
{
|
||||
if(authnameslen[kind] != namelen)
|
||||
return 0;
|
||||
if(memcmp(authnames[kind], name, namelen))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SIN6_ADDR(s) (&((struct sockaddr_in6 *)s)->sin6_addr)
|
||||
|
||||
static Xauth *get_authptr(struct sockaddr *sockname, int display)
|
||||
{
|
||||
char *addr = 0;
|
||||
int addrlen = 0;
|
||||
unsigned short family;
|
||||
char hostnamebuf[256]; /* big enough for max hostname */
|
||||
char dispbuf[40]; /* big enough to hold more than 2^64 base 10 */
|
||||
int dispbuflen;
|
||||
|
||||
family = FamilyLocal; /* 256 */
|
||||
switch(sockname->sa_family)
|
||||
{
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
addr = (char *) SIN6_ADDR(sockname);
|
||||
addrlen = sizeof(*SIN6_ADDR(sockname));
|
||||
if(!IN6_IS_ADDR_V4MAPPED(SIN6_ADDR(sockname)))
|
||||
{
|
||||
if(!IN6_IS_ADDR_LOOPBACK(SIN6_ADDR(sockname)))
|
||||
family = XCB_FAMILY_INTERNET_6;
|
||||
break;
|
||||
}
|
||||
addr += 12;
|
||||
/* if v4-mapped, fall through. */
|
||||
XCB_ALLOW_FALLTHRU
|
||||
#endif
|
||||
case AF_INET:
|
||||
if(!addr)
|
||||
addr = (char *) &((struct sockaddr_in *)sockname)->sin_addr;
|
||||
addrlen = sizeof(((struct sockaddr_in *)sockname)->sin_addr);
|
||||
if(*(in_addr_t *) addr != htonl(INADDR_LOOPBACK))
|
||||
family = XCB_FAMILY_INTERNET;
|
||||
break;
|
||||
case AF_UNIX:
|
||||
break;
|
||||
default:
|
||||
return 0; /* cannot authenticate this family */
|
||||
}
|
||||
|
||||
dispbuflen = snprintf(dispbuf, sizeof(dispbuf), "%d", display);
|
||||
if(dispbuflen < 0)
|
||||
return 0;
|
||||
/* snprintf may have truncate our text */
|
||||
dispbuflen = MIN(dispbuflen, sizeof(dispbuf) - 1);
|
||||
|
||||
if (family == FamilyLocal) {
|
||||
if (gethostname(hostnamebuf, sizeof(hostnamebuf)) == -1)
|
||||
return 0; /* do not know own hostname */
|
||||
addr = hostnamebuf;
|
||||
addrlen = strlen(addr);
|
||||
}
|
||||
|
||||
return XauGetBestAuthByAddr (family,
|
||||
(unsigned short) addrlen, addr,
|
||||
(unsigned short) dispbuflen, dispbuf,
|
||||
N_AUTH_PROTOS, authnames, authnameslen);
|
||||
}
|
||||
|
||||
#ifdef HASXDMAUTH
|
||||
static int next_nonce(void)
|
||||
{
|
||||
static int nonce = 0;
|
||||
static pthread_mutex_t nonce_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
int ret;
|
||||
pthread_mutex_lock(&nonce_mutex);
|
||||
ret = nonce++;
|
||||
pthread_mutex_unlock(&nonce_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void do_append(char *buf, int *idxp, void *val, size_t valsize) {
|
||||
memcpy(buf + *idxp, val, valsize);
|
||||
*idxp += valsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *sockname)
|
||||
{
|
||||
if (authname_match(AUTH_MC1, authptr->name, authptr->name_length)) {
|
||||
info->datalen = memdup(&info->data, authptr->data, authptr->data_length);
|
||||
if(!info->datalen)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#ifdef HASXDMAUTH
|
||||
#define APPEND(buf,idx,val) do_append((buf),&(idx),&(val),sizeof(val))
|
||||
if (authname_match(AUTH_XA1, authptr->name, authptr->name_length)) {
|
||||
int j;
|
||||
|
||||
info->data = malloc(192 / 8);
|
||||
if(!info->data)
|
||||
return 0;
|
||||
|
||||
for (j = 0; j < 8; j++)
|
||||
info->data[j] = authptr->data[j];
|
||||
switch(sockname->sa_family) {
|
||||
case AF_INET:
|
||||
/*block*/ {
|
||||
struct sockaddr_in *si = (struct sockaddr_in *) sockname;
|
||||
APPEND(info->data, j, si->sin_addr.s_addr);
|
||||
APPEND(info->data, j, si->sin_port);
|
||||
}
|
||||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
/*block*/ {
|
||||
struct sockaddr_in6 *si6 = (struct sockaddr_in6 *) sockname;
|
||||
if(IN6_IS_ADDR_V4MAPPED(SIN6_ADDR(sockname)))
|
||||
{
|
||||
do_append(info->data, &j, &si6->sin6_addr.s6_addr[12], 4);
|
||||
APPEND(info->data, j, si6->sin6_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XDM-AUTHORIZATION-1 does not handle IPv6 correctly. Do the
|
||||
same thing Xlib does: use all zeroes for the 4-byte address
|
||||
and 2-byte port number. */
|
||||
uint32_t fakeaddr = 0;
|
||||
uint16_t fakeport = 0;
|
||||
APPEND(info->data, j, fakeaddr);
|
||||
APPEND(info->data, j, fakeport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case AF_UNIX:
|
||||
/*block*/ {
|
||||
uint32_t fakeaddr = htonl(0xffffffff - next_nonce());
|
||||
uint16_t fakeport = htons(getpid());
|
||||
APPEND(info->data, j, fakeaddr);
|
||||
APPEND(info->data, j, fakeport);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
free(info->data);
|
||||
return 0; /* do not know how to build this */
|
||||
}
|
||||
{
|
||||
uint32_t now = htonl(time(0));
|
||||
APPEND(info->data, j, now);
|
||||
}
|
||||
assert(j <= 192 / 8);
|
||||
while (j < 192 / 8)
|
||||
info->data[j++] = 0;
|
||||
info->datalen = j;
|
||||
XdmcpWrap ((unsigned char *) info->data, (unsigned char *) authptr->data + 8, (unsigned char *) info->data, info->datalen);
|
||||
return 1;
|
||||
}
|
||||
#undef APPEND
|
||||
#endif
|
||||
|
||||
return 0; /* Unknown authorization type */
|
||||
}
|
||||
|
||||
/* `sockaddr_un.sun_path' typical size usually ranges between 92 and 108 */
|
||||
#define INITIAL_SOCKNAME_SLACK 108
|
||||
|
||||
/* Return a dynamically allocated socket address structure according
|
||||
to the value returned by either getpeername() or getsockname()
|
||||
(according to POSIX, applications should not assume a particular
|
||||
length for `sockaddr_un.sun_path') */
|
||||
#ifdef _WIN32
|
||||
static struct sockaddr *get_peer_sock_name(int(_stdcall *socket_func)(SOCKET,
|
||||
struct sockaddr *,
|
||||
socklen_t *),
|
||||
int fd)
|
||||
#else
|
||||
static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
|
||||
struct sockaddr *,
|
||||
socklen_t *),
|
||||
int fd)
|
||||
#endif
|
||||
{
|
||||
socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
|
||||
socklen_t actual_socknamelen = socknamelen;
|
||||
struct sockaddr *sockname = malloc(socknamelen);
|
||||
|
||||
if (sockname == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Both getpeername() and getsockname() truncates sockname if
|
||||
there is not enough space and set the required length in
|
||||
actual_socknamelen */
|
||||
if (socket_func(fd, sockname, &actual_socknamelen) == -1)
|
||||
goto sock_or_realloc_error;
|
||||
|
||||
if (actual_socknamelen > socknamelen)
|
||||
{
|
||||
struct sockaddr *new_sockname = NULL;
|
||||
socknamelen = actual_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;
|
||||
|
||||
sock_or_realloc_error:
|
||||
free(sockname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display)
|
||||
{
|
||||
/* code adapted from Xlib/ConnDis.c, xtrans/Xtranssocket.c,
|
||||
xtrans/Xtransutils.c */
|
||||
struct sockaddr *sockname = NULL;
|
||||
int gotsockname = 0;
|
||||
Xauth *authptr = 0;
|
||||
int ret = 1;
|
||||
|
||||
/* Some systems like hpux or Hurd do not expose peer names
|
||||
* for UNIX Domain Sockets, but this is irrelevant,
|
||||
* since compute_auth() ignores the peer name in this
|
||||
* case anyway.*/
|
||||
if ((sockname = get_peer_sock_name(getpeername, fd)) == NULL)
|
||||
{
|
||||
if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
|
||||
return 0; /* can only authenticate sockets */
|
||||
if (sockname->sa_family != AF_UNIX)
|
||||
{
|
||||
free(sockname);
|
||||
return 0; /* except for AF_UNIX, sockets should have peernames */
|
||||
}
|
||||
gotsockname = 1;
|
||||
}
|
||||
|
||||
authptr = get_authptr(sockname, display);
|
||||
if (authptr == 0)
|
||||
{
|
||||
free(sockname);
|
||||
return 0; /* cannot find good auth data */
|
||||
}
|
||||
|
||||
info->namelen = memdup(&info->name, authptr->name, authptr->name_length);
|
||||
if (!info->namelen)
|
||||
goto no_auth; /* out of memory */
|
||||
|
||||
if (!gotsockname)
|
||||
{
|
||||
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);
|
||||
if(!ret)
|
||||
{
|
||||
free(info->name);
|
||||
goto no_auth; /* cannot build auth record */
|
||||
}
|
||||
|
||||
free(sockname);
|
||||
sockname = NULL;
|
||||
|
||||
XauDisposeAuth(authptr);
|
||||
return ret;
|
||||
|
||||
no_auth:
|
||||
free(sockname);
|
||||
|
||||
info->name = 0;
|
||||
info->namelen = 0;
|
||||
XauDisposeAuth(authptr);
|
||||
return 0;
|
||||
}
|
586
dist/libxcb/src/xcb_conn.c
vendored
Normal file
586
dist/libxcb/src/xcb_conn.c
vendored
Normal file
|
@ -0,0 +1,586 @@
|
|||
/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Connection management: the core of XCB. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "xcb.h"
|
||||
#include "xcbint.h"
|
||||
#if USE_POLL
|
||||
#include <poll.h>
|
||||
#elif !defined _WIN32
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "xcb_windefs.h"
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
|
||||
static const xcb_setup_t xcb_error_setup = {
|
||||
0, /* status: failed (but we wouldn't have a xcb_setup_t in this case) */
|
||||
0, /* pad0 */
|
||||
0, 0, /* protocol version, should be 11.0, but isn't */
|
||||
0, /* length, invalid value */
|
||||
0, /* release_number */
|
||||
0, 0, /* resource_id_{base,mask} */
|
||||
0, /* motion_buffer_size */
|
||||
0, /* vendor_len */
|
||||
0, /* maximum_request_length */
|
||||
0, /* roots_len */
|
||||
0, /* pixmap_formats_len */
|
||||
0, /* image_byte_order */
|
||||
0, /* bitmap_format_bit_order */
|
||||
0, /* bitmap_format_scanline_unit */
|
||||
0, /* bitmap_format_scanline_pad */
|
||||
0, 0, /* {min,max}_keycode */
|
||||
{ 0, 0, 0, 0 } /* pad1 */
|
||||
};
|
||||
|
||||
/* Keep this list in sync with is_static_error_conn()! */
|
||||
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 const int xcb_con_closed_screen_er = XCB_CONN_CLOSED_INVALID_SCREEN;
|
||||
|
||||
static int is_static_error_conn(xcb_connection_t *c)
|
||||
{
|
||||
return c == (xcb_connection_t *) &xcb_con_error ||
|
||||
c == (xcb_connection_t *) &xcb_con_closed_mem_er ||
|
||||
c == (xcb_connection_t *) &xcb_con_closed_parse_er ||
|
||||
c == (xcb_connection_t *) &xcb_con_closed_screen_er;
|
||||
}
|
||||
|
||||
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;
|
||||
flags |= O_NONBLOCK;
|
||||
if(fcntl(fd, F_SETFL, flags) == -1)
|
||||
return 0;
|
||||
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)
|
||||
{
|
||||
static const char pad[3];
|
||||
xcb_setup_request_t out;
|
||||
struct iovec parts[6];
|
||||
int count = 0;
|
||||
static const uint32_t endian = 0x01020304;
|
||||
int ret;
|
||||
|
||||
memset(&out, 0, sizeof(out));
|
||||
|
||||
/* B = 0x42 = MSB first, l = 0x6c = LSB first */
|
||||
if(htonl(endian) == endian)
|
||||
out.byte_order = 0x42;
|
||||
else
|
||||
out.byte_order = 0x6c;
|
||||
out.protocol_major_version = X_PROTOCOL;
|
||||
out.protocol_minor_version = X_PROTOCOL_REVISION;
|
||||
out.authorization_protocol_name_len = 0;
|
||||
out.authorization_protocol_data_len = 0;
|
||||
parts[count].iov_len = sizeof(xcb_setup_request_t);
|
||||
parts[count++].iov_base = &out;
|
||||
parts[count].iov_len = XCB_PAD(sizeof(xcb_setup_request_t));
|
||||
parts[count++].iov_base = (char *) pad;
|
||||
|
||||
if(auth_info)
|
||||
{
|
||||
parts[count].iov_len = out.authorization_protocol_name_len = auth_info->namelen;
|
||||
parts[count++].iov_base = auth_info->name;
|
||||
parts[count].iov_len = XCB_PAD(out.authorization_protocol_name_len);
|
||||
parts[count++].iov_base = (char *) pad;
|
||||
parts[count].iov_len = out.authorization_protocol_data_len = auth_info->datalen;
|
||||
parts[count++].iov_base = auth_info->data;
|
||||
parts[count].iov_len = XCB_PAD(out.authorization_protocol_data_len);
|
||||
parts[count++].iov_base = (char *) pad;
|
||||
}
|
||||
assert(count <= (int) (sizeof(parts) / sizeof(*parts)));
|
||||
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
ret = _xcb_out_send(c, parts, count);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_setup(xcb_connection_t *c)
|
||||
{
|
||||
const char newline = '\n';
|
||||
|
||||
/* Read the server response */
|
||||
c->setup = malloc(sizeof(xcb_setup_generic_t));
|
||||
if(!c->setup)
|
||||
return 0;
|
||||
|
||||
if(_xcb_in_read_block(c, c->setup, sizeof(xcb_setup_generic_t)) != sizeof(xcb_setup_generic_t))
|
||||
return 0;
|
||||
|
||||
{
|
||||
void *tmp = realloc(c->setup, c->setup->length * 4 + sizeof(xcb_setup_generic_t));
|
||||
if(!tmp)
|
||||
return 0;
|
||||
c->setup = tmp;
|
||||
}
|
||||
|
||||
if(_xcb_in_read_block(c, (char *) c->setup + sizeof(xcb_setup_generic_t), c->setup->length * 4) <= 0)
|
||||
return 0;
|
||||
|
||||
/* 0 = failed, 2 = authenticate, 1 = success */
|
||||
switch(c->setup->status)
|
||||
{
|
||||
case 0: /* failed */
|
||||
{
|
||||
xcb_setup_failed_t *setup = (xcb_setup_failed_t *) c->setup;
|
||||
write(STDERR_FILENO, xcb_setup_failed_reason(setup), xcb_setup_failed_reason_length(setup));
|
||||
write(STDERR_FILENO, &newline, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 2: /* authenticate */
|
||||
{
|
||||
xcb_setup_authenticate_t *setup = (xcb_setup_authenticate_t *) c->setup;
|
||||
write(STDERR_FILENO, xcb_setup_authenticate_reason(setup), xcb_setup_authenticate_reason_length(setup));
|
||||
write(STDERR_FILENO, &newline, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* precondition: there must be something for us to write. */
|
||||
static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int n;
|
||||
#endif
|
||||
|
||||
assert(!c->out.queue_len);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* 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 */
|
||||
while (*count)
|
||||
{
|
||||
struct iovec *vec = *vector;
|
||||
if (vec->iov_len)
|
||||
{
|
||||
int ret = send(c->fd, vec->iov_base, vec->iov_len, 0);
|
||||
if (ret == SOCKET_ERROR)
|
||||
{
|
||||
int err = WSAGetLastError();
|
||||
if (err == WSAEWOULDBLOCK)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (ret <= 0)
|
||||
{
|
||||
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||
return 0;
|
||||
}
|
||||
c->out.total_written += ret;
|
||||
vec->iov_len -= ret;
|
||||
vec->iov_base = (char *)vec->iov_base + ret;
|
||||
}
|
||||
if (vec->iov_len == 0) {
|
||||
(*vector)++;
|
||||
(*count)--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*count)
|
||||
*vector = 0;
|
||||
|
||||
#else
|
||||
n = *count;
|
||||
if (n > IOV_MAX)
|
||||
n = IOV_MAX;
|
||||
|
||||
#if HAVE_SENDMSG
|
||||
if (c->out.out_fd.nfd) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
char buf[CMSG_SPACE(XCB_MAX_PASS_FD * sizeof(int))];
|
||||
} cmsgbuf;
|
||||
struct msghdr msg = {
|
||||
.msg_name = NULL,
|
||||
.msg_namelen = 0,
|
||||
.msg_iov = *vector,
|
||||
.msg_iovlen = n,
|
||||
.msg_control = cmsgbuf.buf,
|
||||
.msg_controllen = CMSG_LEN(c->out.out_fd.nfd * sizeof (int)),
|
||||
};
|
||||
int i;
|
||||
struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
hdr->cmsg_len = msg.msg_controllen;
|
||||
hdr->cmsg_level = SOL_SOCKET;
|
||||
hdr->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(hdr), c->out.out_fd.fd, c->out.out_fd.nfd * sizeof (int));
|
||||
|
||||
n = sendmsg(c->fd, &msg, 0);
|
||||
if(n < 0 && errno == EAGAIN)
|
||||
return 1;
|
||||
for (i = 0; i < c->out.out_fd.nfd; i++)
|
||||
close(c->out.out_fd.fd[i]);
|
||||
c->out.out_fd.nfd = 0;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
n = writev(c->fd, *vector, n);
|
||||
if(n < 0 && errno == EAGAIN)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(n <= 0)
|
||||
{
|
||||
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->out.total_written += n;
|
||||
for(; *count; --*count, ++*vector)
|
||||
{
|
||||
int cur = (*vector)->iov_len;
|
||||
if(cur > n)
|
||||
cur = n;
|
||||
(*vector)->iov_len -= cur;
|
||||
(*vector)->iov_base = (char *) (*vector)->iov_base + cur;
|
||||
n -= cur;
|
||||
if((*vector)->iov_len)
|
||||
break;
|
||||
}
|
||||
if(!*count)
|
||||
*vector = 0;
|
||||
assert(n == 0);
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Public interface */
|
||||
|
||||
const xcb_setup_t *xcb_get_setup(xcb_connection_t *c)
|
||||
{
|
||||
if(is_static_error_conn(c))
|
||||
return &xcb_error_setup;
|
||||
/* doesn't need locking because it's never written to. */
|
||||
return c->setup;
|
||||
}
|
||||
|
||||
int xcb_get_file_descriptor(xcb_connection_t *c)
|
||||
{
|
||||
if(is_static_error_conn(c))
|
||||
return -1;
|
||||
/* doesn't need locking because it's never written to. */
|
||||
return c->fd;
|
||||
}
|
||||
|
||||
int xcb_connection_has_error(xcb_connection_t *c)
|
||||
{
|
||||
/* doesn't need locking because it's read and written atomically. */
|
||||
return c->has_error;
|
||||
}
|
||||
|
||||
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_conn_ret_error(XCB_CONN_ERROR);
|
||||
}
|
||||
#endif
|
||||
#endif /* !_WIN32*/
|
||||
|
||||
c = calloc(1, sizeof(xcb_connection_t));
|
||||
if(!c) {
|
||||
#ifdef _WIN32
|
||||
closesocket(fd);
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ;
|
||||
}
|
||||
|
||||
c->fd = fd;
|
||||
|
||||
if(!(
|
||||
set_fd_flags(fd) &&
|
||||
pthread_mutex_init(&c->iolock, 0) == 0 &&
|
||||
_xcb_in_init(&c->in) &&
|
||||
_xcb_out_init(&c->out) &&
|
||||
write_setup(c, auth_info) &&
|
||||
read_setup(c) &&
|
||||
_xcb_ext_init(c) &&
|
||||
_xcb_xid_init(c)
|
||||
))
|
||||
{
|
||||
xcb_disconnect(c);
|
||||
return _xcb_conn_ret_error(XCB_CONN_ERROR);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void xcb_disconnect(xcb_connection_t *c)
|
||||
{
|
||||
if(c == NULL || is_static_error_conn(c))
|
||||
return;
|
||||
|
||||
free(c->setup);
|
||||
|
||||
/* disallow further sends and receives */
|
||||
shutdown(c->fd, SHUT_RDWR);
|
||||
#ifdef _WIN32
|
||||
closesocket(c->fd);
|
||||
#else
|
||||
close(c->fd);
|
||||
#endif
|
||||
|
||||
pthread_mutex_destroy(&c->iolock);
|
||||
_xcb_in_destroy(&c->in);
|
||||
_xcb_out_destroy(&c->out);
|
||||
|
||||
_xcb_ext_destroy(c);
|
||||
_xcb_xid_destroy(c);
|
||||
|
||||
free(c);
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Private interface */
|
||||
|
||||
void _xcb_conn_shutdown(xcb_connection_t *c, int err)
|
||||
{
|
||||
c->has_error = err;
|
||||
}
|
||||
|
||||
/* Return connection error state.
|
||||
* To make thread-safe, I need a seperate static
|
||||
* variable for every possible error.
|
||||
* has_error is the first field in xcb_connection_t, so just
|
||||
* return a casted int here; checking has_error (and only
|
||||
* has_error) will be safe.
|
||||
*/
|
||||
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_CLOSED_INVALID_SCREEN:
|
||||
{
|
||||
return (xcb_connection_t *) &xcb_con_closed_screen_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)
|
||||
{
|
||||
int ret;
|
||||
#if USE_POLL
|
||||
struct pollfd fd;
|
||||
#else
|
||||
fd_set rfds, wfds;
|
||||
#endif
|
||||
|
||||
/* If the thing I should be doing is already being done, wait for it. */
|
||||
if(count ? c->out.writing : c->in.reading)
|
||||
{
|
||||
pthread_cond_wait(cond, &c->iolock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if USE_POLL
|
||||
memset(&fd, 0, sizeof(fd));
|
||||
fd.fd = c->fd;
|
||||
fd.events = POLLIN;
|
||||
#else
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(c->fd, &rfds);
|
||||
#endif
|
||||
++c->in.reading;
|
||||
|
||||
#if USE_POLL
|
||||
if(count)
|
||||
{
|
||||
fd.events |= POLLOUT;
|
||||
++c->out.writing;
|
||||
}
|
||||
#else
|
||||
FD_ZERO(&wfds);
|
||||
if(count)
|
||||
{
|
||||
FD_SET(c->fd, &wfds);
|
||||
++c->out.writing;
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
do {
|
||||
#if USE_POLL
|
||||
ret = poll(&fd, 1, -1);
|
||||
/* If poll() returns an event we didn't expect, such as POLLNVAL, treat
|
||||
* it as if it failed. */
|
||||
if(ret >= 0 && (fd.revents & ~fd.events))
|
||||
{
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
|
||||
#endif
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if(ret < 0)
|
||||
{
|
||||
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||
ret = 0;
|
||||
}
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
/* The code allows two threads to call select()/poll() at the same time.
|
||||
* First thread just wants to read, a second thread wants to write, too.
|
||||
* We have to make sure that we don't steal the reading thread's reply
|
||||
* and let it get stuck in select()/poll().
|
||||
* So a thread may read if either:
|
||||
* - There is no other thread that wants to read (the above situation
|
||||
* did not occur).
|
||||
* - It is the reading thread (above situation occurred).
|
||||
*/
|
||||
int may_read = c->in.reading == 1 || !count;
|
||||
#if USE_POLL
|
||||
if(may_read && (fd.revents & POLLIN) != 0)
|
||||
#else
|
||||
if(may_read && FD_ISSET(c->fd, &rfds))
|
||||
#endif
|
||||
ret = ret && _xcb_in_read(c);
|
||||
|
||||
#if USE_POLL
|
||||
if((fd.revents & POLLOUT) != 0)
|
||||
#else
|
||||
if(FD_ISSET(c->fd, &wfds))
|
||||
#endif
|
||||
ret = ret && write_vec(c, vector, count);
|
||||
}
|
||||
|
||||
if(count)
|
||||
--c->out.writing;
|
||||
--c->in.reading;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t xcb_total_read(xcb_connection_t *c)
|
||||
{
|
||||
uint64_t n;
|
||||
|
||||
if (xcb_connection_has_error(c))
|
||||
return 0;
|
||||
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
n = c->in.total_read;
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return n;
|
||||
}
|
||||
|
||||
uint64_t xcb_total_written(xcb_connection_t *c)
|
||||
{
|
||||
uint64_t n;
|
||||
|
||||
if (xcb_connection_has_error(c))
|
||||
return 0;
|
||||
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
n = c->out.total_written;
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
|
||||
return n;
|
||||
}
|
131
dist/libxcb/src/xcb_ext.c
vendored
Normal file
131
dist/libxcb/src/xcb_ext.c
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* A cache for QueryExtension results. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xcb.h"
|
||||
#include "xcbext.h"
|
||||
#include "xcbint.h"
|
||||
|
||||
typedef struct lazyreply {
|
||||
enum lazy_reply_tag tag;
|
||||
union {
|
||||
xcb_query_extension_cookie_t cookie;
|
||||
xcb_query_extension_reply_t *reply;
|
||||
} value;
|
||||
} lazyreply;
|
||||
|
||||
static lazyreply *get_index(xcb_connection_t *c, int idx)
|
||||
{
|
||||
if(idx > c->ext.extensions_size)
|
||||
{
|
||||
int new_size = idx << 1;
|
||||
lazyreply *new_extensions = realloc(c->ext.extensions, sizeof(lazyreply) * new_size);
|
||||
if(!new_extensions)
|
||||
return 0;
|
||||
memset(new_extensions + c->ext.extensions_size, 0, sizeof(lazyreply) * (new_size - c->ext.extensions_size));
|
||||
c->ext.extensions = new_extensions;
|
||||
c->ext.extensions_size = new_size;
|
||||
}
|
||||
return c->ext.extensions + idx - 1;
|
||||
}
|
||||
|
||||
static lazyreply *get_lazyreply(xcb_connection_t *c, xcb_extension_t *ext)
|
||||
{
|
||||
static pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int next_global_id;
|
||||
|
||||
lazyreply *data;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if(!ext->global_id)
|
||||
ext->global_id = ++next_global_id;
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
data = get_index(c, ext->global_id);
|
||||
if(data && data->tag == LAZY_NONE)
|
||||
{
|
||||
/* cache miss: query the server */
|
||||
data->tag = LAZY_COOKIE;
|
||||
data->value.cookie = xcb_query_extension(c, strlen(ext->name), ext->name);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Public interface */
|
||||
|
||||
/* Do not free the returned xcb_query_extension_reply_t - on return, it's aliased
|
||||
* from the cache. */
|
||||
const xcb_query_extension_reply_t *xcb_get_extension_data(xcb_connection_t *c, xcb_extension_t *ext)
|
||||
{
|
||||
lazyreply *data;
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
|
||||
pthread_mutex_lock(&c->ext.lock);
|
||||
data = get_lazyreply(c, ext);
|
||||
if(data && data->tag == LAZY_COOKIE)
|
||||
{
|
||||
data->tag = LAZY_FORCED;
|
||||
data->value.reply = xcb_query_extension_reply(c, data->value.cookie, 0);
|
||||
}
|
||||
pthread_mutex_unlock(&c->ext.lock);
|
||||
|
||||
return data ? data->value.reply : 0;
|
||||
}
|
||||
|
||||
void xcb_prefetch_extension_data(xcb_connection_t *c, xcb_extension_t *ext)
|
||||
{
|
||||
if(c->has_error)
|
||||
return;
|
||||
pthread_mutex_lock(&c->ext.lock);
|
||||
get_lazyreply(c, ext);
|
||||
pthread_mutex_unlock(&c->ext.lock);
|
||||
}
|
||||
|
||||
/* Private interface */
|
||||
|
||||
int _xcb_ext_init(xcb_connection_t *c)
|
||||
{
|
||||
if(pthread_mutex_init(&c->ext.lock, 0))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _xcb_ext_destroy(xcb_connection_t *c)
|
||||
{
|
||||
pthread_mutex_destroy(&c->ext.lock);
|
||||
while(c->ext.extensions_size-- > 0)
|
||||
if(c->ext.extensions[c->ext.extensions_size].tag == LAZY_FORCED)
|
||||
free(c->ext.extensions[c->ext.extensions_size].value.reply);
|
||||
free(c->ext.extensions);
|
||||
}
|
1096
dist/libxcb/src/xcb_in.c
vendored
Normal file
1096
dist/libxcb/src/xcb_in.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
105
dist/libxcb/src/xcb_list.c
vendored
Normal file
105
dist/libxcb/src/xcb_list.c
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* A generic implementation of a list of void-pointers. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xcb.h"
|
||||
#include "xcbint.h"
|
||||
|
||||
typedef struct node {
|
||||
struct node *next;
|
||||
uint64_t key;
|
||||
void *data;
|
||||
} node;
|
||||
|
||||
struct _xcb_map {
|
||||
node *head;
|
||||
node **tail;
|
||||
};
|
||||
|
||||
/* Private interface */
|
||||
|
||||
_xcb_map *_xcb_map_new(void)
|
||||
{
|
||||
_xcb_map *list;
|
||||
list = malloc(sizeof(_xcb_map));
|
||||
if(!list)
|
||||
return 0;
|
||||
list->head = 0;
|
||||
list->tail = &list->head;
|
||||
return list;
|
||||
}
|
||||
|
||||
void _xcb_map_delete(_xcb_map *list, xcb_list_free_func_t do_free)
|
||||
{
|
||||
if(!list)
|
||||
return;
|
||||
while(list->head)
|
||||
{
|
||||
node *cur = list->head;
|
||||
if(do_free)
|
||||
do_free(cur->data);
|
||||
list->head = cur->next;
|
||||
free(cur);
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
|
||||
int _xcb_map_put(_xcb_map *list, uint64_t key, void *data)
|
||||
{
|
||||
node *cur = malloc(sizeof(node));
|
||||
if(!cur)
|
||||
return 0;
|
||||
cur->key = key;
|
||||
cur->data = data;
|
||||
cur->next = 0;
|
||||
*list->tail = cur;
|
||||
list->tail = &cur->next;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *_xcb_map_remove(_xcb_map *list, uint64_t key)
|
||||
{
|
||||
node **cur;
|
||||
for(cur = &list->head; *cur; cur = &(*cur)->next)
|
||||
if((*cur)->key == key)
|
||||
{
|
||||
node *tmp = *cur;
|
||||
void *ret = (*cur)->data;
|
||||
*cur = (*cur)->next;
|
||||
if(!*cur)
|
||||
list->tail = cur;
|
||||
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
501
dist/libxcb/src/xcb_out.c
vendored
Normal file
501
dist/libxcb/src/xcb_out.c
vendored
Normal file
|
@ -0,0 +1,501 @@
|
|||
/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Stuff that sends stuff to the server. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "xcb.h"
|
||||
#include "xcbext.h"
|
||||
#include "xcbint.h"
|
||||
#include "bigreq.h"
|
||||
|
||||
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);
|
||||
c->out.queue_len += vector[0].iov_len;
|
||||
vector[0].iov_base = (char *) vector[0].iov_base + vector[0].iov_len;
|
||||
vector[0].iov_len = 0;
|
||||
++vector, --count;
|
||||
}
|
||||
if(!count)
|
||||
return;
|
||||
|
||||
--vector, ++count;
|
||||
vector[0].iov_base = c->out.queue;
|
||||
vector[0].iov_len = c->out.queue_len;
|
||||
c->out.queue_len = 0;
|
||||
_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)
|
||||
{
|
||||
while(c->out.return_socket && c->out.socket_moving)
|
||||
pthread_cond_wait(&c->out.socket_cond, &c->iolock);
|
||||
if(!c->out.return_socket)
|
||||
return;
|
||||
|
||||
c->out.socket_moving = 1;
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
c->out.return_socket(c->out.socket_closure);
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
c->out.socket_moving = 0;
|
||||
|
||||
pthread_cond_broadcast(&c->out.socket_cond);
|
||||
c->out.return_socket = 0;
|
||||
c->out.socket_closure = 0;
|
||||
_xcb_in_replies_done(c);
|
||||
}
|
||||
|
||||
static void prepare_socket_request(xcb_connection_t *c)
|
||||
{
|
||||
/* We're about to append data to out.queue, so we need to
|
||||
* atomically test for an external socket owner *and* some other
|
||||
* thread currently writing.
|
||||
*
|
||||
* If we have an external socket owner, we have to get the socket back
|
||||
* before we can use it again.
|
||||
*
|
||||
* If some other thread is writing to the socket, we assume it's
|
||||
* writing from out.queue, and so we can't stick data there.
|
||||
*
|
||||
* We satisfy this condition by first calling get_socket_back
|
||||
* (which may drop the lock, but will return when XCB owns the
|
||||
* socket again) and then checking for another writing thread and
|
||||
* escaping the loop if we're ready to go.
|
||||
*/
|
||||
for (;;) {
|
||||
if(c->has_error)
|
||||
return;
|
||||
get_socket_back(c);
|
||||
if (!c->out.writing)
|
||||
break;
|
||||
pthread_cond_wait(&c->out.cond, &c->iolock);
|
||||
}
|
||||
}
|
||||
|
||||
/* Public interface */
|
||||
|
||||
void xcb_prefetch_maximum_request_length(xcb_connection_t *c)
|
||||
{
|
||||
if(c->has_error)
|
||||
return;
|
||||
pthread_mutex_lock(&c->out.reqlenlock);
|
||||
if(c->out.maximum_request_length_tag == LAZY_NONE)
|
||||
{
|
||||
const xcb_query_extension_reply_t *ext;
|
||||
ext = xcb_get_extension_data(c, &xcb_big_requests_id);
|
||||
if(ext && ext->present)
|
||||
{
|
||||
c->out.maximum_request_length_tag = LAZY_COOKIE;
|
||||
c->out.maximum_request_length.cookie = xcb_big_requests_enable(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
c->out.maximum_request_length_tag = LAZY_FORCED;
|
||||
c->out.maximum_request_length.value = c->setup->maximum_request_length;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&c->out.reqlenlock);
|
||||
}
|
||||
|
||||
uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
|
||||
{
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
xcb_prefetch_maximum_request_length(c);
|
||||
pthread_mutex_lock(&c->out.reqlenlock);
|
||||
if(c->out.maximum_request_length_tag == LAZY_COOKIE)
|
||||
{
|
||||
xcb_big_requests_enable_reply_t *r = xcb_big_requests_enable_reply(c, c->out.maximum_request_length.cookie, 0);
|
||||
c->out.maximum_request_length_tag = LAZY_FORCED;
|
||||
if(r)
|
||||
{
|
||||
c->out.maximum_request_length.value = r->maximum_request_length;
|
||||
free(r);
|
||||
}
|
||||
else
|
||||
c->out.maximum_request_length.value = c->setup->maximum_request_length;
|
||||
}
|
||||
pthread_mutex_unlock(&c->out.reqlenlock);
|
||||
return c->out.maximum_request_length.value;
|
||||
}
|
||||
|
||||
static void close_fds(int *fds, unsigned int num_fds)
|
||||
{
|
||||
for (unsigned int index = 0; index < num_fds; index++)
|
||||
close(fds[index]);
|
||||
}
|
||||
|
||||
static void send_fds(xcb_connection_t *c, int *fds, unsigned int num_fds)
|
||||
{
|
||||
#if HAVE_SENDMSG
|
||||
/* Calling _xcb_out_flush_to() can drop the iolock and wait on a condition
|
||||
* variable if another thread is currently writing (c->out.writing > 0).
|
||||
* This call waits for writers to be done and thus _xcb_out_flush_to() will
|
||||
* do the work itself (in which case we are a writer and
|
||||
* prepare_socket_request() will wait for us to be done if another threads
|
||||
* tries to send fds, too). Thanks to this, we can atomically write out FDs.
|
||||
*/
|
||||
prepare_socket_request(c);
|
||||
|
||||
while (num_fds > 0) {
|
||||
while (c->out.out_fd.nfd == XCB_MAX_PASS_FD && !c->has_error) {
|
||||
/* XXX: if c->out.writing > 0, this releases the iolock and
|
||||
* potentially allows other threads to interfere with their own fds.
|
||||
*/
|
||||
_xcb_out_flush_to(c, c->out.request);
|
||||
|
||||
if (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
|
||||
/* We need some request to send FDs with */
|
||||
_xcb_out_send_sync(c);
|
||||
}
|
||||
}
|
||||
if (c->has_error)
|
||||
break;
|
||||
|
||||
c->out.out_fd.fd[c->out.out_fd.nfd++] = fds[0];
|
||||
fds++;
|
||||
num_fds--;
|
||||
}
|
||||
#endif
|
||||
close_fds(fds, num_fds);
|
||||
}
|
||||
|
||||
uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iovec *vector,
|
||||
const xcb_protocol_request_t *req, unsigned int num_fds, int *fds)
|
||||
{
|
||||
uint64_t request;
|
||||
uint32_t prefix[2];
|
||||
int veclen = req->count;
|
||||
enum workarounds workaround = WORKAROUND_NONE;
|
||||
|
||||
if(c->has_error) {
|
||||
close_fds(fds, num_fds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(c != 0);
|
||||
assert(vector != 0);
|
||||
assert(req->count > 0);
|
||||
|
||||
if(!(flags & XCB_REQUEST_RAW))
|
||||
{
|
||||
static const char pad[3];
|
||||
unsigned int i;
|
||||
uint16_t shortlen = 0;
|
||||
size_t longlen = 0;
|
||||
assert(vector[0].iov_len >= 4);
|
||||
/* set the major opcode, and the minor opcode for extensions */
|
||||
if(req->ext)
|
||||
{
|
||||
const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
|
||||
if(!(extension && extension->present))
|
||||
{
|
||||
close_fds(fds, num_fds);
|
||||
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
|
||||
((uint8_t *) vector[0].iov_base)[1] = req->opcode;
|
||||
}
|
||||
else
|
||||
((uint8_t *) vector[0].iov_base)[0] = req->opcode;
|
||||
|
||||
/* put together the length field, possibly using BIGREQUESTS */
|
||||
for(i = 0; i < req->count; ++i)
|
||||
{
|
||||
longlen += vector[i].iov_len;
|
||||
if(!vector[i].iov_base)
|
||||
{
|
||||
vector[i].iov_base = (char *) pad;
|
||||
assert(vector[i].iov_len <= sizeof(pad));
|
||||
}
|
||||
}
|
||||
assert((longlen & 3) == 0);
|
||||
longlen >>= 2;
|
||||
|
||||
if(longlen <= c->setup->maximum_request_length)
|
||||
{
|
||||
/* we don't need BIGREQUESTS. */
|
||||
shortlen = longlen;
|
||||
longlen = 0;
|
||||
}
|
||||
else if(longlen > xcb_get_maximum_request_length(c))
|
||||
{
|
||||
close_fds(fds, num_fds);
|
||||
_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[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;
|
||||
|
||||
/* do we need to work around the X server bug described in glx.xml? */
|
||||
/* XXX: GetFBConfigs won't use BIG-REQUESTS in any sane
|
||||
* configuration, but that should be handled here anyway. */
|
||||
if(req->ext && !req->isvoid && !strcmp(req->ext->name, "GLX") &&
|
||||
((req->opcode == 17 && ((uint32_t *) vector[0].iov_base)[1] == 0x10004) ||
|
||||
req->opcode == 21))
|
||||
workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG;
|
||||
|
||||
/* get a sequence number and arrange for delivery. */
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
|
||||
/* send FDs before establishing a good request number, because this might
|
||||
* call send_sync(), too
|
||||
*/
|
||||
send_fds(c, fds, num_fds);
|
||||
|
||||
prepare_socket_request(c);
|
||||
|
||||
/* 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
|
||||
* 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) - 2) ||
|
||||
(unsigned int) (c->out.request + 1) == 0)
|
||||
{
|
||||
send_sync(c);
|
||||
prepare_socket_request(c);
|
||||
}
|
||||
|
||||
send_request(c, req->isvoid, workaround, flags, vector, veclen);
|
||||
request = c->has_error ? 0 : c->out.request;
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return request;
|
||||
}
|
||||
|
||||
/* request number are actually uint64_t internally but keep API compat with unsigned int */
|
||||
unsigned int xcb_send_request_with_fds(xcb_connection_t *c, int flags, struct iovec *vector,
|
||||
const xcb_protocol_request_t *req, unsigned int num_fds, int *fds)
|
||||
{
|
||||
return xcb_send_request_with_fds64(c, flags, vector, req, num_fds, fds);
|
||||
}
|
||||
|
||||
uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
|
||||
{
|
||||
return xcb_send_request_with_fds64(c, flags, vector, req, 0, NULL);
|
||||
}
|
||||
|
||||
/* request number are actually uint64_t internally but keep API compat with unsigned int */
|
||||
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
|
||||
{
|
||||
return xcb_send_request64(c, flags, vector, req);
|
||||
}
|
||||
|
||||
void
|
||||
xcb_send_fd(xcb_connection_t *c, int fd)
|
||||
{
|
||||
int fds[1] = { fd };
|
||||
|
||||
if (c->has_error) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
send_fds(c, &fds[0], 1);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
}
|
||||
|
||||
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent)
|
||||
{
|
||||
int ret;
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
get_socket_back(c);
|
||||
|
||||
/* _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;
|
||||
c->out.socket_closure = closure;
|
||||
if(flags) {
|
||||
/* c->out.request + 1 will be the first request sent by the external
|
||||
* socket owner. If the socket is returned before this request is sent
|
||||
* it will be detected in _xcb_in_replies_done and this pending_reply
|
||||
* will be discarded.
|
||||
*/
|
||||
_xcb_in_expect_reply(c, c->out.request + 1, WORKAROUND_EXTERNAL_SOCKET_OWNER, flags);
|
||||
}
|
||||
assert(c->out.request == c->out.request_written);
|
||||
*sent = c->out.request;
|
||||
}
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests)
|
||||
{
|
||||
int ret;
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
c->out.request += requests;
|
||||
ret = _xcb_out_send(c, vector, count);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xcb_flush(xcb_connection_t *c)
|
||||
{
|
||||
int ret;
|
||||
if(c->has_error)
|
||||
return 0;
|
||||
pthread_mutex_lock(&c->iolock);
|
||||
ret = _xcb_out_flush_to(c, c->out.request);
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Private interface */
|
||||
|
||||
int _xcb_out_init(_xcb_out *out)
|
||||
{
|
||||
if(pthread_cond_init(&out->socket_cond, 0))
|
||||
return 0;
|
||||
out->return_socket = 0;
|
||||
out->socket_closure = 0;
|
||||
out->socket_moving = 0;
|
||||
|
||||
if(pthread_cond_init(&out->cond, 0))
|
||||
return 0;
|
||||
out->writing = 0;
|
||||
|
||||
out->queue_len = 0;
|
||||
|
||||
out->request = 0;
|
||||
out->request_written = 0;
|
||||
out->request_expected_written = 0;
|
||||
|
||||
if(pthread_mutex_init(&out->reqlenlock, 0))
|
||||
return 0;
|
||||
out->maximum_request_length_tag = LAZY_NONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _xcb_out_destroy(_xcb_out *out)
|
||||
{
|
||||
pthread_mutex_destroy(&out->reqlenlock);
|
||||
pthread_cond_destroy(&out->cond);
|
||||
pthread_cond_destroy(&out->socket_cond);
|
||||
}
|
||||
|
||||
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
|
||||
{
|
||||
int ret = 1;
|
||||
while(ret && count)
|
||||
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count);
|
||||
c->out.request_written = c->out.request;
|
||||
c->out.request_expected_written = c->in.request_expected;
|
||||
pthread_cond_broadcast(&c->out.cond);
|
||||
_xcb_in_wake_up_next_reader(c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _xcb_out_send_sync(xcb_connection_t *c)
|
||||
{
|
||||
prepare_socket_request(c);
|
||||
send_sync(c);
|
||||
}
|
||||
|
||||
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
|
||||
{
|
||||
assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));
|
||||
if(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request))
|
||||
return 1;
|
||||
if(c->out.queue_len)
|
||||
{
|
||||
struct iovec vec;
|
||||
vec.iov_base = c->out.queue;
|
||||
vec.iov_len = c->out.queue_len;
|
||||
c->out.queue_len = 0;
|
||||
return _xcb_out_send(c, &vec, 1);
|
||||
}
|
||||
while(c->out.writing)
|
||||
pthread_cond_wait(&c->out.cond, &c->iolock);
|
||||
assert(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request));
|
||||
return 1;
|
||||
}
|
557
dist/libxcb/src/xcb_util.c
vendored
Normal file
557
dist/libxcb/src/xcb_util.c
vendored
Normal file
|
@ -0,0 +1,557 @@
|
|||
/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Utility functions implementable using only public APIs. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "xcb_windefs.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#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"
|
||||
|
||||
#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
|
||||
# include <tsol/label.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LAUNCHD
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
int xcb_popcount(uint32_t mask)
|
||||
{
|
||||
uint32_t y;
|
||||
y = (mask >> 1) & 033333333333;
|
||||
y = mask - y - ((y >> 1) & 033333333333);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LAUNCHD
|
||||
/* Return true and parse if name matches <path to socket>[.<screen>]
|
||||
* Upon success:
|
||||
* host = <path to socket>
|
||||
* protocol = "unix"
|
||||
* display = 0
|
||||
* screen = <screen>
|
||||
*/
|
||||
static int _xcb_parse_display_path_to_socket(const char *name, char **host, char **protocol,
|
||||
int *displayp, int *screenp)
|
||||
{
|
||||
struct stat sbuf;
|
||||
char path[PATH_MAX];
|
||||
int _screen = 0;
|
||||
|
||||
strlcpy(path, name, sizeof(path));
|
||||
if (0 != stat(path, &sbuf)) {
|
||||
char *dot = strrchr(path, '.');
|
||||
if (!dot)
|
||||
return 0;
|
||||
*dot = '\0';
|
||||
|
||||
if (0 != stat(path, &sbuf))
|
||||
return 0;
|
||||
|
||||
_screen = atoi(dot + 1);
|
||||
}
|
||||
|
||||
if (host) {
|
||||
*host = strdup(path);
|
||||
if (!*host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (protocol) {
|
||||
*protocol = strdup("unix");
|
||||
if (!*protocol) {
|
||||
if (host)
|
||||
free(*host);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (displayp)
|
||||
*displayp = 0;
|
||||
|
||||
if (screenp)
|
||||
*screenp = _screen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _xcb_parse_display(const char *name, char **host, char **protocol,
|
||||
int *displayp, int *screenp)
|
||||
{
|
||||
int len, display, screen;
|
||||
char *slash, *colon, *dot, *end;
|
||||
|
||||
if(!name || !*name)
|
||||
name = getenv("DISPLAY");
|
||||
if(!name)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_LAUNCHD
|
||||
/* First check for <path to socket>[.<screen>] */
|
||||
if (_xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
slash = strrchr(name, '/');
|
||||
|
||||
if (slash) {
|
||||
len = slash - name;
|
||||
if (protocol) {
|
||||
*protocol = malloc(len + 1);
|
||||
if(!*protocol)
|
||||
return 0;
|
||||
memcpy(*protocol, name, len);
|
||||
(*protocol)[len] = '\0';
|
||||
}
|
||||
name = slash + 1;
|
||||
} else
|
||||
if (protocol)
|
||||
*protocol = NULL;
|
||||
|
||||
colon = strrchr(name, ':');
|
||||
if(!colon)
|
||||
goto error_out;
|
||||
len = colon - name;
|
||||
++colon;
|
||||
display = strtoul(colon, &dot, 10);
|
||||
if(dot == colon)
|
||||
goto error_out;
|
||||
if(*dot == '\0')
|
||||
screen = 0;
|
||||
else
|
||||
{
|
||||
if(*dot != '.')
|
||||
goto error_out;
|
||||
++dot;
|
||||
screen = strtoul(dot, &end, 10);
|
||||
if(end == dot || *end != '\0')
|
||||
goto error_out;
|
||||
}
|
||||
/* At this point, the display string is fully parsed and valid, but
|
||||
* the caller's memory is untouched. */
|
||||
|
||||
*host = malloc(len + 1);
|
||||
if(!*host)
|
||||
goto error_out;
|
||||
memcpy(*host, name, len);
|
||||
(*host)[len] = '\0';
|
||||
*displayp = display;
|
||||
if(screenp)
|
||||
*screenp = screen;
|
||||
return 1;
|
||||
|
||||
error_out:
|
||||
if (protocol) {
|
||||
free(*protocol);
|
||||
*protocol = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xcb_parse_display(const char *name, char **host, int *displayp,
|
||||
int *screenp)
|
||||
{
|
||||
return _xcb_parse_display(name, host, NULL, displayp, screenp);
|
||||
}
|
||||
|
||||
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);
|
||||
#endif /* !WIN32 */
|
||||
#ifdef HAVE_ABSTRACT_SOCKETS
|
||||
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
|
||||
#endif
|
||||
|
||||
static int _xcb_open(const char *host, char *protocol, const int display)
|
||||
{
|
||||
int fd;
|
||||
#ifdef __hpux
|
||||
static const char unix_base[] = "/usr/spool/sockets/X11/";
|
||||
#else
|
||||
static const char unix_base[] = "/tmp/.X11-unix/X";
|
||||
#endif
|
||||
const char *base = unix_base;
|
||||
size_t filelen;
|
||||
char *file = NULL;
|
||||
int actual_filelen;
|
||||
|
||||
/* 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
|
||||
|
||||
#ifdef HAVE_LAUNCHD
|
||||
struct stat sbuf;
|
||||
if (0 == stat(host, &sbuf)) {
|
||||
file = strdup(host);
|
||||
if(file == NULL)
|
||||
return -1;
|
||||
filelen = actual_filelen = strlen(file);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
|
||||
file = malloc(filelen);
|
||||
if(file == NULL)
|
||||
return -1;
|
||||
|
||||
/* display specifies Unix socket */
|
||||
actual_filelen = snprintf(file, filelen, "%s%d", base, display);
|
||||
}
|
||||
|
||||
if(actual_filelen < 0)
|
||||
{
|
||||
free(file);
|
||||
return -1;
|
||||
}
|
||||
/* snprintf may truncate the file */
|
||||
filelen = MIN(actual_filelen, filelen - 1);
|
||||
#ifdef HAVE_ABSTRACT_SOCKETS
|
||||
fd = _xcb_open_abstract(protocol, file, filelen);
|
||||
if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED))
|
||||
{
|
||||
free(file);
|
||||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
fd = socket(family, type | SOCK_CLOEXEC, proto);
|
||||
if (fd == -1 && errno == EINVAL)
|
||||
#endif
|
||||
{
|
||||
fd = socket(family, type, proto);
|
||||
#ifndef _WIN32
|
||||
if (fd >= 0)
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
#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
|
||||
&& strcmp("inet6",protocol)
|
||||
#endif
|
||||
)
|
||||
return -1;
|
||||
|
||||
if (*host == '\0')
|
||||
host = "localhost";
|
||||
|
||||
#if HAVE_GETADDRINFO
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
#ifdef AI_NUMERICSERV
|
||||
hints.ai_flags |= AI_NUMERICSERV;
|
||||
#endif
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
#ifdef AF_INET6
|
||||
/* Allow IPv6 addresses enclosed in brackets. */
|
||||
if(host[0] == '[' && (bracket = strrchr(host, ']')) && bracket[1] == '\0')
|
||||
{
|
||||
*bracket = '\0';
|
||||
++host;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
hints.ai_family = AF_INET6;
|
||||
}
|
||||
#endif
|
||||
|
||||
snprintf(service, sizeof(service), "%hu", port);
|
||||
if(getaddrinfo(host, service, &hints, &results))
|
||||
/* FIXME: use gai_strerror, and fill in error connection */
|
||||
return -1;
|
||||
|
||||
for(addr = results; addr; addr = addr->ai_next)
|
||||
{
|
||||
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
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;
|
||||
|
||||
#ifdef _WIN32
|
||||
closesocket(fd);
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
fd = -1;
|
||||
++_c;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static int _xcb_open_unix(char *protocol, const char *file)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
socklen_t len = sizeof(int);
|
||||
int val;
|
||||
|
||||
if (protocol && strcmp("unix",protocol))
|
||||
return -1;
|
||||
|
||||
strcpy(addr.sun_path, file);
|
||||
addr.sun_family = AF_UNIX;
|
||||
#ifdef HAVE_SOCKADDR_SUN_LEN
|
||||
addr.sun_len = SUN_LEN(&addr);
|
||||
#endif
|
||||
fd = _xcb_socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(fd == -1)
|
||||
return -1;
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) == 0 && val < 64 * 1024)
|
||||
{
|
||||
val = 64 * 1024;
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(int));
|
||||
}
|
||||
if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
#ifdef HAVE_ABSTRACT_SOCKETS
|
||||
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr = {0};
|
||||
socklen_t namelen;
|
||||
|
||||
if (protocol && strcmp("unix",protocol))
|
||||
return -1;
|
||||
|
||||
strcpy(addr.sun_path + 1, file);
|
||||
addr.sun_family = AF_UNIX;
|
||||
namelen = offsetof(struct sockaddr_un, sun_path) + 1 + filelen;
|
||||
#ifdef HAVE_SOCKADDR_SUN_LEN
|
||||
addr.sun_len = 1 + filelen;
|
||||
#endif
|
||||
fd = _xcb_socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
if (connect(fd, (struct sockaddr *) &addr, namelen) == -1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
xcb_connection_t *xcb_connect(const char *displayname, int *screenp)
|
||||
{
|
||||
return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
|
||||
}
|
||||
|
||||
xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname, xcb_auth_info_t *auth, int *screenp)
|
||||
{
|
||||
int fd, display = 0;
|
||||
char *host = NULL;
|
||||
char *protocol = NULL;
|
||||
xcb_auth_info_t ourauth;
|
||||
xcb_connection_t *c;
|
||||
|
||||
int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
|
||||
|
||||
if(!parsed) {
|
||||
c = _xcb_conn_ret_error(XCB_CONN_CLOSED_PARSE_ERR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#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_conn_ret_error(XCB_CONN_ERROR);
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(auth) {
|
||||
c = xcb_connect_to_fd(fd, auth);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(_xcb_get_auth_info(fd, &ourauth, display))
|
||||
{
|
||||
c = xcb_connect_to_fd(fd, &ourauth);
|
||||
free(ourauth.name);
|
||||
free(ourauth.data);
|
||||
}
|
||||
else
|
||||
c = xcb_connect_to_fd(fd, 0);
|
||||
|
||||
if(c->has_error)
|
||||
goto out;
|
||||
|
||||
/* Make sure requested screen number is in bounds for this server */
|
||||
if((screenp != NULL) && (*screenp >= (int) c->setup->roots_len)) {
|
||||
xcb_disconnect(c);
|
||||
c = _xcb_conn_ret_error(XCB_CONN_CLOSED_INVALID_SCREEN);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
free(host);
|
||||
free(protocol);
|
||||
return c;
|
||||
}
|
45
dist/libxcb/src/xcb_windefs.h
vendored
Normal file
45
dist/libxcb/src/xcb_windefs.h
vendored
Normal 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 */
|
101
dist/libxcb/src/xcb_xid.c
vendored
Normal file
101
dist/libxcb/src/xcb_xid.c
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* Copyright (C) 2001-2008 Bart Massey and Jamey Sharp.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* XID allocators. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "xcb.h"
|
||||
#include "xcbext.h"
|
||||
#include "xcbint.h"
|
||||
#include "xc_misc.h"
|
||||
|
||||
/* Public interface */
|
||||
|
||||
uint32_t xcb_generate_id(xcb_connection_t *c)
|
||||
{
|
||||
uint32_t ret;
|
||||
if(c->has_error)
|
||||
return -1;
|
||||
pthread_mutex_lock(&c->xid.lock);
|
||||
if(c->xid.last >= c->xid.max - c->xid.inc + 1)
|
||||
{
|
||||
xcb_xc_misc_get_xid_range_reply_t *range;
|
||||
assert(c->xid.last == c->xid.max);
|
||||
if (c->xid.last == 0) {
|
||||
/* finish setting up initial range */
|
||||
c->xid.max = c->setup->resource_id_mask;
|
||||
} else {
|
||||
/* check for extension */
|
||||
const xcb_query_extension_reply_t *xc_misc_reply =
|
||||
xcb_get_extension_data(c, &xcb_xc_misc_id);
|
||||
if (!xc_misc_reply || !xc_misc_reply->present) {
|
||||
pthread_mutex_unlock(&c->xid.lock);
|
||||
return -1;
|
||||
}
|
||||
/* get new range */
|
||||
range = xcb_xc_misc_get_xid_range_reply(c,
|
||||
xcb_xc_misc_get_xid_range(c), 0);
|
||||
/* XXX The latter disjunct is what the server returns
|
||||
when it is out of XIDs. Sweet. */
|
||||
if(!range || (range->start_id == 0 && range->count == 1))
|
||||
{
|
||||
pthread_mutex_unlock(&c->xid.lock);
|
||||
return -1;
|
||||
}
|
||||
assert(range->count > 0 && range->start_id > 0);
|
||||
c->xid.last = range->start_id;
|
||||
c->xid.max = range->start_id + (range->count - 1) * c->xid.inc;
|
||||
free(range);
|
||||
}
|
||||
} else {
|
||||
c->xid.last += c->xid.inc;
|
||||
}
|
||||
ret = c->xid.last | c->xid.base;
|
||||
pthread_mutex_unlock(&c->xid.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Private interface */
|
||||
|
||||
int _xcb_xid_init(xcb_connection_t *c)
|
||||
{
|
||||
if(pthread_mutex_init(&c->xid.lock, 0))
|
||||
return 0;
|
||||
c->xid.last = 0;
|
||||
c->xid.max = 0;
|
||||
c->xid.base = c->setup->resource_id_base;
|
||||
c->xid.inc = c->setup->resource_id_mask & -(c->setup->resource_id_mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _xcb_xid_destroy(xcb_connection_t *c)
|
||||
{
|
||||
pthread_mutex_destroy(&c->xid.lock);
|
||||
}
|
322
dist/libxcb/src/xcbext.h
vendored
Normal file
322
dist/libxcb/src/xcbext.h
vendored
Normal file
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 __XCBEXT_H
|
||||
#define __XCBEXT_H
|
||||
|
||||
#include "xcb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* xcb_ext.c */
|
||||
|
||||
struct xcb_extension_t {
|
||||
const char *name;
|
||||
int global_id;
|
||||
};
|
||||
|
||||
|
||||
/* xcb_out.c */
|
||||
|
||||
typedef struct {
|
||||
size_t count;
|
||||
xcb_extension_t *ext;
|
||||
uint8_t opcode;
|
||||
uint8_t isvoid;
|
||||
} xcb_protocol_request_t;
|
||||
|
||||
enum xcb_send_request_flags_t {
|
||||
XCB_REQUEST_CHECKED = 1 << 0,
|
||||
XCB_REQUEST_RAW = 1 << 1,
|
||||
XCB_REQUEST_DISCARD_REPLY = 1 << 2,
|
||||
XCB_REQUEST_REPLY_FDS = 1 << 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Send a request to the server.
|
||||
* @param c The connection to the X server.
|
||||
* @param flags A combination of flags from the xcb_send_request_flags_t enumeration.
|
||||
* @param vector Data to send; must have two iovecs before start for internal use.
|
||||
* @param request Information about the request to be sent.
|
||||
* @return The request's sequence number on success, 0 otherwise.
|
||||
*
|
||||
* This function sends a new request to the X server. The data of the request is
|
||||
* given as an array of @c iovecs in the @p vector argument. The length of that
|
||||
* array and the necessary management information are given in the @p request
|
||||
* argument.
|
||||
*
|
||||
* When this function returns, the request might or might not be sent already.
|
||||
* Use xcb_flush() to make sure that it really was sent.
|
||||
*
|
||||
* Please note that this function is not the preferred way for sending requests.
|
||||
* It's better to use the generated wrapper functions.
|
||||
*
|
||||
* Please note that xcb might use index -1 and -2 of the @p vector array internally,
|
||||
* so they must be valid!
|
||||
*/
|
||||
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
|
||||
|
||||
/**
|
||||
* @brief Send a request to the server.
|
||||
* @param c The connection to the X server.
|
||||
* @param flags A combination of flags from the xcb_send_request_flags_t enumeration.
|
||||
* @param vector Data to send; must have two iovecs before start for internal use.
|
||||
* @param request Information about the request to be sent.
|
||||
* @param num_fds Number of additional file descriptors to send to the server
|
||||
* @param fds Additional file descriptors that should be send to the server.
|
||||
* @return The request's sequence number on success, 0 otherwise.
|
||||
*
|
||||
* This function sends a new request to the X server. The data of the request is
|
||||
* given as an array of @c iovecs in the @p vector argument. The length of that
|
||||
* array and the necessary management information are given in the @p request
|
||||
* argument.
|
||||
*
|
||||
* If @p num_fds is non-zero, @p fds points to an array of file descriptors that
|
||||
* will be sent to the X server along with this request. After this function
|
||||
* returns, all file descriptors sent are owned by xcb and will be closed
|
||||
* eventually.
|
||||
*
|
||||
* When this function returns, the request might or might not be sent already.
|
||||
* Use xcb_flush() to make sure that it really was sent.
|
||||
*
|
||||
* Please note that this function is not the preferred way for sending requests.
|
||||
*
|
||||
* Please note that xcb might use index -1 and -2 of the @p vector array internally,
|
||||
* so they must be valid!
|
||||
*/
|
||||
unsigned int xcb_send_request_with_fds(xcb_connection_t *c, int flags, struct iovec *vector,
|
||||
const xcb_protocol_request_t *request, unsigned int num_fds, int *fds);
|
||||
|
||||
/**
|
||||
* @brief Send a request to the server, with 64-bit sequence number returned.
|
||||
* @param c The connection to the X server.
|
||||
* @param flags A combination of flags from the xcb_send_request_flags_t enumeration.
|
||||
* @param vector Data to send; must have two iovecs before start for internal use.
|
||||
* @param request Information about the request to be sent.
|
||||
* @return The request's sequence number on success, 0 otherwise.
|
||||
*
|
||||
* This function sends a new request to the X server. The data of the request is
|
||||
* given as an array of @c iovecs in the @p vector argument. The length of that
|
||||
* array and the necessary management information are given in the @p request
|
||||
* argument.
|
||||
*
|
||||
* When this function returns, the request might or might not be sent already.
|
||||
* Use xcb_flush() to make sure that it really was sent.
|
||||
*
|
||||
* Please note that this function is not the preferred way for sending requests.
|
||||
* It's better to use the generated wrapper functions.
|
||||
*
|
||||
* Please note that xcb might use index -1 and -2 of the @p vector array internally,
|
||||
* so they must be valid!
|
||||
*/
|
||||
uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
|
||||
|
||||
/**
|
||||
* @brief Send a request to the server, with 64-bit sequence number returned.
|
||||
* @param c The connection to the X server.
|
||||
* @param flags A combination of flags from the xcb_send_request_flags_t enumeration.
|
||||
* @param vector Data to send; must have two iovecs before start for internal use.
|
||||
* @param request Information about the request to be sent.
|
||||
* @param num_fds Number of additional file descriptors to send to the server
|
||||
* @param fds Additional file descriptors that should be send to the server.
|
||||
* @return The request's sequence number on success, 0 otherwise.
|
||||
*
|
||||
* This function sends a new request to the X server. The data of the request is
|
||||
* given as an array of @c iovecs in the @p vector argument. The length of that
|
||||
* array and the necessary management information are given in the @p request
|
||||
* argument.
|
||||
*
|
||||
* If @p num_fds is non-zero, @p fds points to an array of file descriptors that
|
||||
* will be sent to the X server along with this request. After this function
|
||||
* returns, all file descriptors sent are owned by xcb and will be closed
|
||||
* eventually.
|
||||
*
|
||||
* When this function returns, the request might or might not be sent already.
|
||||
* Use xcb_flush() to make sure that it really was sent.
|
||||
*
|
||||
* Please note that this function is not the preferred way for sending requests.
|
||||
* It's better to use the generated wrapper functions.
|
||||
*
|
||||
* Please note that xcb might use index -1 and -2 of the @p vector array internally,
|
||||
* so they must be valid!
|
||||
*/
|
||||
uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iovec *vector,
|
||||
const xcb_protocol_request_t *request, unsigned int num_fds, int *fds);
|
||||
|
||||
/**
|
||||
* @brief Send a file descriptor to the server in the next call to xcb_send_request.
|
||||
* @param c The connection to the X server.
|
||||
* @param fd The file descriptor to send.
|
||||
*
|
||||
* After this function returns, the file descriptor given is owned by xcb and
|
||||
* will be closed eventually.
|
||||
*
|
||||
* @deprecated This function cannot be used in a thread-safe way. Two threads
|
||||
* that run xcb_send_fd(); xcb_send_request(); could mix up their file
|
||||
* descriptors. Instead, xcb_send_request_with_fds() should be used.
|
||||
*/
|
||||
void xcb_send_fd(xcb_connection_t *c, int fd);
|
||||
|
||||
/**
|
||||
* @brief Take over the write side of the socket
|
||||
* @param c The connection to the X server.
|
||||
* @param return_socket Callback function that will be called when xcb wants
|
||||
* to use the socket again.
|
||||
* @param closure Argument to the callback function.
|
||||
* @param flags A combination of flags from the xcb_send_request_flags_t enumeration.
|
||||
* @param sent Location to the sequence number of the last sequence request.
|
||||
* Must not be NULL.
|
||||
* @return 1 on success, else 0.
|
||||
*
|
||||
* xcb_take_socket allows external code to ask XCB for permission to
|
||||
* take over the write side of the socket and send raw data with
|
||||
* xcb_writev. xcb_take_socket provides the sequence number of the last
|
||||
* 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 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.
|
||||
*
|
||||
* All replies that are generated while the socket is owned externally have
|
||||
* @p flags applied to them. For example, use XCB_REQUEST_CHECK if you don't
|
||||
* want errors to go to xcb's normal error handling, but instead having to be
|
||||
* picked up via xcb_wait_for_reply(), xcb_poll_for_reply() or
|
||||
* xcb_request_check().
|
||||
*/
|
||||
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent);
|
||||
|
||||
/**
|
||||
* @brief Send raw data to the X server.
|
||||
* @param c The connection to the X server.
|
||||
* @param vector Array of data to be sent.
|
||||
* @param count Number of entries in @p vector.
|
||||
* @param requests Number of requests that are being sent.
|
||||
* @return 1 on success, else 0.
|
||||
*
|
||||
* 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);
|
||||
|
||||
|
||||
/* xcb_in.c */
|
||||
|
||||
/**
|
||||
* @brief Wait for the reply of a given request.
|
||||
* @param c The connection to the X server.
|
||||
* @param request Sequence number of the request as returned by xcb_send_request().
|
||||
* @param e Location to store errors in, or NULL. Ignored for unchecked requests.
|
||||
*
|
||||
* Returns the reply to the given request or returns null in the event of
|
||||
* errors. Blocks until the reply or error for the request arrives, or an I/O
|
||||
* error occurs.
|
||||
*/
|
||||
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e);
|
||||
|
||||
/**
|
||||
* @brief Wait for the reply of a given request, with 64-bit sequence number
|
||||
* @param c The connection to the X server.
|
||||
* @param request 64-bit sequence number of the request as returned by xcb_send_request64().
|
||||
* @param e Location to store errors in, or NULL. Ignored for unchecked requests.
|
||||
*
|
||||
* Returns the reply to the given request or returns null in the event of
|
||||
* errors. Blocks until the reply or error for the request arrives, or an I/O
|
||||
* error occurs.
|
||||
*
|
||||
* Unlike its xcb_wait_for_reply() counterpart, the given sequence number is not
|
||||
* automatically "widened" to 64-bit.
|
||||
*/
|
||||
void *xcb_wait_for_reply64(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e);
|
||||
|
||||
/**
|
||||
* @brief Poll for the reply of a given request.
|
||||
* @param c The connection to the X server.
|
||||
* @param request Sequence number of the request as returned by xcb_send_request().
|
||||
* @param reply Location to store the reply in, must not be NULL.
|
||||
* @param error Location to store errors in, or NULL. Ignored for unchecked requests.
|
||||
* @return 1 when the reply to the request was returned, else 0.
|
||||
*
|
||||
* Checks if the reply to the given request already received. Does not block.
|
||||
*/
|
||||
int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error);
|
||||
|
||||
/**
|
||||
* @brief Poll for the reply of a given request, with 64-bit sequence number.
|
||||
* @param c The connection to the X server.
|
||||
* @param request 64-bit sequence number of the request as returned by xcb_send_request().
|
||||
* @param reply Location to store the reply in, must not be NULL.
|
||||
* @param error Location to store errors in, or NULL. Ignored for unchecked requests.
|
||||
* @return 1 when the reply to the request was returned, else 0.
|
||||
*
|
||||
* Checks if the reply to the given request already received. Does not block.
|
||||
*
|
||||
* Unlike its xcb_poll_for_reply() counterpart, the given sequence number is not
|
||||
* automatically "widened" to 64-bit.
|
||||
*/
|
||||
int xcb_poll_for_reply64(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error);
|
||||
|
||||
/**
|
||||
* @brief Don't use this, only needed by the generated code.
|
||||
* @param c The connection to the X server.
|
||||
* @param reply A reply that was received from the server
|
||||
* @param replylen The size of the reply.
|
||||
* @return Pointer to the location where received file descriptors are stored.
|
||||
*/
|
||||
int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen);
|
||||
|
||||
|
||||
/* xcb_util.c */
|
||||
|
||||
/**
|
||||
* @param mask The mask to check
|
||||
* @return The number of set bits in the mask
|
||||
*/
|
||||
int xcb_popcount(uint32_t mask);
|
||||
|
||||
/**
|
||||
* @param list The base of an array
|
||||
* @param len The length of the array
|
||||
* @return The sum of all entries in the array.
|
||||
*/
|
||||
int xcb_sumof(uint8_t *list, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
241
dist/libxcb/src/xcbint.h
vendored
Normal file
241
dist/libxcb/src/xcbint.h
vendored
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 __XCBINT_H
|
||||
#define __XCBINT_H
|
||||
|
||||
#include "bigreq.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_HAS_VISIBILITY
|
||||
#pragma GCC visibility push(hidden)
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0 /* Compatibility with older compilers. */
|
||||
#endif
|
||||
|
||||
#if __has_attribute(fallthrough)
|
||||
# define XCB_ALLOW_FALLTHRU __attribute__ ((fallthrough));
|
||||
#else
|
||||
# define XCB_ALLOW_FALLTHRU /* FALLTHRU */
|
||||
#endif
|
||||
|
||||
enum workarounds {
|
||||
WORKAROUND_NONE,
|
||||
WORKAROUND_GLX_GET_FB_CONFIGS_BUG,
|
||||
WORKAROUND_EXTERNAL_SOCKET_OWNER
|
||||
};
|
||||
|
||||
enum lazy_reply_tag
|
||||
{
|
||||
LAZY_NONE = 0,
|
||||
LAZY_COOKIE,
|
||||
LAZY_FORCED
|
||||
};
|
||||
|
||||
#define XCB_PAD(i) (-(i) & 3)
|
||||
|
||||
#define XCB_SEQUENCE_COMPARE(a,op,b) ((int64_t) ((a) - (b)) op 0)
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type,member) ((size_t) &((type *)0)->member)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#define container_of(pointer,type,member) ((type *)(((char *)(pointer)) - offsetof(type, member)))
|
||||
|
||||
/* xcb_list.c */
|
||||
|
||||
typedef void (*xcb_list_free_func_t)(void *);
|
||||
|
||||
typedef struct _xcb_map _xcb_map;
|
||||
|
||||
_xcb_map *_xcb_map_new(void);
|
||||
void _xcb_map_delete(_xcb_map *q, xcb_list_free_func_t do_free);
|
||||
int _xcb_map_put(_xcb_map *q, uint64_t key, void *data);
|
||||
void *_xcb_map_remove(_xcb_map *q, uint64_t key);
|
||||
|
||||
|
||||
/* xcb_out.c */
|
||||
|
||||
#if HAVE_SENDMSG
|
||||
#define XCB_MAX_PASS_FD 16
|
||||
|
||||
typedef struct _xcb_fd {
|
||||
int fd[XCB_MAX_PASS_FD];
|
||||
int nfd;
|
||||
int ifd;
|
||||
} _xcb_fd;
|
||||
#endif
|
||||
|
||||
typedef struct _xcb_out {
|
||||
pthread_cond_t cond;
|
||||
int writing;
|
||||
|
||||
pthread_cond_t socket_cond;
|
||||
void (*return_socket)(void *closure);
|
||||
void *socket_closure;
|
||||
int socket_moving;
|
||||
|
||||
char queue[XCB_QUEUE_BUFFER_SIZE];
|
||||
int queue_len;
|
||||
|
||||
uint64_t request;
|
||||
uint64_t request_written;
|
||||
uint64_t request_expected_written;
|
||||
uint64_t total_written;
|
||||
|
||||
pthread_mutex_t reqlenlock;
|
||||
enum lazy_reply_tag maximum_request_length_tag;
|
||||
union {
|
||||
xcb_big_requests_enable_cookie_t cookie;
|
||||
uint32_t value;
|
||||
} maximum_request_length;
|
||||
#if HAVE_SENDMSG
|
||||
_xcb_fd out_fd;
|
||||
#endif
|
||||
} _xcb_out;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/* xcb_in.c */
|
||||
|
||||
typedef struct _xcb_in {
|
||||
pthread_cond_t event_cond;
|
||||
int reading;
|
||||
|
||||
char queue[4096];
|
||||
int queue_len;
|
||||
|
||||
uint64_t request_expected;
|
||||
uint64_t request_read;
|
||||
uint64_t request_completed;
|
||||
uint64_t total_read;
|
||||
struct reply_list *current_reply;
|
||||
struct reply_list **current_reply_tail;
|
||||
|
||||
_xcb_map *replies;
|
||||
struct event_list *events;
|
||||
struct event_list **events_tail;
|
||||
struct reader_list *readers;
|
||||
struct special_list *special_waiters;
|
||||
|
||||
struct pending_reply *pending_replies;
|
||||
struct pending_reply **pending_replies_tail;
|
||||
#if HAVE_SENDMSG
|
||||
_xcb_fd in_fd;
|
||||
#endif
|
||||
struct xcb_special_event *special_events;
|
||||
} _xcb_in;
|
||||
|
||||
int _xcb_in_init(_xcb_in *in);
|
||||
void _xcb_in_destroy(_xcb_in *in);
|
||||
|
||||
void _xcb_in_wake_up_next_reader(xcb_connection_t *c);
|
||||
|
||||
int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds workaround, int flags);
|
||||
void _xcb_in_replies_done(xcb_connection_t *c);
|
||||
|
||||
int _xcb_in_read(xcb_connection_t *c);
|
||||
int _xcb_in_read_block(xcb_connection_t *c, void *buf, int nread);
|
||||
|
||||
|
||||
/* xcb_xid.c */
|
||||
|
||||
typedef struct _xcb_xid {
|
||||
pthread_mutex_t lock;
|
||||
uint32_t last;
|
||||
uint32_t base;
|
||||
uint32_t max;
|
||||
uint32_t inc;
|
||||
} _xcb_xid;
|
||||
|
||||
int _xcb_xid_init(xcb_connection_t *c);
|
||||
void _xcb_xid_destroy(xcb_connection_t *c);
|
||||
|
||||
|
||||
/* xcb_ext.c */
|
||||
|
||||
typedef struct _xcb_ext {
|
||||
pthread_mutex_t lock;
|
||||
struct lazyreply *extensions;
|
||||
int extensions_size;
|
||||
} _xcb_ext;
|
||||
|
||||
int _xcb_ext_init(xcb_connection_t *c);
|
||||
void _xcb_ext_destroy(xcb_connection_t *c);
|
||||
|
||||
|
||||
/* xcb_conn.c */
|
||||
|
||||
struct xcb_connection_t {
|
||||
/* This must be the first field; see _xcb_conn_ret_error(). */
|
||||
int has_error;
|
||||
|
||||
/* constant data */
|
||||
xcb_setup_t *setup;
|
||||
int fd;
|
||||
|
||||
/* I/O data */
|
||||
pthread_mutex_t iolock;
|
||||
_xcb_in in;
|
||||
_xcb_out out;
|
||||
|
||||
/* misc data */
|
||||
_xcb_ext ext;
|
||||
_xcb_xid xid;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/* xcb_auth.c */
|
||||
|
||||
int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display);
|
||||
|
||||
#ifdef GCC_HAS_VISIBILITY
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue