Compare commits
338 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
93e6da2e2e | ||
|
6a7661f60a | ||
|
daf2c53976 | ||
|
021e887de9 | ||
|
124690ba63 | ||
|
ebea71700f | ||
|
622152ee42 | ||
|
4574ab269b | ||
|
b78d304531 | ||
|
389f22d1cb | ||
|
86a478032b | ||
|
c268499c30 | ||
|
c671b9b30a | ||
|
3c946010c8 | ||
|
02a7bbed39 | ||
|
18c3f055e7 | ||
|
453115f7ee | ||
|
f11691a098 | ||
|
cc4b93c9cd | ||
|
1519334652 | ||
|
038636786a | ||
|
8935793f1f | ||
|
095255531b | ||
|
ccdef1a8a5 | ||
|
18e109d755 | ||
|
fd04ab24a5 | ||
|
4d1a578dd5 | ||
|
e2a3e80eb8 | ||
|
3333d5bde8 | ||
|
973b510e95 | ||
|
cb8c70f5a6 | ||
|
33f3dbe369 | ||
|
c9513aac2d | ||
|
06e1ef43bb | ||
|
d53ad60d77 | ||
|
e2ee5aabe9 | ||
|
9dcb081708 | ||
|
7d798d3ccb | ||
|
7071b4a13c | ||
|
ee60239b73 | ||
|
3123dfe723 | ||
|
816407655f | ||
|
c2c4a2cd19 | ||
|
ddafdba11f | ||
|
43fbf03e54 | ||
|
233d7b7f1f | ||
|
dc28118747 | ||
|
26396bf156 | ||
|
a503167f75 | ||
|
3c76c0579f | ||
|
bdc3f21a52 | ||
|
068af21cb3 | ||
|
4d678b162b | ||
|
21414e7c44 | ||
|
4b0d9d3868 | ||
|
cd0fba98a2 | ||
|
2ef8655987 | ||
|
4cbcac4eca | ||
|
f01f3c378e | ||
|
704e0a91b1 | ||
|
4b40b44cb6 | ||
|
78c492deaa | ||
|
8f7e4c4e9f | ||
|
f9f4b00aad | ||
|
59e271e15b | ||
|
21324989b7 | ||
|
656c08c542 | ||
|
be1745c8eb | ||
|
58f37377c8 | ||
|
7bac366953 | ||
|
02ff3eadf4 | ||
|
542befe40a | ||
|
8287ebd7b7 | ||
|
bbda345a71 | ||
|
7e0f166579 | ||
|
a3e9821bec | ||
|
c7aa4e682f | ||
|
d10194a321 | ||
|
fad81b6342 | ||
|
f830eb93c9 | ||
|
ee9dfc9a76 | ||
|
0c2c5d50f8 | ||
|
9bce1f72e3 | ||
|
65b298c7ca | ||
|
32a9084546 | ||
|
8740a288ca | ||
|
d34785a34f | ||
|
b11fca06f7 | ||
|
095353ff1a | ||
|
b3516102b4 | ||
|
c03388ff9e | ||
|
7758257567 | ||
|
32a2189183 | ||
|
6e0378ebbf | ||
|
4033d39d4d | ||
|
b15c96f950 | ||
|
c5d923d8ff | ||
|
5b40681c88 | ||
|
f85661c3bc | ||
|
8584c0e095 | ||
|
658fb4a5f0 | ||
|
b15aa6bd4e | ||
|
cc04cfb41b | ||
|
25f9e7e45a | ||
|
bbdf1d133f | ||
|
ff6cb3913b | ||
|
cb621341a6 | ||
|
c49aa98594 | ||
|
a90be9955d | ||
|
f9f925107e | ||
|
17f9bda6c2 | ||
|
c65005e9d0 | ||
|
6872e92582 | ||
|
8bf8b62316 | ||
|
ec435aebd6 | ||
|
89498d1d45 | ||
|
2871d4b1b8 | ||
|
30976e5255 | ||
|
0ab52cbcc6 | ||
|
80341d5df3 | ||
|
86ea6645d9 | ||
|
70d32ce7d8 | ||
|
12d23b934f | ||
|
1b37d6ad3a | ||
|
e3ec1f7463 | ||
|
5353c0216e | ||
|
c6f3fb2529 | ||
|
912cd97a6d | ||
|
422458b663 | ||
|
b1e4a3bbd8 | ||
|
6234225b4b | ||
|
18ff453edd | ||
|
d905b88618 | ||
|
17f6e04493 | ||
|
51a0d57acc | ||
|
4a915c0dba | ||
|
fda1fb4ed4 | ||
|
265d38882c | ||
|
bbca7b82f8 | ||
|
fdb291b414 | ||
|
a7c75be5b1 | ||
|
277ea629de | ||
|
382d306d6c | ||
|
d74d066949 | ||
|
b0e6c2de09 | ||
|
c4e40f646b | ||
|
355d4d6ab9 | ||
|
966fba6ba4 | ||
|
a5e90ae6a1 | ||
|
529e3bfc20 | ||
|
74f552c1b3 | ||
|
23f57ac8bf | ||
|
7f07b57be5 | ||
|
d1e8ec96fc | ||
|
c5c6cfa4d2 | ||
|
70ea5da64b | ||
|
7e6af51b4e | ||
|
8221d249b7 | ||
|
e3c728ee3d | ||
|
cae2e39856 | ||
|
bfbf83b1d8 | ||
|
285d566a5c | ||
|
285838cfe4 | ||
|
49a61c8b45 | ||
|
125135452a | ||
|
bc5a104754 | ||
|
72e45969ff | ||
|
d978a4f69b | ||
|
29e419c584 | ||
|
be0fe56c3b | ||
|
e2813e1cde | ||
|
32de4c4213 | ||
|
1f6cd9f1fc | ||
|
cb686b5767 | ||
|
2fb14e5883 | ||
|
4dcbfd77b7 | ||
|
d84dd752ef | ||
|
4ffa6f83b9 | ||
|
d7eb0bdf3b | ||
|
e4061b8f00 | ||
|
3cdd524cad | ||
|
c056adcd92 | ||
|
412928f113 | ||
|
9ba6aa759e | ||
|
942eabaae3 | ||
|
517cb0e888 | ||
|
0a17b61a89 | ||
|
414b1037c5 | ||
|
c4f2c70bc3 | ||
|
e7263931af | ||
|
3b72a2c9d1 | ||
|
010872f611 | ||
|
f653464554 | ||
|
9c2a6dc20c | ||
|
ea4406a8e0 | ||
|
a1299eb2a2 | ||
|
b30b11ac49 | ||
|
ce5395eb46 | ||
|
18f0afab3f | ||
|
5d1dbb468b | ||
|
c7c5b710f2 | ||
|
e8663a9358 | ||
|
af8067cbf4 | ||
|
83f28ef865 | ||
|
cca6074090 | ||
|
7a9373078e | ||
|
93d733e85d | ||
|
79019541e7 | ||
|
7983bf0fbd | ||
|
7b53fb0f9b | ||
|
98c227a222 | ||
|
d04a4a03a9 | ||
|
f4d5b84800 | ||
|
e4e0c6eec8 | ||
|
f1405d9fe4 | ||
|
ac47e0ecdb | ||
|
c52f2891b4 | ||
|
a8d11c36ed | ||
|
cbe54c97b3 | ||
|
6746ab1549 | ||
|
b6d8c8fe61 | ||
|
e3b34ad346 | ||
|
50fb3a6312 | ||
|
dd01db570c | ||
|
0289348f2c | ||
|
b9efd2a09a | ||
|
5648ddd2b9 | ||
|
cb51f271b2 | ||
|
bc6a4f557f | ||
|
45619dc71e | ||
|
a1e67b141a | ||
|
8b6bb1a719 | ||
|
9ae84ad187 | ||
|
1b33867fa9 | ||
|
e602b653c1 | ||
|
6b6044cb8a | ||
|
0dd8f8d26a | ||
|
76a2166de9 | ||
|
9db4517c87 | ||
|
4ffe54f690 | ||
|
4f52f884f4 | ||
|
23911a707b | ||
|
c16cc5467e | ||
|
08cc068ead | ||
|
ff53285ae3 | ||
|
90889794ad | ||
|
b52790e8ed | ||
|
ed93a6a2a8 | ||
|
c3deeaf714 | ||
|
5f8f2ba1c4 | ||
|
71a295082e | ||
|
df217bf7c9 | ||
|
a4417b1611 | ||
|
cc7fab2d5e | ||
|
ea71d7d7e3 | ||
|
57a62e99b1 | ||
|
236f914ea7 | ||
|
9061ee45b8 | ||
|
7d235c62f0 | ||
|
f7bd139616 | ||
|
68d30adde9 | ||
|
87b7bf875e | ||
|
6db1a2686f | ||
|
da1d15082b | ||
|
b95b33e8c0 | ||
|
31b57676e8 | ||
|
0e9246def5 | ||
|
4aa7a2c849 | ||
|
769acff0da | ||
|
9b4d6f30a3 | ||
|
5ceeaaa429 | ||
|
b12038e9ae | ||
|
163c47bdc0 | ||
|
aa02096b8e | ||
|
4f25ee1644 | ||
|
662ad589c5 | ||
|
294c9f455c | ||
|
e300ee4920 | ||
|
527df3c84b | ||
|
b64cd0df88 | ||
|
b027922ebf | ||
|
82b1f3919a | ||
|
42c4adeff4 | ||
|
4b502dd696 | ||
|
7131d5d070 | ||
|
70976d87f1 | ||
|
3678159e4e | ||
|
2415c11dec | ||
|
29a974f212 | ||
|
131e867fca | ||
|
1469e87965 | ||
|
6310475e23 | ||
|
29ab5aeb9b | ||
|
2edfd5c375 | ||
|
8c3325f8bb | ||
|
c2e0236462 | ||
|
9efced72a3 | ||
|
3c58136971 | ||
|
69b78ced1a | ||
|
8ecd754b16 | ||
|
5755582444 | ||
|
ed37b08751 | ||
|
6c8b539c2a | ||
|
3a74b5e7a1 | ||
|
ee1bc1d28a | ||
|
b672d1514c | ||
|
29cca33b90 | ||
|
8c1d2021ca | ||
|
28a71c6567 | ||
|
a22909c0f5 | ||
|
1c4717de36 | ||
|
03bcccb132 | ||
|
28d3925800 | ||
|
f0565e8f06 | ||
|
20da10490f | ||
|
7f5cfcc2fd | ||
|
2040f10a4e | ||
|
5e8a7ade2d | ||
|
b89f634ff9 | ||
|
22e1013131 | ||
|
fe0e32b5fa | ||
|
77b594f958 | ||
|
b187f029d6 | ||
|
a700eeb502 | ||
|
1c590d5a86 | ||
|
566ae9baee | ||
|
4e665e1580 | ||
|
d003145609 | ||
|
86704124b1 | ||
|
80322d1163 | ||
|
8c2707773b | ||
|
2dcf8b025b | ||
|
56962e42a5 | ||
|
0e0c80e749 | ||
|
e8009194c9 | ||
|
d302f1e9b1 | ||
|
36c9a985aa | ||
|
bce72f63d2 |
|
@ -0,0 +1,3 @@
|
||||||
|
begin-language: "Autoconf-without-aclocal-m4"
|
||||||
|
args: --cache=build-aux
|
||||||
|
end-language: "Autoconf-without-aclocal-m4"
|
|
@ -1,30 +1,28 @@
|
||||||
aclocal.m4
|
*.la
|
||||||
autom4te.cache
|
|
||||||
compile
|
|
||||||
depcomp
|
|
||||||
install-sh
|
|
||||||
libtool
|
|
||||||
ltmain.sh
|
|
||||||
missing
|
|
||||||
mkinstalldirs
|
|
||||||
config.guess
|
|
||||||
config.h
|
|
||||||
config.h.in
|
|
||||||
config.log
|
|
||||||
config.status
|
|
||||||
config.sub
|
|
||||||
configure
|
|
||||||
configure.lineno
|
|
||||||
.deps
|
|
||||||
.dirstamp
|
|
||||||
.libs
|
|
||||||
*.lo
|
*.lo
|
||||||
*.loT
|
*.loT
|
||||||
*.la
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
stamp-h1
|
|
||||||
*.o
|
*.o
|
||||||
*.pc
|
*.pc
|
||||||
*.tar.bz2
|
*.tar.bz2
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
.deps
|
||||||
|
.dirstamp
|
||||||
|
.libs
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
build-aux
|
||||||
|
config.h*
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure
|
||||||
|
configure.lineno
|
||||||
|
libtool
|
||||||
|
m4/l*.m4
|
||||||
|
mkinstalldirs
|
||||||
|
stamp-h1
|
||||||
|
ChangeLog
|
||||||
|
INSTALL
|
||||||
|
check-pc-requires.log
|
||||||
|
check-pc-requires.trs
|
||||||
|
test-suite.log
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0 filetype=yaml:
|
||||||
|
#
|
||||||
|
# This CI uses the freedesktop.org ci-templates.
|
||||||
|
# Please see the ci-templates documentation for details:
|
||||||
|
# https://freedesktop.pages.freedesktop.org/ci-templates/
|
||||||
|
|
||||||
|
.templates_sha: &template_sha b791bd48996e3ced9ca13f1c5ee82be8540b8adb # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||||
|
|
||||||
|
|
||||||
|
include:
|
||||||
|
# Arch container builder template
|
||||||
|
- project: 'freedesktop/ci-templates'
|
||||||
|
ref: *template_sha
|
||||||
|
file: '/templates/arch.yml'
|
||||||
|
- project: 'freedesktop/ci-templates'
|
||||||
|
ref: *template_sha
|
||||||
|
file: '/templates/ci-fairy.yml'
|
||||||
|
- template: Security/SAST.gitlab-ci.yml
|
||||||
|
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- prep # prep work like rebuilding the container images if there is a change
|
||||||
|
- install xcbproto
|
||||||
|
- build # for actually building and testing things in a container
|
||||||
|
- test
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
|
||||||
|
variables:
|
||||||
|
FDO_UPSTREAM_REPO: 'xorg/lib/libxcb'
|
||||||
|
# The tag should be updated each time the list of packages is updated.
|
||||||
|
# Changing a tag forces the associated image to be rebuilt.
|
||||||
|
# Note: the tag has no meaning, we use a date format purely for readability
|
||||||
|
FDO_DISTRIBUTION_TAG: '2023-08-21.0'
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: 'git gcc pkgconf autoconf automake libtool make xorg-util-macros python doxygen graphviz check libxslt libxau libxdmcp'
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify that commit messages are as expected
|
||||||
|
#
|
||||||
|
check-commits:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: prep
|
||||||
|
script:
|
||||||
|
- ci-fairy check-commits --junit-xml=results.xml
|
||||||
|
except:
|
||||||
|
- master@xorg/lib/libxcb
|
||||||
|
variables:
|
||||||
|
GIT_DEPTH: 100
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
junit: results.xml
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify that the merge request has the allow-collaboration checkbox ticked
|
||||||
|
#
|
||||||
|
check-merge-request:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: deploy
|
||||||
|
script:
|
||||||
|
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
|
||||||
|
artifacts:
|
||||||
|
when: on_failure
|
||||||
|
reports:
|
||||||
|
junit: results.xml
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build a container with the given tag and the packages pre-installed.
|
||||||
|
# This only happens if/when the tag changes, otherwise the existing image is
|
||||||
|
# re-used.
|
||||||
|
#
|
||||||
|
container-prep:
|
||||||
|
extends:
|
||||||
|
- .fdo.container-build@arch
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build latest xcbproto from git, instead of relying on the container
|
||||||
|
# to package a new enough version.
|
||||||
|
#
|
||||||
|
xcbproto-build:
|
||||||
|
extends:
|
||||||
|
- .fdo.distribution-image@arch
|
||||||
|
stage: install xcbproto
|
||||||
|
script:
|
||||||
|
- export INSTDIR="$PWD/_inst"
|
||||||
|
- git clone --depth=1 https://gitlab.freedesktop.org/xorg/proto/xcbproto
|
||||||
|
- pushd xcbproto > /dev/null
|
||||||
|
- mkdir _builddir
|
||||||
|
- pushd _builddir > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules --prefix="$INSTDIR"
|
||||||
|
- make -j${FDO_CI_CONCURRENT:-4} install
|
||||||
|
- popd > /dev/null
|
||||||
|
- popd > /dev/null
|
||||||
|
variables:
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- _inst
|
||||||
|
|
||||||
|
#
|
||||||
|
# The default build, runs on the image built above.
|
||||||
|
#
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
extends:
|
||||||
|
- .fdo.distribution-image@arch
|
||||||
|
script:
|
||||||
|
- export INSTDIR="$PWD/_inst"
|
||||||
|
- export PKG_CONFIG_PATH=$(find $INSTDIR/ -name '*.pc' -printf "%h:")
|
||||||
|
- autoreconf -ivf
|
||||||
|
- mkdir _builddir
|
||||||
|
- pushd _builddir > /dev/null
|
||||||
|
- ../configure --disable-silent-rules --enable-devel-docs --with-doxygen
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
- make distcheck
|
||||||
|
- popd > /dev/null
|
229
INSTALL
229
INSTALL
|
@ -1,229 +0,0 @@
|
||||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
|
|
||||||
Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free documentation; the Free Software Foundation gives
|
|
||||||
unlimited permission to copy, distribute and modify it.
|
|
||||||
|
|
||||||
Basic Installation
|
|
||||||
==================
|
|
||||||
|
|
||||||
These are generic installation instructions.
|
|
||||||
|
|
||||||
The `configure' shell script attempts to guess correct values for
|
|
||||||
various system-dependent variables used during compilation. It uses
|
|
||||||
those values to create a `Makefile' in each directory of the package.
|
|
||||||
It may also create one or more `.h' files containing system-dependent
|
|
||||||
definitions. Finally, it creates a shell script `config.status' that
|
|
||||||
you can run in the future to recreate the current configuration, and a
|
|
||||||
file `config.log' containing compiler output (useful mainly for
|
|
||||||
debugging `configure').
|
|
||||||
|
|
||||||
It can also use an optional file (typically called `config.cache'
|
|
||||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
|
||||||
the results of its tests to speed up reconfiguring. (Caching is
|
|
||||||
disabled by default to prevent problems with accidental use of stale
|
|
||||||
cache files.)
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
|
||||||
to figure out how `configure' could check whether to do them, and mail
|
|
||||||
diffs or instructions to the address given in the `README' so they can
|
|
||||||
be considered for the next release. If you are using the cache, and at
|
|
||||||
some point `config.cache' contains results you don't want to keep, you
|
|
||||||
may remove or edit it.
|
|
||||||
|
|
||||||
The file `configure.ac' (or `configure.in') is used to create
|
|
||||||
`configure' by a program called `autoconf'. You only need
|
|
||||||
`configure.ac' if you want to change it or regenerate `configure' using
|
|
||||||
a newer version of `autoconf'.
|
|
||||||
|
|
||||||
The simplest way to compile this package is:
|
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
|
||||||
`./configure' to configure the package for your system. If you're
|
|
||||||
using `csh' on an old version of System V, you might need to type
|
|
||||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
|
||||||
`configure' itself.
|
|
||||||
|
|
||||||
Running `configure' takes awhile. While running, it prints some
|
|
||||||
messages telling which features it is checking for.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
|
||||||
|
|
||||||
3. Optionally, type `make check' to run any self-tests that come with
|
|
||||||
the package.
|
|
||||||
|
|
||||||
4. Type `make install' to install the programs and any data files and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
5. You can remove the program binaries and object files from the
|
|
||||||
source code directory by typing `make clean'. To also remove the
|
|
||||||
files that `configure' created (so you can compile the package for
|
|
||||||
a different kind of computer), type `make distclean'. There is
|
|
||||||
also a `make maintainer-clean' target, but that is intended mainly
|
|
||||||
for the package's developers. If you use it, you may have to get
|
|
||||||
all sorts of other programs in order to regenerate files that came
|
|
||||||
with the distribution.
|
|
||||||
|
|
||||||
Compilers and Options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that
|
|
||||||
the `configure' script does not know about. Run `./configure --help'
|
|
||||||
for details on some of the pertinent environment variables.
|
|
||||||
|
|
||||||
You can give `configure' initial values for configuration parameters
|
|
||||||
by setting variables in the command line or in the environment. Here
|
|
||||||
is an example:
|
|
||||||
|
|
||||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
|
||||||
|
|
||||||
*Note Defining Variables::, for more details.
|
|
||||||
|
|
||||||
Compiling For Multiple Architectures
|
|
||||||
====================================
|
|
||||||
|
|
||||||
You can compile the package for more than one kind of computer at the
|
|
||||||
same time, by placing the object files for each architecture in their
|
|
||||||
own directory. To do this, you must use a version of `make' that
|
|
||||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
|
||||||
directory where you want the object files and executables to go and run
|
|
||||||
the `configure' script. `configure' automatically checks for the
|
|
||||||
source code in the directory that `configure' is in and in `..'.
|
|
||||||
|
|
||||||
If you have to use a `make' that does not support the `VPATH'
|
|
||||||
variable, you have to compile the package for one architecture at a
|
|
||||||
time in the source code directory. After you have installed the
|
|
||||||
package for one architecture, use `make distclean' before reconfiguring
|
|
||||||
for another architecture.
|
|
||||||
|
|
||||||
Installation Names
|
|
||||||
==================
|
|
||||||
|
|
||||||
By default, `make install' will install the package's files in
|
|
||||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
|
||||||
installation prefix other than `/usr/local' by giving `configure' the
|
|
||||||
option `--prefix=PATH'.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
|
||||||
PATH as the prefix for installing programs and libraries.
|
|
||||||
Documentation and other data files will still use the regular prefix.
|
|
||||||
|
|
||||||
In addition, if you use an unusual directory layout you can give
|
|
||||||
options like `--bindir=PATH' to specify different values for particular
|
|
||||||
kinds of files. Run `configure --help' for a list of the directories
|
|
||||||
you can set and what kinds of files go in them.
|
|
||||||
|
|
||||||
If the package supports it, you can cause programs to be installed
|
|
||||||
with an extra prefix or suffix on their names by giving `configure' the
|
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
||||||
|
|
||||||
Optional Features
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
||||||
is something like `gnu-as' or `x' (for the X Window System). The
|
|
||||||
`README' should mention any `--enable-' and `--with-' options that the
|
|
||||||
package recognizes.
|
|
||||||
|
|
||||||
For packages that use the X Window System, `configure' can usually
|
|
||||||
find the X include and library files automatically, but if it doesn't,
|
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
|
||||||
`--x-libraries=DIR' to specify their locations.
|
|
||||||
|
|
||||||
Specifying the System Type
|
|
||||||
==========================
|
|
||||||
|
|
||||||
There may be some features `configure' cannot figure out
|
|
||||||
automatically, but needs to determine by the type of machine the package
|
|
||||||
will run on. Usually, assuming the package is built to be run on the
|
|
||||||
_same_ architectures, `configure' can figure that out, but if it prints
|
|
||||||
a message saying it cannot guess the machine type, give it the
|
|
||||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
|
||||||
type, such as `sun4', or a canonical name which has the form:
|
|
||||||
|
|
||||||
CPU-COMPANY-SYSTEM
|
|
||||||
|
|
||||||
where SYSTEM can have one of these forms:
|
|
||||||
|
|
||||||
OS KERNEL-OS
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
|
||||||
`config.sub' isn't included in this package, then this package doesn't
|
|
||||||
need to know the machine type.
|
|
||||||
|
|
||||||
If you are _building_ compiler tools for cross-compiling, you should
|
|
||||||
use the `--target=TYPE' option to select the type of system they will
|
|
||||||
produce code for.
|
|
||||||
|
|
||||||
If you want to _use_ a cross compiler, that generates code for a
|
|
||||||
platform different from the build platform, you should specify the
|
|
||||||
"host" platform (i.e., that on which the generated programs will
|
|
||||||
eventually be run) with `--host=TYPE'.
|
|
||||||
|
|
||||||
Sharing Defaults
|
|
||||||
================
|
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share,
|
|
||||||
you can create a site shell script called `config.site' that gives
|
|
||||||
default values for variables like `CC', `cache_file', and `prefix'.
|
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
|
||||||
A warning: not all `configure' scripts look for a site script.
|
|
||||||
|
|
||||||
Defining Variables
|
|
||||||
==================
|
|
||||||
|
|
||||||
Variables not defined in a site shell script can be set in the
|
|
||||||
environment passed to `configure'. However, some packages may run
|
|
||||||
configure again during the build, and the customized values of these
|
|
||||||
variables may be lost. In order to avoid this problem, you should set
|
|
||||||
them in the `configure' command line, using `VAR=value'. For example:
|
|
||||||
|
|
||||||
./configure CC=/usr/local2/bin/gcc
|
|
||||||
|
|
||||||
will cause the specified gcc to be used as the C compiler (unless it is
|
|
||||||
overridden in the site shell script).
|
|
||||||
|
|
||||||
`configure' Invocation
|
|
||||||
======================
|
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it
|
|
||||||
operates.
|
|
||||||
|
|
||||||
`--help'
|
|
||||||
`-h'
|
|
||||||
Print a summary of the options to `configure', and exit.
|
|
||||||
|
|
||||||
`--version'
|
|
||||||
`-V'
|
|
||||||
Print the version of Autoconf used to generate the `configure'
|
|
||||||
script, and exit.
|
|
||||||
|
|
||||||
`--cache-file=FILE'
|
|
||||||
Enable the cache: use and save the results of the tests in FILE,
|
|
||||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
|
||||||
disable caching.
|
|
||||||
|
|
||||||
`--config-cache'
|
|
||||||
`-C'
|
|
||||||
Alias for `--cache-file=config.cache'.
|
|
||||||
|
|
||||||
`--quiet'
|
|
||||||
`--silent'
|
|
||||||
`-q'
|
|
||||||
Do not print messages saying which checks are being made. To
|
|
||||||
suppress all normal output, redirect it to `/dev/null' (any error
|
|
||||||
messages will still be shown).
|
|
||||||
|
|
||||||
`--srcdir=DIR'
|
|
||||||
Look for the package's source code in directory DIR. Usually
|
|
||||||
`configure' can determine that directory automatically.
|
|
||||||
|
|
||||||
`configure' also accepts some other, not widely useful, options. Run
|
|
||||||
`configure --help' for more details.
|
|
||||||
|
|
40
Makefile.am
40
Makefile.am
|
@ -1,4 +1,6 @@
|
||||||
SUBDIRS=src tests doc
|
ACLOCAL_AMFLAGS=-I m4
|
||||||
|
|
||||||
|
SUBDIRS=src tests doc man
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
|
||||||
|
@ -10,15 +12,24 @@ endif
|
||||||
if BUILD_DAMAGE
|
if BUILD_DAMAGE
|
||||||
pkgconfig_DATA += xcb-damage.pc
|
pkgconfig_DATA += xcb-damage.pc
|
||||||
endif
|
endif
|
||||||
|
if BUILD_DBE
|
||||||
|
pkgconfig_DATA += xcb-dbe.pc
|
||||||
|
endif
|
||||||
if BUILD_DPMS
|
if BUILD_DPMS
|
||||||
pkgconfig_DATA += xcb-dpms.pc
|
pkgconfig_DATA += xcb-dpms.pc
|
||||||
endif
|
endif
|
||||||
if BUILD_DRI2
|
if BUILD_DRI2
|
||||||
pkgconfig_DATA += xcb-dri2.pc
|
pkgconfig_DATA += xcb-dri2.pc
|
||||||
endif
|
endif
|
||||||
|
if BUILD_DRI3
|
||||||
|
pkgconfig_DATA += xcb-dri3.pc
|
||||||
|
endif
|
||||||
if BUILD_GLX
|
if BUILD_GLX
|
||||||
pkgconfig_DATA += xcb-glx.pc
|
pkgconfig_DATA += xcb-glx.pc
|
||||||
endif
|
endif
|
||||||
|
if BUILD_PRESENT
|
||||||
|
pkgconfig_DATA += xcb-present.pc
|
||||||
|
endif
|
||||||
if BUILD_RANDR
|
if BUILD_RANDR
|
||||||
pkgconfig_DATA += xcb-randr.pc
|
pkgconfig_DATA += xcb-randr.pc
|
||||||
endif
|
endif
|
||||||
|
@ -58,6 +69,9 @@ endif
|
||||||
if BUILD_XINPUT
|
if BUILD_XINPUT
|
||||||
pkgconfig_DATA += xcb-xinput.pc
|
pkgconfig_DATA += xcb-xinput.pc
|
||||||
endif
|
endif
|
||||||
|
if BUILD_XKB
|
||||||
|
pkgconfig_DATA += xcb-xkb.pc
|
||||||
|
endif
|
||||||
if BUILD_XPRINT
|
if BUILD_XPRINT
|
||||||
pkgconfig_DATA += xcb-xprint.pc
|
pkgconfig_DATA += xcb-xprint.pc
|
||||||
endif
|
endif
|
||||||
|
@ -73,10 +87,32 @@ endif
|
||||||
if BUILD_XVMC
|
if BUILD_XVMC
|
||||||
pkgconfig_DATA += xcb-xvmc.pc
|
pkgconfig_DATA += xcb-xvmc.pc
|
||||||
endif
|
endif
|
||||||
|
if BUILD_GE
|
||||||
|
pkgconfig_DATA += xcb-ge.pc
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
AM_TESTS_ENVIRONMENT = \
|
||||||
|
AM_SRCDIR=${srcdir}
|
||||||
|
|
||||||
|
TESTS=check-pc-requires
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
tools/README \
|
tools/README \
|
||||||
tools/api_conv.pl \
|
tools/api_conv.pl \
|
||||||
tools/constants \
|
tools/constants \
|
||||||
autogen.sh
|
autogen.sh \
|
||||||
|
README.md \
|
||||||
|
$(TESTS)
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = ChangeLog INSTALL
|
||||||
|
|
||||||
|
.PHONY: ChangeLog INSTALL
|
||||||
|
|
||||||
|
INSTALL:
|
||||||
|
$(INSTALL_CMD)
|
||||||
|
|
||||||
|
ChangeLog:
|
||||||
|
$(CHANGELOG_CMD)
|
||||||
|
|
||||||
|
dist-hook: ChangeLog INSTALL
|
||||||
|
|
175
NEWS
175
NEWS
|
@ -1,3 +1,178 @@
|
||||||
|
Release 1.14 (2020-02-22)
|
||||||
|
=========================
|
||||||
|
* Add xcb_total_read() and xcb_total_written() API
|
||||||
|
* Support check >= 0.13 API (for make check)
|
||||||
|
* Bug fix to handle EINTR from recvmsg
|
||||||
|
* Only require pthread-stubs on non-Linux platforms
|
||||||
|
|
||||||
|
Release 1.13.1 (2018-09-27)
|
||||||
|
===========================
|
||||||
|
* Don't flag extra reply in xcb_take_socket
|
||||||
|
|
||||||
|
Release 1.13 (2018-02-28)
|
||||||
|
=========================
|
||||||
|
* Add support for variable-sized lists of FDs
|
||||||
|
* Poll for events when blocking waiting for special events
|
||||||
|
* xinput: Enable XInput extension by default
|
||||||
|
* ge: Add explicit support for GenericEvent extension
|
||||||
|
* Fix documentation warnings from clang
|
||||||
|
* Cosmetic cleanups
|
||||||
|
|
||||||
|
Release 1.12 (2016-05-18)
|
||||||
|
=========================
|
||||||
|
* configure: Various fixes for dri3 and FD passing support
|
||||||
|
* configure: Don't report all the warning CFLAGS
|
||||||
|
* configure: Disable Xevie and Xprint by default
|
||||||
|
* Add support for various new constructs in the XML schema
|
||||||
|
* Make some functions also accept connections in an error state
|
||||||
|
* Never return NULL from xcb_get_setup()
|
||||||
|
* Use Requires.private in .pc files to avoid overlinking
|
||||||
|
* Fix align-pads for switches which start at unaligned positions
|
||||||
|
* Use anonymous structs for some nested structs
|
||||||
|
* Also generate accessors for variable-sized events and requests
|
||||||
|
* Improved python3 compatibility
|
||||||
|
* Generate C99 initializers instead of comments
|
||||||
|
* Various simplifications to the python code
|
||||||
|
* Fix line breaks in xcb-requests manual page
|
||||||
|
* Always close FDs in xcb_send_fd()
|
||||||
|
* Fix thread-safety issues with FD passing
|
||||||
|
* Add xcb_send_request_with_fds() and xcb_send_request_with_fds64()
|
||||||
|
* Fix endless loop with too many outstanding FDs to send
|
||||||
|
* Link with winsock library on MinGW
|
||||||
|
* Disable some unfinished API for some server-side code by default
|
||||||
|
* Use align-offsets computed by xcb-proto instead of low bits of pointers
|
||||||
|
* Fix iterator interaction with align padding
|
||||||
|
* Stop serializing padding by default
|
||||||
|
* Increase unix socket send buffer to at least 64KiB
|
||||||
|
|
||||||
|
Release 1.11.1 (2015-09-06)
|
||||||
|
===========================
|
||||||
|
* Expose 64-bit sequence numbers for XLib
|
||||||
|
* Fix some hangs related to xcb_wait_for_special_event()
|
||||||
|
|
||||||
|
Release 1.11 (2014-08-01)
|
||||||
|
=========================
|
||||||
|
* Force structures with 64-bit fields to be packed
|
||||||
|
* Add support for <pad align="n">
|
||||||
|
* Use X.org's build machinery from xorg-macros
|
||||||
|
* Fix leak with xcb_disconnect() and connections in an error state
|
||||||
|
* Make xcb_disconnect(NULL) safe
|
||||||
|
* Use less #include statements in generated code
|
||||||
|
* Automatically validate the Requires lines in our .pc.in files
|
||||||
|
* Fix a race that resulted in a failed assertion
|
||||||
|
* Improve launchd secure socket support
|
||||||
|
* Improve API documentation
|
||||||
|
* Remove trailing whitespaces
|
||||||
|
* c_client.py: prefix all monkey-patched fields with c_
|
||||||
|
* c_client.py: make the man page output deterministic
|
||||||
|
* c_client.py: remove useless generated comments
|
||||||
|
* xcb.h: add 'struct' before xcb_setup_t, xcb_query_extension_reply_t
|
||||||
|
|
||||||
|
Release 1.10 (2013-12-22)
|
||||||
|
=========================
|
||||||
|
* Bump libxcb-xkb SONAME due to ABI break introduced in 1.9.2
|
||||||
|
* Enable libxcb-xkb by default
|
||||||
|
* Bump libxcb-sync SONAME
|
||||||
|
* c_client.py: Fix _sizeof() functions
|
||||||
|
* c_client.py: Do not create pointers in unions
|
||||||
|
* c_client.py: Always initialize xcb_align_to
|
||||||
|
* Re-introduce xcb_ge_event_t (deprecated, xcb_ge_generic_event_t should be
|
||||||
|
used instead)
|
||||||
|
* Fix alignment issues in FD passing code
|
||||||
|
* Fix poll() if POLLIN == ROLLRDNORM|POLLRDBAND
|
||||||
|
* Use /usr/spool/sockets/X11/ on HP-UX for UNIX sockets
|
||||||
|
* Make xsltproc optional
|
||||||
|
|
||||||
|
Release 1.9.3 (2013-11-07)
|
||||||
|
==========================
|
||||||
|
* Check if we need to define _XOPEN_SOURCE for struct msghdr.msg_control
|
||||||
|
* Add configure option to enable or disable fd passing with sendmsg
|
||||||
|
* Switch to using the CMSG_* macros for FD passing
|
||||||
|
* Initialize automake earlier (bugfix for #66413)
|
||||||
|
|
||||||
|
Release 1.9.2 (2013-11-07)
|
||||||
|
==========================
|
||||||
|
* Add Present extension
|
||||||
|
* Add DRI3 library
|
||||||
|
* Add event queue splitting
|
||||||
|
* Add support for receiving fds in replies
|
||||||
|
* Add xcb_send_fd API
|
||||||
|
* Remove xcb_ge_event_t from xcb.h
|
||||||
|
* c_client.py: Inject full_sequence into GE events
|
||||||
|
* c_client.py: Handle multiple expr. in a bitcase
|
||||||
|
|
||||||
|
Release 1.9.1 (2013-05-30)
|
||||||
|
==========================
|
||||||
|
* Fix python code to work with python-3
|
||||||
|
* Security fix for integer overflow in read_packet() [CVE-2013-2064]
|
||||||
|
|
||||||
|
Release 1.9 (2012-10-05)
|
||||||
|
========================
|
||||||
|
* Always include "config.h" at the start of all C source files.
|
||||||
|
* Add AC_USE_SYSTEM_EXTENSIONS to allow use of more system functionality
|
||||||
|
* Return connection failure if display string specifies non-existent screen
|
||||||
|
* c_client: Fix parallel-make issue creating 'man' directory
|
||||||
|
* xcb_connect: launchd: Don't fall back on tcp if $DISPLAY is a path to a launchd socket
|
||||||
|
* c_client.py: generate manpages
|
||||||
|
* Allow xcb_send_request with >MAX_IOV iovecs
|
||||||
|
* Add a .gitignore for src/man/
|
||||||
|
* Fix a multi-thread deadlock
|
||||||
|
|
||||||
|
Release 1.8.1 (2012-03-09)
|
||||||
|
==========================
|
||||||
|
- Fix a busy loop on BSD and Mac OS
|
||||||
|
- Bump xcb-proto requirement
|
||||||
|
- Fallback to TCP if no protocol is specified and the UNIX connection fails
|
||||||
|
- Update use of error_connection under WIN32 to _xcb_conn_ret_error()
|
||||||
|
- Fix build of xcb_auth.c with XDMCP on WIN32
|
||||||
|
- Revert "Fix include order with Xdmcp on WIN32"
|
||||||
|
- darwin: Use read(2) rather than recv(2)
|
||||||
|
- Add xkb_internals and xkb_issues to EXTRA_DIST.
|
||||||
|
|
||||||
|
Release 1.8 (2012-01-11)
|
||||||
|
========================
|
||||||
|
- xcb_disconnect: call shutdown() to force a disconnect
|
||||||
|
- Use special path to sockets when running under Solaris Trusted Extensions
|
||||||
|
- Remove unused DECnet code
|
||||||
|
- Add #include <sys/socket.h> to xcb_conn.c
|
||||||
|
- Make launchd code in xcb_util.c match surrounding code indent levels
|
||||||
|
- If protocol is "unix", use a Unix domain socket, not TCP
|
||||||
|
- Added more error states and removed global error_connection
|
||||||
|
- Handle XGE events with the "send event" flag
|
||||||
|
- added xcb_sumof() with restriction to uint8_t
|
||||||
|
- xkb: updated configure.ac/Makefile.am
|
||||||
|
- xkb: added pkg config file
|
||||||
|
- special case 'intermixed variable and fixed size fields': fixed reply side, needs testing
|
||||||
|
- added accessors for special cases
|
||||||
|
- Add support for building with Python 3
|
||||||
|
- Insert, not append explicit xcbgen dir python path
|
||||||
|
- xcb_request_check: Sync even if an event was read for this sequence.
|
||||||
|
- _xcb_conn_wait: Shut down the connection on unexpected poll() events.
|
||||||
|
- xcb_send_request: Send all requests using a common internal send_request.
|
||||||
|
- xcb_request_check: Hold the I/O lock while deciding to sync.
|
||||||
|
- xcb_discard_reply: Simplify by re-using poll_for_reply helper.
|
||||||
|
- xcb_in: Use 64-bit sequence numbers internally everywhere.
|
||||||
|
- Enable AM_SILENT_RULES on automake 1.11 or newer.
|
||||||
|
- Factor reader_list management out of wait_for_reply.
|
||||||
|
- Dequeue readers that can't receive any new responses.
|
||||||
|
- Delete the old c-client.xsl.
|
||||||
|
- Keep ALIGNOF definition out of the public namespace.
|
||||||
|
- darwin: Don't use poll() when expected to run on darwin10 and prior
|
||||||
|
- Add Win32
|
||||||
|
- Allow disconnecting connections that are in error state.
|
||||||
|
- Make xcb_take_socket keep flushing until idle
|
||||||
|
- Support pre-IPv6 systems (without getaddrinfo)
|
||||||
|
- Drop AI_ADDRCONFIG when resolving TCP addresses
|
||||||
|
- xcb_auth: Fix memory leak in _xcb_get_auth_info.
|
||||||
|
- Don't emit out-of-module sizeof definitions
|
||||||
|
- Clean up a couple of warnings in xprint
|
||||||
|
- Prevent reply waiters from being blocked.
|
||||||
|
- Prevent theoretical double free and leak on get_peer_sock_name.
|
||||||
|
- Introduce a variant of xcb_poll_for_event for examining event queue.
|
||||||
|
- xcb_take_socket: Document sequence wrap requirements
|
||||||
|
- Compute alignment correctly
|
||||||
|
- Fix a dead-lock due to xcb_poll_for_reply
|
||||||
|
|
||||||
Release 1.7 (2010-08-13)
|
Release 1.7 (2010-08-13)
|
||||||
========================
|
========================
|
||||||
- Always wake up readers after writing
|
- Always wake up readers after writing
|
||||||
|
|
|
@ -2,7 +2,7 @@ About libxcb
|
||||||
============
|
============
|
||||||
|
|
||||||
libxcb provides an interface to the X Window System protocol, which
|
libxcb provides an interface to the X Window System protocol, which
|
||||||
replaces the current Xlib interface. It has several advantages over
|
replaces the traditional Xlib interface. It has several advantages over
|
||||||
Xlib, including:
|
Xlib, including:
|
||||||
- size: small, simple library, and lower memory footprint
|
- size: small, simple library, and lower memory footprint
|
||||||
- latency hiding: batch several requests and wait for the replies later
|
- latency hiding: batch several requests and wait for the replies later
|
||||||
|
@ -10,27 +10,32 @@ Xlib, including:
|
||||||
- proven thread support: transparently access XCB from multiple threads
|
- proven thread support: transparently access XCB from multiple threads
|
||||||
- easy extension implementation: interfaces auto-generated from XML-XCB
|
- easy extension implementation: interfaces auto-generated from XML-XCB
|
||||||
|
|
||||||
Xlib can also use XCB as a transport layer, allowing software to make
|
Xlib also uses XCB as a transport layer, allowing software to make
|
||||||
requests and receive responses with both, which eases porting to XCB.
|
requests and receive responses with both, which eases porting to XCB.
|
||||||
However, client programs, libraries, and toolkits will gain the most
|
However, client programs, libraries, and toolkits will gain the most
|
||||||
benefit from a native XCB port.
|
benefit from a native XCB port.
|
||||||
|
|
||||||
|
More information about xcb is available from our website:
|
||||||
|
|
||||||
Please report any issues you find to the freedesktop.org bug tracker,
|
https://xcb.freedesktop.org/
|
||||||
at:
|
|
||||||
|
|
||||||
<https://bugs.freedesktop.org/enter_bug.cgi?product=XCB>
|
Please report any issues you find to the freedesktop.org bug tracker at:
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/xorg/lib/libxcb/issues
|
||||||
|
|
||||||
Discussion about XCB occurs on the XCB mailing list:
|
Discussion about XCB occurs on the XCB mailing list:
|
||||||
|
|
||||||
<mailto:xcb at lists.freedesktop.org>
|
https://lists.freedesktop.org/mailman/listinfo/xcb
|
||||||
<http://lists.freedesktop.org/mailman/listinfo/xcb>
|
|
||||||
|
You can obtain the latest development versions of XCB using GIT from
|
||||||
|
the libxcb code repository at:
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/xorg/lib/libxcb
|
||||||
|
|
||||||
You can obtain the latest development versions of XCB using GIT.
|
|
||||||
For anonymous checkouts, use:
|
For anonymous checkouts, use:
|
||||||
|
|
||||||
git clone git://anongit.freedesktop.org/git/xcb/libxcb
|
git clone https://gitlab.freedesktop.org/xorg/lib/libxcb.git
|
||||||
|
|
||||||
For developers, use:
|
For developers, use:
|
||||||
|
|
||||||
git clone git+ssh://git.freedesktop.org/git/xcb/libxcb
|
git clone git@gitlab.freedesktop.org:xorg/lib/libxcb.git
|
142
acinclude.m4
142
acinclude.m4
|
@ -1,142 +0,0 @@
|
||||||
dnl Detection and configuration of the visibility feature of gcc
|
|
||||||
dnl Vincent Torri 2006-02-11
|
|
||||||
dnl
|
|
||||||
dnl XCB_CHECK_VISIBILITY([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
|
||||||
dnl Check the visibility feature of gcc
|
|
||||||
dnl
|
|
||||||
AC_DEFUN([XCB_CHECK_VISIBILITY],
|
|
||||||
[
|
|
||||||
AC_MSG_CHECKING([whether ${CC} supports symbol visibility])
|
|
||||||
|
|
||||||
save_CFLAGS=${CFLAGS}
|
|
||||||
CFLAGS="$CFLAGS -fvisibility=hidden -fvisibility-inlines-hidden"
|
|
||||||
AC_COMPILE_IFELSE(
|
|
||||||
[AC_LANG_PROGRAM(
|
|
||||||
[[
|
|
||||||
#pragma GCC visibility push(hidden)
|
|
||||||
extern void f(int);
|
|
||||||
#pragma GCC visibility pop
|
|
||||||
]],
|
|
||||||
[[]]
|
|
||||||
)],
|
|
||||||
[AC_DEFINE(
|
|
||||||
GCC_HAS_VISIBILITY,
|
|
||||||
[],
|
|
||||||
[Defined if GCC supports the visibility feature])
|
|
||||||
m4_if([$1], [], [:], [$1])
|
|
||||||
AC_MSG_RESULT(yes)],
|
|
||||||
[m4_if([$2], [], [:], [$2])
|
|
||||||
AC_MSG_RESULT(no)])
|
|
||||||
|
|
||||||
CFLAGS=${save_CFLAGS}
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl Configure script for doxygen
|
|
||||||
dnl Vincent Torri 2006-05-11
|
|
||||||
dnl
|
|
||||||
dnl XCB_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
|
||||||
dnl Test for the doxygen program, and define BUILD_DOCS and DOXYGEN.
|
|
||||||
dnl
|
|
||||||
AC_DEFUN([XCB_CHECK_DOXYGEN],
|
|
||||||
[
|
|
||||||
DOXYGEN="doxygen"
|
|
||||||
|
|
||||||
dnl
|
|
||||||
dnl Disable the build of the documentation
|
|
||||||
dnl
|
|
||||||
AC_ARG_ENABLE(
|
|
||||||
[build_docs],
|
|
||||||
AC_HELP_STRING(
|
|
||||||
[--disable-build-docs],
|
|
||||||
[Disable the build of the documentation]),
|
|
||||||
[if test x"$enableval" != x"yes" ; then
|
|
||||||
enable_build_docs="no"
|
|
||||||
else
|
|
||||||
enable_build_docs="yes"
|
|
||||||
fi],
|
|
||||||
[enable_build_docs="yes"])
|
|
||||||
|
|
||||||
if test "$enable_build_docs" = "no" ; then
|
|
||||||
BUILD_DOCS=no
|
|
||||||
else
|
|
||||||
dnl
|
|
||||||
dnl Get the prefix where doxygen is installed.
|
|
||||||
dnl
|
|
||||||
AC_ARG_WITH(
|
|
||||||
[doxygen],
|
|
||||||
AC_HELP_STRING(
|
|
||||||
[--with-doxygen=FILE],
|
|
||||||
[doxygen program to use (eg /usr/bin/doxygen)]),
|
|
||||||
dnl
|
|
||||||
dnl Check the given doxygen program.
|
|
||||||
dnl
|
|
||||||
[DOXYGEN=${withval}
|
|
||||||
AC_CHECK_PROG(
|
|
||||||
[BUILD_DOCS],
|
|
||||||
[${DOXYGEN}],
|
|
||||||
[yes],
|
|
||||||
[no])
|
|
||||||
if test $BUILD_DOCS = no; then
|
|
||||||
echo "WARNING:"
|
|
||||||
echo "The doxygen program you specified:"
|
|
||||||
echo "$DOXYGEN"
|
|
||||||
echo "was not found. Please check the path and make sure "
|
|
||||||
echo "the program exists and is executable."
|
|
||||||
AC_MSG_WARN(
|
|
||||||
[Warning: no doxygen detected. Documentation will not be built])
|
|
||||||
fi],
|
|
||||||
[AC_CHECK_PROG(
|
|
||||||
[BUILD_DOCS],
|
|
||||||
[${DOXYGEN}],
|
|
||||||
[yes],
|
|
||||||
[no])
|
|
||||||
if test ${BUILD_DOCS} = no; then
|
|
||||||
echo "WARNING:"
|
|
||||||
echo "The doxygen program was not found in your execute"
|
|
||||||
echo "You may have doxygen installed somewhere not covered by your path."
|
|
||||||
echo ""
|
|
||||||
echo "If this is the case make sure you have the packages installed, AND"
|
|
||||||
echo "that the doxygen program is in your execute path (see your"
|
|
||||||
echo "shell manual page on setting the \$PATH environment variable), OR"
|
|
||||||
echo "alternatively, specify the program to use with --with-doxygen."
|
|
||||||
AC_MSG_WARN(
|
|
||||||
[Warning: no doxygen detected. Documentation will not be built])
|
|
||||||
fi])
|
|
||||||
AC_PATH_PROG(DOT, dot, no)
|
|
||||||
if test "$DOT" = "no"; then
|
|
||||||
AC_MSG_WARN([Warning: no dot detected. Documentation will not be built])
|
|
||||||
BUILD_DOCS="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([whether documentation is built])
|
|
||||||
AC_MSG_RESULT([${BUILD_DOCS}])
|
|
||||||
|
|
||||||
dnl
|
|
||||||
dnl Substitution
|
|
||||||
dnl
|
|
||||||
AC_SUBST([DOXYGEN])
|
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_DOCS, test "x$BUILD_DOCS" = "xyes")
|
|
||||||
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl Detection and configuration of the visibility feature of gcc
|
|
||||||
dnl Vincent Torri 2006-02-11
|
|
||||||
dnl
|
|
||||||
dnl XCB_EXTENSION(name, default)
|
|
||||||
dnl set the X extension
|
|
||||||
dnl
|
|
||||||
AC_DEFUN([XCB_EXTENSION],
|
|
||||||
[
|
|
||||||
pushdef([UP], translit([$1], [-a-z], [_A-Z]))dnl
|
|
||||||
pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(DOWN,
|
|
||||||
[AS_HELP_STRING([--enable-[]DOWN], [Build XCB $1 Extension (default: $2)])],
|
|
||||||
[BUILD_[]UP=$enableval],
|
|
||||||
[BUILD_[]UP=$2])
|
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_[]UP, [test "x$BUILD_[]UP" = "xyes"])
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl End of acinclude.m4
|
|
13
autogen.sh
13
autogen.sh
|
@ -1,12 +1,17 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
srcdir=`dirname $0`
|
srcdir=`dirname "$0"`
|
||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
|
||||||
ORIGDIR=`pwd`
|
ORIGDIR=`pwd`
|
||||||
cd $srcdir
|
cd "$srcdir"
|
||||||
|
|
||||||
autoreconf -v --install || exit 1
|
autoreconf -v --install || exit 1
|
||||||
cd $ORIGDIR || exit $?
|
cd "$ORIGDIR" || exit $?
|
||||||
|
|
||||||
$srcdir/configure --enable-maintainer-mode "$@"
|
git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
|
||||||
|
git config --local format.subjectPrefix "PATCH libxcb"
|
||||||
|
|
||||||
|
if test -z "$NOCONFIGURE"; then
|
||||||
|
exec "$srcdir"/configure "$@"
|
||||||
|
fi
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case "$AM_SRCDIR" in
|
||||||
|
"")
|
||||||
|
AM_SRCDIR="."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
fix=n
|
||||||
|
status=0
|
||||||
|
case "$1" in
|
||||||
|
"-fix")
|
||||||
|
fix=y
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
for inc in src/*.h; do
|
||||||
|
package=xcb-`basename $inc .h`
|
||||||
|
pcin="$AM_SRCDIR"/$package.pc.in
|
||||||
|
if [ -f $pcin ]; then
|
||||||
|
included=`grep '# *include' $inc |
|
||||||
|
sed -e 's/[^<"]*[<"]//' -e 's/[>"]//' |
|
||||||
|
grep -v 'xcb.h\|xproto.h'`
|
||||||
|
requires=`grep '^Requires.private:' $pcin`
|
||||||
|
missing=""
|
||||||
|
for i in $included; do
|
||||||
|
ibase=`basename $i .h`
|
||||||
|
r="xcb-$ibase"
|
||||||
|
rpcin="$AM_SRCDIR"/$r.pc.in
|
||||||
|
if [ -f $rpcin ]; then
|
||||||
|
m="$r"
|
||||||
|
for has in $requires; do
|
||||||
|
if [ $has = $r ]; then
|
||||||
|
m=""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
case "$m" in
|
||||||
|
"")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case "$missing" in
|
||||||
|
"")
|
||||||
|
missing=$m
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
missing="$missing $m"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
case "$missing" in
|
||||||
|
"")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ "$fix" = "y" ]; then
|
||||||
|
echo $package adding dependency on $missing
|
||||||
|
sed -i '/^Requires.private:/s/$/ '"$missing"'/' $pcin
|
||||||
|
else
|
||||||
|
echo $package missing $missing
|
||||||
|
status=1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit $status
|
255
configure.ac
255
configure.ac
|
@ -1,39 +1,62 @@
|
||||||
# -*- Autoconf -*-
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
# Process this file with autoconf to produce a configure script.
|
|
||||||
|
|
||||||
AC_PREREQ(2.57)
|
# Initialize Autoconf
|
||||||
AC_INIT([libxcb],
|
AC_PREREQ([2.60])
|
||||||
1.7,
|
AC_INIT([libxcb],[1.17.0],
|
||||||
[xcb@lists.freedesktop.org])
|
[https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues],
|
||||||
|
[libxcb])
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_SRCDIR([xcb.pc.in])
|
AC_CONFIG_SRCDIR([xcb.pc.in])
|
||||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
|
||||||
|
|
||||||
AM_PATH_PYTHON([2.5])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(CHECK, [check >= 0.9.4], [HAVE_CHECK=yes], [HAVE_CHECK=no])
|
|
||||||
AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes)
|
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([src/config.h])
|
AC_CONFIG_HEADERS([src/config.h])
|
||||||
|
|
||||||
AC_PROG_LIBTOOL
|
# Initialize Automake
|
||||||
AC_PROG_CC
|
AM_INIT_AUTOMAKE([foreign dist-xz])
|
||||||
|
AM_PATH_PYTHON([3.0])
|
||||||
|
|
||||||
AC_PATH_PROG(XSLTPROC, xsltproc, no)
|
# Set common system defines for POSIX extensions, such as _GNU_SOURCE
|
||||||
if test "$XSLTPROC" = "no"; then
|
# Must be called before any macros that run the compiler (like AC_PROG_LIBTOOL)
|
||||||
AC_MSG_ERROR([XCB requires xsltproc.])
|
# to avoid autoconf errors.
|
||||||
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
AC_SYS_LARGEFILE
|
||||||
|
|
||||||
|
# Initialize libtool
|
||||||
|
LT_PREREQ([2.2])
|
||||||
|
LT_INIT([win32-dll])
|
||||||
|
|
||||||
|
# Require xorg-macros minimum of 1.18 - Initial version
|
||||||
|
m4_ifndef([XORG_MACROS_VERSION],
|
||||||
|
[m4_fatal([must install xorg-macros 1.18 or later before running autoconf/autogen])])
|
||||||
|
XORG_MACROS_VERSION(1.18)
|
||||||
|
XORG_DEFAULT_OPTIONS
|
||||||
|
XORG_ENABLE_DEVEL_DOCS
|
||||||
|
XORG_WITH_DOXYGEN
|
||||||
|
|
||||||
|
# The dot drawing tool is checked by XORG_WITH_DOXYGEN, needed for xcb manual
|
||||||
|
if test x"$HAVE_DOT" = xno; then
|
||||||
|
AC_MSG_WARN([dot not found - doxygen targets will be skipped])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HTML_CHECK_RESULT=false
|
PKG_CHECK_MODULES(CHECK, [check >= 0.9.6], [HAVE_CHECK=yes], [HAVE_CHECK=no])
|
||||||
|
AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes)
|
||||||
|
|
||||||
|
XSLTPROC=no
|
||||||
|
HTML_CHECK_RESULT=no
|
||||||
if test x"$HAVE_CHECK" = xyes; then
|
if test x"$HAVE_CHECK" = xyes; then
|
||||||
|
AC_PATH_PROG(XSLTPROC, xsltproc, no)
|
||||||
if test x"$XSLTPROC" != xno; then
|
if test x"$XSLTPROC" != xno; then
|
||||||
HTML_CHECK_RESULT=true
|
HTML_CHECK_RESULT=yes
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
AC_SUBST(HTML_CHECK_RESULT)
|
AC_SUBST(HTML_CHECK_RESULT)
|
||||||
|
|
||||||
# Checks for pkg-config packages
|
# Checks for pkg-config packages
|
||||||
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.6)
|
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.17.0)
|
||||||
NEEDED="pthread-stubs xau >= 0.99.2"
|
NEEDED="xau >= 0.99.2"
|
||||||
|
case $host_os in
|
||||||
|
linux*|darwin*|solaris*|dragonfly*|freebsd*|netbsd*) ;;
|
||||||
|
*) NEEDED="$NEEDED pthread-stubs" ;;
|
||||||
|
esac
|
||||||
PKG_CHECK_MODULES(NEEDED, $NEEDED)
|
PKG_CHECK_MODULES(NEEDED, $NEEDED)
|
||||||
|
|
||||||
have_xdmcp="no"
|
have_xdmcp="no"
|
||||||
|
@ -68,19 +91,70 @@ XCBPROTO_XCBPYTHONDIR=`$PKG_CONFIG --variable=pythondir xcb-proto`
|
||||||
AC_MSG_RESULT($XCBPROTO_XCBPYTHONDIR)
|
AC_MSG_RESULT($XCBPROTO_XCBPYTHONDIR)
|
||||||
AC_SUBST(XCBPROTO_XCBPYTHONDIR)
|
AC_SUBST(XCBPROTO_XCBPYTHONDIR)
|
||||||
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_SEARCH_LIBS(getaddrinfo, socket)
|
AC_SEARCH_LIBS(getaddrinfo, socket)
|
||||||
AC_SEARCH_LIBS(connect, socket)
|
AC_SEARCH_LIBS(connect, socket)
|
||||||
|
|
||||||
|
# Find support for sending a message from a socket
|
||||||
|
AC_SEARCH_LIBS(sendmsg, socket, [have_sendmsg="yes"], [have_sendmsg="no"])
|
||||||
|
|
||||||
|
# XPG4v2/UNIX95 added msg_control - check to see if we need to define
|
||||||
|
# _XOPEN_SOURCE to get it (such as on Solaris)
|
||||||
|
AC_CHECK_MEMBER([struct msghdr.msg_control], [], [],
|
||||||
|
[
|
||||||
|
AC_INCLUDES_DEFAULT
|
||||||
|
#include <sys/socket.h>
|
||||||
|
])
|
||||||
|
# First try for Solaris in C99 compliant mode, which requires XPG6/UNIX03
|
||||||
|
if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then
|
||||||
|
unset ac_cv_member_struct_msghdr_msg_control
|
||||||
|
AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=600])
|
||||||
|
AC_CHECK_MEMBER([struct msghdr.msg_control],
|
||||||
|
[AC_DEFINE([_XOPEN_SOURCE], [600],
|
||||||
|
[Defined if needed to expose struct msghdr.msg_control])
|
||||||
|
], [], [
|
||||||
|
#define _XOPEN_SOURCE 600
|
||||||
|
AC_INCLUDES_DEFAULT
|
||||||
|
#include <sys/socket.h>
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
# If that didn't work, fall back to XPG5/UNIX98 with C89
|
||||||
|
if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then
|
||||||
|
unset ac_cv_member_struct_msghdr_msg_control
|
||||||
|
AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=500])
|
||||||
|
AC_CHECK_MEMBER([struct msghdr.msg_control],
|
||||||
|
[AC_DEFINE([_XOPEN_SOURCE], [500],
|
||||||
|
[Defined if needed to expose struct msghdr.msg_control])
|
||||||
|
], [have_sendmsg="no"], [
|
||||||
|
#define _XOPEN_SOURCE 500
|
||||||
|
AC_INCLUDES_DEFAULT
|
||||||
|
#include <sys/socket.h>
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
|
||||||
|
case x$have_sendmsg in
|
||||||
|
xyes)
|
||||||
|
AC_DEFINE([HAVE_SENDMSG],1,[Define if your platform supports sendmsg])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
have_win32="no"
|
||||||
|
lt_enable_auto_import=""
|
||||||
case $host_os in
|
case $host_os in
|
||||||
|
mingw*)
|
||||||
|
have_win32="yes"
|
||||||
|
lt_enable_auto_import="-Wl,--enable-auto-import"
|
||||||
|
;;
|
||||||
linux*)
|
linux*)
|
||||||
AC_DEFINE([HAVE_ABSTRACT_SOCKETS], 1, [Define if your platform supports abstract sockets])
|
AC_DEFINE([HAVE_ABSTRACT_SOCKETS], 1, [Define if your platform supports abstract sockets])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
AC_SUBST(lt_enable_auto_import)
|
||||||
|
AM_CONDITIONAL([XCB_HAVE_WIN32], [test "x${have_win32}" = "xyes"])
|
||||||
|
|
||||||
dnl define buffer queue size
|
dnl define buffer queue size
|
||||||
AC_ARG_WITH([queue-size],
|
AC_ARG_WITH([queue-size],
|
||||||
AC_HELP_STRING([--with-queue-size=SIZE],
|
AS_HELP_STRING([--with-queue-size=SIZE],
|
||||||
[Set the XCB buffer queue size (default is 16384)]),
|
[Set the XCB buffer queue size (default is 16384)]),
|
||||||
[xcb_queue_buffer_size="$withval"],
|
[xcb_queue_buffer_size="$withval"],
|
||||||
[xcb_queue_buffer_size=16384])
|
[xcb_queue_buffer_size=16384])
|
||||||
|
@ -95,76 +169,93 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl check for support for Solaris Trusted Extensions
|
||||||
|
AC_CHECK_HEADERS([tsol/label.h])
|
||||||
|
AC_CHECK_FUNCS([is_system_labeled])
|
||||||
|
|
||||||
|
dnl check for IOV_MAX, and fall back to UIO_MAXIOV on BSDish systems
|
||||||
|
AC_CHECK_DECL([IOV_MAX], [],
|
||||||
|
[AC_CHECK_DECL([UIO_MAXIOV], [AC_DEFINE([IOV_MAX], [UIO_MAXIOV])],
|
||||||
|
[AC_DEFINE([IOV_MAX], [16], [Define if not provided by <limits.h>])],
|
||||||
|
[[#include <sys/uio.h>]])],
|
||||||
|
[[#include <limits.h>]])
|
||||||
|
|
||||||
xcbincludedir='${includedir}/xcb'
|
xcbincludedir='${includedir}/xcb'
|
||||||
AC_SUBST(xcbincludedir)
|
AC_SUBST(xcbincludedir)
|
||||||
|
|
||||||
if test "x$GCC" = xyes ; then
|
|
||||||
CWARNFLAGS="-Wall -pedantic -Wpointer-arith \
|
|
||||||
-Wstrict-prototypes -Wmissing-declarations -Wnested-externs"
|
|
||||||
else
|
|
||||||
AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"])
|
|
||||||
if test "x$SUNCC" = "xyes"; then
|
|
||||||
CWARNFLAGS="-v"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(CWARNFLAGS)
|
|
||||||
|
|
||||||
XCB_CHECK_VISIBILITY()
|
XCB_CHECK_VISIBILITY()
|
||||||
|
|
||||||
# htmldir is not defined prior to autoconf 2.59c, so on earlier versions
|
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
|
||||||
# set an equivalent value.
|
|
||||||
AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
|
|
||||||
['${datadir}/doc/${PACKAGE_TARNAME}'],
|
|
||||||
['${datadir}/doc/${PACKAGE}'])
|
|
||||||
])])
|
|
||||||
|
|
||||||
XCB_CHECK_DOXYGEN()
|
|
||||||
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
# darwin has poll() but can't be used to poll character devices (atleast through SnowLeopard)
|
# darwin through Snow Leopard has poll() but can't be used to poll character devices.
|
||||||
darwin*) ;;
|
darwin@<:@789@:>@*|darwin10*) ;;
|
||||||
|
darwin*)
|
||||||
|
_ac_xorg_macosx_version_min=""
|
||||||
|
if echo $CPPFLAGS $CFLAGS | grep -q mmacosx-version-min ; then
|
||||||
|
_ac_xorg_macosx_version_min=`echo $CPPFLAGS $CFLAGS | sed 's/^.*-mmacosx-version-min=\(@<:@^ @:>@*\).*$/\1/'`
|
||||||
|
else
|
||||||
|
_ac_xorg_macosx_version_min=$MACOSX_DEPLOYMENT_TARGET
|
||||||
|
fi
|
||||||
|
case $_ac_xorg_macosx_version_min in
|
||||||
|
10.@<:@0123456@:>@|10.@<:@0123456@:>@.*) ;;
|
||||||
|
*)
|
||||||
|
AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
unset _ac_xorg_macosx_version_min
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
|
AC_CHECK_FUNC(poll, [AC_DEFINE(USE_POLL, 1, [poll() function is available])], )
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
XCB_EXTENSION(Composite, "yes")
|
dnl Link with winsock for socket functions on MinGW
|
||||||
XCB_EXTENSION(Damage, "yes")
|
case $host_os in
|
||||||
XCB_EXTENSION(DPMS, "yes")
|
*mingw*)
|
||||||
XCB_EXTENSION(DRI2, "yes")
|
AC_CHECK_LIB([ws2_32],[main])
|
||||||
XCB_EXTENSION(GLX, "yes")
|
;;
|
||||||
XCB_EXTENSION(RandR, "yes")
|
*)
|
||||||
XCB_EXTENSION(Record, "yes")
|
;;
|
||||||
XCB_EXTENSION(Render, "yes")
|
esac
|
||||||
XCB_EXTENSION(Resource, "yes")
|
|
||||||
XCB_EXTENSION(Screensaver, "yes")
|
|
||||||
XCB_EXTENSION(Shape, "yes")
|
|
||||||
XCB_EXTENSION(Shm, "yes")
|
|
||||||
XCB_EXTENSION(Sync, "yes")
|
|
||||||
XCB_EXTENSION(Xevie, "yes")
|
|
||||||
XCB_EXTENSION(XFixes, "yes")
|
|
||||||
XCB_EXTENSION(XFree86-DRI, "yes")
|
|
||||||
XCB_EXTENSION(Xinerama, "yes")
|
|
||||||
XCB_EXTENSION(XInput, "no")
|
|
||||||
XCB_EXTENSION(Xprint, "yes")
|
|
||||||
XCB_EXTENSION(SELinux, "no")
|
|
||||||
XCB_EXTENSION(XTest, "yes")
|
|
||||||
XCB_EXTENSION(Xv, "yes")
|
|
||||||
XCB_EXTENSION(XvMC, "yes")
|
|
||||||
|
|
||||||
AC_ARG_WITH(launchd, AS_HELP_STRING([--with-launchd], [Build with support for Apple's launchd (default: auto)]), [LAUNCHD=$withval], [LAUNCHD=auto])
|
XCB_EXTENSION(Composite, yes)
|
||||||
if test "x$LAUNCHD" = xauto; then
|
XCB_EXTENSION(Damage, yes)
|
||||||
unset LAUNCHD
|
XCB_EXTENSION(Dbe, yes)
|
||||||
AC_CHECK_PROG(LAUNCHD, [launchd], [yes], [no], [$PATH$PATH_SEPARATOR/sbin])
|
XCB_EXTENSION(DPMS, yes)
|
||||||
fi
|
XCB_EXTENSION(DRI2, yes)
|
||||||
|
XCB_EXTENSION(DRI3, $have_sendmsg)
|
||||||
|
XCB_EXTENSION(GE, no)
|
||||||
|
XCB_EXTENSION(GLX, yes)
|
||||||
|
XCB_EXTENSION(Present, yes)
|
||||||
|
XCB_EXTENSION(RandR, yes)
|
||||||
|
XCB_EXTENSION(Record, yes)
|
||||||
|
XCB_EXTENSION(Render, yes)
|
||||||
|
XCB_EXTENSION(Resource, yes)
|
||||||
|
XCB_EXTENSION(Screensaver, yes)
|
||||||
|
XCB_EXTENSION(Shape, yes)
|
||||||
|
XCB_EXTENSION(Shm, yes)
|
||||||
|
XCB_EXTENSION(Sync, yes)
|
||||||
|
XCB_EXTENSION(Xevie, no)
|
||||||
|
XCB_EXTENSION(XFixes, yes)
|
||||||
|
XCB_EXTENSION(XFree86-DRI, yes)
|
||||||
|
XCB_EXTENSION(Xinerama, yes)
|
||||||
|
XCB_EXTENSION(XInput, yes)
|
||||||
|
XCB_EXTENSION(XKB, yes)
|
||||||
|
XCB_EXTENSION(Xprint, no)
|
||||||
|
XCB_EXTENSION(SELinux, no)
|
||||||
|
XCB_EXTENSION(XTest, yes)
|
||||||
|
XCB_EXTENSION(Xv, yes)
|
||||||
|
XCB_EXTENSION(XvMC, yes)
|
||||||
|
|
||||||
if test "x$LAUNCHD" = xyes ; then
|
AC_ARG_WITH(serverside-support, AS_HELP_STRING([--with-serverside-support], [Build with support for server-side usage of xcb. This is still EXPERIMENTAL! ABI/API may change! (default: no)]), [XCB_SERVERSIDE_SUPPORT=$withval], [XCB_SERVERSIDE_SUPPORT=no])
|
||||||
AC_DEFINE(HAVE_LAUNCHD, 1, [launchd support available])
|
|
||||||
fi
|
AM_CONDITIONAL(XCB_SERVERSIDE_SUPPORT, test "x$XCB_SERVERSIDE_SUPPORT" = "xyes")
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
|
man/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
])
|
])
|
||||||
|
@ -173,9 +264,13 @@ AC_CONFIG_FILES([
|
||||||
xcb.pc
|
xcb.pc
|
||||||
xcb-composite.pc
|
xcb-composite.pc
|
||||||
xcb-damage.pc
|
xcb-damage.pc
|
||||||
|
xcb-dbe.pc
|
||||||
xcb-dpms.pc
|
xcb-dpms.pc
|
||||||
xcb-dri2.pc
|
xcb-dri2.pc
|
||||||
|
xcb-dri3.pc
|
||||||
|
xcb-ge.pc
|
||||||
xcb-glx.pc
|
xcb-glx.pc
|
||||||
|
xcb-present.pc
|
||||||
xcb-randr.pc
|
xcb-randr.pc
|
||||||
xcb-record.pc
|
xcb-record.pc
|
||||||
xcb-render.pc
|
xcb-render.pc
|
||||||
|
@ -189,6 +284,7 @@ xcb-xf86dri.pc
|
||||||
xcb-xfixes.pc
|
xcb-xfixes.pc
|
||||||
xcb-xinerama.pc
|
xcb-xinerama.pc
|
||||||
xcb-xinput.pc
|
xcb-xinput.pc
|
||||||
|
xcb-xkb.pc
|
||||||
xcb-xprint.pc
|
xcb-xprint.pc
|
||||||
xcb-xselinux.pc
|
xcb-xselinux.pc
|
||||||
xcb-xtest.pc
|
xcb-xtest.pc
|
||||||
|
@ -209,14 +305,19 @@ echo " Package: ${PACKAGE_NAME} ${PACKAGE_VERSION}"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Configuration"
|
echo " Configuration"
|
||||||
echo " XDM support.........: ${have_xdmcp}"
|
echo " XDM support.........: ${have_xdmcp}"
|
||||||
|
echo " sendmsg fd passing..: ${have_sendmsg}"
|
||||||
echo " Build unit tests....: ${HAVE_CHECK}"
|
echo " Build unit tests....: ${HAVE_CHECK}"
|
||||||
|
echo " with html results.: ${HTML_CHECK_RESULT}"
|
||||||
echo " XCB buffer size.....: ${xcb_queue_buffer_size}"
|
echo " XCB buffer size.....: ${xcb_queue_buffer_size}"
|
||||||
echo ""
|
echo ""
|
||||||
echo " X11 extensions"
|
echo " X11 extensions"
|
||||||
echo " Composite...........: ${BUILD_COMPOSITE}"
|
echo " Composite...........: ${BUILD_COMPOSITE}"
|
||||||
echo " Damage..............: ${BUILD_DAMAGE}"
|
echo " Damage..............: ${BUILD_DAMAGE}"
|
||||||
|
echo " Dbe.................: ${BUILD_DBE}"
|
||||||
echo " Dpms................: ${BUILD_DPMS}"
|
echo " Dpms................: ${BUILD_DPMS}"
|
||||||
echo " Dri2................: ${BUILD_DRI2}"
|
echo " Dri2................: ${BUILD_DRI2}"
|
||||||
|
echo " Dri3................: ${BUILD_DRI3}"
|
||||||
|
echo " GenericEvent........: ${BUILD_GE}"
|
||||||
echo " Glx.................: ${BUILD_GLX}"
|
echo " Glx.................: ${BUILD_GLX}"
|
||||||
echo " Randr...............: ${BUILD_RANDR}"
|
echo " Randr...............: ${BUILD_RANDR}"
|
||||||
echo " Record..............: ${BUILD_RECORD}"
|
echo " Record..............: ${BUILD_RECORD}"
|
||||||
|
@ -232,6 +333,7 @@ echo " Xfixes..............: ${BUILD_XFIXES}"
|
||||||
echo " Xfree86-dri.........: ${BUILD_XFREE86_DRI}"
|
echo " Xfree86-dri.........: ${BUILD_XFREE86_DRI}"
|
||||||
echo " xinerama............: ${BUILD_XINERAMA}"
|
echo " xinerama............: ${BUILD_XINERAMA}"
|
||||||
echo " xinput..............: ${BUILD_XINPUT}"
|
echo " xinput..............: ${BUILD_XINPUT}"
|
||||||
|
echo " xkb.................: ${BUILD_XKB}"
|
||||||
echo " xprint..............: ${BUILD_XPRINT}"
|
echo " xprint..............: ${BUILD_XPRINT}"
|
||||||
echo " xtest...............: ${BUILD_XTEST}"
|
echo " xtest...............: ${BUILD_XTEST}"
|
||||||
echo " xv..................: ${BUILD_XV}"
|
echo " xv..................: ${BUILD_XV}"
|
||||||
|
@ -240,7 +342,6 @@ echo ""
|
||||||
echo " Used CFLAGS:"
|
echo " Used CFLAGS:"
|
||||||
echo " CPPFLAGS............: ${CPPFLAGS}"
|
echo " CPPFLAGS............: ${CPPFLAGS}"
|
||||||
echo " CFLAGS..............: ${CFLAGS}"
|
echo " CFLAGS..............: ${CFLAGS}"
|
||||||
echo " Warning CFLAGS......: ${CWARNFLAGS}"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Installation:"
|
echo " Installation:"
|
||||||
echo " Prefix..............: ${prefix}"
|
echo " Prefix..............: ${prefix}"
|
||||||
|
|
|
@ -2,11 +2,15 @@
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
tutorial/index.html \
|
tutorial/index.html \
|
||||||
tutorial/xcb.css \
|
tutorial/xcb.css \
|
||||||
xcb.doxygen.in
|
xcb.doxygen.in \
|
||||||
|
xkb_internals \
|
||||||
|
xkb_issues
|
||||||
|
|
||||||
docdirs = $(srcdir)/tutorial
|
docdirs = $(srcdir)/tutorial
|
||||||
|
|
||||||
if BUILD_DOCS
|
if ENABLE_DEVEL_DOCS
|
||||||
|
if HAVE_DOXYGEN
|
||||||
|
if HAVE_DOT
|
||||||
|
|
||||||
docdirs += manual
|
docdirs += manual
|
||||||
|
|
||||||
|
@ -19,6 +23,8 @@ clean-local:
|
||||||
rm -rf manual/
|
rm -rf manual/
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
all-local: $(docdirs)
|
all-local: $(docdirs)
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
<li><a class="subsection" href="#DoesBackingStore">DoesBackingStore</a>
|
<li><a class="subsection" href="#DoesBackingStore">DoesBackingStore</a>
|
||||||
<li><a class="subsection" href="#EventMaskOfScreen">EventMaskOfScreen</a>
|
<li><a class="subsection" href="#EventMaskOfScreen">EventMaskOfScreen</a>
|
||||||
</ol>
|
</ol>
|
||||||
<li><a class="subsection" href="#misc">Miscellaneaous macros</a>
|
<li><a class="subsection" href="#misc">Miscellaneous macros</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a class="subsection" href="#DisplayOfScreen">DisplayOfScreen</a>
|
<li><a class="subsection" href="#DisplayOfScreen">DisplayOfScreen</a>
|
||||||
<li><a class="subsection" href="#DisplayCells">DisplayCells / CellsOfScreen</a>
|
<li><a class="subsection" href="#DisplayCells">DisplayCells / CellsOfScreen</a>
|
||||||
|
@ -1331,7 +1331,7 @@ main ()
|
||||||
/* We draw the polygonal line */
|
/* We draw the polygonal line */
|
||||||
xcb_poly_line (c, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline);
|
xcb_poly_line (c, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline);
|
||||||
|
|
||||||
/* We draw the segements */
|
/* We draw the segments */
|
||||||
xcb_poly_segment (c, win, foreground, 2, segments);
|
xcb_poly_segment (c, win, foreground, 2, segments);
|
||||||
|
|
||||||
/* We draw the rectangles */
|
/* We draw the rectangles */
|
||||||
|
@ -1470,10 +1470,10 @@ xcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values);
|
||||||
</pre>
|
</pre>
|
||||||
<div class="emph">
|
<div class="emph">
|
||||||
<p>
|
<p>
|
||||||
Note: A common bug programmers do is adding code to handle new
|
Note: A common bug programmers have is adding code to handle new
|
||||||
event types in their program, while forgetting to add the
|
event types in their program, while forgetting to add the
|
||||||
masks for these events in the creation of the window. Such a
|
masks for these events in the creation of the window. Such a
|
||||||
programmer then should sit down for hours debugging his
|
programmer would then sit there for hours debugging their
|
||||||
program, wondering "Why doesn't my program notice that I
|
program, wondering "Why doesn't my program notice that I
|
||||||
released the button?", only to find that they registered for
|
released the button?", only to find that they registered for
|
||||||
button press events but not for button release events.
|
button press events but not for button release events.
|
||||||
|
@ -1830,7 +1830,7 @@ typedef xcb_enter_notify_event_t xcb_leave_notify_event_t;
|
||||||
keyboard focus using the window manager (often by clicking
|
keyboard focus using the window manager (often by clicking
|
||||||
on the title bar of the desired window). Once our window
|
on the title bar of the desired window). Once our window
|
||||||
has the keyboard focus, every key press or key release will
|
has the keyboard focus, every key press or key release will
|
||||||
cause an event to be sent to our program (if it regsitered
|
cause an event to be sent to our program (if it registered
|
||||||
for these event types...).
|
for these event types...).
|
||||||
</p>
|
</p>
|
||||||
<li class="subsubtitle"><a name="keypress">Keyboard press and release events</a>
|
<li class="subsubtitle"><a name="keypress">Keyboard press and release events</a>
|
||||||
|
@ -2090,7 +2090,7 @@ xcb_void_cookie_t xcb_open_font (xcb_connection_t *c,
|
||||||
Once a font is opened, you have to create a Graphic Context
|
Once a font is opened, you have to create a Graphic Context
|
||||||
that will contain the informations about the color of the
|
that will contain the informations about the color of the
|
||||||
foreground and the background used when you draw a text in a
|
foreground and the background used when you draw a text in a
|
||||||
Drawable. Here is an exemple of a Graphic Context that will
|
Drawable. Here is an example of a Graphic Context that will
|
||||||
allow us to draw an opened font with a black foreground and a
|
allow us to draw an opened font with a black foreground and a
|
||||||
white background:
|
white background:
|
||||||
</p>
|
</p>
|
||||||
|
@ -2297,9 +2297,7 @@ int main ()
|
||||||
values[0] = screen->white_pixel;
|
values[0] = screen->white_pixel;
|
||||||
values[1] =
|
values[1] =
|
||||||
XCB_EVENT_MASK_KEY_RELEASE |
|
XCB_EVENT_MASK_KEY_RELEASE |
|
||||||
XCB_EVENT_MASK_BUTTON_PRESS |
|
XCB_EVENT_MASK_EXPOSURE;
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
|
||||||
XCB_EVENT_MASK_POINTER_MOTION;
|
|
||||||
cookie_window = xcb_create_window_checked (c,
|
cookie_window = xcb_create_window_checked (c,
|
||||||
screen->root_depth,
|
screen->root_depth,
|
||||||
window, screen->root,
|
window, screen->root,
|
||||||
|
@ -2404,7 +2402,7 @@ xcb_void_cookie_t xcb_change_property (xcb_connection_t *c, /* Connection
|
||||||
const void *data); /* Data */
|
const void *data); /* Data */
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
The <span class="code">mode</span> parameter coud be one of
|
The <span class="code">mode</span> parameter could be one of
|
||||||
the following values (defined in enumeration xcb_prop_mode_t in
|
the following values (defined in enumeration xcb_prop_mode_t in
|
||||||
the xproto.h header file):
|
the xproto.h header file):
|
||||||
</p>
|
</p>
|
||||||
|
@ -2939,7 +2937,7 @@ xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connecti
|
||||||
latter case, each time the mouse moves onto your window, the
|
latter case, each time the mouse moves onto your window, the
|
||||||
screen color map will be replaced by your window's color map,
|
screen color map will be replaced by your window's color map,
|
||||||
and you'll see all the other windows on screen change their
|
and you'll see all the other windows on screen change their
|
||||||
colors into something quite bizzare. In fact, this is the
|
colors into something quite bizarre. In fact, this is the
|
||||||
effect you get with X applications that use the "-install"
|
effect you get with X applications that use the "-install"
|
||||||
command line option.
|
command line option.
|
||||||
</p>
|
</p>
|
||||||
|
@ -3302,10 +3300,10 @@ xcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c, /* Pointer to the
|
||||||
<li class="title"><a name="mousecursor">Messing with the mouse cursor</a>
|
<li class="title"><a name="mousecursor">Messing with the mouse cursor</a>
|
||||||
<p>
|
<p>
|
||||||
It it possible to modify the shape of the mouse pointer (also
|
It it possible to modify the shape of the mouse pointer (also
|
||||||
called the X pointer) when in certain states, as we otfen see in
|
called the X pointer) when in certain states, as we often see in
|
||||||
programs. For example, a busy application would often display
|
programs. For example, a busy application would often display
|
||||||
the sand clock over its main window, to give the user a visual
|
the hourglass cursor over its main window, to give the user a visual
|
||||||
hint that he should wait. Let's see how we can change the mouse
|
hint that they should wait. Let's see how we can change the mouse
|
||||||
cursor of our windows.
|
cursor of our windows.
|
||||||
</p>
|
</p>
|
||||||
<ol>
|
<ol>
|
||||||
|
@ -3341,7 +3339,7 @@ xcb_void_cookie_t xcb_create_glyph_cursor (xcb_connection_t *c,
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
So we first open that font (see <a href="#loadfont">Loading a Font</a>)
|
So we first open that font (see <a href="#loadfont">Loading a Font</a>)
|
||||||
and create the new cursor. As for every X ressource, we have to
|
and create the new cursor. As for every X resource, we have to
|
||||||
ask for an X id with <span class="code">xcb_generate_id</span>
|
ask for an X id with <span class="code">xcb_generate_id</span>
|
||||||
first:
|
first:
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
|
||||||
|
XKB introduces several uncommon data structures:
|
||||||
|
- switch allows conditional inclusion of fields
|
||||||
|
- several complex objects intermix variable and fixed size fields
|
||||||
|
- lists with a variable number of variable size objects
|
||||||
|
|
||||||
|
To handle these objects, a number of new functions is generated:
|
||||||
|
- _serialize() turns a structured object into a byte stream,
|
||||||
|
(re)ordering or including fields according to the protocol
|
||||||
|
- _unserialize() rewrites data from a buffer into a structured object
|
||||||
|
- _unpack() expands a buffer representing a switch object into
|
||||||
|
a special structured type, all flags needed to resolve the switch
|
||||||
|
expression have to given as parameters
|
||||||
|
- _sizeof() calculates the size of a serialized object, often by calling
|
||||||
|
_unserialize()/_unpack() internally
|
||||||
|
|
||||||
|
The new structured data type for switch is special as it contains fixed
|
||||||
|
and variable size fields. Variable size fields can be accessed via pointers.
|
||||||
|
|
||||||
|
If switch appears in a request, an additional set of request helpers is
|
||||||
|
generated with the suffix _aux or _aux_(un)checked. While the 'common'
|
||||||
|
request functions require that switch has been serialized before, the _aux
|
||||||
|
variants take the structured data type. They are especially designed to
|
||||||
|
replace certain functions in xcb-util/aux.
|
||||||
|
|
||||||
|
Accessors for switch members need two parameters, where the first is usually
|
||||||
|
a pointer to the respective request or reply structure, while the second
|
||||||
|
is a pointer to the unpacked switch data structure.
|
||||||
|
|
||||||
|
Functions from the serialize family that take a double pointer can allocate
|
||||||
|
memory on their own, which is useful if the size of a buffer has to be
|
||||||
|
calculated depending on the data within. These functions call malloc() when
|
||||||
|
the double pointer is given as the address of a pointer that has been
|
||||||
|
initialized to 0. It is the responsibility of the user to free any allocated
|
||||||
|
memory.
|
||||||
|
|
||||||
|
Intermixed variable and fixed size fields are an important special case in XKB.
|
||||||
|
The current implementation resolves the issue by reordering the fields before
|
||||||
|
sending them on the wire as well as before returning a reply. That means that
|
||||||
|
these objects look like 'common' XCB data types and they can be accessed as such
|
||||||
|
(i.e. fixed size fields directly via the structured type and variable size fields
|
||||||
|
via accessors/iterators).
|
||||||
|
|
||||||
|
In case a list with variable size elements needs to be accessed, it is necessary
|
||||||
|
to use iterators. The iterator functions take care of determining the actual
|
||||||
|
object size for each element automatically.
|
||||||
|
|
||||||
|
A small and preliminary set of auxiliary functions is available in xkb_util.c
|
||||||
|
in the check_xkb module.
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
There are a number of problematic special cases in XKB. The issues
|
||||||
|
mentioned here are at most partly resolved.
|
||||||
|
|
||||||
|
1. The are several XxxDoodad structures defined in xkb.xml. They are used
|
||||||
|
in a few lists, but in a rather special way:
|
||||||
|
The struct "CommonDoodad" is supposed to be a rather generic data type,
|
||||||
|
combining the most basic Doodad fields that are common in all these structures.
|
||||||
|
All Doodads are encapsulated in a union type simply called "Doodad".
|
||||||
|
Now this union is used in subsequent list definitions, aiming at a kind of
|
||||||
|
'polymorphism': From inspection of the protocol and Xlib, the Doodads are to
|
||||||
|
be discriminated based on their type field.
|
||||||
|
However the special meaning of the type field is not encoded in the protocol.
|
||||||
|
Furthermore the TextDoodad and the LogoDoodad are variable size types due to
|
||||||
|
some fields of type CountedString16, thereby turning the union into a
|
||||||
|
possibly variable size type as well.
|
||||||
|
However, for lists with variable size elements, special sizeof functions are
|
||||||
|
required. These cannot be autogenerated as it cannot be referred which
|
||||||
|
Doodad type to use for the union.
|
||||||
|
Therefore, the Doodad type structures are unsupported at the moment.
|
||||||
|
|
||||||
|
2. There are still some bugs in xkb.xml: Either certain fields are missing
|
||||||
|
that are required by the protocol, or Xlib simply has another understanding
|
||||||
|
of the protocol.
|
||||||
|
|
||||||
|
3. The interface for accessors should be reviewed.
|
||||||
|
|
||||||
|
4. Currently some bitcases carry 'name' attributes. These could be avoided if
|
||||||
|
the data within would consist of a singe struct field only.
|
||||||
|
|
||||||
|
5. switch could get a 'fixed_size' attribute, so when rewriting valueparam to switch,
|
||||||
|
an uint32_t * pointer could be used instead of void *.
|
||||||
|
|
||||||
|
6. The automatic inclusion of padding requires some complicated coding in the
|
||||||
|
generator. This is errorprone and could be avoided if all padding is explicitly
|
||||||
|
given in the protocol definition. For variable size fields that require padding,
|
||||||
|
the pad tag could get a 'fieldref' attribute. That way padding could be handled
|
||||||
|
a lot easier in the autogenerator.
|
|
@ -0,0 +1,4 @@
|
||||||
|
[wrap-git]
|
||||||
|
url = https://gitea.gigo-games.dk/frederik/libxcb.git
|
||||||
|
revision = HEAD
|
||||||
|
depth = 1
|
|
@ -0,0 +1,70 @@
|
||||||
|
dnl Detection and configuration of the visibility feature of gcc
|
||||||
|
dnl Vincent Torri 2006-02-11
|
||||||
|
dnl
|
||||||
|
dnl XCB_CHECK_VISIBILITY([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||||
|
dnl Check the visibility feature of gcc
|
||||||
|
dnl
|
||||||
|
AC_DEFUN([XCB_CHECK_VISIBILITY],
|
||||||
|
[
|
||||||
|
AC_MSG_CHECKING([whether ${CC} supports symbol visibility])
|
||||||
|
|
||||||
|
save_CFLAGS=${CFLAGS}
|
||||||
|
CFLAGS="$CFLAGS -fvisibility=hidden -fvisibility-inlines-hidden"
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[[
|
||||||
|
#pragma GCC visibility push(hidden)
|
||||||
|
extern void f(int);
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
]],
|
||||||
|
[[]]
|
||||||
|
)],
|
||||||
|
[AC_DEFINE(
|
||||||
|
GCC_HAS_VISIBILITY,
|
||||||
|
[],
|
||||||
|
[Defined if GCC supports the visibility feature])
|
||||||
|
m4_if([$1], [], [:], [$1])
|
||||||
|
AC_MSG_RESULT(yes)],
|
||||||
|
[m4_if([$2], [], [:], [$2])
|
||||||
|
AC_MSG_RESULT(no)])
|
||||||
|
|
||||||
|
CFLAGS=${save_CFLAGS}
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Detection and configuration of the visibility feature of gcc
|
||||||
|
dnl Vincent Torri 2006-02-11
|
||||||
|
dnl
|
||||||
|
dnl XCB_EXTENSION(name, default)
|
||||||
|
dnl set the X extension
|
||||||
|
dnl
|
||||||
|
AC_DEFUN([XCB_EXTENSION],
|
||||||
|
[dnl
|
||||||
|
pushdef([UP], translit([$1], [-a-z], [_A-Z]))dnl
|
||||||
|
pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl
|
||||||
|
dnl
|
||||||
|
m4_if([$2], [yes], [m4_define([xcb_defopt], [yes])],
|
||||||
|
[$2], [no], [m4_define([xcb_defopt], [no])],
|
||||||
|
m4_define([xcb_defopt], [auto]))dnl
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(DOWN,
|
||||||
|
[AS_HELP_STRING([--enable-[]DOWN],
|
||||||
|
[Build XCB $1 Extension (default: ]xcb_defopt[)])],
|
||||||
|
[BUILD_[]UP=$enableval],
|
||||||
|
[BUILD_[]UP=xcb_defopt])
|
||||||
|
dnl
|
||||||
|
m4_if(xcb_defopt, [auto], [
|
||||||
|
# This extension has a default value of "auto" and depends on the value of $2
|
||||||
|
if test "x$BUILD_[]UP" = "xauto" ; then
|
||||||
|
BUILD_[]UP=$2
|
||||||
|
fi
|
||||||
|
if test "x$BUILD_[]UP" = "xyes" ; then
|
||||||
|
if test "x$2" = "xno" ; then
|
||||||
|
AC_MSG_ERROR([Extension []UP requested, but dependencies are not met])
|
||||||
|
fi
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_undefine([xcb_defopt])dnl
|
||||||
|
AM_CONDITIONAL(BUILD_[]UP, [test "x$BUILD_[]UP" = "xyes"])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl End of acinclude.m4
|
|
@ -0,0 +1 @@
|
||||||
|
*.[0-9]
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
libmandir = $(LIB_MAN_DIR)
|
||||||
|
|
||||||
|
libman_PRE = \
|
||||||
|
xcb-examples.man \
|
||||||
|
xcb-requests.man
|
||||||
|
|
||||||
|
libman_DATA = $(libman_PRE:man=$(LIB_MAN_SUFFIX))
|
||||||
|
|
||||||
|
EXTRA_DIST = $(libman_PRE)
|
||||||
|
|
||||||
|
CLEANFILES = $(libman_DATA)
|
||||||
|
|
||||||
|
# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
|
||||||
|
SUFFIXES = .$(LIB_MAN_SUFFIX) .man
|
||||||
|
|
||||||
|
.man.$(LIB_MAN_SUFFIX):
|
||||||
|
$(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
|
|
@ -0,0 +1,59 @@
|
||||||
|
.TH xcb-examples __libmansuffix__ __xorgversion__ "XCB examples"
|
||||||
|
.ad l
|
||||||
|
.SH NAME
|
||||||
|
xcb-examples \- manpage examples
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Many of the XCB manpages contain example code. These examples intend to explain
|
||||||
|
how to use one particular part of XCB. They almost never represent a standalone
|
||||||
|
(or even useful) program - X11 programs are relatively involved and
|
||||||
|
thus beyond the scope of a manpage example.
|
||||||
|
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
|
||||||
|
Every example assumes you have an \fIxcb_connection\fP and possibly other
|
||||||
|
variables at hand. For illustrating how \fIxcb_get_property\fP works, you need
|
||||||
|
the window of which you want to get the property, for example. To make it clear
|
||||||
|
that these variables are your responsibility, these examples consist of a
|
||||||
|
single function which takes the necessary variables as parameters.
|
||||||
|
|
||||||
|
.SH FLUSHING
|
||||||
|
|
||||||
|
Flushing means calling \fIxcb_flush\fP to clear the XCB-internal write buffer
|
||||||
|
and send all pending requests to the X11 server. You don't explicitly need to
|
||||||
|
flush before using a reply function (like \fIxcb_query_pointer_reply\fP), but
|
||||||
|
you do need to flush before entering the event loop of your program.
|
||||||
|
|
||||||
|
There are only two cases when XCB flushes by itself. The first case is when
|
||||||
|
its write buffer becomes full, the second case is when you are asking for
|
||||||
|
the reply of a request which wasn't flushed out yet (like
|
||||||
|
\fIxcb_query_pointer_reply\fP). This last point also includes
|
||||||
|
xcb_request_check(). Please note that waiting for an event does \fBNOT\fP
|
||||||
|
flush.
|
||||||
|
|
||||||
|
Examples generally include the \fIxcb_flush\fP call where appropriate (for
|
||||||
|
example after setting a property). Therefore, including these functions and
|
||||||
|
calling them in your application should just work. However, you might get
|
||||||
|
better results when flushing outside of the function, depending on the
|
||||||
|
architecture of your program.
|
||||||
|
|
||||||
|
.SH COMPILATION
|
||||||
|
|
||||||
|
If an example does not compile (without warnings) when using \fI-std=c99\fP,
|
||||||
|
that is considered a documentation bug. Similarly, not handling errors or
|
||||||
|
leaking memory is also considered a documentation bug. Please inform us about
|
||||||
|
it on xcb@lists.freedesktop.org.
|
||||||
|
|
||||||
|
.SH CODING STYLE
|
||||||
|
|
||||||
|
Every example uses 4 spaces for indentation.
|
||||||
|
|
||||||
|
Comments are in asterisks, like /* this */.
|
||||||
|
|
||||||
|
No line is longer than 80 characters (including indentation).
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR xcb_connect (__libmansuffix__),
|
||||||
|
.BR xcb_get_property (__libmansuffix__),
|
||||||
|
.BR xcb_flush (__libmansuffix__)
|
||||||
|
.SH AUTHOR
|
||||||
|
Michael Stapelberg <michael+xcb at stapelberg dot de>
|
|
@ -0,0 +1,165 @@
|
||||||
|
.TH xcb-requests __libmansuffix__ __xorgversion__ "XCB examples"
|
||||||
|
.ad l
|
||||||
|
.SH NAME
|
||||||
|
xcb-requests \- about request manpages
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Every request in X11, like \fIMapWindow\fP, corresponds to a number of
|
||||||
|
functions and data structures in XCB. For \fIMapWindow\fP, XCB provides the
|
||||||
|
function \fIxcb_map_window\fP, which fills the \fIxcb_map_window_request_t\fP
|
||||||
|
data structure and writes that to the X11 connection. Since the \fIMapWindow\fP
|
||||||
|
request does not have a reply, this is the most simple case.
|
||||||
|
|
||||||
|
.SH REPLIES
|
||||||
|
|
||||||
|
Many requests have replies. For each reply, XCB provides at least a
|
||||||
|
corresponding data structure and a function to return a pointer to a filled
|
||||||
|
data structure. Let's take the \fIInternAtom\fP request as an example: XCB
|
||||||
|
provides the \fIxcb_intern_atom_reply_t\fP data structure and
|
||||||
|
\fIxcb_intern_atom_reply\fP function. For replies which are more complex (for
|
||||||
|
example lists, such as in \fIxcb_list_fonts\fP), accessor functions are
|
||||||
|
provided.
|
||||||
|
|
||||||
|
.SH COOKIES
|
||||||
|
|
||||||
|
XCB returns a cookie for each request you send. This is an XCB-specific data
|
||||||
|
structure containing the sequence number with which the request was sent to the
|
||||||
|
X11 server. To get any reply, you have to provide that cookie (so that XCB
|
||||||
|
knows which of the waiting replies you want). Here is an example to illustrate
|
||||||
|
the use of cookies:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.sp
|
||||||
|
void my_example(xcb_connection *conn) {
|
||||||
|
xcb_intern_atom_cookie_t cookie;
|
||||||
|
xcb_intern_atom_reply_t *reply;
|
||||||
|
|
||||||
|
cookie = xcb_intern_atom(conn, 0, strlen("_NET_WM_NAME"), "_NET_WM_NAME");
|
||||||
|
/* ... do other work here if possible ... */
|
||||||
|
if ((reply = xcb_intern_atom_reply(conn, cookie, NULL))) {
|
||||||
|
printf("The _NET_WM_NAME atom has ID %u\\n", reply->atom);
|
||||||
|
}
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH CHECKED VS. UNCHECKED
|
||||||
|
|
||||||
|
The checked and unchecked suffixes for functions determine which kind of error
|
||||||
|
handling is used for this specific request.
|
||||||
|
|
||||||
|
For requests which have no reply (for example \fIxcb_map_window\fP), errors
|
||||||
|
will be delivered to the event loop (you will receive an X11 event of type 0
|
||||||
|
when calling \fIxcb_poll_for_event\fP).
|
||||||
|
If you want to explicitly check for errors in a blocking fashion, call the
|
||||||
|
_checked version of the function (for example \fIxcb_map_window_checked\fP) and
|
||||||
|
use \fIxcb_request_check\fP.
|
||||||
|
|
||||||
|
For requests which have a reply (for example \fIxcb_intern_atom\fP), errors
|
||||||
|
will be checked when calling the reply function. To get errors in the event
|
||||||
|
loop instead, use the _unchecked version of the function (for example
|
||||||
|
\fIxcb_intern_atom_unchecked\fP).
|
||||||
|
|
||||||
|
Here is an example which illustrates the four different ways of handling errors:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.sp
|
||||||
|
/*
|
||||||
|
* Request without a reply, handling errors in the event loop (default)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void my_example(xcb_connection *conn, xcb_window_t window) {
|
||||||
|
/* This is a request without a reply. Errors will be delivered to the event
|
||||||
|
* loop. Getting an error to xcb_map_window most likely is a bug in our
|
||||||
|
* program, so we don't need to check for that in a blocking way. */
|
||||||
|
xcb_map_window(conn, window);
|
||||||
|
|
||||||
|
/* ... of course your event loop would not be in the same function ... */
|
||||||
|
while ((event = xcb_wait_for_event(conn)) != NULL) {
|
||||||
|
if (event->response_type == 0) {
|
||||||
|
fprintf("Received X11 error %d\\n", error->error_code);
|
||||||
|
free(event);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... handle a normal event ... */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request without a reply, handling errors directly
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void my_example(xcb_connection *conn, xcb_window_t deco, xcb_window_t window) {
|
||||||
|
/* A reparenting window manager wants to know whether a new window was
|
||||||
|
* successfully reparented. If not (because the window got destroyed
|
||||||
|
* already, for example), it does not make sense to map an empty window
|
||||||
|
* decoration at all, so we need to know this right now. */
|
||||||
|
xcb_void_cookie_t cookie = xcb_reparent_window_checked(conn, window,
|
||||||
|
deco, 0, 0);
|
||||||
|
xcb_generic_error_t *error;
|
||||||
|
if ((error = xcb_request_check(conn, cookie))) {
|
||||||
|
fprintf(stderr, "Could not reparent the window\\n");
|
||||||
|
free(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... do window manager stuff here ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request with a reply, handling errors directly (default)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void my_example(xcb_connection *conn, xcb_window_t window) {
|
||||||
|
xcb_intern_atom_cookie_t cookie;
|
||||||
|
xcb_intern_atom_reply_t *reply;
|
||||||
|
xcb_generic_error_t *error;
|
||||||
|
|
||||||
|
cookie = xcb_intern_atom(c, 0, strlen("_NET_WM_NAME"), "_NET_WM_NAME");
|
||||||
|
/* ... do other work here if possible ... */
|
||||||
|
if ((reply = xcb_intern_atom_reply(c, cookie, &error))) {
|
||||||
|
printf("The _NET_WM_NAME atom has ID %u\\n", reply->atom);
|
||||||
|
free(reply);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "X11 Error %d\\n", error->error_code);
|
||||||
|
free(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request with a reply, handling errors in the event loop
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void my_example(xcb_connection *conn, xcb_window_t window) {
|
||||||
|
xcb_intern_atom_cookie_t cookie;
|
||||||
|
xcb_intern_atom_reply_t *reply;
|
||||||
|
|
||||||
|
cookie = xcb_intern_atom_unchecked(c, 0, strlen("_NET_WM_NAME"),
|
||||||
|
"_NET_WM_NAME");
|
||||||
|
/* ... do other work here if possible ... */
|
||||||
|
if ((reply = xcb_intern_atom_reply(c, cookie, NULL))) {
|
||||||
|
printf("The _NET_WM_NAME atom has ID %u\\n", reply->atom);
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... of course your event loop would not be in the same function ... */
|
||||||
|
while ((event = xcb_wait_for_event(conn)) != NULL) {
|
||||||
|
if (event->response_type == 0) {
|
||||||
|
fprintf("Received X11 error %d\\n", error->error_code);
|
||||||
|
free(event);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... handle a normal event ... */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR xcb_map_window (__libmansuffix__),
|
||||||
|
.BR xcb_intern_atom (__libmansuffix__),
|
||||||
|
.BR xcb_list_fonts (__libmansuffix__),
|
||||||
|
.BR xcb_poll_for_event (__libmansuffix__),
|
||||||
|
.BR xcb_request_check (__libmansuffix__)
|
||||||
|
.SH AUTHOR
|
||||||
|
Michael Stapelberg <michael+xcb at stapelberg dot de>
|
|
@ -1,9 +1,13 @@
|
||||||
bigreq.*
|
bigreq.*
|
||||||
composite.*
|
composite.*
|
||||||
damage.*
|
damage.*
|
||||||
|
dbe.*
|
||||||
dpms.*
|
dpms.*
|
||||||
dri2.*
|
dri2.*
|
||||||
|
dri3.*
|
||||||
|
ge.*
|
||||||
glx.*
|
glx.*
|
||||||
|
present.*
|
||||||
randr.*
|
randr.*
|
||||||
record.*
|
record.*
|
||||||
render.*
|
render.*
|
||||||
|
@ -18,6 +22,7 @@ xf86dri.*
|
||||||
xfixes.*
|
xfixes.*
|
||||||
xinerama.*
|
xinerama.*
|
||||||
xinput.*
|
xinput.*
|
||||||
|
xkb.*
|
||||||
xprint.*
|
xprint.*
|
||||||
xselinux.*
|
xselinux.*
|
||||||
xtest.*
|
xtest.*
|
||||||
|
|
114
src/Makefile.am
114
src/Makefile.am
|
@ -4,7 +4,7 @@ EXTSOURCES = xproto.c \
|
||||||
bigreq.c \
|
bigreq.c \
|
||||||
xc_misc.c
|
xc_misc.c
|
||||||
|
|
||||||
AM_CFLAGS = $(CWARNFLAGS) $(NEEDED_CFLAGS) $(XDMCP_CFLAGS)
|
AM_CFLAGS = $(BASE_CFLAGS) $(NEEDED_CFLAGS) $(XDMCP_CFLAGS)
|
||||||
libxcb_la_LIBADD = $(NEEDED_LIBS) $(XDMCP_LIBS)
|
libxcb_la_LIBADD = $(NEEDED_LIBS) $(XDMCP_LIBS)
|
||||||
libxcb_la_SOURCES = \
|
libxcb_la_SOURCES = \
|
||||||
xcb_conn.c xcb_out.c xcb_in.c xcb_ext.c xcb_xid.c \
|
xcb_conn.c xcb_out.c xcb_in.c xcb_ext.c xcb_xid.c \
|
||||||
|
@ -18,7 +18,7 @@ nodist_libxcb_la_SOURCES = xproto.c bigreq.c xc_misc.c
|
||||||
# * If you add an interface, increment current and age and set revision to 0.
|
# * If you add an interface, increment current and age and set revision to 0.
|
||||||
# * If you change or remove an interface, increment current and set revision
|
# * If you change or remove an interface, increment current and set revision
|
||||||
# and age to 0.
|
# and age to 0.
|
||||||
libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined
|
libxcb_la_LDFLAGS = -version-info 2:0:1 -no-undefined @lt_enable_auto_import@
|
||||||
|
|
||||||
XCB_LIBS = libxcb.la
|
XCB_LIBS = libxcb.la
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ XCB_LIBS = libxcb.la
|
||||||
EXTSOURCES += composite.c
|
EXTSOURCES += composite.c
|
||||||
if BUILD_COMPOSITE
|
if BUILD_COMPOSITE
|
||||||
lib_LTLIBRARIES += libxcb-composite.la
|
lib_LTLIBRARIES += libxcb-composite.la
|
||||||
libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_composite_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_composite_la_LIBADD = $(XCB_LIBS)
|
libxcb_composite_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_composite_la_SOURCES = composite.c composite.h
|
nodist_libxcb_composite_la_SOURCES = composite.c composite.h
|
||||||
endif
|
endif
|
||||||
|
@ -35,15 +35,23 @@ endif
|
||||||
EXTSOURCES += damage.c
|
EXTSOURCES += damage.c
|
||||||
if BUILD_DAMAGE
|
if BUILD_DAMAGE
|
||||||
lib_LTLIBRARIES += libxcb-damage.la
|
lib_LTLIBRARIES += libxcb-damage.la
|
||||||
libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_damage_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_damage_la_LIBADD = $(XCB_LIBS)
|
libxcb_damage_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_damage_la_SOURCES = damage.c damage.h
|
nodist_libxcb_damage_la_SOURCES = damage.c damage.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
EXTSOURCES += dbe.c
|
||||||
|
if BUILD_DBE
|
||||||
|
lib_LTLIBRARIES += libxcb-dbe.la
|
||||||
|
libxcb_dbe_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
|
libxcb_dbe_la_LIBADD = $(XCB_LIBS)
|
||||||
|
nodist_libxcb_dbe_la_SOURCES = dbe.c dbe.h
|
||||||
|
endif
|
||||||
|
|
||||||
EXTSOURCES += dpms.c
|
EXTSOURCES += dpms.c
|
||||||
if BUILD_DPMS
|
if BUILD_DPMS
|
||||||
lib_LTLIBRARIES += libxcb-dpms.la
|
lib_LTLIBRARIES += libxcb-dpms.la
|
||||||
libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_dpms_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_dpms_la_LIBADD = $(XCB_LIBS)
|
libxcb_dpms_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_dpms_la_SOURCES = dpms.c dpms.h
|
nodist_libxcb_dpms_la_SOURCES = dpms.c dpms.h
|
||||||
endif
|
endif
|
||||||
|
@ -51,15 +59,31 @@ endif
|
||||||
EXTSOURCES += dri2.c
|
EXTSOURCES += dri2.c
|
||||||
if BUILD_DRI2
|
if BUILD_DRI2
|
||||||
lib_LTLIBRARIES += libxcb-dri2.la
|
lib_LTLIBRARIES += libxcb-dri2.la
|
||||||
libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_dri2_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_dri2_la_LIBADD = $(XCB_LIBS)
|
libxcb_dri2_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h
|
nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h
|
||||||
endif
|
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
|
EXTSOURCES += glx.c
|
||||||
if BUILD_GLX
|
if BUILD_GLX
|
||||||
lib_LTLIBRARIES += libxcb-glx.la
|
lib_LTLIBRARIES += libxcb-glx.la
|
||||||
libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_glx_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_glx_la_LIBADD = $(XCB_LIBS)
|
libxcb_glx_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_glx_la_SOURCES = glx.c glx.h
|
nodist_libxcb_glx_la_SOURCES = glx.c glx.h
|
||||||
endif
|
endif
|
||||||
|
@ -67,7 +91,7 @@ endif
|
||||||
EXTSOURCES += randr.c
|
EXTSOURCES += randr.c
|
||||||
if BUILD_RANDR
|
if BUILD_RANDR
|
||||||
lib_LTLIBRARIES += libxcb-randr.la
|
lib_LTLIBRARIES += libxcb-randr.la
|
||||||
libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined
|
libxcb_randr_la_LDFLAGS = -version-info 1:0:1 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_randr_la_LIBADD = $(XCB_LIBS)
|
libxcb_randr_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_randr_la_SOURCES = randr.c randr.h
|
nodist_libxcb_randr_la_SOURCES = randr.c randr.h
|
||||||
endif
|
endif
|
||||||
|
@ -75,7 +99,7 @@ endif
|
||||||
EXTSOURCES += record.c
|
EXTSOURCES += record.c
|
||||||
if BUILD_RECORD
|
if BUILD_RECORD
|
||||||
lib_LTLIBRARIES += libxcb-record.la
|
lib_LTLIBRARIES += libxcb-record.la
|
||||||
libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_record_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_record_la_LIBADD = $(XCB_LIBS)
|
libxcb_record_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_record_la_SOURCES = record.c record.h
|
nodist_libxcb_record_la_SOURCES = record.c record.h
|
||||||
endif
|
endif
|
||||||
|
@ -83,7 +107,7 @@ endif
|
||||||
EXTSOURCES += render.c
|
EXTSOURCES += render.c
|
||||||
if BUILD_RENDER
|
if BUILD_RENDER
|
||||||
lib_LTLIBRARIES += libxcb-render.la
|
lib_LTLIBRARIES += libxcb-render.la
|
||||||
libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_render_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_render_la_LIBADD = $(XCB_LIBS)
|
libxcb_render_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_render_la_SOURCES = render.c render.h
|
nodist_libxcb_render_la_SOURCES = render.c render.h
|
||||||
endif
|
endif
|
||||||
|
@ -91,7 +115,7 @@ endif
|
||||||
EXTSOURCES += res.c
|
EXTSOURCES += res.c
|
||||||
if BUILD_RESOURCE
|
if BUILD_RESOURCE
|
||||||
lib_LTLIBRARIES += libxcb-res.la
|
lib_LTLIBRARIES += libxcb-res.la
|
||||||
libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_res_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_res_la_LIBADD = $(XCB_LIBS)
|
libxcb_res_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_res_la_SOURCES = res.c res.h
|
nodist_libxcb_res_la_SOURCES = res.c res.h
|
||||||
endif
|
endif
|
||||||
|
@ -99,7 +123,7 @@ endif
|
||||||
EXTSOURCES += screensaver.c
|
EXTSOURCES += screensaver.c
|
||||||
if BUILD_SCREENSAVER
|
if BUILD_SCREENSAVER
|
||||||
lib_LTLIBRARIES += libxcb-screensaver.la
|
lib_LTLIBRARIES += libxcb-screensaver.la
|
||||||
libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_screensaver_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_screensaver_la_LIBADD = $(XCB_LIBS)
|
libxcb_screensaver_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_screensaver_la_SOURCES = screensaver.c screensaver.h
|
nodist_libxcb_screensaver_la_SOURCES = screensaver.c screensaver.h
|
||||||
endif
|
endif
|
||||||
|
@ -107,7 +131,7 @@ endif
|
||||||
EXTSOURCES += shape.c
|
EXTSOURCES += shape.c
|
||||||
if BUILD_SHAPE
|
if BUILD_SHAPE
|
||||||
lib_LTLIBRARIES += libxcb-shape.la
|
lib_LTLIBRARIES += libxcb-shape.la
|
||||||
libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_shape_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_shape_la_LIBADD = $(XCB_LIBS)
|
libxcb_shape_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_shape_la_SOURCES = shape.c shape.h
|
nodist_libxcb_shape_la_SOURCES = shape.c shape.h
|
||||||
endif
|
endif
|
||||||
|
@ -115,7 +139,7 @@ endif
|
||||||
EXTSOURCES += shm.c
|
EXTSOURCES += shm.c
|
||||||
if BUILD_SHM
|
if BUILD_SHM
|
||||||
lib_LTLIBRARIES += libxcb-shm.la
|
lib_LTLIBRARIES += libxcb-shm.la
|
||||||
libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_shm_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_shm_la_LIBADD = $(XCB_LIBS)
|
libxcb_shm_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_shm_la_SOURCES = shm.c shm.h
|
nodist_libxcb_shm_la_SOURCES = shm.c shm.h
|
||||||
endif
|
endif
|
||||||
|
@ -123,7 +147,7 @@ endif
|
||||||
EXTSOURCES += sync.c
|
EXTSOURCES += sync.c
|
||||||
if BUILD_SYNC
|
if BUILD_SYNC
|
||||||
lib_LTLIBRARIES += libxcb-sync.la
|
lib_LTLIBRARIES += libxcb-sync.la
|
||||||
libxcb_sync_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_sync_la_LDFLAGS = -version-info 1:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_sync_la_LIBADD = $(XCB_LIBS)
|
libxcb_sync_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_sync_la_SOURCES = sync.c sync.h
|
nodist_libxcb_sync_la_SOURCES = sync.c sync.h
|
||||||
endif
|
endif
|
||||||
|
@ -131,7 +155,7 @@ endif
|
||||||
EXTSOURCES += xevie.c
|
EXTSOURCES += xevie.c
|
||||||
if BUILD_XEVIE
|
if BUILD_XEVIE
|
||||||
lib_LTLIBRARIES += libxcb-xevie.la
|
lib_LTLIBRARIES += libxcb-xevie.la
|
||||||
libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xevie_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xevie_la_LIBADD = $(XCB_LIBS)
|
libxcb_xevie_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xevie_la_SOURCES = xevie.c xevie.h
|
nodist_libxcb_xevie_la_SOURCES = xevie.c xevie.h
|
||||||
endif
|
endif
|
||||||
|
@ -139,7 +163,7 @@ endif
|
||||||
EXTSOURCES += xf86dri.c
|
EXTSOURCES += xf86dri.c
|
||||||
if BUILD_XFREE86_DRI
|
if BUILD_XFREE86_DRI
|
||||||
lib_LTLIBRARIES += libxcb-xf86dri.la
|
lib_LTLIBRARIES += libxcb-xf86dri.la
|
||||||
libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xf86dri_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xf86dri_la_LIBADD = $(XCB_LIBS)
|
libxcb_xf86dri_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xf86dri_la_SOURCES = xf86dri.c xf86dri.h
|
nodist_libxcb_xf86dri_la_SOURCES = xf86dri.c xf86dri.h
|
||||||
endif
|
endif
|
||||||
|
@ -147,7 +171,7 @@ endif
|
||||||
EXTSOURCES += xfixes.c
|
EXTSOURCES += xfixes.c
|
||||||
if BUILD_XFIXES
|
if BUILD_XFIXES
|
||||||
lib_LTLIBRARIES += libxcb-xfixes.la
|
lib_LTLIBRARIES += libxcb-xfixes.la
|
||||||
libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xfixes_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xfixes_la_LIBADD = $(XCB_LIBS)
|
libxcb_xfixes_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xfixes_la_SOURCES = xfixes.c xfixes.h
|
nodist_libxcb_xfixes_la_SOURCES = xfixes.c xfixes.h
|
||||||
endif
|
endif
|
||||||
|
@ -155,7 +179,7 @@ endif
|
||||||
EXTSOURCES += xinerama.c
|
EXTSOURCES += xinerama.c
|
||||||
if BUILD_XINERAMA
|
if BUILD_XINERAMA
|
||||||
lib_LTLIBRARIES += libxcb-xinerama.la
|
lib_LTLIBRARIES += libxcb-xinerama.la
|
||||||
libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xinerama_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xinerama_la_LIBADD = $(XCB_LIBS)
|
libxcb_xinerama_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xinerama_la_SOURCES = xinerama.c xinerama.h
|
nodist_libxcb_xinerama_la_SOURCES = xinerama.c xinerama.h
|
||||||
endif
|
endif
|
||||||
|
@ -163,15 +187,23 @@ endif
|
||||||
EXTSOURCES += xinput.c
|
EXTSOURCES += xinput.c
|
||||||
if BUILD_XINPUT
|
if BUILD_XINPUT
|
||||||
lib_LTLIBRARIES += libxcb-xinput.la
|
lib_LTLIBRARIES += libxcb-xinput.la
|
||||||
libxcb_xinput_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xinput_la_LDFLAGS = -version-info 1:0:1 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xinput_la_LIBADD = $(XCB_LIBS)
|
libxcb_xinput_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xinput_la_SOURCES = xinput.c xinput.h
|
nodist_libxcb_xinput_la_SOURCES = xinput.c xinput.h
|
||||||
endif
|
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
|
EXTSOURCES += xprint.c
|
||||||
if BUILD_XPRINT
|
if BUILD_XPRINT
|
||||||
lib_LTLIBRARIES += libxcb-xprint.la
|
lib_LTLIBRARIES += libxcb-xprint.la
|
||||||
libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xprint_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xprint_la_LIBADD = $(XCB_LIBS)
|
libxcb_xprint_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xprint_la_SOURCES = xprint.c xprint.h
|
nodist_libxcb_xprint_la_SOURCES = xprint.c xprint.h
|
||||||
endif
|
endif
|
||||||
|
@ -179,7 +211,7 @@ endif
|
||||||
EXTSOURCES += xselinux.c
|
EXTSOURCES += xselinux.c
|
||||||
if BUILD_SELINUX
|
if BUILD_SELINUX
|
||||||
lib_LTLIBRARIES += libxcb-xselinux.la
|
lib_LTLIBRARIES += libxcb-xselinux.la
|
||||||
libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xselinux_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xselinux_la_LIBADD = $(XCB_LIBS)
|
libxcb_xselinux_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xselinux_la_SOURCES = xselinux.c xselinux.h
|
nodist_libxcb_xselinux_la_SOURCES = xselinux.c xselinux.h
|
||||||
endif
|
endif
|
||||||
|
@ -187,7 +219,7 @@ endif
|
||||||
EXTSOURCES += xtest.c
|
EXTSOURCES += xtest.c
|
||||||
if BUILD_XTEST
|
if BUILD_XTEST
|
||||||
lib_LTLIBRARIES += libxcb-xtest.la
|
lib_LTLIBRARIES += libxcb-xtest.la
|
||||||
libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xtest_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xtest_la_LIBADD = $(XCB_LIBS)
|
libxcb_xtest_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xtest_la_SOURCES = xtest.c xtest.h
|
nodist_libxcb_xtest_la_SOURCES = xtest.c xtest.h
|
||||||
endif
|
endif
|
||||||
|
@ -195,7 +227,7 @@ endif
|
||||||
EXTSOURCES += xv.c
|
EXTSOURCES += xv.c
|
||||||
if BUILD_XV
|
if BUILD_XV
|
||||||
lib_LTLIBRARIES += libxcb-xv.la
|
lib_LTLIBRARIES += libxcb-xv.la
|
||||||
libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xv_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xv_la_LIBADD = $(XCB_LIBS)
|
libxcb_xv_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xv_la_SOURCES = xv.c xv.h
|
nodist_libxcb_xv_la_SOURCES = xv.c xv.h
|
||||||
endif
|
endif
|
||||||
|
@ -203,19 +235,43 @@ endif
|
||||||
EXTSOURCES += xvmc.c
|
EXTSOURCES += xvmc.c
|
||||||
if BUILD_XVMC
|
if BUILD_XVMC
|
||||||
lib_LTLIBRARIES += libxcb-xvmc.la
|
lib_LTLIBRARIES += libxcb-xvmc.la
|
||||||
libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libxcb_xvmc_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
|
||||||
libxcb_xvmc_la_LIBADD = $(XCB_LIBS)
|
libxcb_xvmc_la_LIBADD = $(XCB_LIBS)
|
||||||
nodist_libxcb_xvmc_la_SOURCES = xvmc.c xvmc.h
|
nodist_libxcb_xvmc_la_SOURCES = xvmc.c xvmc.h
|
||||||
endif
|
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)
|
EXTHEADERS=$(EXTSOURCES:.c=.h)
|
||||||
xcbinclude_HEADERS = xcb.h xcbext.h
|
xcbinclude_HEADERS = xcb.h xcbext.h
|
||||||
|
if XCB_HAVE_WIN32
|
||||||
|
xcbinclude_HEADERS += xcb_windefs.h
|
||||||
|
endif
|
||||||
nodist_xcbinclude_HEADERS = $(EXTHEADERS)
|
nodist_xcbinclude_HEADERS = $(EXTHEADERS)
|
||||||
noinst_HEADERS = xcbint.h
|
noinst_HEADERS = xcbint.h
|
||||||
|
|
||||||
BUILT_SOURCES = $(EXTSOURCES)
|
BUILT_MAN_PAGES = man/xcb_*
|
||||||
CLEANFILES = $(EXTSOURCES) $(EXTHEADERS)
|
libmandir = $(LIB_MAN_DIR)
|
||||||
|
libman_DATA = $(BUILT_MAN_PAGES)
|
||||||
|
|
||||||
$(EXTSOURCES): c_client.py
|
BUILT_SOURCES = $(EXTSOURCES) $(BUILT_MAN_PAGES)
|
||||||
$(PYTHON) $(srcdir)/c_client.py -p $(XCBPROTO_XCBPYTHONDIR) $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml)
|
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)
|
||||||
|
|
1551
src/c-client.xsl
1551
src/c-client.xsl
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
||||||
|
*.[0-9]
|
||||||
|
*.[0-9]x
|
274
src/xcb.h
274
src/xcb.h
|
@ -29,13 +29,13 @@
|
||||||
#define __XCB_H__
|
#define __XCB_H__
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#if defined(__solaris__)
|
|
||||||
#include <inttypes.h>
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#else
|
||||||
|
#include "xcb_windefs.h"
|
||||||
|
#endif
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +47,36 @@ extern "C" {
|
||||||
* @file xcb.h
|
* @file xcb.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __has_attribute
|
||||||
|
# define __has_attribute(x) 0 /* Compatibility with older compilers. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the below checks, we currently assume that __GNUC__ indicates
|
||||||
|
* gcc 3.0 (released 2001) or later, as we require support for C99.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Supported in gcc 2.5 and later */
|
||||||
|
#if defined(__GNUC__) || __has_attribute(__const__)
|
||||||
|
#define XCB_CONST_FUNCTION __attribute__((__const__))
|
||||||
|
#else
|
||||||
|
#define XCB_CONST_FUNCTION XCB_PURE_FUNCTION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Supported in gcc 2.7 and later */
|
||||||
|
#if defined(__GNUC__) || __has_attribute(__packed__)
|
||||||
|
#define XCB_PACKED __attribute__((__packed__))
|
||||||
|
#else
|
||||||
|
#define XCB_PACKED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Supported in gcc 2.96 and later */
|
||||||
|
#if defined(__GNUC__) || __has_attribute(__pure__)
|
||||||
|
#define XCB_PURE_FUNCTION __attribute__((__pure__))
|
||||||
|
#else
|
||||||
|
#define XCB_PURE_FUNCTION
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup XCB_Core_API XCB Core API
|
* @defgroup XCB_Core_API XCB Core API
|
||||||
* @brief Core API of the XCB library.
|
* @brief Core API of the XCB library.
|
||||||
|
@ -65,6 +95,27 @@ extern "C" {
|
||||||
/** X_TCP_PORT + display number = server port for TCP transport */
|
/** X_TCP_PORT + display number = server port for TCP transport */
|
||||||
#define X_TCP_PORT 6000
|
#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))
|
#define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
|
||||||
|
|
||||||
/* Opaque structures */
|
/* Opaque structures */
|
||||||
|
@ -115,11 +166,26 @@ typedef struct {
|
||||||
uint32_t full_sequence; /**< full sequence */
|
uint32_t full_sequence; /**< full sequence */
|
||||||
} xcb_generic_event_t;
|
} 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
|
* @brief GE event
|
||||||
*
|
*
|
||||||
* An event as sent by the XGE extension. The length field specifies the
|
* An event as sent by the XGE extension. The length field specifies the
|
||||||
* number of 4-byte blocks trailing the struct.
|
* 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 {
|
typedef struct {
|
||||||
uint8_t response_type; /**< Type of the response */
|
uint8_t response_type; /**< Type of the response */
|
||||||
|
@ -195,7 +261,7 @@ typedef struct xcb_auth_info_t {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Forces any buffered output to be written to the server.
|
* @brief Forces any buffered output to be written to the server.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
* @return > @c 0 on success, <= @c 0 otherwise.
|
* @return > @c 0 on success, <= @c 0 otherwise.
|
||||||
*
|
*
|
||||||
* Forces any buffered output to be written to the server. Blocks
|
* Forces any buffered output to be written to the server. Blocks
|
||||||
|
@ -205,7 +271,7 @@ int xcb_flush(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the maximum request length that this server accepts.
|
* @brief Returns the maximum request length that this server accepts.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
* @return The maximum request length field.
|
* @return The maximum request length field.
|
||||||
*
|
*
|
||||||
* In the absence of the BIG-REQUESTS extension, returns the
|
* In the absence of the BIG-REQUESTS extension, returns the
|
||||||
|
@ -222,7 +288,7 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prefetch the maximum request length without blocking.
|
* @brief Prefetch the maximum request length without blocking.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
*
|
*
|
||||||
* Without blocking, does as much work as possible toward computing
|
* Without blocking, does as much work as possible toward computing
|
||||||
* the maximum request length accepted by the X server.
|
* the maximum request length accepted by the X server.
|
||||||
|
@ -244,7 +310,7 @@ void xcb_prefetch_maximum_request_length(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the next event or error from the server.
|
* @brief Returns the next event or error from the server.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
* @return The next event from the server.
|
* @return The next event from the server.
|
||||||
*
|
*
|
||||||
* Returns the next event or error from the server, or returns null in
|
* Returns the next event or error from the server, or returns null in
|
||||||
|
@ -255,8 +321,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the next event or error from the server.
|
* @brief Returns the next event or error from the server.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
* error status of the operation.
|
|
||||||
* @return The next event from the server.
|
* @return The next event from the server.
|
||||||
*
|
*
|
||||||
* Returns the next event or error from the server, if one is
|
* Returns the next event or error from the server, if one is
|
||||||
|
@ -267,10 +332,58 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c);
|
||||||
*/
|
*/
|
||||||
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c);
|
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the next event without reading from the connection.
|
||||||
|
* @param c The connection to the X server.
|
||||||
|
* @return The next already queued event from the server.
|
||||||
|
*
|
||||||
|
* This is a version of xcb_poll_for_event that only examines the
|
||||||
|
* event queue for new events. The function doesn't try to read new
|
||||||
|
* events from the connection if no queued events are found.
|
||||||
|
*
|
||||||
|
* This function is useful for callers that know in advance that all
|
||||||
|
* interesting events have already been read from the connection. For
|
||||||
|
* example, callers might use xcb_wait_for_reply and be interested
|
||||||
|
* only of events that preceded a specific reply.
|
||||||
|
*/
|
||||||
|
xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c);
|
||||||
|
|
||||||
|
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.
|
* @brief Return the error for a request, or NULL if none can ever arrive.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
* @param cookie: The request cookie.
|
* @param cookie The request cookie.
|
||||||
* @return The error for the request, or NULL if none can ever arrive.
|
* @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
|
* The xcb_void_cookie_t cookie supplied to this function must have resulted
|
||||||
|
@ -287,8 +400,8 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Discards the reply for a request.
|
* @brief Discards the reply for a request.
|
||||||
* @param c: The connection to the X server.
|
* @param c The connection to the X server.
|
||||||
* @param sequence: The request sequence number from a cookie.
|
* @param sequence The request sequence number from a cookie.
|
||||||
*
|
*
|
||||||
* Discards the reply for a request. Additionally, any error generated
|
* Discards the reply for a request. Additionally, any error generated
|
||||||
* by the request is also discarded (unless it was an _unchecked request
|
* by the request is also discarded (unless it was an _unchecked request
|
||||||
|
@ -301,18 +414,33 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co
|
||||||
*/
|
*/
|
||||||
void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence);
|
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 */
|
/* xcb_ext.c */
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 Caches reply information from QueryExtension requests.
|
* @brief Caches reply information from QueryExtension requests.
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
* @param ext: The extension data.
|
* @param ext The extension data.
|
||||||
* @return A pointer to the xcb_query_extension_reply_t for the extension.
|
* @return A pointer to the xcb_query_extension_reply_t for the extension.
|
||||||
*
|
*
|
||||||
* This function is the primary interface to the "extension cache",
|
* This function is the primary interface to the "extension cache",
|
||||||
|
@ -325,12 +453,12 @@ typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as k
|
||||||
* The result must not be freed. This storage is managed by the cache
|
* The result must not be freed. This storage is managed by the cache
|
||||||
* itself.
|
* itself.
|
||||||
*/
|
*/
|
||||||
const xcb_query_extension_reply_t *xcb_get_extension_data(xcb_connection_t *c, xcb_extension_t *ext);
|
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
|
* @brief Prefetch of extension data into the extension cache
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
* @param ext: The extension data.
|
* @param ext The extension data.
|
||||||
*
|
*
|
||||||
* This function allows a "prefetch" of extension data into the
|
* This function allows a "prefetch" of extension data into the
|
||||||
* extension cache. Invoking the function may cause a call to
|
* extension cache. Invoking the function may cause a call to
|
||||||
|
@ -345,7 +473,7 @@ void xcb_prefetch_extension_data(xcb_connection_t *c, xcb_extension_t *ext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access the data returned by the server.
|
* @brief Access the data returned by the server.
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
* @return A pointer to an xcb_setup_t structure.
|
* @return A pointer to an xcb_setup_t structure.
|
||||||
*
|
*
|
||||||
* Accessor for the data returned by the server when the xcb_connection_t
|
* Accessor for the data returned by the server when the xcb_connection_t
|
||||||
|
@ -361,37 +489,45 @@ void xcb_prefetch_extension_data(xcb_connection_t *c, xcb_extension_t *ext);
|
||||||
*
|
*
|
||||||
* The result must not be freed.
|
* The result must not be freed.
|
||||||
*/
|
*/
|
||||||
const xcb_setup_t *xcb_get_setup(xcb_connection_t *c);
|
XCB_PURE_FUNCTION
|
||||||
|
const struct xcb_setup_t *xcb_get_setup(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access the file descriptor of the connection.
|
* @brief Access the file descriptor of the connection.
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
* @return The file descriptor.
|
* @return The file descriptor.
|
||||||
*
|
*
|
||||||
* Accessor for the file descriptor that was passed to the
|
* Accessor for the file descriptor that was passed to the
|
||||||
* xcb_connect_to_fd call that returned @p c.
|
* xcb_connect_to_fd call that returned @p c.
|
||||||
*/
|
*/
|
||||||
|
XCB_PURE_FUNCTION
|
||||||
int xcb_get_file_descriptor(xcb_connection_t *c);
|
int xcb_get_file_descriptor(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Test whether the connection has shut down due to a fatal error.
|
* @brief Test whether the connection has shut down due to a fatal error.
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
* @return 1 if the connection is in an error state; 0 otherwise.
|
* @return > 0 if the connection is in an error state; 0 otherwise.
|
||||||
*
|
*
|
||||||
* Some errors that occur in the context of an xcb_connection_t
|
* Some errors that occur in the context of an xcb_connection_t
|
||||||
* are unrecoverable. When such an error occurs, the
|
* are unrecoverable. When such an error occurs, the
|
||||||
* connection is shut down and further operations on the
|
* connection is shut down and further operations on the
|
||||||
* xcb_connection_t have no effect.
|
* xcb_connection_t have no effect, but memory will not be freed until
|
||||||
|
* xcb_disconnect() is called on the xcb_connection_t.
|
||||||
*
|
*
|
||||||
* @todo Other functions should document the conditions in
|
* @return XCB_CONN_ERROR, because of socket errors, pipe errors or other stream errors.
|
||||||
* which they shut down the connection.
|
* @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.
|
||||||
*/
|
*/
|
||||||
|
XCB_PURE_FUNCTION
|
||||||
int xcb_connection_has_error(xcb_connection_t *c);
|
int xcb_connection_has_error(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Connects to the X server.
|
* @brief Connects to the X server.
|
||||||
* @param fd: The file descriptor.
|
* @param fd The file descriptor.
|
||||||
* @param auth_info: Authentication data.
|
* @param auth_info Authentication data.
|
||||||
* @return A newly allocated xcb_connection_t structure.
|
* @return A newly allocated xcb_connection_t structure.
|
||||||
*
|
*
|
||||||
* Connects to an X server, given the open socket @p fd and the
|
* Connects to an X server, given the open socket @p fd and the
|
||||||
|
@ -399,15 +535,20 @@ int xcb_connection_has_error(xcb_connection_t *c);
|
||||||
* bidirectionally connected to an X server. If the connection
|
* bidirectionally connected to an X server. If the connection
|
||||||
* should be unauthenticated, @p auth_info must be @c
|
* should be unauthenticated, @p auth_info must be @c
|
||||||
* NULL.
|
* 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);
|
xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes the connection.
|
* @brief Closes the connection.
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
*
|
*
|
||||||
* Closes the file descriptor and frees all memory associated with the
|
* Closes the file descriptor and frees all memory associated with the
|
||||||
* connection @c c.
|
* connection @c c. If @p c is @c NULL, nothing is done.
|
||||||
*/
|
*/
|
||||||
void xcb_disconnect(xcb_connection_t *c);
|
void xcb_disconnect(xcb_connection_t *c);
|
||||||
|
|
||||||
|
@ -416,10 +557,10 @@ void xcb_disconnect(xcb_connection_t *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Parses a display string name in the form documented by X(7x).
|
* @brief Parses a display string name in the form documented by X(7x).
|
||||||
* @param name: The name of the display.
|
* @param name The name of the display.
|
||||||
* @param host: A pointer to a malloc'd copy of the hostname.
|
* @param host A pointer to a malloc'd copy of the hostname.
|
||||||
* @param display: A pointer to the display number.
|
* @param display A pointer to the display number.
|
||||||
* @param screen: A pointer to the screen number.
|
* @param screen A pointer to the screen number.
|
||||||
* @return 0 on failure, non 0 otherwise.
|
* @return 0 on failure, non 0 otherwise.
|
||||||
*
|
*
|
||||||
* Parses the display string name @p display_name in the form
|
* Parses the display string name @p display_name in the form
|
||||||
|
@ -435,8 +576,8 @@ int xcb_parse_display(const char *name, char **host, int *display, int *screen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Connects to the X server.
|
* @brief Connects to the X server.
|
||||||
* @param displayname: The name of the display.
|
* @param displayname The name of the display.
|
||||||
* @param screenp: A pointer to a preferred screen number.
|
* @param screenp A pointer to a preferred screen number.
|
||||||
* @return A newly allocated xcb_connection_t structure.
|
* @return A newly allocated xcb_connection_t structure.
|
||||||
*
|
*
|
||||||
* Connects to the X server specified by @p displayname. If @p
|
* Connects to the X server specified by @p displayname. If @p
|
||||||
|
@ -444,20 +585,30 @@ int xcb_parse_display(const char *name, char **host, int *display, int *screen);
|
||||||
* variable. If a particular screen on that server is preferred, the
|
* 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
|
* int pointed to by @p screenp (if not @c NULL) will be set to that
|
||||||
* screen; otherwise the screen will be set to 0.
|
* 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);
|
xcb_connection_t *xcb_connect(const char *displayname, int *screenp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Connects to the X server, using an authorization information.
|
* @brief Connects to the X server, using an authorization information.
|
||||||
* @param display: The name of the display.
|
* @param display The name of the display.
|
||||||
* @param auth: The authorization information.
|
* @param auth The authorization information.
|
||||||
* @param screen: A pointer to a preferred screen number.
|
* @param screen A pointer to a preferred screen number.
|
||||||
* @return A newly allocated xcb_connection_t structure.
|
* @return A newly allocated xcb_connection_t structure.
|
||||||
*
|
*
|
||||||
* Connects to the X server specified by @p displayname, using the
|
* Connects to the X server specified by @p displayname, using the
|
||||||
* authorization @p auth. If a particular screen on that server is
|
* authorization @p auth. If a particular screen on that server is
|
||||||
* preferred, the int pointed to by @p screenp (if not @c NULL) will
|
* 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.
|
* 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_connection_t *xcb_connect_to_display_with_auth_info(const char *display, xcb_auth_info_t *auth, int *screen);
|
||||||
|
|
||||||
|
@ -466,8 +617,8 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *display, xcb
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates an XID for a new object.
|
* @brief Allocates an XID for a new object.
|
||||||
* @param c: The connection.
|
* @param c The connection.
|
||||||
* @return A newly allocated XID.
|
* @return A newly allocated XID, or -1 on failure.
|
||||||
*
|
*
|
||||||
* Allocates an XID for a new object. Typically used just prior to
|
* Allocates an XID for a new object. Typically used just prior to
|
||||||
* various object creation functions, such as xcb_create_window.
|
* various object creation functions, such as xcb_create_window.
|
||||||
|
@ -475,6 +626,35 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *display, xcb
|
||||||
uint32_t xcb_generate_id(xcb_connection_t *c);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,14 +25,35 @@
|
||||||
|
|
||||||
/* Authorization systems for the X protocol. */
|
/* Authorization systems for the X protocol. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <X11/Xauth.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 <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <sys/param.h>
|
#endif /* _WIN32 */
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "xcbint.h"
|
#include "xcbint.h"
|
||||||
|
@ -52,7 +73,7 @@ enum auth_protos {
|
||||||
#define AUTH_PROTO_XDM_AUTHORIZATION "XDM-AUTHORIZATION-1"
|
#define AUTH_PROTO_XDM_AUTHORIZATION "XDM-AUTHORIZATION-1"
|
||||||
#define AUTH_PROTO_MIT_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1"
|
#define AUTH_PROTO_MIT_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1"
|
||||||
|
|
||||||
static char *authnames[N_AUTH_PROTOS] = {
|
static const char *authnames[N_AUTH_PROTOS] = {
|
||||||
#ifdef HASXDMAUTH
|
#ifdef HASXDMAUTH
|
||||||
AUTH_PROTO_XDM_AUTHORIZATION,
|
AUTH_PROTO_XDM_AUTHORIZATION,
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,6 +134,7 @@ static Xauth *get_authptr(struct sockaddr *sockname, int display)
|
||||||
}
|
}
|
||||||
addr += 12;
|
addr += 12;
|
||||||
/* if v4-mapped, fall through. */
|
/* if v4-mapped, fall through. */
|
||||||
|
XCB_ALLOW_FALLTHRU
|
||||||
#endif
|
#endif
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
if(!addr)
|
if(!addr)
|
||||||
|
@ -143,7 +165,7 @@ static Xauth *get_authptr(struct sockaddr *sockname, int display)
|
||||||
return XauGetBestAuthByAddr (family,
|
return XauGetBestAuthByAddr (family,
|
||||||
(unsigned short) addrlen, addr,
|
(unsigned short) addrlen, addr,
|
||||||
(unsigned short) dispbuflen, dispbuf,
|
(unsigned short) dispbuflen, dispbuf,
|
||||||
N_AUTH_PROTOS, authnames, authnameslen);
|
N_AUTH_PROTOS, (char **)authnames, authnameslen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HASXDMAUTH
|
#ifdef HASXDMAUTH
|
||||||
|
@ -249,14 +271,21 @@ static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *
|
||||||
to the value returned by either getpeername() or getsockname()
|
to the value returned by either getpeername() or getsockname()
|
||||||
(according to POSIX, applications should not assume a particular
|
(according to POSIX, applications should not assume a particular
|
||||||
length for `sockaddr_un.sun_path') */
|
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,
|
static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
|
||||||
struct sockaddr *,
|
struct sockaddr *,
|
||||||
socklen_t *),
|
socklen_t *),
|
||||||
int fd)
|
int fd)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
|
socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
|
||||||
socklen_t actual_socknamelen = socknamelen;
|
socklen_t actual_socknamelen = socknamelen;
|
||||||
struct sockaddr *sockname = malloc(socknamelen), *new_sockname = NULL;
|
struct sockaddr *sockname = malloc(socknamelen);
|
||||||
|
|
||||||
if (sockname == NULL)
|
if (sockname == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -269,14 +298,17 @@ static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
|
||||||
|
|
||||||
if (actual_socknamelen > socknamelen)
|
if (actual_socknamelen > socknamelen)
|
||||||
{
|
{
|
||||||
|
struct sockaddr *new_sockname = NULL;
|
||||||
socknamelen = actual_socknamelen;
|
socknamelen = actual_socknamelen;
|
||||||
|
|
||||||
if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL ||
|
if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL)
|
||||||
socket_func(fd, new_sockname, &actual_socknamelen) == -1 ||
|
|
||||||
actual_socknamelen > socknamelen)
|
|
||||||
goto sock_or_realloc_error;
|
goto sock_or_realloc_error;
|
||||||
|
|
||||||
sockname = new_sockname;
|
sockname = new_sockname;
|
||||||
|
|
||||||
|
if (socket_func(fd, sockname, &actual_socknamelen) == -1 ||
|
||||||
|
actual_socknamelen > socknamelen)
|
||||||
|
goto sock_or_realloc_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sockname;
|
return sockname;
|
||||||
|
@ -322,11 +354,16 @@ int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display)
|
||||||
if (!info->namelen)
|
if (!info->namelen)
|
||||||
goto no_auth; /* out of memory */
|
goto no_auth; /* out of memory */
|
||||||
|
|
||||||
if (!gotsockname && (sockname = get_peer_sock_name(getsockname, fd)) == NULL)
|
if (!gotsockname)
|
||||||
|
{
|
||||||
|
free(sockname);
|
||||||
|
|
||||||
|
if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
|
||||||
{
|
{
|
||||||
free(info->name);
|
free(info->name);
|
||||||
goto no_auth; /* can only authenticate sockets */
|
goto no_auth; /* can only authenticate sockets */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = compute_auth(info, authptr, sockname);
|
ret = compute_auth(info, authptr, sockname);
|
||||||
if(!ret)
|
if(!ret)
|
||||||
|
|
279
src/xcb_conn.c
279
src/xcb_conn.c
|
@ -25,33 +25,93 @@
|
||||||
|
|
||||||
/* Connection management: the core of XCB. */
|
/* Connection management: the core of XCB. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "xcbint.h"
|
#include "xcbint.h"
|
||||||
#if USE_POLL
|
#if USE_POLL
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#else
|
#elif !defined _WIN32
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#endif
|
#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 {
|
typedef struct {
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t pad0[5];
|
uint8_t pad0[5];
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
} xcb_setup_generic_t;
|
} xcb_setup_generic_t;
|
||||||
|
|
||||||
static const int error_connection = 1;
|
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)
|
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);
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
if(flags == -1)
|
if(flags == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -61,6 +121,7 @@ static int set_fd_flags(const int fd)
|
||||||
if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif /* _WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
|
static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
|
||||||
|
@ -109,6 +170,8 @@ static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
|
||||||
|
|
||||||
static int read_setup(xcb_connection_t *c)
|
static int read_setup(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
|
const char newline = '\n';
|
||||||
|
|
||||||
/* Read the server response */
|
/* Read the server response */
|
||||||
c->setup = malloc(sizeof(xcb_setup_generic_t));
|
c->setup = malloc(sizeof(xcb_setup_generic_t));
|
||||||
if(!c->setup)
|
if(!c->setup)
|
||||||
|
@ -134,6 +197,7 @@ static int read_setup(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
xcb_setup_failed_t *setup = (xcb_setup_failed_t *) c->setup;
|
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, xcb_setup_failed_reason(setup), xcb_setup_failed_reason_length(setup));
|
||||||
|
write(STDERR_FILENO, &newline, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +205,7 @@ static int read_setup(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
xcb_setup_authenticate_t *setup = (xcb_setup_authenticate_t *) c->setup;
|
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, xcb_setup_authenticate_reason(setup), xcb_setup_authenticate_reason_length(setup));
|
||||||
|
write(STDERR_FILENO, &newline, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,31 +216,114 @@ static int read_setup(xcb_connection_t *c)
|
||||||
/* precondition: there must be something for us to write. */
|
/* precondition: there must be something for us to write. */
|
||||||
static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
|
static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
|
||||||
{
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
int n;
|
int n;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(!c->out.queue_len);
|
assert(!c->out.queue_len);
|
||||||
n = writev(c->fd, *vector, *count);
|
|
||||||
|
#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)
|
if(n < 0 && errno == EAGAIN)
|
||||||
return 1;
|
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)
|
if(n <= 0)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->out.total_written += n;
|
||||||
for(; *count; --*count, ++*vector)
|
for(; *count; --*count, ++*vector)
|
||||||
{
|
{
|
||||||
int cur = (*vector)->iov_len;
|
int cur = (*vector)->iov_len;
|
||||||
if(cur > n)
|
if(cur > n)
|
||||||
cur = n;
|
cur = n;
|
||||||
|
if(cur) {
|
||||||
(*vector)->iov_len -= cur;
|
(*vector)->iov_len -= cur;
|
||||||
(*vector)->iov_base = (char *) (*vector)->iov_base + cur;
|
(*vector)->iov_base = (char *) (*vector)->iov_base + cur;
|
||||||
n -= cur;
|
n -= cur;
|
||||||
|
}
|
||||||
if((*vector)->iov_len)
|
if((*vector)->iov_len)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!*count)
|
if(!*count)
|
||||||
*vector = 0;
|
*vector = 0;
|
||||||
assert(n == 0);
|
assert(n == 0);
|
||||||
|
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,15 +331,15 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
|
||||||
|
|
||||||
const xcb_setup_t *xcb_get_setup(xcb_connection_t *c)
|
const xcb_setup_t *xcb_get_setup(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
if(c->has_error)
|
if(is_static_error_conn(c))
|
||||||
return 0;
|
return &xcb_error_setup;
|
||||||
/* doesn't need locking because it's never written to. */
|
/* doesn't need locking because it's never written to. */
|
||||||
return c->setup;
|
return c->setup;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xcb_get_file_descriptor(xcb_connection_t *c)
|
int xcb_get_file_descriptor(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
if(c->has_error)
|
if(is_static_error_conn(c))
|
||||||
return -1;
|
return -1;
|
||||||
/* doesn't need locking because it's never written to. */
|
/* doesn't need locking because it's never written to. */
|
||||||
return c->fd;
|
return c->fd;
|
||||||
|
@ -207,18 +355,24 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
|
||||||
{
|
{
|
||||||
xcb_connection_t* c;
|
xcb_connection_t* c;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#ifndef USE_POLL
|
#ifndef USE_POLL
|
||||||
if(fd >= FD_SETSIZE) /* would overflow in FD_SET */
|
if(fd >= FD_SETSIZE) /* would overflow in FD_SET */
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
return (xcb_connection_t *) &error_connection;
|
return _xcb_conn_ret_error(XCB_CONN_ERROR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* !_WIN32*/
|
||||||
|
|
||||||
c = calloc(1, sizeof(xcb_connection_t));
|
c = calloc(1, sizeof(xcb_connection_t));
|
||||||
if(!c) {
|
if(!c) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
closesocket(fd);
|
||||||
|
#else
|
||||||
close(fd);
|
close(fd);
|
||||||
return (xcb_connection_t *) &error_connection;
|
#endif
|
||||||
|
return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->fd = fd;
|
c->fd = fd;
|
||||||
|
@ -235,7 +389,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
xcb_disconnect(c);
|
xcb_disconnect(c);
|
||||||
return (xcb_connection_t *) &error_connection;
|
return _xcb_conn_ret_error(XCB_CONN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
@ -243,11 +397,18 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
|
||||||
|
|
||||||
void xcb_disconnect(xcb_connection_t *c)
|
void xcb_disconnect(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
if(c->has_error)
|
if(c == NULL || is_static_error_conn(c))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
free(c->setup);
|
free(c->setup);
|
||||||
|
|
||||||
|
/* disallow further sends and receives */
|
||||||
|
shutdown(c->fd, SHUT_RDWR);
|
||||||
|
#ifdef _WIN32
|
||||||
|
closesocket(c->fd);
|
||||||
|
#else
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
pthread_mutex_destroy(&c->iolock);
|
pthread_mutex_destroy(&c->iolock);
|
||||||
_xcb_in_destroy(&c->in);
|
_xcb_in_destroy(&c->in);
|
||||||
|
@ -257,13 +418,49 @@ void xcb_disconnect(xcb_connection_t *c)
|
||||||
_xcb_xid_destroy(c);
|
_xcb_xid_destroy(c);
|
||||||
|
|
||||||
free(c);
|
free(c);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Private interface */
|
/* Private interface */
|
||||||
|
|
||||||
void _xcb_conn_shutdown(xcb_connection_t *c)
|
void _xcb_conn_shutdown(xcb_connection_t *c, int err)
|
||||||
{
|
{
|
||||||
c->has_error = 1;
|
c->has_error = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return connection error state.
|
||||||
|
* To make thread-safe, I need a seperate static
|
||||||
|
* variable for every possible error.
|
||||||
|
* 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 _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
|
||||||
|
@ -311,28 +508,45 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
|
||||||
do {
|
do {
|
||||||
#if USE_POLL
|
#if USE_POLL
|
||||||
ret = poll(&fd, 1, -1);
|
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
|
#else
|
||||||
ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
|
ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
} while (ret == -1 && errno == EINTR);
|
} while (ret == -1 && errno == EINTR);
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&c->iolock);
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
|
||||||
if(ret)
|
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 USE_POLL
|
||||||
if((fd.revents & POLLIN) == POLLIN)
|
if(may_read && (fd.revents & POLLIN) != 0)
|
||||||
#else
|
#else
|
||||||
if(FD_ISSET(c->fd, &rfds))
|
if(may_read && FD_ISSET(c->fd, &rfds))
|
||||||
#endif
|
#endif
|
||||||
ret = ret && _xcb_in_read(c);
|
ret = ret && _xcb_in_read(c);
|
||||||
|
|
||||||
#if USE_POLL
|
#if USE_POLL
|
||||||
if((fd.revents & POLLOUT) == POLLOUT)
|
if((fd.revents & POLLOUT) != 0)
|
||||||
#else
|
#else
|
||||||
if(FD_ISSET(c->fd, &wfds))
|
if(FD_ISSET(c->fd, &wfds))
|
||||||
#endif
|
#endif
|
||||||
|
@ -345,3 +559,30 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
|
||||||
|
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
/* A cache for QueryExtension results. */
|
/* A cache for QueryExtension results. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
708
src/xcb_in.c
708
src/xcb_in.c
|
@ -25,21 +25,32 @@
|
||||||
|
|
||||||
/* Stuff that reads stuff from the server. */
|
/* Stuff that reads stuff from the server. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if USE_POLL
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "xcb_windefs.h"
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "xcbext.h"
|
#include "xcbext.h"
|
||||||
#include "xcbint.h"
|
#include "xcbint.h"
|
||||||
#if USE_POLL
|
|
||||||
#include <poll.h>
|
|
||||||
#else
|
|
||||||
#include <sys/select.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define XCB_ERROR 0
|
#define XCB_ERROR 0
|
||||||
#define XCB_REPLY 1
|
#define XCB_REPLY 1
|
||||||
|
@ -50,6 +61,23 @@ struct event_list {
|
||||||
struct event_list *next;
|
struct event_list *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xcb_special_event {
|
||||||
|
|
||||||
|
struct xcb_special_event *next;
|
||||||
|
|
||||||
|
/* Match XGE events for the specific extension and event ID (the
|
||||||
|
* first 32 bit word after evtype)
|
||||||
|
*/
|
||||||
|
uint8_t extension;
|
||||||
|
uint32_t eid;
|
||||||
|
uint32_t *stamp;
|
||||||
|
|
||||||
|
struct event_list *events;
|
||||||
|
struct event_list **events_tail;
|
||||||
|
|
||||||
|
pthread_cond_t special_event_cond;
|
||||||
|
};
|
||||||
|
|
||||||
struct reply_list {
|
struct reply_list {
|
||||||
void *reply;
|
void *reply;
|
||||||
struct reply_list *next;
|
struct reply_list *next;
|
||||||
|
@ -64,16 +92,88 @@ typedef struct pending_reply {
|
||||||
} pending_reply;
|
} pending_reply;
|
||||||
|
|
||||||
typedef struct reader_list {
|
typedef struct reader_list {
|
||||||
unsigned int request;
|
uint64_t request;
|
||||||
pthread_cond_t *data;
|
pthread_cond_t *data;
|
||||||
struct reader_list *next;
|
struct reader_list *next;
|
||||||
} reader_list;
|
} reader_list;
|
||||||
|
|
||||||
|
typedef struct special_list {
|
||||||
|
xcb_special_event_t *se;
|
||||||
|
struct special_list *next;
|
||||||
|
} special_list;
|
||||||
|
|
||||||
|
static void remove_finished_readers(reader_list **prev_reader, uint64_t completed)
|
||||||
|
{
|
||||||
|
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, completed))
|
||||||
|
{
|
||||||
|
/* If you don't have what you're looking for now, you never
|
||||||
|
* will. Wake up and leave me alone. */
|
||||||
|
pthread_cond_signal((*prev_reader)->data);
|
||||||
|
*prev_reader = (*prev_reader)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_SENDMSG
|
||||||
|
static int read_fds(xcb_connection_t *c, int *fds, int nfd)
|
||||||
|
{
|
||||||
|
int *ifds = &c->in.in_fd.fd[c->in.in_fd.ifd];
|
||||||
|
int infd = c->in.in_fd.nfd - c->in.in_fd.ifd;
|
||||||
|
|
||||||
|
if (nfd > infd)
|
||||||
|
return 0;
|
||||||
|
memcpy(fds, ifds, nfd * sizeof (int));
|
||||||
|
c->in.in_fd.ifd += nfd;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct xcb_ge_special_event_t {
|
||||||
|
uint8_t response_type; /**< */
|
||||||
|
uint8_t extension; /**< */
|
||||||
|
uint16_t sequence; /**< */
|
||||||
|
uint32_t length; /**< */
|
||||||
|
uint16_t evtype; /**< */
|
||||||
|
uint8_t pad0[2]; /**< */
|
||||||
|
uint32_t eid; /**< */
|
||||||
|
uint8_t pad1[16]; /**< */
|
||||||
|
} xcb_ge_special_event_t;
|
||||||
|
|
||||||
|
static int event_special(xcb_connection_t *c,
|
||||||
|
struct event_list *event)
|
||||||
|
{
|
||||||
|
struct xcb_special_event *special_event;
|
||||||
|
struct xcb_ge_special_event_t *ges = (void *) event->event;
|
||||||
|
|
||||||
|
/* Special events are always XGE events */
|
||||||
|
if ((ges->response_type & 0x7f) != XCB_XGE_EVENT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (special_event = c->in.special_events;
|
||||||
|
special_event;
|
||||||
|
special_event = special_event->next)
|
||||||
|
{
|
||||||
|
if (ges->extension == special_event->extension &&
|
||||||
|
ges->eid == special_event->eid)
|
||||||
|
{
|
||||||
|
*special_event->events_tail = event;
|
||||||
|
special_event->events_tail = &event->next;
|
||||||
|
if (special_event->stamp)
|
||||||
|
++(*special_event->stamp);
|
||||||
|
pthread_cond_signal(&special_event->special_event_cond);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int read_packet(xcb_connection_t *c)
|
static int read_packet(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
xcb_generic_reply_t genrep;
|
xcb_generic_reply_t genrep;
|
||||||
int length = 32;
|
uint64_t length = 32;
|
||||||
int eventlength = 0; /* length after first 32 bytes for GenericEvents */
|
uint64_t eventlength = 0; /* length after first 32 bytes for GenericEvents */
|
||||||
|
int nfd = 0; /* Number of file descriptors attached to the reply */
|
||||||
|
uint64_t bufsize;
|
||||||
void *buf;
|
void *buf;
|
||||||
pending_reply *pend = 0;
|
pending_reply *pend = 0;
|
||||||
struct event_list *event;
|
struct event_list *event;
|
||||||
|
@ -119,6 +219,8 @@ static int read_packet(xcb_connection_t *c)
|
||||||
|
|
||||||
if(genrep.response_type == XCB_ERROR)
|
if(genrep.response_type == XCB_ERROR)
|
||||||
c->in.request_completed = c->in.request_read;
|
c->in.request_completed = c->in.request_read;
|
||||||
|
|
||||||
|
remove_finished_readers(&c->in.readers, c->in.request_completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(genrep.response_type == XCB_ERROR || genrep.response_type == XCB_REPLY)
|
if(genrep.response_type == XCB_ERROR || genrep.response_type == XCB_REPLY)
|
||||||
|
@ -137,20 +239,35 @@ static int read_packet(xcb_connection_t *c)
|
||||||
if(pend && pend->workaround == WORKAROUND_GLX_GET_FB_CONFIGS_BUG)
|
if(pend && pend->workaround == WORKAROUND_GLX_GET_FB_CONFIGS_BUG)
|
||||||
{
|
{
|
||||||
uint32_t *p = (uint32_t *) c->in.queue;
|
uint32_t *p = (uint32_t *) c->in.queue;
|
||||||
genrep.length = p[2] * p[3] * 2;
|
uint64_t new_length = ((uint64_t)p[2]) * ((uint64_t)p[3]);
|
||||||
|
if(new_length >= (UINT32_MAX / UINT32_C(16)))
|
||||||
|
{
|
||||||
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
length += genrep.length * 4;
|
genrep.length = (uint32_t)(new_length * UINT64_C(2));
|
||||||
|
}
|
||||||
|
length += genrep.length * UINT64_C(4);
|
||||||
|
|
||||||
|
/* XXX a bit of a hack -- we "know" that all FD replys place
|
||||||
|
* the number of fds in the pad0 byte */
|
||||||
|
if (pend && pend->flags & XCB_REQUEST_REPLY_FDS)
|
||||||
|
nfd = genrep.pad0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XGE events may have sizes > 32 */
|
/* XGE events may have sizes > 32 */
|
||||||
if (genrep.response_type == XCB_XGE_EVENT)
|
if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT)
|
||||||
eventlength = genrep.length * 4;
|
eventlength = genrep.length * UINT64_C(4);
|
||||||
|
|
||||||
buf = malloc(length + eventlength +
|
bufsize = length + eventlength + nfd * sizeof(int) +
|
||||||
(genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)));
|
(genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t));
|
||||||
|
if (bufsize < INT32_MAX)
|
||||||
|
buf = malloc((size_t) bufsize);
|
||||||
|
else
|
||||||
|
buf = NULL;
|
||||||
if(!buf)
|
if(!buf)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +287,17 @@ static int read_packet(xcb_connection_t *c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_SENDMSG
|
||||||
|
if (nfd)
|
||||||
|
{
|
||||||
|
if (!read_fds(c, (int *) &((char *) buf)[length], nfd))
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(pend && (pend->flags & XCB_REQUEST_DISCARD_REPLY))
|
if(pend && (pend->flags & XCB_REQUEST_DISCARD_REPLY))
|
||||||
{
|
{
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -183,11 +311,10 @@ static int read_packet(xcb_connection_t *c)
|
||||||
if( genrep.response_type == XCB_REPLY ||
|
if( genrep.response_type == XCB_REPLY ||
|
||||||
(genrep.response_type == XCB_ERROR && pend && (pend->flags & XCB_REQUEST_CHECKED)))
|
(genrep.response_type == XCB_ERROR && pend && (pend->flags & XCB_REQUEST_CHECKED)))
|
||||||
{
|
{
|
||||||
reader_list *reader;
|
|
||||||
struct reply_list *cur = malloc(sizeof(struct reply_list));
|
struct reply_list *cur = malloc(sizeof(struct reply_list));
|
||||||
if(!cur)
|
if(!cur)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
|
||||||
free(buf);
|
free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -195,17 +322,8 @@ static int read_packet(xcb_connection_t *c)
|
||||||
cur->next = 0;
|
cur->next = 0;
|
||||||
*c->in.current_reply_tail = cur;
|
*c->in.current_reply_tail = cur;
|
||||||
c->in.current_reply_tail = &cur->next;
|
c->in.current_reply_tail = &cur->next;
|
||||||
for(reader = c->in.readers;
|
if(c->in.readers && c->in.readers->request == c->in.request_read)
|
||||||
reader &&
|
pthread_cond_signal(c->in.readers->data);
|
||||||
XCB_SEQUENCE_COMPARE_32(reader->request, <=, c->in.request_read);
|
|
||||||
reader = reader->next)
|
|
||||||
{
|
|
||||||
if(XCB_SEQUENCE_COMPARE_32(reader->request, ==, c->in.request_read))
|
|
||||||
{
|
|
||||||
pthread_cond_signal(reader->data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,15 +331,18 @@ static int read_packet(xcb_connection_t *c)
|
||||||
event = malloc(sizeof(struct event_list));
|
event = malloc(sizeof(struct event_list));
|
||||||
if(!event)
|
if(!event)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
|
||||||
free(buf);
|
free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
event->event = buf;
|
event->event = buf;
|
||||||
event->next = 0;
|
event->next = 0;
|
||||||
|
|
||||||
|
if (!event_special(c, event)) {
|
||||||
*c->in.events_tail = event;
|
*c->in.events_tail = event;
|
||||||
c->in.events_tail = &event->next;
|
c->in.events_tail = &event->next;
|
||||||
pthread_cond_signal(&c->in.event_cond);
|
pthread_cond_signal(&c->in.event_cond);
|
||||||
|
}
|
||||||
return 1; /* I have something for you... */
|
return 1; /* I have something for you... */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,15 +371,19 @@ static void free_reply_list(struct reply_list *head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_block(const int fd, void *buf, const ssize_t len)
|
static int read_block(const int fd, void *buf, const intptr_t len)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
while(done < len)
|
while(done < len)
|
||||||
{
|
{
|
||||||
int ret = read(fd, ((char *) buf) + done, len - done);
|
int ret = recv(fd, ((char *) buf) + done, len - done, 0);
|
||||||
if(ret > 0)
|
if(ret > 0)
|
||||||
done += ret;
|
done += ret;
|
||||||
|
#ifndef _WIN32
|
||||||
if(ret < 0 && errno == EAGAIN)
|
if(ret < 0 && errno == EAGAIN)
|
||||||
|
#else
|
||||||
|
if(ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||||
|
#endif /* !_Win32 */
|
||||||
{
|
{
|
||||||
#if USE_POLL
|
#if USE_POLL
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
|
@ -272,10 +397,13 @@ static int read_block(const int fd, void *buf, const ssize_t len)
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fd, &fds);
|
FD_SET(fd, &fds);
|
||||||
|
|
||||||
|
/* Initializing errno here makes sure that for Win32 this loop will execute only once */
|
||||||
|
errno = 0;
|
||||||
do {
|
do {
|
||||||
ret = select(fd + 1, &fds, 0, 0, 0);
|
ret = select(fd + 1, &fds, 0, 0, 0);
|
||||||
} while (ret == -1 && errno == EINTR);
|
} while (ret == -1 && errno == EINTR);
|
||||||
#endif
|
#endif /* USE_POLL */
|
||||||
}
|
}
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -283,7 +411,7 @@ static int read_block(const int fd, void *buf, const ssize_t len)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error)
|
static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error)
|
||||||
{
|
{
|
||||||
struct reply_list *head;
|
struct reply_list *head;
|
||||||
|
|
||||||
|
@ -292,7 +420,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
|
||||||
head = 0;
|
head = 0;
|
||||||
/* We've read requests past the one we want, so if it has replies we have
|
/* We've read requests past the one we want, so if it has replies we have
|
||||||
* them all and they're in the replies map. */
|
* them all and they're in the replies map. */
|
||||||
else if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
|
else if(XCB_SEQUENCE_COMPARE(request, <, c->in.request_read))
|
||||||
{
|
{
|
||||||
head = _xcb_map_remove(c->in.replies, request);
|
head = _xcb_map_remove(c->in.replies, request);
|
||||||
if(head && head->next)
|
if(head && head->next)
|
||||||
|
@ -300,7 +428,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
|
||||||
}
|
}
|
||||||
/* We're currently processing the responses to the request we want, and we
|
/* We're currently processing the responses to the request we want, and we
|
||||||
* have a reply ready to return. So just return it without blocking. */
|
* have a reply ready to return. So just return it without blocking. */
|
||||||
else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
|
else if(request == c->in.request_read && c->in.current_reply)
|
||||||
{
|
{
|
||||||
head = c->in.current_reply;
|
head = c->in.current_reply;
|
||||||
c->in.current_reply = head->next;
|
c->in.current_reply = head->next;
|
||||||
|
@ -309,7 +437,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
|
||||||
}
|
}
|
||||||
/* We know this request can't have any more replies, and we've already
|
/* We know this request can't have any more replies, and we've already
|
||||||
* established it doesn't have a reply now. Don't bother blocking. */
|
* established it doesn't have a reply now. Don't bother blocking. */
|
||||||
else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_completed))
|
else if(request == c->in.request_completed)
|
||||||
head = 0;
|
head = 0;
|
||||||
/* We may have more replies on the way for this request: block until we're
|
/* We may have more replies on the way for this request: block until we're
|
||||||
* sure. */
|
* sure. */
|
||||||
|
@ -338,72 +466,120 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void insert_reader(reader_list **prev_reader, reader_list *reader, uint64_t request, pthread_cond_t *cond)
|
||||||
|
{
|
||||||
|
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request))
|
||||||
|
prev_reader = &(*prev_reader)->next;
|
||||||
|
reader->request = request;
|
||||||
|
reader->data = cond;
|
||||||
|
reader->next = *prev_reader;
|
||||||
|
*prev_reader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_reader(reader_list **prev_reader, reader_list *reader)
|
||||||
|
{
|
||||||
|
while(*prev_reader && XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, reader->request))
|
||||||
|
if(*prev_reader == reader)
|
||||||
|
{
|
||||||
|
*prev_reader = (*prev_reader)->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_special(special_list **prev_special, special_list *special, xcb_special_event_t *se)
|
||||||
|
{
|
||||||
|
special->se = se;
|
||||||
|
special->next = *prev_special;
|
||||||
|
*prev_special = special;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_special(special_list **prev_special, special_list *special)
|
||||||
|
{
|
||||||
|
while(*prev_special)
|
||||||
|
{
|
||||||
|
if(*prev_special == special)
|
||||||
|
{
|
||||||
|
*prev_special = (*prev_special)->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev_special = &(*prev_special)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e)
|
||||||
|
{
|
||||||
|
void *ret = 0;
|
||||||
|
|
||||||
|
/* If this request has not been written yet, write it. */
|
||||||
|
if(c->out.return_socket || _xcb_out_flush_to(c, request))
|
||||||
|
{
|
||||||
|
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
reader_list reader;
|
||||||
|
|
||||||
|
insert_reader(&c->in.readers, &reader, request, &cond);
|
||||||
|
|
||||||
|
while(!poll_for_reply(c, request, &ret, e))
|
||||||
|
if(!_xcb_conn_wait(c, &cond, 0, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
remove_reader(&c->in.readers, &reader);
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
_xcb_in_wake_up_next_reader(c);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t widen(xcb_connection_t *c, unsigned int request)
|
||||||
|
{
|
||||||
|
uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
|
||||||
|
if(widened_request > c->out.request)
|
||||||
|
widened_request -= UINT64_C(1) << 32;
|
||||||
|
return widened_request;
|
||||||
|
}
|
||||||
|
|
||||||
/* Public interface */
|
/* Public interface */
|
||||||
|
|
||||||
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
|
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
|
||||||
{
|
{
|
||||||
uint64_t widened_request;
|
void *ret;
|
||||||
void *ret = 0;
|
|
||||||
if(e)
|
if(e)
|
||||||
*e = 0;
|
*e = 0;
|
||||||
if(c->has_error)
|
if(c->has_error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&c->iolock);
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
ret = wait_for_reply(c, widen(c, request), e);
|
||||||
widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
|
|
||||||
if(widened_request > c->out.request)
|
|
||||||
widened_request -= UINT64_C(1) << 32;
|
|
||||||
|
|
||||||
/* If this request has not been written yet, write it. */
|
|
||||||
if(c->out.return_socket || _xcb_out_flush_to(c, widened_request))
|
|
||||||
{
|
|
||||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
|
||||||
reader_list reader;
|
|
||||||
reader_list **prev_reader;
|
|
||||||
|
|
||||||
for(prev_reader = &c->in.readers;
|
|
||||||
*prev_reader &&
|
|
||||||
XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
|
|
||||||
prev_reader = &(*prev_reader)->next)
|
|
||||||
{
|
|
||||||
/* empty */;
|
|
||||||
}
|
|
||||||
reader.request = request;
|
|
||||||
reader.data = &cond;
|
|
||||||
reader.next = *prev_reader;
|
|
||||||
*prev_reader = &reader;
|
|
||||||
|
|
||||||
while(!poll_for_reply(c, request, &ret, e))
|
|
||||||
if(!_xcb_conn_wait(c, &cond, 0, 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
for(prev_reader = &c->in.readers;
|
|
||||||
*prev_reader &&
|
|
||||||
XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
|
|
||||||
prev_reader = &(*prev_reader)->next)
|
|
||||||
{
|
|
||||||
if(*prev_reader == &reader)
|
|
||||||
{
|
|
||||||
*prev_reader = (*prev_reader)->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_cond_destroy(&cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
_xcb_in_wake_up_next_reader(c);
|
|
||||||
pthread_mutex_unlock(&c->iolock);
|
pthread_mutex_unlock(&c->iolock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *xcb_wait_for_reply64(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
if(e)
|
||||||
|
*e = 0;
|
||||||
|
if(c->has_error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
ret = wait_for_reply(c, request, e);
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t reply_size)
|
||||||
|
{
|
||||||
|
return (int *) (&((char *) reply)[reply_size]);
|
||||||
|
}
|
||||||
|
|
||||||
static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_next, uint64_t seq)
|
static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_next, uint64_t seq)
|
||||||
{
|
{
|
||||||
pending_reply *pend;
|
pending_reply *pend;
|
||||||
pend = malloc(sizeof(*pend));
|
pend = malloc(sizeof(*pend));
|
||||||
if(!pend)
|
if(!pend)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,66 +594,27 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
|
||||||
c->in.pending_replies_tail = &pend->next;
|
c->in.pending_replies_tail = &pend->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void discard_reply(xcb_connection_t *c, unsigned int request)
|
static void discard_reply(xcb_connection_t *c, uint64_t request)
|
||||||
{
|
{
|
||||||
pending_reply *pend = 0;
|
void *reply;
|
||||||
pending_reply **prev_pend;
|
pending_reply **prev_pend;
|
||||||
uint64_t widened_request;
|
|
||||||
|
|
||||||
/* We've read requests past the one we want, so if it has replies we have
|
/* Free any replies or errors that we've already read. Stop if
|
||||||
* them all and they're in the replies map. */
|
* xcb_wait_for_reply would block or we've run out of replies. */
|
||||||
if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
|
while(poll_for_reply(c, request, &reply, 0) && reply)
|
||||||
{
|
free(reply);
|
||||||
struct reply_list *head;
|
|
||||||
head = _xcb_map_remove(c->in.replies, request);
|
/* If we've proven there are no more responses coming, we're done. */
|
||||||
while (head)
|
if(XCB_SEQUENCE_COMPARE(request, <=, c->in.request_completed))
|
||||||
{
|
|
||||||
struct reply_list *next = head->next;
|
|
||||||
free(head->reply);
|
|
||||||
free(head);
|
|
||||||
head = next;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* We're currently processing the responses to the request we want, and we
|
|
||||||
* have a reply ready to return. Free it, and mark the pend to free any further
|
|
||||||
* replies. */
|
|
||||||
if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
|
|
||||||
{
|
|
||||||
struct reply_list *head;
|
|
||||||
head = c->in.current_reply;
|
|
||||||
c->in.current_reply = NULL;
|
|
||||||
c->in.current_reply_tail = &c->in.current_reply;
|
|
||||||
while (head)
|
|
||||||
{
|
|
||||||
struct reply_list *next = head->next;
|
|
||||||
free(head->reply);
|
|
||||||
free(head);
|
|
||||||
head = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
pend = c->in.pending_replies;
|
|
||||||
if(pend &&
|
|
||||||
!(XCB_SEQUENCE_COMPARE(pend->first_request, <=, c->in.request_read) &&
|
|
||||||
(pend->workaround == WORKAROUND_EXTERNAL_SOCKET_OWNER ||
|
|
||||||
XCB_SEQUENCE_COMPARE(c->in.request_read, <=, pend->last_request))))
|
|
||||||
pend = 0;
|
|
||||||
if(pend)
|
|
||||||
pend->flags |= XCB_REQUEST_DISCARD_REPLY;
|
|
||||||
else
|
|
||||||
insert_pending_discard(c, &c->in.pending_replies, c->in.request_read);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Walk the list of pending requests. Mark the first match for deletion. */
|
/* Walk the list of pending requests. Mark the first match for deletion. */
|
||||||
for(prev_pend = &c->in.pending_replies; *prev_pend; prev_pend = &(*prev_pend)->next)
|
for(prev_pend = &c->in.pending_replies; *prev_pend; prev_pend = &(*prev_pend)->next)
|
||||||
{
|
{
|
||||||
if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, >, request))
|
if(XCB_SEQUENCE_COMPARE((*prev_pend)->first_request, >, request))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, ==, request))
|
if((*prev_pend)->first_request == request)
|
||||||
{
|
{
|
||||||
/* Pending reply found. Mark for discard: */
|
/* Pending reply found. Mark for discard: */
|
||||||
(*prev_pend)->flags |= XCB_REQUEST_DISCARD_REPLY;
|
(*prev_pend)->flags |= XCB_REQUEST_DISCARD_REPLY;
|
||||||
|
@ -486,14 +623,24 @@ static void discard_reply(xcb_connection_t *c, unsigned int request)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pending reply not found (likely due to _unchecked request). Create one: */
|
/* Pending reply not found (likely due to _unchecked request). Create one: */
|
||||||
widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
|
insert_pending_discard(c, prev_pend, request);
|
||||||
if(widened_request > c->out.request)
|
|
||||||
widened_request -= UINT64_C(1) << 32;
|
|
||||||
|
|
||||||
insert_pending_discard(c, prev_pend, widened_request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
|
void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
|
||||||
|
{
|
||||||
|
if(c->has_error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If an error occurred when issuing the request, fail immediately. */
|
||||||
|
if(!sequence)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
discard_reply(c, widen(c, sequence));
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xcb_discard_reply64(xcb_connection_t *c, uint64_t sequence)
|
||||||
{
|
{
|
||||||
if(c->has_error)
|
if(c->has_error)
|
||||||
return;
|
return;
|
||||||
|
@ -519,6 +666,27 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply,
|
||||||
}
|
}
|
||||||
assert(reply != 0);
|
assert(reply != 0);
|
||||||
pthread_mutex_lock(&c->iolock);
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
ret = poll_for_reply(c, widen(c, request), reply, error);
|
||||||
|
if(!ret && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
|
||||||
|
ret = poll_for_reply(c, widen(c, request), reply, error);
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xcb_poll_for_reply64(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if(c->has_error)
|
||||||
|
{
|
||||||
|
*reply = 0;
|
||||||
|
if(error)
|
||||||
|
*error = 0;
|
||||||
|
return 1; /* would not block */
|
||||||
|
}
|
||||||
|
assert(reply != 0);
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
ret = poll_for_reply(c, request, reply, error);
|
||||||
|
if(!ret && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
|
||||||
ret = poll_for_reply(c, request, reply, error);
|
ret = poll_for_reply(c, request, reply, error);
|
||||||
pthread_mutex_unlock(&c->iolock);
|
pthread_mutex_unlock(&c->iolock);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -540,7 +708,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
|
static xcb_generic_event_t *poll_for_next_event(xcb_connection_t *c, int queued)
|
||||||
{
|
{
|
||||||
xcb_generic_event_t *ret = 0;
|
xcb_generic_event_t *ret = 0;
|
||||||
if(!c->has_error)
|
if(!c->has_error)
|
||||||
|
@ -548,33 +716,177 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
|
||||||
pthread_mutex_lock(&c->iolock);
|
pthread_mutex_lock(&c->iolock);
|
||||||
/* FIXME: follow X meets Z architecture changes. */
|
/* FIXME: follow X meets Z architecture changes. */
|
||||||
ret = get_event(c);
|
ret = get_event(c);
|
||||||
if(!ret && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
|
if(!ret && !queued && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
|
||||||
ret = get_event(c);
|
ret = get_event(c);
|
||||||
pthread_mutex_unlock(&c->iolock);
|
pthread_mutex_unlock(&c->iolock);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
return poll_for_next_event(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
return poll_for_next_event(c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
|
xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
|
||||||
{
|
{
|
||||||
/* FIXME: this could hold the lock to avoid syncing unnecessarily, but
|
uint64_t request;
|
||||||
* that would require factoring the locking out of xcb_get_input_focus,
|
xcb_generic_error_t *ret = 0;
|
||||||
* xcb_get_input_focus_reply, and xcb_wait_for_reply. */
|
|
||||||
xcb_generic_error_t *ret;
|
|
||||||
void *reply;
|
void *reply;
|
||||||
if(c->has_error)
|
if(c->has_error)
|
||||||
return 0;
|
return 0;
|
||||||
if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_expected)
|
pthread_mutex_lock(&c->iolock);
|
||||||
&& XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
|
request = widen(c, cookie.sequence);
|
||||||
|
if (XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed))
|
||||||
{
|
{
|
||||||
free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret));
|
if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected))
|
||||||
assert(!ret);
|
{
|
||||||
|
_xcb_out_send_sync(c);
|
||||||
}
|
}
|
||||||
reply = xcb_wait_for_reply(c, cookie.sequence, &ret);
|
if (XCB_SEQUENCE_COMPARE(request, >=, c->out.request_expected_written))
|
||||||
|
{
|
||||||
|
_xcb_out_flush_to(c, c->out.request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply = wait_for_reply(c, request, &ret);
|
||||||
assert(!reply);
|
assert(!reply);
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xcb_generic_event_t *get_special_event(xcb_connection_t *c,
|
||||||
|
xcb_special_event_t *se)
|
||||||
|
{
|
||||||
|
xcb_generic_event_t *event = NULL;
|
||||||
|
struct event_list *events;
|
||||||
|
|
||||||
|
if ((events = se->events) != NULL) {
|
||||||
|
event = events->event;
|
||||||
|
if (!(se->events = events->next))
|
||||||
|
se->events_tail = &se->events;
|
||||||
|
free (events);
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
|
||||||
|
xcb_special_event_t *se)
|
||||||
|
{
|
||||||
|
xcb_generic_event_t *event;
|
||||||
|
|
||||||
|
if(c->has_error)
|
||||||
|
return 0;
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
event = get_special_event(c, se);
|
||||||
|
if(!event && c->in.reading == 0 && _xcb_in_read(c)) /* _xcb_in_read shuts down the connection on error */
|
||||||
|
event = get_special_event(c, se);
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
|
||||||
|
xcb_special_event_t *se)
|
||||||
|
{
|
||||||
|
special_list special;
|
||||||
|
xcb_generic_event_t *event;
|
||||||
|
|
||||||
|
if(c->has_error)
|
||||||
|
return 0;
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
|
||||||
|
insert_special(&c->in.special_waiters, &special, se);
|
||||||
|
|
||||||
|
/* get_special_event returns 0 on empty list. */
|
||||||
|
while(!(event = get_special_event(c, se)))
|
||||||
|
if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
remove_special(&c->in.special_waiters, &special);
|
||||||
|
|
||||||
|
_xcb_in_wake_up_next_reader(c);
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_special_event_t *
|
||||||
|
xcb_register_for_special_xge(xcb_connection_t *c,
|
||||||
|
xcb_extension_t *ext,
|
||||||
|
uint32_t eid,
|
||||||
|
uint32_t *stamp)
|
||||||
|
{
|
||||||
|
xcb_special_event_t *se;
|
||||||
|
const xcb_query_extension_reply_t *ext_reply;
|
||||||
|
|
||||||
|
if(c->has_error)
|
||||||
|
return NULL;
|
||||||
|
ext_reply = xcb_get_extension_data(c, ext);
|
||||||
|
if (!ext_reply)
|
||||||
|
return NULL;
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
for (se = c->in.special_events; se; se = se->next) {
|
||||||
|
if (se->extension == ext_reply->major_opcode &&
|
||||||
|
se->eid == eid) {
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
se = calloc(1, sizeof(xcb_special_event_t));
|
||||||
|
if (!se) {
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
se->extension = ext_reply->major_opcode;
|
||||||
|
se->eid = eid;
|
||||||
|
|
||||||
|
se->events = NULL;
|
||||||
|
se->events_tail = &se->events;
|
||||||
|
se->stamp = stamp;
|
||||||
|
|
||||||
|
pthread_cond_init(&se->special_event_cond, 0);
|
||||||
|
|
||||||
|
se->next = c->in.special_events;
|
||||||
|
c->in.special_events = se;
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xcb_unregister_for_special_event(xcb_connection_t *c,
|
||||||
|
xcb_special_event_t *se)
|
||||||
|
{
|
||||||
|
xcb_special_event_t *s, **prev;
|
||||||
|
struct event_list *events, *next;
|
||||||
|
|
||||||
|
if (!se)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (c->has_error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&c->iolock);
|
||||||
|
|
||||||
|
for (prev = &c->in.special_events; (s = *prev) != NULL; prev = &(s->next)) {
|
||||||
|
if (s == se) {
|
||||||
|
*prev = se->next;
|
||||||
|
for (events = se->events; events; events = next) {
|
||||||
|
next = events->next;
|
||||||
|
free (events->event);
|
||||||
|
free (events);
|
||||||
|
}
|
||||||
|
pthread_cond_destroy(&se->special_event_cond);
|
||||||
|
free (se);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&c->iolock);
|
||||||
|
}
|
||||||
|
|
||||||
/* Private interface */
|
/* Private interface */
|
||||||
|
|
||||||
int _xcb_in_init(_xcb_in *in)
|
int _xcb_in_init(_xcb_in *in)
|
||||||
|
@ -624,6 +936,8 @@ void _xcb_in_wake_up_next_reader(xcb_connection_t *c)
|
||||||
int pthreadret;
|
int pthreadret;
|
||||||
if(c->in.readers)
|
if(c->in.readers)
|
||||||
pthreadret = pthread_cond_signal(c->in.readers->data);
|
pthreadret = pthread_cond_signal(c->in.readers->data);
|
||||||
|
else if(c->in.special_waiters)
|
||||||
|
pthreadret = pthread_cond_signal(&c->in.special_waiters->se->special_event_cond);
|
||||||
else
|
else
|
||||||
pthreadret = pthread_cond_signal(&c->in.event_cond);
|
pthreadret = pthread_cond_signal(&c->in.event_cond);
|
||||||
assert(pthreadret == 0);
|
assert(pthreadret == 0);
|
||||||
|
@ -635,7 +949,7 @@ int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds
|
||||||
assert(workaround != WORKAROUND_NONE || flags != 0);
|
assert(workaround != WORKAROUND_NONE || flags != 0);
|
||||||
if(!pend)
|
if(!pend)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pend->first_request = pend->last_request = request;
|
pend->first_request = pend->last_request = request;
|
||||||
|
@ -655,22 +969,106 @@ void _xcb_in_replies_done(xcb_connection_t *c)
|
||||||
pend = container_of(c->in.pending_replies_tail, struct pending_reply, next);
|
pend = container_of(c->in.pending_replies_tail, struct pending_reply, next);
|
||||||
if(pend->workaround == WORKAROUND_EXTERNAL_SOCKET_OWNER)
|
if(pend->workaround == WORKAROUND_EXTERNAL_SOCKET_OWNER)
|
||||||
{
|
{
|
||||||
|
if (XCB_SEQUENCE_COMPARE(pend->first_request, <=, c->out.request)) {
|
||||||
pend->last_request = c->out.request;
|
pend->last_request = c->out.request;
|
||||||
pend->workaround = WORKAROUND_NONE;
|
pend->workaround = WORKAROUND_NONE;
|
||||||
|
} else {
|
||||||
|
/* The socket was taken, but no requests were actually sent
|
||||||
|
* so just discard the pending_reply that was created.
|
||||||
|
*/
|
||||||
|
struct pending_reply **prev_next = &c->in.pending_replies;
|
||||||
|
while (*prev_next != pend)
|
||||||
|
prev_next = &(*prev_next)->next;
|
||||||
|
*prev_next = NULL;
|
||||||
|
c->in.pending_replies_tail = prev_next;
|
||||||
|
free(pend);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _xcb_in_read(xcb_connection_t *c)
|
int _xcb_in_read(xcb_connection_t *c)
|
||||||
{
|
{
|
||||||
int n = read(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len);
|
int n;
|
||||||
if(n > 0)
|
|
||||||
|
#if HAVE_SENDMSG
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = c->in.queue + c->in.queue_len,
|
||||||
|
.iov_len = sizeof(c->in.queue) - c->in.queue_len,
|
||||||
|
};
|
||||||
|
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 = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = cmsgbuf.buf,
|
||||||
|
.msg_controllen = CMSG_SPACE(sizeof(int) * (XCB_MAX_PASS_FD - c->in.in_fd.nfd)),
|
||||||
|
};
|
||||||
|
n = recvmsg(c->fd, &msg, 0);
|
||||||
|
|
||||||
|
/* Check for truncation errors. Only MSG_CTRUNC is
|
||||||
|
* probably possible here, which would indicate that
|
||||||
|
* the sender tried to transmit more than XCB_MAX_PASS_FD
|
||||||
|
* file descriptors.
|
||||||
|
*/
|
||||||
|
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
|
||||||
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_FDPASSING_FAILED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len, 0);
|
||||||
|
#endif
|
||||||
|
if(n > 0) {
|
||||||
|
#if HAVE_SENDMSG
|
||||||
|
struct cmsghdr *hdr;
|
||||||
|
|
||||||
|
if (msg.msg_controllen >= sizeof (struct cmsghdr)) {
|
||||||
|
for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
|
||||||
|
if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
|
||||||
|
int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
|
||||||
|
memcpy(&c->in.in_fd.fd[c->in.in_fd.nfd], CMSG_DATA(hdr), nfd * sizeof (int));
|
||||||
|
c->in.in_fd.nfd += nfd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
c->in.total_read += n;
|
||||||
c->in.queue_len += n;
|
c->in.queue_len += n;
|
||||||
|
}
|
||||||
while(read_packet(c))
|
while(read_packet(c))
|
||||||
/* empty */;
|
/* empty */;
|
||||||
if((n > 0) || (n < 0 && errno == EAGAIN))
|
#if HAVE_SENDMSG
|
||||||
|
if (c->in.in_fd.nfd) {
|
||||||
|
c->in.in_fd.nfd -= c->in.in_fd.ifd;
|
||||||
|
memmove(&c->in.in_fd.fd[0],
|
||||||
|
&c->in.in_fd.fd[c->in.in_fd.ifd],
|
||||||
|
c->in.in_fd.nfd * sizeof (int));
|
||||||
|
c->in.in_fd.ifd = 0;
|
||||||
|
|
||||||
|
/* If we have any left-over file descriptors after emptying
|
||||||
|
* the input buffer, then the server sent some that we weren't
|
||||||
|
* expecting. Close them and mark the connection as broken;
|
||||||
|
*/
|
||||||
|
if (c->in.queue_len == 0 && c->in.in_fd.nfd != 0) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < c->in.in_fd.nfd; i++)
|
||||||
|
close(c->in.in_fd.fd[i]);
|
||||||
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_FDPASSING_FAILED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef _WIN32
|
||||||
|
if((n > 0) || (n < 0 && (errno == EAGAIN || errno == EINTR)))
|
||||||
|
#else
|
||||||
|
if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK))
|
||||||
|
#endif /* !_WIN32 */
|
||||||
return 1;
|
return 1;
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,7 +1087,7 @@ int _xcb_in_read_block(xcb_connection_t *c, void *buf, int len)
|
||||||
int ret = read_block(c->fd, (char *) buf + done, len - done);
|
int ret = read_block(c->fd, (char *) buf + done, len - done);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
/* A generic implementation of a list of void-pointers. */
|
/* A generic implementation of a list of void-pointers. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
@ -32,7 +36,7 @@
|
||||||
|
|
||||||
typedef struct node {
|
typedef struct node {
|
||||||
struct node *next;
|
struct node *next;
|
||||||
unsigned int key;
|
uint64_t key;
|
||||||
void *data;
|
void *data;
|
||||||
} node;
|
} node;
|
||||||
|
|
||||||
|
@ -43,7 +47,7 @@ struct _xcb_map {
|
||||||
|
|
||||||
/* Private interface */
|
/* Private interface */
|
||||||
|
|
||||||
_xcb_map *_xcb_map_new()
|
_xcb_map *_xcb_map_new(void)
|
||||||
{
|
{
|
||||||
_xcb_map *list;
|
_xcb_map *list;
|
||||||
list = malloc(sizeof(_xcb_map));
|
list = malloc(sizeof(_xcb_map));
|
||||||
|
@ -69,7 +73,7 @@ void _xcb_map_delete(_xcb_map *list, xcb_list_free_func_t do_free)
|
||||||
free(list);
|
free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _xcb_map_put(_xcb_map *list, unsigned int key, void *data)
|
int _xcb_map_put(_xcb_map *list, uint64_t key, void *data)
|
||||||
{
|
{
|
||||||
node *cur = malloc(sizeof(node));
|
node *cur = malloc(sizeof(node));
|
||||||
if(!cur)
|
if(!cur)
|
||||||
|
@ -82,7 +86,7 @@ int _xcb_map_put(_xcb_map *list, unsigned int key, void *data)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_xcb_map_remove(_xcb_map *list, unsigned int key)
|
void *_xcb_map_remove(_xcb_map *list, uint64_t key)
|
||||||
{
|
{
|
||||||
node **cur;
|
node **cur;
|
||||||
for(cur = &list->head; *cur; cur = &(*cur)->next)
|
for(cur = &list->head; *cur; cur = &(*cur)->next)
|
||||||
|
|
251
src/xcb_out.c
251
src/xcb_out.c
|
@ -25,9 +25,17 @@
|
||||||
|
|
||||||
/* Stuff that sends stuff to the server. */
|
/* Stuff that sends stuff to the server. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
@ -35,8 +43,17 @@
|
||||||
#include "xcbint.h"
|
#include "xcbint.h"
|
||||||
#include "bigreq.h"
|
#include "bigreq.h"
|
||||||
|
|
||||||
static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
|
static inline void send_request(xcb_connection_t *c, int isvoid, enum workarounds workaround, int flags, struct iovec *vector, int count)
|
||||||
{
|
{
|
||||||
|
if(c->has_error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++c->out.request;
|
||||||
|
if(!isvoid)
|
||||||
|
c->in.request_expected = c->out.request;
|
||||||
|
if(workaround != WORKAROUND_NONE || flags != 0)
|
||||||
|
_xcb_in_expect_reply(c, c->out.request, workaround, flags);
|
||||||
|
|
||||||
while(count && c->out.queue_len + vector[0].iov_len <= sizeof(c->out.queue))
|
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);
|
memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len);
|
||||||
|
@ -46,13 +63,29 @@ static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
|
||||||
++vector, --count;
|
++vector, --count;
|
||||||
}
|
}
|
||||||
if(!count)
|
if(!count)
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
--vector, ++count;
|
--vector, ++count;
|
||||||
vector[0].iov_base = c->out.queue;
|
vector[0].iov_base = c->out.queue;
|
||||||
vector[0].iov_len = c->out.queue_len;
|
vector[0].iov_len = c->out.queue_len;
|
||||||
c->out.queue_len = 0;
|
c->out.queue_len = 0;
|
||||||
return _xcb_out_send(c, vector, count);
|
_xcb_out_send(c, vector, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_sync(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
static const union {
|
||||||
|
struct {
|
||||||
|
uint8_t major;
|
||||||
|
uint8_t pad;
|
||||||
|
uint16_t len;
|
||||||
|
} fields;
|
||||||
|
uint32_t packet;
|
||||||
|
} sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
|
||||||
|
struct iovec vector[2];
|
||||||
|
vector[1].iov_base = (char *) &sync_req;
|
||||||
|
vector[1].iov_len = sizeof(sync_req);
|
||||||
|
send_request(c, 0, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY, vector + 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_socket_back(xcb_connection_t *c)
|
static void get_socket_back(xcb_connection_t *c)
|
||||||
|
@ -74,6 +107,33 @@ static void get_socket_back(xcb_connection_t *c)
|
||||||
_xcb_in_replies_done(c);
|
_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 */
|
/* Public interface */
|
||||||
|
|
||||||
void xcb_prefetch_maximum_request_length(xcb_connection_t *c)
|
void xcb_prefetch_maximum_request_length(xcb_connection_t *c)
|
||||||
|
@ -121,23 +181,59 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
|
||||||
return c->out.maximum_request_length.value;
|
return c->out.maximum_request_length.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
|
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)
|
||||||
{
|
{
|
||||||
static const union {
|
|
||||||
struct {
|
|
||||||
uint8_t major;
|
|
||||||
uint8_t pad;
|
|
||||||
uint16_t len;
|
|
||||||
} fields;
|
|
||||||
uint32_t packet;
|
|
||||||
} sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
|
|
||||||
uint64_t request;
|
uint64_t request;
|
||||||
uint32_t prefix[3] = { 0 };
|
uint32_t prefix[2];
|
||||||
int veclen = req->count;
|
int veclen = req->count;
|
||||||
enum workarounds workaround = WORKAROUND_NONE;
|
enum workarounds workaround = WORKAROUND_NONE;
|
||||||
|
|
||||||
if(c->has_error)
|
if(c->has_error) {
|
||||||
|
close_fds(fds, num_fds);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
assert(c != 0);
|
assert(c != 0);
|
||||||
assert(vector != 0);
|
assert(vector != 0);
|
||||||
|
@ -156,7 +252,8 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
|
||||||
const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
|
const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
|
||||||
if(!(extension && extension->present))
|
if(!(extension && extension->present))
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(c);
|
close_fds(fds, num_fds);
|
||||||
|
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
|
((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
|
||||||
|
@ -186,14 +283,23 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
|
||||||
}
|
}
|
||||||
else if(longlen > xcb_get_maximum_request_length(c))
|
else if(longlen > xcb_get_maximum_request_length(c))
|
||||||
{
|
{
|
||||||
_xcb_conn_shutdown(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? */
|
return 0; /* server can't take this; maybe need BIGREQUESTS? */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the length field. */
|
/* set the length field. */
|
||||||
((uint16_t *) vector[0].iov_base)[1] = shortlen;
|
((uint16_t *) vector[0].iov_base)[1] = shortlen;
|
||||||
if(!shortlen)
|
if(!shortlen)
|
||||||
prefix[2] = ++longlen;
|
{
|
||||||
|
prefix[0] = ((uint32_t *) vector[0].iov_base)[0];
|
||||||
|
prefix[1] = ++longlen;
|
||||||
|
vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1;
|
||||||
|
vector[0].iov_len -= sizeof(uint32_t);
|
||||||
|
--vector, ++veclen;
|
||||||
|
vector[0].iov_base = prefix;
|
||||||
|
vector[0].iov_len = sizeof(prefix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flags &= ~XCB_REQUEST_RAW;
|
flags &= ~XCB_REQUEST_RAW;
|
||||||
|
|
||||||
|
@ -207,54 +313,66 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
|
||||||
|
|
||||||
/* get a sequence number and arrange for delivery. */
|
/* get a sequence number and arrange for delivery. */
|
||||||
pthread_mutex_lock(&c->iolock);
|
pthread_mutex_lock(&c->iolock);
|
||||||
/* wait for other writing threads to get out of my way. */
|
|
||||||
while(c->out.writing)
|
|
||||||
pthread_cond_wait(&c->out.cond, &c->iolock);
|
|
||||||
get_socket_back(c);
|
|
||||||
|
|
||||||
request = ++c->out.request;
|
/* 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
|
/* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
|
||||||
* a reply.
|
* a reply.
|
||||||
* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
|
* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
|
||||||
* applications see sequence 0 as that is used to indicate
|
* applications see sequence 0 as that is used to indicate
|
||||||
* an error in sending the request */
|
* an error in sending the request
|
||||||
while((req->isvoid &&
|
*/
|
||||||
c->out.request == c->in.request_expected + (1 << 16) - 1) ||
|
|
||||||
request == 0)
|
while ((req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) ||
|
||||||
|
(unsigned int) (c->out.request + 1) == 0)
|
||||||
{
|
{
|
||||||
prefix[0] = sync_req.packet;
|
send_sync(c);
|
||||||
_xcb_in_expect_reply(c, request, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY);
|
prepare_socket_request(c);
|
||||||
c->in.request_expected = c->out.request;
|
|
||||||
request = ++c->out.request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(workaround != WORKAROUND_NONE || flags != 0)
|
send_request(c, req->isvoid, workaround, flags, vector, veclen);
|
||||||
_xcb_in_expect_reply(c, request, workaround, flags);
|
request = c->has_error ? 0 : c->out.request;
|
||||||
if(!req->isvoid)
|
|
||||||
c->in.request_expected = c->out.request;
|
|
||||||
|
|
||||||
if(prefix[0] || prefix[2])
|
|
||||||
{
|
|
||||||
--vector, ++veclen;
|
|
||||||
if(prefix[2])
|
|
||||||
{
|
|
||||||
prefix[1] = ((uint32_t *) vector[1].iov_base)[0];
|
|
||||||
vector[1].iov_base = (uint32_t *) vector[1].iov_base + 1;
|
|
||||||
vector[1].iov_len -= sizeof(uint32_t);
|
|
||||||
}
|
|
||||||
vector[0].iov_len = sizeof(uint32_t) * ((prefix[0] ? 1 : 0) + (prefix[2] ? 2 : 0));
|
|
||||||
vector[0].iov_base = prefix + !prefix[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!write_block(c, vector, veclen))
|
|
||||||
{
|
|
||||||
_xcb_conn_shutdown(c);
|
|
||||||
request = 0;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&c->iolock);
|
pthread_mutex_unlock(&c->iolock);
|
||||||
return request;
|
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 xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -262,13 +380,25 @@ int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), v
|
||||||
return 0;
|
return 0;
|
||||||
pthread_mutex_lock(&c->iolock);
|
pthread_mutex_lock(&c->iolock);
|
||||||
get_socket_back(c);
|
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);
|
ret = _xcb_out_flush_to(c, c->out.request);
|
||||||
|
while (ret && c->out.request != c->out.request_written);
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
c->out.return_socket = return_socket;
|
c->out.return_socket = return_socket;
|
||||||
c->out.socket_closure = closure;
|
c->out.socket_closure = closure;
|
||||||
if(flags)
|
if(flags) {
|
||||||
_xcb_in_expect_reply(c, c->out.request, WORKAROUND_EXTERNAL_SOCKET_OWNER, 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);
|
assert(c->out.request == c->out.request_written);
|
||||||
*sent = c->out.request;
|
*sent = c->out.request;
|
||||||
}
|
}
|
||||||
|
@ -317,6 +447,7 @@ int _xcb_out_init(_xcb_out *out)
|
||||||
|
|
||||||
out->request = 0;
|
out->request = 0;
|
||||||
out->request_written = 0;
|
out->request_written = 0;
|
||||||
|
out->request_expected_written = 0;
|
||||||
|
|
||||||
if(pthread_mutex_init(&out->reqlenlock, 0))
|
if(pthread_mutex_init(&out->reqlenlock, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -327,8 +458,9 @@ int _xcb_out_init(_xcb_out *out)
|
||||||
|
|
||||||
void _xcb_out_destroy(_xcb_out *out)
|
void _xcb_out_destroy(_xcb_out *out)
|
||||||
{
|
{
|
||||||
pthread_cond_destroy(&out->cond);
|
|
||||||
pthread_mutex_destroy(&out->reqlenlock);
|
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 _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
|
||||||
|
@ -337,11 +469,18 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
|
||||||
while(ret && count)
|
while(ret && count)
|
||||||
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count);
|
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count);
|
||||||
c->out.request_written = c->out.request;
|
c->out.request_written = c->out.request;
|
||||||
|
c->out.request_expected_written = c->in.request_expected;
|
||||||
pthread_cond_broadcast(&c->out.cond);
|
pthread_cond_broadcast(&c->out.cond);
|
||||||
_xcb_in_wake_up_next_reader(c);
|
_xcb_in_wake_up_next_reader(c);
|
||||||
return ret;
|
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)
|
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
|
||||||
{
|
{
|
||||||
assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));
|
assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));
|
||||||
|
|
365
src/xcb_util.c
365
src/xcb_util.c
|
@ -25,38 +25,136 @@
|
||||||
|
|
||||||
/* Utility functions implementable using only public APIs. */
|
/* Utility functions implementable using only public APIs. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/un.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#ifdef DNETCONN
|
|
||||||
#include <netdnet/dnetdb.h>
|
|
||||||
#include <netdnet/dn.h>
|
|
||||||
#endif
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.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 "xcb.h"
|
||||||
#include "xcbext.h"
|
#include "xcbext.h"
|
||||||
#include "xcbint.h"
|
#include "xcbint.h"
|
||||||
|
|
||||||
static const int error_connection = 1;
|
#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
|
||||||
|
# include <tsol/label.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#ifndef __has_builtin
|
||||||
|
# define __has_builtin(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
int xcb_popcount(uint32_t mask)
|
int xcb_popcount(uint32_t mask)
|
||||||
{
|
{
|
||||||
|
#if __has_builtin(__builtin_popcount)
|
||||||
|
return __builtin_popcount(mask);
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Count the number of bits set to 1 in a 32-bit word.
|
||||||
|
* Algorithm from MIT AI Lab Memo 239: "HAKMEM", ITEM 169.
|
||||||
|
* https://dspace.mit.edu/handle/1721.1/6086
|
||||||
|
*/
|
||||||
uint32_t y;
|
uint32_t y;
|
||||||
y = (mask >> 1) & 033333333333;
|
y = (mask >> 1) & 033333333333;
|
||||||
y = mask - y - ((y >> 1) & 033333333333);
|
y = mask - y - ((y >> 1) & 033333333333);
|
||||||
return ((y + (y >> 3)) & 030707070707) % 077;
|
return ((y + (y >> 3)) & 030707070707) % 077;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int xcb_sumof(uint8_t *list, int len)
|
||||||
|
{
|
||||||
|
int i, s = 0;
|
||||||
|
for(i=0; i<len; i++) {
|
||||||
|
s += *list;
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
/* In addition to the AF_UNIX path, there may be a screen number.
|
||||||
|
* The trailing \0 is already accounted in the size of sun_path. */
|
||||||
|
char path[sizeof(((struct sockaddr_un*)0)->sun_path) + 1 + 10];
|
||||||
|
size_t len;
|
||||||
|
int _screen = 0, res;
|
||||||
|
|
||||||
|
len = strlen(name);
|
||||||
|
if (len >= sizeof(path))
|
||||||
|
return 0;
|
||||||
|
memcpy(path, name, len + 1);
|
||||||
|
res = stat(path, &sbuf);
|
||||||
|
if (0 != res) {
|
||||||
|
unsigned long lscreen;
|
||||||
|
char *dot, *endptr;
|
||||||
|
if (res != -1 || (errno != ENOENT && errno != ENOTDIR))
|
||||||
|
return 0;
|
||||||
|
dot = strrchr(path, '.');
|
||||||
|
if (!dot || dot[1] < '1' || dot[1] > '9')
|
||||||
|
return 0;
|
||||||
|
*dot = '\0';
|
||||||
|
errno = 0;
|
||||||
|
lscreen = strtoul(dot + 1, &endptr, 10);
|
||||||
|
if (lscreen > INT_MAX || !endptr || *endptr || errno)
|
||||||
|
return 0;
|
||||||
|
if (0 != stat(path, &sbuf))
|
||||||
|
return 0;
|
||||||
|
_screen = (int)lscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _xcb_parse_display(const char *name, char **host, char **protocol,
|
static int _xcb_parse_display(const char *name, char **host, char **protocol,
|
||||||
|
@ -70,11 +168,13 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol,
|
||||||
if(!name)
|
if(!name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef HAVE_LAUNCHD
|
/* First check for <path to socket>[.<screen>] */
|
||||||
if(strncmp(name, "/tmp/launch", 11) == 0)
|
if (name[0] == '/')
|
||||||
slash = NULL;
|
return _xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp);
|
||||||
else
|
|
||||||
#endif
|
if (strncmp(name, "unix:", 5) == 0)
|
||||||
|
return _xcb_parse_display_path_to_socket(name + 5, host, protocol, displayp, screenp);
|
||||||
|
|
||||||
slash = strrchr(name, '/');
|
slash = strrchr(name, '/');
|
||||||
|
|
||||||
if (slash) {
|
if (slash) {
|
||||||
|
@ -139,10 +239,9 @@ int xcb_parse_display(const char *name, char **host, int *displayp,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port);
|
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);
|
static int _xcb_open_unix(char *protocol, const char *file);
|
||||||
#ifdef DNETCONN
|
#endif /* !WIN32 */
|
||||||
static int _xcb_open_decnet(const char *host, char *protocol, const unsigned short port);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_ABSTRACT_SOCKETS
|
#ifdef HAVE_ABSTRACT_SOCKETS
|
||||||
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
|
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
|
||||||
#endif
|
#endif
|
||||||
|
@ -150,43 +249,55 @@ static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
|
||||||
static int _xcb_open(const char *host, char *protocol, const int display)
|
static int _xcb_open(const char *host, char *protocol, const int display)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
#ifdef __hpux
|
||||||
|
static const char unix_base[] = "/usr/spool/sockets/X11/";
|
||||||
|
#else
|
||||||
static const char unix_base[] = "/tmp/.X11-unix/X";
|
static const char unix_base[] = "/tmp/.X11-unix/X";
|
||||||
|
#endif
|
||||||
const char *base = unix_base;
|
const char *base = unix_base;
|
||||||
size_t filelen;
|
size_t filelen;
|
||||||
char *file = NULL;
|
char *file = NULL;
|
||||||
int actual_filelen;
|
int actual_filelen;
|
||||||
|
|
||||||
#ifdef HAVE_LAUNCHD
|
#ifndef _WIN32
|
||||||
if(strncmp(host, "/tmp/launch", 11) == 0) {
|
if (protocol && strcmp("unix", protocol) == 0 && host && host[0] == '/') {
|
||||||
base = host;
|
/* Full path to socket provided, ignore everything else */
|
||||||
host = "";
|
filelen = strlen(host) + 1;
|
||||||
protocol = NULL;
|
if (filelen > INT_MAX)
|
||||||
}
|
return -1;
|
||||||
|
file = malloc(filelen);
|
||||||
|
if (file == NULL)
|
||||||
|
return -1;
|
||||||
|
memcpy(file, host, filelen);
|
||||||
|
actual_filelen = (int)(filelen - 1);
|
||||||
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
/* If protocol or host is "unix", fall through to Unix socket code below */
|
||||||
if(*host || protocol)
|
if ((!protocol || (strcmp("unix",protocol) != 0)) &&
|
||||||
|
(*host != '\0') && (strcmp("unix",host) != 0))
|
||||||
{
|
{
|
||||||
#ifdef DNETCONN
|
|
||||||
/* DECnet displays have two colons, so _xcb_parse_display will have
|
|
||||||
left one at the end. However, an IPv6 address can end with *two*
|
|
||||||
colons, so only treat this as a DECnet display if host ends with
|
|
||||||
exactly one colon. */
|
|
||||||
char *colon = strchr(host, ':');
|
|
||||||
if(colon && *(colon+1) == '\0')
|
|
||||||
{
|
|
||||||
*colon = '\0';
|
|
||||||
return _xcb_open_decnet(host, protocol, display);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (protocol
|
|
||||||
|| strcmp("unix",host)) { /* follow the old unix: rule */
|
|
||||||
|
|
||||||
/* display specifies TCP */
|
/* display specifies TCP */
|
||||||
unsigned short port = X_TCP_PORT + display;
|
unsigned short port = X_TCP_PORT + display;
|
||||||
return _xcb_open_tcp(host, protocol, port);
|
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())
|
||||||
|
{
|
||||||
|
const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
|
||||||
|
char tsol_socket[PATH_MAX];
|
||||||
|
struct stat sbuf;
|
||||||
|
|
||||||
|
snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display);
|
||||||
|
|
||||||
|
if (stat(tsol_socket, &sbuf) == 0)
|
||||||
|
base = tsol_base;
|
||||||
|
else if (errno != ENOENT)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
|
filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
|
||||||
file = malloc(filelen);
|
file = malloc(filelen);
|
||||||
|
@ -194,12 +305,8 @@ static int _xcb_open(const char *host, char *protocol, const int display)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* display specifies Unix socket */
|
/* display specifies Unix socket */
|
||||||
#ifdef HAVE_LAUNCHD
|
|
||||||
if(strncmp(base, "/tmp/launch", 11) == 0)
|
|
||||||
actual_filelen = snprintf(file, filelen, "%s:%d", base, display);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
actual_filelen = snprintf(file, filelen, "%s%d", base, display);
|
actual_filelen = snprintf(file, filelen, "%s%d", base, display);
|
||||||
|
|
||||||
if(actual_filelen < 0)
|
if(actual_filelen < 0)
|
||||||
{
|
{
|
||||||
free(file);
|
free(file);
|
||||||
|
@ -214,12 +321,19 @@ static int _xcb_open(const char *host, char *protocol, const int display)
|
||||||
free(file);
|
free(file);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
fd = _xcb_open_unix(protocol, file);
|
fd = _xcb_open_unix(protocol, file);
|
||||||
free(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;
|
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)
|
static int _xcb_socket(int family, int type, int proto)
|
||||||
|
@ -232,59 +346,36 @@ static int _xcb_socket(int family, int type, int proto)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
fd = socket(family, type, proto);
|
fd = socket(family, type, proto);
|
||||||
|
#ifndef _WIN32
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DNETCONN
|
|
||||||
static int _xcb_open_decnet(const char *host, const char *protocol, const unsigned short port)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_dn addr;
|
|
||||||
struct accessdata_dn accessdata;
|
|
||||||
struct nodeent *nodeaddr = getnodebyname(host);
|
|
||||||
|
|
||||||
if(!nodeaddr)
|
|
||||||
return -1;
|
|
||||||
if (protocol && strcmp("dnet",protocol))
|
|
||||||
return -1;
|
|
||||||
addr.sdn_family = AF_DECnet;
|
|
||||||
|
|
||||||
addr.sdn_add.a_len = nodeaddr->n_length;
|
|
||||||
memcpy(addr.sdn_add.a_addr, nodeaddr->n_addr, addr.sdn_add.a_len);
|
|
||||||
|
|
||||||
addr.sdn_objnamel = sprintf((char *)addr.sdn_objname, "X$X%d", port);
|
|
||||||
if(addr.sdn_objnamel < 0)
|
|
||||||
return -1;
|
|
||||||
addr.sdn_objnum = 0;
|
|
||||||
|
|
||||||
fd = _xcb_socket(PF_DECnet, SOCK_STREAM, 0);
|
|
||||||
if(fd == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memset(&accessdata, 0, sizeof(accessdata));
|
|
||||||
accessdata.acc_accl = sprintf((char*)accessdata.acc_acc, "%d", getuid());
|
|
||||||
if(accessdata.acc_accl < 0)
|
|
||||||
return -1;
|
|
||||||
setsockopt(fd, DNPROTO_NSP, SO_CONACCESS, &accessdata, sizeof(accessdata));
|
|
||||||
|
|
||||||
if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
#endif
|
#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)
|
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
#if HAVE_GETADDRINFO
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
char service[6]; /* "65535" with the trailing '\0' */
|
char service[6]; /* "65535" with the trailing '\0' */
|
||||||
struct addrinfo *results, *addr;
|
struct addrinfo *results, *addr;
|
||||||
char *bracket;
|
char *bracket;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
|
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
|
||||||
#ifdef AF_INET6
|
#ifdef AF_INET6
|
||||||
|
@ -296,10 +387,8 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
|
||||||
if (*host == '\0')
|
if (*host == '\0')
|
||||||
host = "localhost";
|
host = "localhost";
|
||||||
|
|
||||||
|
#if HAVE_GETADDRINFO
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
#ifdef AI_ADDRCONFIG
|
|
||||||
hints.ai_flags |= AI_ADDRCONFIG;
|
|
||||||
#endif
|
|
||||||
#ifdef AI_NUMERICSERV
|
#ifdef AI_NUMERICSERV
|
||||||
hints.ai_flags |= AI_NUMERICSERV;
|
hints.ai_flags |= AI_NUMERICSERV;
|
||||||
#endif
|
#endif
|
||||||
|
@ -325,25 +414,59 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
|
||||||
for(addr = results; addr; addr = addr->ai_next)
|
for(addr = results; addr; addr = addr->ai_next)
|
||||||
{
|
{
|
||||||
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||||
if(fd >= 0) {
|
if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
|
||||||
int on = 1;
|
|
||||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
|
|
||||||
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
|
|
||||||
|
|
||||||
if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
|
|
||||||
break;
|
break;
|
||||||
|
#ifdef _WIN32
|
||||||
|
closesocket(fd);
|
||||||
|
#else
|
||||||
close(fd);
|
close(fd);
|
||||||
|
#endif
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
freeaddrinfo(results);
|
freeaddrinfo(results);
|
||||||
return fd;
|
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)
|
static int _xcb_open_unix(char *protocol, const char *file)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
|
socklen_t len = sizeof(int);
|
||||||
|
int val;
|
||||||
|
|
||||||
if (protocol && strcmp("unix",protocol))
|
if (protocol && strcmp("unix",protocol))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -356,12 +479,18 @@ static int _xcb_open_unix(char *protocol, const char *file)
|
||||||
fd = _xcb_socket(AF_UNIX, SOCK_STREAM, 0);
|
fd = _xcb_socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -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) {
|
if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
#ifdef HAVE_ABSTRACT_SOCKETS
|
#ifdef HAVE_ABSTRACT_SOCKETS
|
||||||
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
|
static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
|
||||||
|
@ -406,22 +535,32 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
|
||||||
int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
|
int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
|
||||||
|
|
||||||
if(!parsed) {
|
if(!parsed) {
|
||||||
c = (xcb_connection_t *) &error_connection;
|
c = _xcb_conn_ret_error(XCB_CONN_CLOSED_PARSE_ERR);
|
||||||
goto out;
|
goto out;
|
||||||
} else
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSADATA wsaData;
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
|
c = _xcb_conn_ret_error(XCB_CONN_ERROR);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fd = _xcb_open(host, protocol, display);
|
fd = _xcb_open(host, protocol, display);
|
||||||
|
|
||||||
if(fd == -1) {
|
if(fd == -1) {
|
||||||
c = (xcb_connection_t *) &error_connection;
|
c = _xcb_conn_ret_error(XCB_CONN_ERROR);
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auth) {
|
if(auth) {
|
||||||
c = xcb_connect_to_fd(fd, auth);
|
c = xcb_connect_to_fd(fd, auth);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
else if(_xcb_get_auth_info(fd, &ourauth, display))
|
||||||
if(_xcb_get_auth_info(fd, &ourauth, display))
|
|
||||||
{
|
{
|
||||||
c = xcb_connect_to_fd(fd, &ourauth);
|
c = xcb_connect_to_fd(fd, &ourauth);
|
||||||
free(ourauth.name);
|
free(ourauth.name);
|
||||||
|
@ -430,6 +569,16 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
|
||||||
else
|
else
|
||||||
c = xcb_connect_to_fd(fd, 0);
|
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:
|
out:
|
||||||
free(host);
|
free(host);
|
||||||
free(protocol);
|
free(protocol);
|
||||||
|
|
|
@ -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 */
|
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
/* XID allocators. */
|
/* XID allocators. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
@ -51,7 +55,7 @@ uint32_t xcb_generate_id(xcb_connection_t *c)
|
||||||
/* check for extension */
|
/* check for extension */
|
||||||
const xcb_query_extension_reply_t *xc_misc_reply =
|
const xcb_query_extension_reply_t *xc_misc_reply =
|
||||||
xcb_get_extension_data(c, &xcb_xc_misc_id);
|
xcb_get_extension_data(c, &xcb_xc_misc_id);
|
||||||
if (!xc_misc_reply) {
|
if (!xc_misc_reply || !xc_misc_reply->present) {
|
||||||
pthread_mutex_unlock(&c->xid.lock);
|
pthread_mutex_unlock(&c->xid.lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
245
src/xcbext.h
245
src/xcbext.h
|
@ -54,39 +54,270 @@ typedef struct {
|
||||||
enum xcb_send_request_flags_t {
|
enum xcb_send_request_flags_t {
|
||||||
XCB_REQUEST_CHECKED = 1 << 0,
|
XCB_REQUEST_CHECKED = 1 << 0,
|
||||||
XCB_REQUEST_RAW = 1 << 1,
|
XCB_REQUEST_RAW = 1 << 1,
|
||||||
XCB_REQUEST_DISCARD_REPLY = 1 << 2
|
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);
|
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
|
||||||
|
|
||||||
/* xcb_take_socket allows external code to ask XCB for permission to
|
/**
|
||||||
|
* @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
|
* 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
|
* xcb_writev. xcb_take_socket provides the sequence number of the last
|
||||||
* request XCB sent. The caller of xcb_take_socket must supply a
|
* 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
|
* callback which XCB can call when it wants the write side of the
|
||||||
* socket back to make a request. This callback synchronizes with the
|
* socket back to make a request. This callback synchronizes with the
|
||||||
* external socket owner, flushes any output queues if appropriate, and
|
* external socket owner and flushes any output queues if appropriate.
|
||||||
* then returns the sequence number of the last request sent over the
|
* If you are sending requests which won't cause a reply, please note the
|
||||||
* socket. */
|
* 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);
|
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent);
|
||||||
|
|
||||||
/* You must own the write-side of the socket (you've called
|
/**
|
||||||
|
* @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_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.
|
* 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);
|
int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests);
|
||||||
|
|
||||||
|
|
||||||
/* xcb_in.c */
|
/* 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);
|
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);
|
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.
|
||||||
|
*/
|
||||||
|
XCB_CONST_FUNCTION
|
||||||
|
int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen);
|
||||||
|
|
||||||
|
|
||||||
/* xcb_util.c */
|
/* xcb_util.c */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mask The mask to check
|
||||||
|
* @return The number of set bits in the mask
|
||||||
|
*/
|
||||||
|
XCB_CONST_FUNCTION
|
||||||
int xcb_popcount(uint32_t 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.
|
||||||
|
*/
|
||||||
|
XCB_PURE_FUNCTION
|
||||||
|
int xcb_sumof(uint8_t *list, int len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
44
src/xcbint.h
44
src/xcbint.h
|
@ -38,6 +38,16 @@
|
||||||
#pragma GCC visibility push(hidden)
|
#pragma GCC visibility push(hidden)
|
||||||
#endif
|
#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 {
|
enum workarounds {
|
||||||
WORKAROUND_NONE,
|
WORKAROUND_NONE,
|
||||||
WORKAROUND_GLX_GET_FB_CONFIGS_BUG,
|
WORKAROUND_GLX_GET_FB_CONFIGS_BUG,
|
||||||
|
@ -54,7 +64,6 @@ enum lazy_reply_tag
|
||||||
#define XCB_PAD(i) (-(i) & 3)
|
#define XCB_PAD(i) (-(i) & 3)
|
||||||
|
|
||||||
#define XCB_SEQUENCE_COMPARE(a,op,b) ((int64_t) ((a) - (b)) op 0)
|
#define XCB_SEQUENCE_COMPARE(a,op,b) ((int64_t) ((a) - (b)) op 0)
|
||||||
#define XCB_SEQUENCE_COMPARE_32(a,op,b) (((int) (a) - (int) (b)) op 0)
|
|
||||||
|
|
||||||
#ifndef offsetof
|
#ifndef offsetof
|
||||||
#define offsetof(type,member) ((size_t) &((type *)0)->member)
|
#define offsetof(type,member) ((size_t) &((type *)0)->member)
|
||||||
|
@ -74,12 +83,22 @@ typedef struct _xcb_map _xcb_map;
|
||||||
|
|
||||||
_xcb_map *_xcb_map_new(void);
|
_xcb_map *_xcb_map_new(void);
|
||||||
void _xcb_map_delete(_xcb_map *q, xcb_list_free_func_t do_free);
|
void _xcb_map_delete(_xcb_map *q, xcb_list_free_func_t do_free);
|
||||||
int _xcb_map_put(_xcb_map *q, unsigned int key, void *data);
|
int _xcb_map_put(_xcb_map *q, uint64_t key, void *data);
|
||||||
void *_xcb_map_remove(_xcb_map *q, unsigned int key);
|
void *_xcb_map_remove(_xcb_map *q, uint64_t key);
|
||||||
|
|
||||||
|
|
||||||
/* xcb_out.c */
|
/* 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 {
|
typedef struct _xcb_out {
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
int writing;
|
int writing;
|
||||||
|
@ -94,6 +113,8 @@ typedef struct _xcb_out {
|
||||||
|
|
||||||
uint64_t request;
|
uint64_t request;
|
||||||
uint64_t request_written;
|
uint64_t request_written;
|
||||||
|
uint64_t request_expected_written;
|
||||||
|
uint64_t total_written;
|
||||||
|
|
||||||
pthread_mutex_t reqlenlock;
|
pthread_mutex_t reqlenlock;
|
||||||
enum lazy_reply_tag maximum_request_length_tag;
|
enum lazy_reply_tag maximum_request_length_tag;
|
||||||
|
@ -101,12 +122,16 @@ typedef struct _xcb_out {
|
||||||
xcb_big_requests_enable_cookie_t cookie;
|
xcb_big_requests_enable_cookie_t cookie;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
} maximum_request_length;
|
} maximum_request_length;
|
||||||
|
#if HAVE_SENDMSG
|
||||||
|
_xcb_fd out_fd;
|
||||||
|
#endif
|
||||||
} _xcb_out;
|
} _xcb_out;
|
||||||
|
|
||||||
int _xcb_out_init(_xcb_out *out);
|
int _xcb_out_init(_xcb_out *out);
|
||||||
void _xcb_out_destroy(_xcb_out *out);
|
void _xcb_out_destroy(_xcb_out *out);
|
||||||
|
|
||||||
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count);
|
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);
|
int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request);
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,6 +147,7 @@ typedef struct _xcb_in {
|
||||||
uint64_t request_expected;
|
uint64_t request_expected;
|
||||||
uint64_t request_read;
|
uint64_t request_read;
|
||||||
uint64_t request_completed;
|
uint64_t request_completed;
|
||||||
|
uint64_t total_read;
|
||||||
struct reply_list *current_reply;
|
struct reply_list *current_reply;
|
||||||
struct reply_list **current_reply_tail;
|
struct reply_list **current_reply_tail;
|
||||||
|
|
||||||
|
@ -129,9 +155,14 @@ typedef struct _xcb_in {
|
||||||
struct event_list *events;
|
struct event_list *events;
|
||||||
struct event_list **events_tail;
|
struct event_list **events_tail;
|
||||||
struct reader_list *readers;
|
struct reader_list *readers;
|
||||||
|
struct special_list *special_waiters;
|
||||||
|
|
||||||
struct pending_reply *pending_replies;
|
struct pending_reply *pending_replies;
|
||||||
struct pending_reply **pending_replies_tail;
|
struct pending_reply **pending_replies_tail;
|
||||||
|
#if HAVE_SENDMSG
|
||||||
|
_xcb_fd in_fd;
|
||||||
|
#endif
|
||||||
|
struct xcb_special_event *special_events;
|
||||||
} _xcb_in;
|
} _xcb_in;
|
||||||
|
|
||||||
int _xcb_in_init(_xcb_in *in);
|
int _xcb_in_init(_xcb_in *in);
|
||||||
|
@ -175,6 +206,7 @@ void _xcb_ext_destroy(xcb_connection_t *c);
|
||||||
/* xcb_conn.c */
|
/* xcb_conn.c */
|
||||||
|
|
||||||
struct xcb_connection_t {
|
struct xcb_connection_t {
|
||||||
|
/* This must be the first field; see _xcb_conn_ret_error(). */
|
||||||
int has_error;
|
int has_error;
|
||||||
|
|
||||||
/* constant data */
|
/* constant data */
|
||||||
|
@ -191,7 +223,11 @@ struct xcb_connection_t {
|
||||||
_xcb_xid xid;
|
_xcb_xid xid;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _xcb_conn_shutdown(xcb_connection_t *c);
|
void _xcb_conn_shutdown(xcb_connection_t *c, int err);
|
||||||
|
|
||||||
|
XCB_CONST_FUNCTION
|
||||||
|
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);
|
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
CheckLog.html
|
CheckLog.html
|
||||||
CheckLog_xcb.xml
|
CheckLog_xcb.xml
|
||||||
check_all
|
check_all
|
||||||
|
check_all.log
|
||||||
|
check_all.trs
|
||||||
|
test-suite.log
|
||||||
|
|
|
@ -12,12 +12,9 @@ TESTS = check_all
|
||||||
check_PROGRAMS = check_all
|
check_PROGRAMS = check_all
|
||||||
check_all_SOURCES = check_all.c check_suites.h check_public.c
|
check_all_SOURCES = check_all.c check_suites.h check_public.c
|
||||||
|
|
||||||
all-local::
|
|
||||||
$(RM) CheckLog*.xml
|
|
||||||
|
|
||||||
check-local: check-TESTS
|
check-local: check-TESTS
|
||||||
$(RM) CheckLog.html
|
$(RM) CheckLog.html
|
||||||
if test x$(HTML_CHECK_RESULT) = xtrue; then \
|
if test x$(HTML_CHECK_RESULT) = xyes; then \
|
||||||
$(XSLTPROC) $(srcdir)/CheckLog.xsl CheckLog*.xml > CheckLog.html; \
|
$(XSLTPROC) $(srcdir)/CheckLog.xsl CheckLog*.xml > CheckLog.html; \
|
||||||
else \
|
else \
|
||||||
touch CheckLog.html; \
|
touch CheckLog.html; \
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "check_suites.h"
|
#include "check_suites.h"
|
||||||
|
|
||||||
|
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13
|
||||||
void suite_add_test(Suite *s, TFun tf, const char *name)
|
void suite_add_test(Suite *s, TFun tf, const char *name)
|
||||||
|
#else
|
||||||
|
void suite_add_test(Suite *s, const TTest *tt, const char *name)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
TCase *tc = tcase_create(name);
|
TCase *tc = tcase_create(name);
|
||||||
|
|
||||||
|
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13
|
||||||
tcase_add_test(tc, tf);
|
tcase_add_test(tc, tf);
|
||||||
|
#else
|
||||||
|
tcase_add_test(tc, tt);
|
||||||
|
#endif
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef __unix__
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include "check_suites.h"
|
#include "check_suites.h"
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "xcbext.h"
|
#include "xcbext.h"
|
||||||
|
@ -12,6 +16,10 @@ typedef enum test_type_t {
|
||||||
} test_type_t;
|
} test_type_t;
|
||||||
static const char *const test_string[] = { "", "via $DISPLAY " };
|
static const char *const test_string[] = { "", "via $DISPLAY " };
|
||||||
|
|
||||||
|
/* putenv(3) takes a pointer to a writable string that it adds directly
|
||||||
|
to the environment, so it must be in persistent memory, not on the stack */
|
||||||
|
static char display_env[] = "DISPLAY=";
|
||||||
|
|
||||||
static void parse_display_pass(const char *name, const char *host, const int display, const int screen)
|
static void parse_display_pass(const char *name, const char *host, const int display, const int screen)
|
||||||
{
|
{
|
||||||
int success;
|
int success;
|
||||||
|
@ -25,7 +33,7 @@ static void parse_display_pass(const char *name, const char *host, const int dis
|
||||||
if(test_type == TEST_ARGUMENT)
|
if(test_type == TEST_ARGUMENT)
|
||||||
{
|
{
|
||||||
argument = name;
|
argument = name;
|
||||||
putenv("DISPLAY=");
|
putenv(display_env);
|
||||||
}
|
}
|
||||||
else if(test_type == TEST_ENVIRONMENT)
|
else if(test_type == TEST_ENVIRONMENT)
|
||||||
{
|
{
|
||||||
|
@ -37,20 +45,20 @@ static void parse_display_pass(const char *name, const char *host, const int dis
|
||||||
got_display = got_screen = -42;
|
got_display = got_screen = -42;
|
||||||
mark_point();
|
mark_point();
|
||||||
success = xcb_parse_display(argument, &got_host, &got_display, &got_screen);
|
success = xcb_parse_display(argument, &got_host, &got_display, &got_screen);
|
||||||
fail_unless(success, "unexpected parse failure %sfor '%s'", test_string[test_type], name);
|
ck_assert_msg(success, "unexpected parse failure %sfor '%s'", test_string[test_type], name);
|
||||||
fail_unless(strcmp(host, got_host) == 0, "parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host);
|
ck_assert_msg(strcmp(host, got_host) == 0, "parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host);
|
||||||
fail_unless(display == got_display, "parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display);
|
ck_assert_msg(display == got_display, "parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display);
|
||||||
fail_unless(screen == got_screen, "parse %sproduced unexpected screen '%d' for '%s': expected '%d'", test_string[test_type], got_screen, name, screen);
|
ck_assert_msg(screen == got_screen, "parse %sproduced unexpected screen '%d' for '%s': expected '%d'", test_string[test_type], got_screen, name, screen);
|
||||||
|
|
||||||
got_host = (char *) -1;
|
got_host = (char *) -1;
|
||||||
got_display = got_screen = -42;
|
got_display = got_screen = -42;
|
||||||
mark_point();
|
mark_point();
|
||||||
success = xcb_parse_display(argument, &got_host, &got_display, 0);
|
success = xcb_parse_display(argument, &got_host, &got_display, 0);
|
||||||
fail_unless(success, "unexpected screenless parse failure %sfor '%s'", test_string[test_type], name);
|
ck_assert_msg(success, "unexpected screenless parse failure %sfor '%s'", test_string[test_type], name);
|
||||||
fail_unless(strcmp(host, got_host) == 0, "screenless parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host);
|
ck_assert_msg(strcmp(host, got_host) == 0, "screenless parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host);
|
||||||
fail_unless(display == got_display, "screenless parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display);
|
ck_assert_msg(display == got_display, "screenless parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display);
|
||||||
}
|
}
|
||||||
putenv("DISPLAY=");
|
putenv(display_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_display_fail(const char *name)
|
static void parse_display_fail(const char *name)
|
||||||
|
@ -66,7 +74,7 @@ static void parse_display_fail(const char *name)
|
||||||
if(test_type == TEST_ARGUMENT)
|
if(test_type == TEST_ARGUMENT)
|
||||||
{
|
{
|
||||||
argument = name;
|
argument = name;
|
||||||
putenv("DISPLAY=");
|
putenv(display_env);
|
||||||
}
|
}
|
||||||
else if(test_type == TEST_ENVIRONMENT)
|
else if(test_type == TEST_ENVIRONMENT)
|
||||||
{
|
{
|
||||||
|
@ -79,24 +87,55 @@ static void parse_display_fail(const char *name)
|
||||||
got_display = got_screen = -42;
|
got_display = got_screen = -42;
|
||||||
mark_point();
|
mark_point();
|
||||||
success = xcb_parse_display(argument, &got_host, &got_display, &got_screen);
|
success = xcb_parse_display(argument, &got_host, &got_display, &got_screen);
|
||||||
fail_unless(!success, "unexpected parse success %sfor '%s'", test_string[test_type], name);
|
ck_assert_msg(!success, "unexpected parse success %sfor '%s'", test_string[test_type], name);
|
||||||
fail_unless(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host);
|
ck_assert_msg(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host);
|
||||||
fail_unless(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display);
|
ck_assert_msg(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display);
|
||||||
fail_unless(got_screen == -42, "screen changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_screen);
|
ck_assert_msg(got_screen == -42, "screen changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_screen);
|
||||||
|
|
||||||
got_host = (char *) -1;
|
got_host = (char *) -1;
|
||||||
got_display = got_screen = -42;
|
got_display = got_screen = -42;
|
||||||
mark_point();
|
mark_point();
|
||||||
success = xcb_parse_display(argument, &got_host, &got_display, 0);
|
success = xcb_parse_display(argument, &got_host, &got_display, 0);
|
||||||
fail_unless(!success, "unexpected screenless parse success %sfor '%s'", test_string[test_type], name);
|
ck_assert_msg(!success, "unexpected screenless parse success %sfor '%s'", test_string[test_type], name);
|
||||||
fail_unless(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host);
|
ck_assert_msg(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host);
|
||||||
fail_unless(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display);
|
ck_assert_msg(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display);
|
||||||
}
|
}
|
||||||
putenv("DISPLAY=");
|
putenv(display_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(parse_display_unix)
|
START_TEST(parse_display_unix)
|
||||||
{
|
{
|
||||||
|
#ifdef __unix__
|
||||||
|
char buf[sizeof "/tmp/xcb-test.XXXXXXX"];
|
||||||
|
char buf2[sizeof(buf) + 7];
|
||||||
|
int r, v;
|
||||||
|
memcpy(buf, "/tmp/xcb-test.XXXXXXX", sizeof buf);
|
||||||
|
v = mkstemp(buf);
|
||||||
|
ck_assert_msg(v >= 0, "cannot create temporary file");
|
||||||
|
parse_display_pass(buf, buf, 0, 0);
|
||||||
|
r = snprintf(buf2, sizeof buf2, "unix:%s", buf);
|
||||||
|
if (r < 5 || r >= (int)sizeof buf2) {
|
||||||
|
ck_assert_msg(0, "snprintf() failed (return value %d)", r);
|
||||||
|
unlink(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parse_display_pass(buf2, buf, 0, 0);
|
||||||
|
r = snprintf(buf2, sizeof buf2, "unix:%s.1", buf);
|
||||||
|
if (r < 7 || r >= (int)sizeof buf2) {
|
||||||
|
ck_assert_msg(0, "snprintf() failed (return value %d)", r);
|
||||||
|
unlink(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parse_display_pass(buf2, buf, 0, 1);
|
||||||
|
r = snprintf(buf2, sizeof buf2, "%s.1", buf);
|
||||||
|
if (r < 2 || r >= (int)sizeof buf2) {
|
||||||
|
ck_assert_msg(0, "snprintf() failed (return value %d)", r);
|
||||||
|
unlink(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parse_display_pass(buf2, buf, 0, 1);
|
||||||
|
unlink(buf);
|
||||||
|
#endif
|
||||||
parse_display_pass(":0", "", 0, 0);
|
parse_display_pass(":0", "", 0, 0);
|
||||||
parse_display_pass(":1", "", 1, 0);
|
parse_display_pass(":1", "", 1, 0);
|
||||||
parse_display_pass(":0.1", "", 0, 1);
|
parse_display_pass(":0.1", "", 0, 1);
|
||||||
|
@ -183,7 +222,7 @@ END_TEST
|
||||||
|
|
||||||
static void popcount_eq(uint32_t bits, int count)
|
static void popcount_eq(uint32_t bits, int count)
|
||||||
{
|
{
|
||||||
fail_unless(xcb_popcount(bits) == count, "unexpected popcount(%08x) != %d", bits, count);
|
ck_assert_msg(xcb_popcount(bits) == count, "unexpected popcount(%08x) != %d", bits, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(popcount)
|
START_TEST(popcount)
|
||||||
|
@ -206,7 +245,7 @@ END_TEST
|
||||||
Suite *public_suite(void)
|
Suite *public_suite(void)
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("Public API");
|
Suite *s = suite_create("Public API");
|
||||||
putenv("DISPLAY=");
|
putenv(display_env);
|
||||||
suite_add_test(s, parse_display_unix, "xcb_parse_display unix");
|
suite_add_test(s, parse_display_unix, "xcb_parse_display unix");
|
||||||
suite_add_test(s, parse_display_ip, "xcb_parse_display ip");
|
suite_add_test(s, parse_display_ip, "xcb_parse_display ip");
|
||||||
suite_add_test(s, parse_display_ipv4, "xcb_parse_display ipv4");
|
suite_add_test(s, parse_display_ipv4, "xcb_parse_display ipv4");
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
|
|
||||||
|
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13
|
||||||
void suite_add_test(Suite *s, TFun tf, const char *name);
|
void suite_add_test(Suite *s, TFun tf, const char *name);
|
||||||
|
#else
|
||||||
|
void suite_add_test(Suite *s, const TTest *tt, const char *name);
|
||||||
|
#endif
|
||||||
Suite *public_suite(void);
|
Suite *public_suite(void);
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Composite
|
Name: XCB Composite
|
||||||
Description: XCB Composite Extension
|
Description: XCB Composite Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb xcb-xfixes
|
Requires.private: xcb xcb-xfixes
|
||||||
Libs: -L${libdir} -lxcb-composite
|
Libs: -L${libdir} -lxcb-composite
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Damage
|
Name: XCB Damage
|
||||||
Description: XCB Damage Extension
|
Description: XCB Damage Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb xcb-xfixes
|
Requires.private: xcb xcb-xfixes
|
||||||
Libs: -L${libdir} -lxcb-damage
|
Libs: -L${libdir} -lxcb-damage
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: XCB Dbe
|
||||||
|
Description: XCB Double Buffer Extension
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires.private: xcb
|
||||||
|
Libs: -L${libdir} -lxcb-dbe
|
||||||
|
Cflags: -I${includedir}
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB DPMS
|
Name: XCB DPMS
|
||||||
Description: XCB DPMS Extension
|
Description: XCB DPMS Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-dpms
|
Libs: -L${libdir} -lxcb-dpms
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB DRI2
|
Name: XCB DRI2
|
||||||
Description: XCB DRI2 Extension
|
Description: XCB DRI2 Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-dri2
|
Libs: -L${libdir} -lxcb-dri2
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: XCB DRI3
|
||||||
|
Description: XCB DRI3 Extension
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires.private: xcb
|
||||||
|
Libs: -L${libdir} -lxcb-dri3
|
||||||
|
Cflags: -I${includedir}
|
|
@ -0,0 +1,11 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: XCB GenericEvent
|
||||||
|
Description: XCB GenericEvent Extension
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires.private: xcb
|
||||||
|
Libs: -L${libdir} -lxcb-ge
|
||||||
|
Cflags: -I${includedir}
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB GLX
|
Name: XCB GLX
|
||||||
Description: XCB GLX Extension
|
Description: XCB GLX Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-glx
|
Libs: -L${libdir} -lxcb-glx
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: XCB Present
|
||||||
|
Description: XCB Present Extension
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires.private: xcb xcb-randr xcb-xfixes xcb-sync xcb-dri3
|
||||||
|
Libs: -L${libdir} -lxcb-present
|
||||||
|
Cflags: -I${includedir}
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB RandR
|
Name: XCB RandR
|
||||||
Description: XCB RandR Extension
|
Description: XCB RandR Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb xcb-render
|
||||||
Libs: -L${libdir} -lxcb-randr
|
Libs: -L${libdir} -lxcb-randr
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Record
|
Name: XCB Record
|
||||||
Description: XCB Record Extension
|
Description: XCB Record Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-record
|
Libs: -L${libdir} -lxcb-record
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Render
|
Name: XCB Render
|
||||||
Description: XCB Render Extension
|
Description: XCB Render Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-render
|
Libs: -L${libdir} -lxcb-render
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Res
|
Name: XCB Res
|
||||||
Description: XCB X-Resource Extension
|
Description: XCB X-Resource Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-res
|
Libs: -L${libdir} -lxcb-res
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Screensaver
|
Name: XCB Screensaver
|
||||||
Description: XCB Screensaver Extension
|
Description: XCB Screensaver Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-screensaver
|
Libs: -L${libdir} -lxcb-screensaver
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Shape
|
Name: XCB Shape
|
||||||
Description: XCB Shape Extension
|
Description: XCB Shape Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-shape
|
Libs: -L${libdir} -lxcb-shape
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Shm
|
Name: XCB Shm
|
||||||
Description: XCB Shm Extension
|
Description: XCB Shm Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-shm
|
Libs: -L${libdir} -lxcb-shm
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Sync
|
Name: XCB Sync
|
||||||
Description: XCB Sync Extension
|
Description: XCB Sync Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-sync
|
Libs: -L${libdir} -lxcb-sync
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Xevie
|
Name: XCB Xevie
|
||||||
Description: XCB Xevie Extension
|
Description: XCB Xevie Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-xevie
|
Libs: -L${libdir} -lxcb-xevie
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB XFree86-DRI
|
Name: XCB XFree86-DRI
|
||||||
Description: XCB XFree86-DRI Extension
|
Description: XCB XFree86-DRI Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-xf86dri
|
Libs: -L${libdir} -lxcb-xf86dri
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB XFixes
|
Name: XCB XFixes
|
||||||
Description: XCB XFixes Extension
|
Description: XCB XFixes Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb xcb-render xcb-shape
|
Requires.private: xcb xcb-render xcb-shape
|
||||||
Libs: -L${libdir} -lxcb-xfixes
|
Libs: -L${libdir} -lxcb-xfixes
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Xinerama
|
Name: XCB Xinerama
|
||||||
Description: XCB Xinerama Extension
|
Description: XCB Xinerama Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-xinerama
|
Libs: -L${libdir} -lxcb-xinerama
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB XInput
|
Name: XCB XInput
|
||||||
Description: XCB XInput Extension (EXPERIMENTAL)
|
Description: XCB XInput Extension (EXPERIMENTAL)
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb xcb-xfixes
|
||||||
Libs: -L${libdir} -lxcb-xinput
|
Libs: -L${libdir} -lxcb-xinput
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: XCB XKB
|
||||||
|
Description: XCB Keyboard Extension (EXPERIMENTAL)
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires.private: xcb
|
||||||
|
Libs: -L${libdir} -lxcb-xkb
|
||||||
|
Cflags: -I${includedir}
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Xprint
|
Name: XCB Xprint
|
||||||
Description: XCB Xprint Extension
|
Description: XCB Xprint Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-xprint
|
Libs: -L${libdir} -lxcb-xprint
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB SELinux
|
Name: XCB SELinux
|
||||||
Description: XCB SELinux Extension
|
Description: XCB SELinux Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-xselinux
|
Libs: -L${libdir} -lxcb-xselinux
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB XTEST
|
Name: XCB XTEST
|
||||||
Description: XCB XTEST Extension
|
Description: XCB XTEST Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb
|
Requires.private: xcb
|
||||||
Libs: -L${libdir} -lxcb-xtest
|
Libs: -L${libdir} -lxcb-xtest
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB Xv
|
Name: XCB Xv
|
||||||
Description: XCB Xv Extension
|
Description: XCB Xv Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb xcb-shm
|
Requires.private: xcb xcb-shm
|
||||||
Libs: -L${libdir} -lxcb-xv
|
Libs: -L${libdir} -lxcb-xv
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
|
@ -6,6 +6,6 @@ includedir=@includedir@
|
||||||
Name: XCB XvMC
|
Name: XCB XvMC
|
||||||
Description: XCB XvMC Extension
|
Description: XCB XvMC Extension
|
||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Requires: xcb xcb-xv
|
Requires.private: xcb xcb-xv
|
||||||
Libs: -L${libdir} -lxcb-xvmc
|
Libs: -L${libdir} -lxcb-xvmc
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
Loading…
Reference in New Issue