Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

1
vendor/x11rb/.cargo-checksum.json vendored Normal file

File diff suppressed because one or more lines are too long

428
vendor/x11rb/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,428 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "as-raw-xcb-connection"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
[[package]]
name = "bitflags"
version = "2.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "errno"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "gethostname"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55"
dependencies = [
"rustix",
"windows-targets 0.52.6",
]
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "libloading"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.53.3",
]
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "polling"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix",
"windows-sys",
]
[[package]]
name = "raw-window-handle"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
[[package]]
name = "rustix"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.3",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "x11rb"
version = "0.13.2"
dependencies = [
"as-raw-xcb-connection",
"gethostname",
"libc",
"libloading",
"once_cell",
"polling",
"raw-window-handle",
"rustix",
"tracing",
"tracing-subscriber",
"x11rb-protocol",
"xcursor",
]
[[package]]
name = "x11rb-protocol"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
[[package]]
name = "xcursor"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b"

281
vendor/x11rb/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,281 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.64"
name = "x11rb"
version = "0.13.2"
authors = [
"Uli Schlachter <psychon@znc.in>",
"Eduardo Sánchez Muñoz <eduardosm-dev@e64.io>",
"notgull <jtnunley01@gmail.com>",
]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Rust bindings to X11"
readme = "README.md"
keywords = [
"xcb",
"X11",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/psychon/x11rb"
resolver = "1"
[package.metadata.docs.rs]
all-features = true
[features]
all-extensions = [
"x11rb-protocol/all-extensions",
"composite",
"damage",
"dbe",
"dpms",
"dri2",
"dri3",
"glx",
"present",
"randr",
"record",
"render",
"res",
"screensaver",
"shape",
"shm",
"sync",
"xevie",
"xf86dri",
"xf86vidmode",
"xfixes",
"xinerama",
"xinput",
"xkb",
"xprint",
"xselinux",
"xtest",
"xv",
"xvmc",
]
allow-unsafe-code = [
"libc",
"as-raw-xcb-connection",
]
composite = [
"x11rb-protocol/composite",
"xfixes",
]
cursor = [
"render",
"resource_manager",
"xcursor",
]
damage = [
"x11rb-protocol/damage",
"xfixes",
]
dbe = ["x11rb-protocol/dbe"]
dl-libxcb = [
"allow-unsafe-code",
"libloading",
"once_cell",
]
dpms = ["x11rb-protocol/dpms"]
dri2 = ["x11rb-protocol/dri2"]
dri3 = ["x11rb-protocol/dri3"]
extra-traits = ["x11rb-protocol/extra-traits"]
glx = ["x11rb-protocol/glx"]
image = []
present = [
"x11rb-protocol/present",
"randr",
"xfixes",
"sync",
]
randr = [
"x11rb-protocol/randr",
"render",
]
record = ["x11rb-protocol/record"]
render = ["x11rb-protocol/render"]
request-parsing = ["x11rb-protocol/request-parsing"]
res = ["x11rb-protocol/res"]
resource_manager = ["x11rb-protocol/resource_manager"]
screensaver = ["x11rb-protocol/screensaver"]
shape = ["x11rb-protocol/shape"]
shm = ["x11rb-protocol/shm"]
sync = ["x11rb-protocol/sync"]
xevie = ["x11rb-protocol/xevie"]
xf86dri = ["x11rb-protocol/xf86dri"]
xf86vidmode = ["x11rb-protocol/xf86vidmode"]
xfixes = [
"x11rb-protocol/xfixes",
"render",
"shape",
]
xinerama = ["x11rb-protocol/xinerama"]
xinput = [
"x11rb-protocol/xinput",
"xfixes",
]
xkb = ["x11rb-protocol/xkb"]
xprint = ["x11rb-protocol/xprint"]
xselinux = ["x11rb-protocol/xselinux"]
xtest = ["x11rb-protocol/xtest"]
xv = [
"x11rb-protocol/xv",
"shm",
]
xvmc = [
"x11rb-protocol/xvmc",
"xv",
]
[lib]
name = "x11rb"
path = "src/lib.rs"
[[example]]
name = "check_unchecked_requests"
path = "examples/check_unchecked_requests.rs"
[[example]]
name = "display_ppm"
path = "examples/display_ppm.rs"
required-features = ["image"]
[[example]]
name = "generic_events"
path = "examples/generic_events.rs"
required-features = ["present"]
[[example]]
name = "hypnomoire"
path = "examples/hypnomoire.rs"
[[example]]
name = "list_fonts"
path = "examples/list_fonts.rs"
[[example]]
name = "record"
path = "examples/record.rs"
required-features = ["record"]
[[example]]
name = "shared_memory"
path = "examples/shared_memory.rs"
required-features = [
"libc",
"shm",
]
[[example]]
name = "simple_window"
path = "examples/simple_window.rs"
required-features = [
"cursor",
"resource_manager",
"tracing",
"tracing-subscriber/env-filter",
]
[[example]]
name = "simple_window_manager"
path = "examples/simple_window_manager.rs"
[[example]]
name = "tutorial"
path = "examples/tutorial.rs"
[[example]]
name = "xclock_utc"
path = "examples/xclock_utc.rs"
[[example]]
name = "xeyes"
path = "examples/xeyes.rs"
required-features = ["shape"]
[[test]]
name = "multithread_test"
path = "tests/multithread_test.rs"
[[test]]
name = "regression_tests"
path = "tests/regression_tests.rs"
[[test]]
name = "resource_manager"
path = "tests/resource_manager.rs"
[[test]]
name = "x11_utils"
path = "tests/x11_utils.rs"
[dependencies.as-raw-xcb-connection]
version = "1.0"
optional = true
[dependencies.gethostname]
version = "1.0"
[dependencies.libc]
version = "0.2"
optional = true
[dependencies.libloading]
version = "0.8.0"
optional = true
[dependencies.once_cell]
version = "1.19"
optional = true
[dependencies.raw-window-handle]
version = "0.5.0"
optional = true
[dependencies.rustix]
version = "1.0"
features = [
"std",
"event",
"fs",
"net",
"system",
]
default-features = false
[dependencies.tracing]
version = "0.1"
optional = true
default-features = false
[dependencies.x11rb-protocol]
version = "0.13.2"
features = ["std"]
default-features = false
[dependencies.xcursor]
version = "0.3.7"
optional = true
[dev-dependencies.polling]
version = "3.4"
[dev-dependencies.tracing-subscriber]
version = "0.3"

202
vendor/x11rb/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
vendor/x11rb/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright 2019 x11rb Contributers
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 OR COPYRIGHT HOLDERS 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.

69
vendor/x11rb/README.md vendored Normal file
View File

@@ -0,0 +1,69 @@
# X11 rust bindings
[![GitHub Actions Status](https://github.com/psychon/x11rb/workflows/CI/badge.svg)](https://github.com/psychon/x11rb/actions)
[![Crate](https://img.shields.io/crates/v/x11rb.svg)](https://crates.io/crates/x11rb)
[![API](https://docs.rs/x11rb/badge.svg)](https://docs.rs/x11rb)
![Minimum rustc version](https://img.shields.io/badge/rustc-1.64+-lightgray.svg)
[![License](https://img.shields.io/crates/l/x11rb.svg)](https://github.com/psychon/x11rb#license)
Feel free to open issues for any problems or questions you might have.
A comparison with some other Rust X11 libraries is available in an [extra
document](doc/comparison.md).
## Building
This crate uses a code generator that is implemented in Rust. A copy of the
generated code is included, so you do not need to run the generator unless
you have modified the definitions or the generator itself.
The code generator uses the X11 XML description from `xcb-proto`. A copy of
xcb-proto that comes with the source code is used.
The interaction with libxcb via `XCBConnection` requires at least libxcb 1.12.
## Crate features
Most X11 extensions are feature-gated. For example, to use the shared memory
extension, the `shm` feature has to be enabled.
The `all-extensions` feature just enables all X11 extensions.
Additionally, the `allow-unsafe-code` feature enables `XCBConnection`. This uses
`libxcb` internally and allows sharing the underlying `xcb_connection_t` pointer
with other code.
The `cursor` feature enables X11 cursor support via the `cursor` module. This
module helps with loading cursors from the current cursor theme.
## Current state
The full X11 protocol is supported by this library. All extensions that are
available in `xcb-proto` can be used and even [FD
passing](x11rb/examples/shared_memory.rs) with the server is supported.
The changelog is available in a [separate file](doc/changelog.md).
## License
Licensed under either of
* Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
The subdirectory xcb-proto-1.17.0 contains a vendored copy of the
package of the same name. It is covered by the MIT license. See
[xcb-proto-1.17.0/COPYING](xcb-proto-1.17.0/COPYING) for details.
## Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

View File

@@ -0,0 +1,85 @@
// This program shows error handling. It causes some X11 errors and shows where they end up.
//
// This program also serves as a (bad) integration test. To verify that the expected behaviour
// occurs, it needs to do some extra work. In particular, all calls to .sequence_number() are not
// needed for the example, but only for the test. Where needed, extra comments indicate how the
// short version of each case would look.
extern crate x11rb;
use x11rb::connection::Connection;
use x11rb::errors::ReplyError;
use x11rb::protocol::xproto::ConnectionExt as _;
use x11rb::protocol::Event;
use x11rb::wrapper::ConnectionExt as _;
const INVALID_WINDOW: u32 = 0;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, _) = connect(None).unwrap();
// For requests with responses, there are four possibilities:
// We can just normally get the response or error to the request via reply()
let res = conn.get_geometry(INVALID_WINDOW)?.reply();
assert!(res.is_err());
// We can decide that we do not care about the response and also do not care about errors via
// discard_reply_and_errors()
conn.get_geometry(INVALID_WINDOW)?
.discard_reply_and_errors();
// Errors can show up as 'events' in wait_for_event() via reply_unchecked()
let cookie = conn.get_geometry(INVALID_WINDOW)?;
let seq1 = cookie.sequence_number();
let res = cookie.reply_unchecked()?;
assert!(res.is_none());
// The short version of the above would be:
// let res = conn.get_geomtry(INVALID_WINDOW)?.reply_unchecked()?;
// Errors can show up as 'events' in wait_for_event() by just dropping the cookie
let cookie = conn.get_geometry(INVALID_WINDOW)?;
let seq2 = cookie.sequence_number();
drop(cookie);
// The short version of the above would be:
// drop(conn.get_geometry(INVALID_WINDOW)?);
// For requests without responses, there are three possibilities
// We can check for errors explicitly
match conn.destroy_window(INVALID_WINDOW)?.check() {
Err(ReplyError::X11Error(_)) => {}
e => panic!("{e:?} unexpected"),
}
// We can silently ignore the error
conn.destroy_window(INVALID_WINDOW)?.ignore_error();
// An error can be handled as an event.
let cookie = conn.destroy_window(INVALID_WINDOW)?;
let seq3 = cookie.sequence_number();
drop(cookie);
// The short version of the above would be:
// drop(conn.destroy_window(INVALID_WINDOW)?);
// Synchronise with the server so that all errors are already received.
conn.sync()?;
// Now check if the things above really caused errors. This is the part that is supposed to
// turn this example into a (bad) integration test.
for &seq in &[seq1, seq2, seq3] {
let (event, seq2) = conn.wait_for_event_with_sequence()?;
match event {
Event::Error(_) => {}
event => panic!("Unexpectedly got {event:?} instead of an X11 error"),
}
assert_eq!(seq, seq2);
}
assert!(conn.poll_for_event()?.is_none());
println!("Done");
Ok(())
}
include!("integration_test_util/connect.rs");

289
vendor/x11rb/examples/display_ppm.rs vendored Normal file
View File

@@ -0,0 +1,289 @@
// This example reads a .ppm file and displays the image on screen. It shows how to work
// with images.
use x11rb::connection::Connection;
use x11rb::errors::ReplyOrIdError;
use x11rb::image::{ColorComponent, Image, PixelLayout};
use x11rb::protocol::xproto::{
AtomEnum, ConnectionExt, CreateGCAux, CreateWindowAux, PropMode, Screen, VisualClass, Visualid,
Window, WindowClass,
};
use x11rb::protocol::Event;
use x11rb::wrapper::ConnectionExt as _;
x11rb::atom_manager! {
Atoms: AtomsCookie {
WM_PROTOCOLS,
WM_DELETE_WINDOW,
}
}
/// Create a window with the given image as background.
fn create_window(
conn: &impl Connection,
screen: &Screen,
atoms: &Atoms,
image: &Image,
) -> Result<Window, ReplyOrIdError> {
let win_id = conn.generate_id()?;
let pixmap_id = conn.generate_id()?;
let gc_id = conn.generate_id()?;
conn.create_gc(
gc_id,
screen.root,
&CreateGCAux::default().graphics_exposures(0),
)?;
conn.create_pixmap(
screen.root_depth,
pixmap_id,
screen.root,
image.width(),
image.height(),
)?;
image.put(conn, pixmap_id, gc_id, 0, 0)?;
conn.free_gc(gc_id)?;
conn.create_window(
screen.root_depth,
win_id,
screen.root,
0,
0,
image.width(),
image.height(),
0,
WindowClass::INPUT_OUTPUT,
0,
&CreateWindowAux::default().background_pixmap(pixmap_id),
)?;
conn.free_pixmap(pixmap_id)?;
conn.change_property32(
PropMode::REPLACE,
win_id,
atoms.WM_PROTOCOLS,
AtomEnum::ATOM,
&[atoms.WM_DELETE_WINDOW],
)?;
Ok(win_id)
}
/// Check that the given visual is "as expected" (pixel values are 0xRRGGBB with RR/GG/BB being the
/// colors). Otherwise, this exits the process.
fn check_visual(screen: &Screen, id: Visualid) -> PixelLayout {
// Find the information about the visual and at the same time check its depth.
let visual_info = screen
.allowed_depths
.iter()
.filter_map(|depth| {
let info = depth.visuals.iter().find(|depth| depth.visual_id == id);
info.map(|info| (depth.depth, info))
})
.next();
let (depth, visual_type) = match visual_info {
Some(info) => info,
None => {
eprintln!("Did not find the root visual's description?!");
std::process::exit(1);
}
};
// Check that the pixels have red/green/blue components that we can set directly.
match visual_type.class {
VisualClass::TRUE_COLOR | VisualClass::DIRECT_COLOR => {}
_ => {
eprintln!("The root visual is not true / direct color, but {visual_type:?}");
std::process::exit(1);
}
}
let result = PixelLayout::from_visual_type(*visual_type)
.expect("The server sent a malformed visual type");
assert_eq!(result.depth(), depth);
result
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load the image
let image = match std::env::args_os().nth(1) {
None => {
eprintln!(
"Expected a file name of a PPM as argument, using a built-in default image instead"
);
ppm_parser::parse_ppm_bytes(&BUILTIN_IMAGE)?
}
Some(arg) => ppm_parser::parse_ppm_file(&arg)?,
};
let (conn, screen_num) = connect(None)?;
// The following is only needed for start_timeout_thread(), which is used for 'tests'
let conn1 = std::sync::Arc::new(conn);
let conn = &*conn1;
let screen = &conn.setup().roots[screen_num];
let pixel_layout = check_visual(screen, screen.root_visual);
// Convert the image from the PPM format into the server's native format.
let ppm_layout = PixelLayout::new(
ColorComponent::new(8, 16)?,
ColorComponent::new(8, 8)?,
ColorComponent::new(8, 0)?,
);
let image = image.reencode(ppm_layout, pixel_layout, conn.setup())?;
let atoms = Atoms::new(conn)?.reply()?;
let win_id = create_window(conn, screen, &atoms, &image)?;
conn.map_window(win_id)?;
util::start_timeout_thread(conn1.clone(), win_id);
conn.flush()?;
loop {
let event = conn.wait_for_event().unwrap();
match event {
Event::ClientMessage(event) => {
let data = event.data.as_data32();
if event.format == 32 && event.window == win_id && data[0] == atoms.WM_DELETE_WINDOW
{
println!("Window was asked to close");
return Ok(());
}
}
Event::Error(err) => println!("Got an unexpected error: {err:?}"),
ev => println!("Got an unknown event: {ev:?}"),
}
}
}
mod ppm_parser {
use std::ffi::OsStr;
use std::io::{Error as IOError, ErrorKind, Read, Result as IOResult};
use x11rb::image::{BitsPerPixel, Image, ImageOrder, ScanlinePad};
fn make_io_error(text: &'static str) -> IOError {
IOError::new(ErrorKind::Other, text)
}
/// Read until the next b'\n'.
fn read_to_end_of_line(input: &mut impl Read) -> IOResult<()> {
let mut byte = [0; 1];
loop {
input.read_exact(&mut byte)?;
if byte[0] == b'\n' {
return Ok(());
}
}
}
/// Read a decimal number from the input.
fn read_decimal(input: &mut impl Read) -> IOResult<u16> {
let mut byte = [0; 1];
// Skip leading whitespace and comments
loop {
input.read_exact(&mut byte)?;
match byte[0] {
b' ' | b'\t' | b'\r' => {}
// Comment, skip a whole line
b'#' => read_to_end_of_line(input)?,
_ => break,
}
}
// Now comes a number
if !byte[0].is_ascii_digit() {
return Err(make_io_error("Failed parsing a number"));
}
let mut result: u16 = 0;
while byte[0].is_ascii_digit() {
let value = u16::from(byte[0] - b'0');
result = result
.checked_mul(10)
.map(|result| result + value)
.ok_or_else(|| make_io_error("Overflow while parsing number"))?;
input.read_exact(&mut byte)?;
}
// After the number, there should be some whitespace.
if byte[0].is_ascii_whitespace() {
Ok(result)
} else {
Err(make_io_error("Unexpected character in header"))
}
}
fn parse_ppm(input: &mut impl Read) -> IOResult<Image<'static>> {
let mut header = [0; 2];
input.read_exact(&mut header)?;
if header != *b"P6" {
return Err(make_io_error("Incorrect file header"));
}
read_to_end_of_line(input)?;
let width = read_decimal(input)?;
let height = read_decimal(input)?;
let max = read_decimal(input)?;
if max != 255 {
eprintln!("Image declares a max pixel value of {max}, but I expected 255.");
eprintln!("Something will happen...?");
}
let mut image = Image::allocate(
width,
height,
ScanlinePad::Pad8,
24,
BitsPerPixel::B24,
ImageOrder::MsbFirst,
);
input.read_exact(image.data_mut())?;
Ok(image)
}
pub fn parse_ppm_bytes(bytes: &[u8]) -> IOResult<Image<'static>> {
use std::io::Cursor;
parse_ppm(&mut Cursor::new(bytes))
}
pub fn parse_ppm_file(file_name: &OsStr) -> IOResult<Image<'static>> {
use std::fs::File;
use std::io::BufReader;
parse_ppm(&mut BufReader::new(File::open(file_name)?))
}
}
// Simple builtin PPM that is used if none is provided on the command line
#[rustfmt::skip]
const BUILTIN_IMAGE: [u8; 35] = [
b'P', b'6', b'\n',
// width and height
b'4', b' ', b'2', b'\n',
b'2', b'5', b'5', b'\n',
// Black pixel
0x00, 0x00, 0x00,
// red pixel
0xff, 0x00, 0x00,
// green pixel
0x00, 0xff, 0x00,
// blue pixel
0x00, 0x00, 0xff,
// white pixel
0xff, 0xff, 0xff,
// cyan pixel
0x00, 0xff, 0xff,
// magenta pixel
0xff, 0x00, 0xff,
// yellow pixel
0xff, 0xff, 0x00,
];
include!("integration_test_util/connect.rs");
include!("integration_test_util/util.rs");

88
vendor/x11rb/examples/generic_events.rs vendored Normal file
View File

@@ -0,0 +1,88 @@
// This example tests support for generic events (XGE). It generates a window and uses the PRESENT
// extension to cause an XGE event to be sent.
use std::process::exit;
use x11rb::connection::{Connection as _, RequestConnection as _};
use x11rb::protocol::xproto::{
ConfigureWindowAux, ConnectionExt as _, CreateWindowAux, WindowClass,
};
use x11rb::protocol::{present, Event};
use x11rb::COPY_DEPTH_FROM_PARENT;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, screen_num) = connect(None)?;
let screen = &conn.setup().roots[screen_num];
if conn
.extension_information(present::X11_EXTENSION_NAME)?
.is_none()
{
eprintln!("Present extension is not supported");
exit(1);
}
// Create a window
let win_id = conn.generate_id()?;
let win_aux = CreateWindowAux::new().background_pixel(screen.white_pixel);
conn.create_window(
COPY_DEPTH_FROM_PARENT,
win_id,
screen.root,
0,
0,
10,
10,
0,
WindowClass::INPUT_OUTPUT,
0,
&win_aux,
)?;
// Ask for present ConfigureNotify events
let event_id = conn.generate_id()?;
present::select_input(
&conn,
event_id,
win_id,
present::EventMask::CONFIGURE_NOTIFY,
)?;
// Cause an event
conn.configure_window(win_id, &ConfigureWindowAux::new().width(20))?;
// Wait for the event
conn.flush()?;
let event = conn.wait_for_event()?;
// Now check that the event really is what we wanted to get
let event = match event {
Event::PresentConfigureNotify(event) => event,
other => panic!("Unexpected event {other:?}"),
};
println!(
"Got a Present ConfigureNotify event for event ID 0x{:x} and window 0x{:x}.",
event.event, event.window
);
println!(
"x={}, y={}, width={}, height={}, off_x={}, off_y={}, pixmap_width={}, pixmap_height={}, \
pixmap_flags={:x}",
event.x,
event.y,
event.width,
event.height,
event.off_x,
event.off_y,
event.pixmap_width,
event.pixmap_height,
event.pixmap_flags,
);
assert_eq!(
(20, 10, 0),
(event.pixmap_width, event.pixmap_height, event.pixmap_flags)
);
Ok(())
}
include!("integration_test_util/connect.rs");

277
vendor/x11rb/examples/hypnomoire.rs vendored Normal file
View File

@@ -0,0 +1,277 @@
// This is a (rough) port of hypnomoire from the xcb-demo repository.
// The original file has Copyright (C) 2001-2002 Bart Massey and Jamey Sharp and is licensed under
// a MIT license.
extern crate x11rb;
use std::f64::consts::PI;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use x11rb::connection::Connection;
use x11rb::errors::{ReplyError, ReplyOrIdError};
use x11rb::protocol::xproto::*;
use x11rb::protocol::Event;
use x11rb::wrapper::ConnectionExt as _;
use x11rb::COPY_DEPTH_FROM_PARENT;
/// Lag angle for the follow line
const LAG: f64 = 0.3;
/// Frames per second
const FRAME_RATE: u64 = 10;
/// Number of windows to show
const WINS: usize = 3;
#[derive(Default)]
struct WindowState {
window: Window,
pixmap: Pixmap,
angle_velocity: f64,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, screen_num) = connect(None)?;
let conn = Arc::new(conn);
let screen = &conn.setup().roots[screen_num];
let white = conn.generate_id()?;
let black = conn.generate_id()?;
conn.create_gc(
white,
screen.root,
&CreateGCAux::new()
.graphics_exposures(0)
.foreground(screen.white_pixel),
)?;
conn.create_gc(
black,
screen.root,
&CreateGCAux::new()
.graphics_exposures(0)
.foreground(screen.black_pixel),
)?;
let windows: Vec<_> = (0..WINS)
.map(|_| Arc::new(Mutex::new(WindowState::default())))
.collect();
for win in windows.iter() {
let conn2 = Arc::clone(&conn);
let win = Arc::clone(win);
thread::spawn(move || run(conn2, win, screen_num, white, black));
}
event_thread(conn, windows, white)?;
Ok(())
}
fn run<C: Connection>(
conn: Arc<C>,
window_state: Arc<Mutex<WindowState>>,
screen_num: usize,
white: Gcontext,
black: Gcontext,
) -> Result<(), ReplyOrIdError> {
let wm_protocols = conn.intern_atom(false, b"WM_PROTOCOLS")?;
let wm_delete_window = conn.intern_atom(false, b"WM_DELETE_WINDOW")?;
let wm_protocols = wm_protocols.reply()?.atom;
let wm_delete_window = wm_delete_window.reply()?.atom;
let screen = &conn.setup().roots[screen_num];
let default_size = 300;
let pixmap = conn.generate_id()?;
let window = conn.generate_id()?;
{
let mut guard = window_state.lock().unwrap();
guard.pixmap = pixmap;
guard.window = window;
guard.angle_velocity = 0.05;
}
conn.create_window(
COPY_DEPTH_FROM_PARENT,
window,
screen.root,
0, // x
0, // y
default_size, // width
default_size, // height
0,
WindowClass::INPUT_OUTPUT,
screen.root_visual,
&CreateWindowAux::new()
.background_pixel(screen.white_pixel)
.event_mask(
EventMask::BUTTON_RELEASE | EventMask::EXPOSURE | EventMask::STRUCTURE_NOTIFY,
)
.do_not_propogate_mask(EventMask::BUTTON_PRESS),
)?;
conn.change_property32(
PropMode::REPLACE,
window,
wm_protocols,
AtomEnum::ATOM,
&[wm_delete_window],
)?;
conn.map_window(window)?;
conn.create_pixmap(
screen.root_depth,
pixmap,
window,
default_size,
default_size,
)?;
let rect = Rectangle {
x: 0,
y: 0,
width: default_size,
height: default_size,
};
conn.poly_fill_rectangle(pixmap, white, &[rect])?;
let mut theta: f64 = 0.0;
let radius = f64::from(default_size) + 1.0;
loop {
let guard = window_state.lock().unwrap();
let (center_x, center_y) = (default_size as i16 / 2, default_size as i16 / 2);
let (sin, cos) = theta.sin_cos();
let (x, y) = ((radius * cos) as i16, (radius * sin) as i16);
let lines = [
Point {
x: center_x,
y: center_y,
},
Point { x, y },
];
conn.poly_line(CoordMode::PREVIOUS, pixmap, black, &lines)?;
let (sin, cos) = (theta + LAG).sin_cos();
let (x, y) = ((radius * cos) as i16, (radius * sin) as i16);
let lines = [
Point {
x: center_x,
y: center_y,
},
Point { x, y },
];
conn.poly_line(CoordMode::PREVIOUS, pixmap, white, &lines)?;
conn.copy_area(
pixmap,
window,
white,
0,
0,
0,
0,
default_size,
default_size,
)?;
conn.flush()?;
theta += guard.angle_velocity;
while theta > 2.0 * PI {
theta -= 2.0 * PI;
}
while theta < 0.0 {
theta += 2.0 * PI;
}
drop(guard);
thread::sleep(Duration::from_micros(1_000_000 / FRAME_RATE));
}
}
fn event_thread<C>(
conn_arc: Arc<C>,
windows: Vec<Arc<Mutex<WindowState>>>,
white: Gcontext,
) -> Result<(), ReplyError>
where
C: Connection + Send + Sync + 'static,
{
let mut first_window_mapped = false;
let conn = &*conn_arc;
loop {
let event = conn.wait_for_event()?;
match event {
Event::Expose(event) => {
if let Some(state) = find_window_by_id(&windows, event.window) {
let state = state.lock().unwrap();
conn.copy_area(
state.pixmap,
state.window,
white,
event.x as _,
event.y as _,
event.x as _,
event.y as _,
event.width,
event.height,
)?;
if event.count == 0 {
conn.flush()?;
}
} else {
eprintln!("Expose on unknown window!");
}
}
Event::ButtonRelease(event) => {
if let Some(state) = find_window_by_id(&windows, event.event) {
let mut state = state.lock().unwrap();
match event.detail {
// Button 1 is left mouse button
1 => state.angle_velocity *= -1.0,
// Buttons 4 and 5 are mouse wheel
4 => state.angle_velocity += 0.001,
5 => state.angle_velocity -= 0.001,
_ => {}
}
} else {
eprintln!("ButtonRelease on unknown window!");
}
}
Event::MapNotify(event) => {
if !first_window_mapped {
first_window_mapped = true;
util::start_timeout_thread(conn_arc.clone(), event.window);
}
}
Event::ClientMessage(_) => {
// We simply assume that this is a message to close. Since we are the main thread,
// everything closes when we exit.
return Ok(());
}
Event::Error(err) => {
eprintln!("Got an X11 error: {err:?}");
}
_ => {}
}
}
}
fn find_window_by_id(
windows: &[Arc<Mutex<WindowState>>],
window: Window,
) -> Option<&Arc<Mutex<WindowState>>> {
windows.iter().find(|state| {
state
.lock()
.map(|state| state.window == window)
.unwrap_or(false)
})
}
include!("integration_test_util/util.rs");
include!("integration_test_util/connect.rs");

View File

@@ -0,0 +1,24 @@
/// Establish a new connection to an X11 server.
///
/// Returns a `XCBConnection` if `allow-unsafe-code`, otherwise returns a `RustConnection`.
/// This function is meant to test code with both connection types. Production code
/// usually wants to use `x11rb::connect`, `x11rb::rust_connection::RustConnection::connect`
/// or `x11rb::xcb_ffi::XCBConnection::connect`.
pub fn connect(
dpy_name: Option<&str>,
) -> Result<(impl x11rb::connection::Connection + Send + Sync, usize), x11rb::errors::ConnectError>
{
#[cfg(feature = "allow-unsafe-code")]
{
let dpy_name = dpy_name
.map(std::ffi::CString::new)
.transpose()
.map_err(|_| x11rb::errors::DisplayParsingError::Unknown)?;
let dpy_name = dpy_name.as_deref();
x11rb::xcb_ffi::XCBConnection::connect(dpy_name)
}
#[cfg(not(feature = "allow-unsafe-code"))]
{
x11rb::rust_connection::RustConnection::connect(dpy_name)
}
}

View File

@@ -0,0 +1,55 @@
// As far as I can see, I cannot easily share code between different examples. The following code
// is used by several examples to react to the $X11RB_EXAMPLE_TIMEOUT variable. This code is
// include!()d in the examples
mod util {
use std::env;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use x11rb::connection::Connection;
use x11rb::protocol::xproto::{
ClientMessageEvent, ConnectionExt as _, EventMask, Window,
};
pub fn start_timeout_thread<C>(conn: Arc<C>, window: Window)
where
C: Connection + Send + Sync + 'static,
{
let timeout = match env::var("X11RB_EXAMPLE_TIMEOUT")
.ok()
.and_then(|str| str.parse().ok())
{
None => return,
Some(timeout) => timeout,
};
thread::spawn(move || {
let wm_protocols = conn.intern_atom(false, b"WM_PROTOCOLS").unwrap();
let wm_delete_window = conn.intern_atom(false, b"WM_DELETE_WINDOW").unwrap();
thread::sleep(Duration::from_secs(timeout));
let event = ClientMessageEvent::new(
32,
window,
wm_protocols.reply().unwrap().atom,
[wm_delete_window.reply().unwrap().atom, 0, 0, 0, 0],
);
if let Err(err) = conn.send_event(false, window, EventMask::NO_EVENT, event) {
eprintln!("Error while sending event: {err:?}");
}
if let Err(err) = conn.send_event(
false,
window,
EventMask::SUBSTRUCTURE_REDIRECT,
event,
) {
eprintln!("Error while sending event: {err:?}");
}
conn.flush().unwrap();
});
}
}

50
vendor/x11rb/examples/list_fonts.rs vendored Normal file
View File

@@ -0,0 +1,50 @@
// This program should produce output identical to `xlsfonts -lu`.
extern crate x11rb;
use x11rb::protocol::xproto::{ConnectionExt, FontDraw};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, _) = connect(None)?;
println!("DIR MIN MAX EXIST DFLT PROP ASC DESC NAME");
for reply in conn.list_fonts_with_info(u16::MAX, b"*")? {
let reply = reply?;
let dir = if reply.draw_direction == FontDraw::LEFT_TO_RIGHT {
"-->"
} else if reply.draw_direction == FontDraw::RIGHT_TO_LEFT {
"<--"
} else {
"???"
};
let (min, max, indicator) = if reply.min_byte1 == 0 && reply.max_byte1 == 0 {
(reply.min_char_or_byte2, reply.max_char_or_byte2, ' ')
} else {
(u16::from(reply.min_byte1), u16::from(reply.max_byte1), '*')
};
let all = if reply.all_chars_exist { "all" } else { "some" };
let name = String::from_utf8_lossy(&reply.name);
println!(
"{} {}{:3} {}{:3} {:>5} {:4} {:4} {:3} {:4} {}",
dir,
indicator,
min,
indicator,
max,
all,
reply.default_char,
reply.properties.len(),
reply.font_ascent,
reply.font_descent,
name
);
}
Ok(())
}
include!("integration_test_util/connect.rs");

171
vendor/x11rb/examples/record.rs vendored Normal file
View File

@@ -0,0 +1,171 @@
// This example shows how to use the record extension.
//
// The short version is: You do not want to use the record extension.
//
// The long version is: It's ugly and here is how it works.
//
// If you want to learn more about the record extension, it is recommended to read
// https://www.x.org/releases/X11R7.6/doc/recordproto/record.html
//
// This example is based on
// https://github.com/nibrahim/showkeys/blob/master/tests/record-example.c, which is GPLv3 and
// contains no copyright information. According to the git history, it was written by
// Noufal Ibrahim <noufal@nibrahim.net.in> in 2011.
use std::convert::TryFrom;
use x11rb::connection::Connection;
use x11rb::connection::RequestConnection;
use x11rb::errors::ParseError;
use x11rb::protocol::record::{self, ConnectionExt as _};
use x11rb::protocol::xproto;
use x11rb::wrapper::ConnectionExt;
use x11rb::x11_utils::TryParse;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// From https://www.x.org/releases/X11R7.6/doc/recordproto/record.html:
// "The typical communication model for a recording client is to open two connections to the
// server and use one for RC control and the other for reading protocol data."
let (ctrl_conn, _) = connect(None)?;
let (data_conn, _) = connect(None)?;
// Check if the record extension is supported.
if ctrl_conn
.extension_information(record::X11_EXTENSION_NAME)?
.is_none()
{
eprintln!("The X11 server does not support the RECORD extension");
return Ok(());
}
let ver = ctrl_conn
.record_query_version(
record::X11_XML_VERSION.0 as _,
record::X11_XML_VERSION.1 as _,
)?
.reply()?;
println!(
"requested RECORD extension version {:?}, server supports {:?}",
record::X11_XML_VERSION,
(ver.major_version, ver.minor_version)
);
// Set up a recording context
let rc = ctrl_conn.generate_id()?;
let empty = record::Range8 { first: 0, last: 0 };
let empty_ext = record::ExtRange {
major: empty,
minor: record::Range16 { first: 0, last: 0 },
};
let range = record::Range {
core_requests: empty,
core_replies: empty,
ext_requests: empty_ext,
ext_replies: empty_ext,
delivered_events: empty,
device_events: record::Range8 {
// We want notification of core X11 events between key press and motion notify
first: xproto::KEY_PRESS_EVENT,
last: xproto::MOTION_NOTIFY_EVENT,
},
errors: empty,
client_started: false,
client_died: false,
};
ctrl_conn
.record_create_context(rc, 0, &[record::CS::ALL_CLIENTS.into()], &[range])?
.check()?;
// Apply a timeout if we are requested to do so.
match std::env::var("X11RB_EXAMPLE_TIMEOUT")
.ok()
.and_then(|str| str.parse().ok())
{
None => {}
Some(timeout) => {
std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(timeout));
ctrl_conn.record_disable_context(rc).unwrap();
ctrl_conn.sync().unwrap();
});
}
}
// The above check() makes sure that the server already handled the CreateContext request.
// Alternatively, we could do ctrl_conn.sync() here for the same effect.
// We now switch to using "the other" connection.
// FIXME: These constants should be added to the XML
const START_OF_DATA: u8 = 4;
const RECORD_FROM_SERVER: u8 = 0;
for reply in data_conn.record_enable_context(rc)? {
let reply = reply?;
if reply.client_swapped {
println!("Byte swapped clients are unsupported");
} else if reply.category == RECORD_FROM_SERVER {
let mut remaining = &reply.data[..];
let mut should_exit = false;
while !remaining.is_empty() {
let (r, exit) = print_reply_data(&reply.data)?;
remaining = r;
if exit {
should_exit = true;
}
}
if should_exit {
break;
}
} else if reply.category == START_OF_DATA {
println!("Press Escape to exit...");
} else {
println!("Got a reply with an unsupported category: {reply:?}");
}
}
Ok(())
}
// Print a single reply data packet and return the remaining data. When escape is pressed, true is
// also returned to indicate that we should exit.
fn print_reply_data(data: &[u8]) -> Result<(&[u8], bool), ParseError> {
match data[0] {
xproto::KEY_PRESS_EVENT => {
let (event, remaining) = xproto::KeyPressEvent::try_parse(data)?;
println!("key press: {event:?}");
Ok((remaining, false))
}
xproto::KEY_RELEASE_EVENT => {
let (event, remaining) = xproto::KeyReleaseEvent::try_parse(data)?;
println!("key release: {event:?}");
Ok((remaining, event.detail == 9))
}
xproto::BUTTON_PRESS_EVENT => {
let (event, remaining) = xproto::ButtonPressEvent::try_parse(data)?;
println!("button press: {event:?}");
Ok((remaining, false))
}
xproto::BUTTON_RELEASE_EVENT => {
let (event, remaining) = xproto::ButtonReleaseEvent::try_parse(data)?;
println!("button release: {event:?}");
Ok((remaining, false))
}
xproto::MOTION_NOTIFY_EVENT => {
let (event, remaining) = xproto::MotionNotifyEvent::try_parse(data)?;
println!("motion notify: {event:?}");
Ok((remaining, false))
}
0 => {
// This is a reply, we compute its length as follows
let (length, _) = u32::try_parse(&data[4..])?;
let length = usize::try_from(length).unwrap() * 4 + 32;
println!("unparsed reply: {:?}", &data[..length]);
Ok((&data[length..], false))
}
_ => {
// Error or event, they always have length 32
// TODO: What about XGE events?
println!("unparsed error/event: {:?}", &data[..32]);
Ok((&data[32..], false))
}
}
}
include!("integration_test_util/connect.rs");

175
vendor/x11rb/examples/shared_memory.rs vendored Normal file
View File

@@ -0,0 +1,175 @@
extern crate x11rb;
use std::fs::{remove_file, File, OpenOptions};
use std::io::{Result as IOResult, Write};
use std::os::unix::io::AsRawFd;
use std::ptr::null_mut;
use libc::{mmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
use rustix::fd::OwnedFd;
use x11rb::connection::Connection;
use x11rb::errors::{ConnectionError, ReplyError, ReplyOrIdError};
use x11rb::protocol::shm::{self, ConnectionExt as _};
use x11rb::protocol::xproto::{self, ImageFormat, PixmapWrapper};
const TEMP_FILE_CONTENT: [u8; 8] = [0x00, 0x01, 0x02, 0x03, 0xff, 0xfe, 0xfd, 0xfc];
/// Get the supported SHM version from the X11 server
fn check_shm_version<C: Connection>(conn: &C) -> Result<Option<(u16, u16)>, ReplyError> {
if conn
.extension_information(shm::X11_EXTENSION_NAME)?
.is_none()
{
return Ok(None);
}
let shm_version = conn.shm_query_version()?.reply()?;
Ok(Some((shm_version.major_version, shm_version.minor_version)))
}
/// Get the bytes describing the first pixel at the given offset of the given shared memory segment
/// (interpreted in the screen's root_visual)
fn get_shared_memory_content_at_offset<C: Connection>(
conn: &C,
screen: &xproto::Screen,
shmseg: shm::Seg,
offset: u32,
) -> Result<Vec<u8>, ReplyOrIdError> {
let width = match screen.root_depth {
24 => 1,
16 => 2,
8 => 4,
_ => panic!("I do not know how to handle depth {}", screen.root_depth),
};
let pixmap = conn.generate_id()?;
conn.shm_create_pixmap(
pixmap,
screen.root,
width,
1,
screen.root_depth,
shmseg,
offset,
)?;
let pixmap = PixmapWrapper::for_pixmap(conn, pixmap);
let image = xproto::get_image(
conn,
ImageFormat::Z_PIXMAP,
pixmap.pixmap(),
0,
0,
width,
1,
!0,
)?
.reply()?;
Ok(image.data)
}
fn use_shared_mem<C: Connection>(
conn: &C,
screen_num: usize,
shmseg: shm::Seg,
) -> Result<(), ReplyOrIdError> {
let screen = &conn.setup().roots[screen_num];
let content = get_shared_memory_content_at_offset(conn, screen, shmseg, 0)?;
assert_eq!(content[..], TEMP_FILE_CONTENT[0..4]);
let content = get_shared_memory_content_at_offset(conn, screen, shmseg, 4)?;
assert_eq!(content[..], TEMP_FILE_CONTENT[4..8]);
Ok(())
}
/// Make a temporary file
fn make_file() -> IOResult<File> {
let file_name = "shared_memory.bin";
let mut file = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.truncate(true)
.open(file_name)?;
file.write_all(&TEMP_FILE_CONTENT)?;
remove_file(file_name)?;
Ok(file)
}
fn send_fd<C: Connection>(conn: &C, screen_num: usize, file: File) -> Result<(), ReplyOrIdError> {
let shmseg = conn.generate_id()?;
conn.shm_attach_fd(shmseg, OwnedFd::from(file), false)?;
use_shared_mem(conn, screen_num, shmseg)?;
conn.shm_detach(shmseg)?;
Ok(())
}
fn receive_fd<C: Connection>(conn: &C, screen_num: usize) -> Result<(), ReplyOrIdError> {
let shmseg = conn.generate_id()?;
let segment_size = TEMP_FILE_CONTENT.len() as _;
let reply = conn
.shm_create_segment(shmseg, segment_size, false)?
.reply()?;
let shm::CreateSegmentReply { shm_fd, .. } = reply;
let addr = unsafe {
mmap(
null_mut(),
segment_size as _,
PROT_READ | PROT_WRITE,
MAP_SHARED,
shm_fd.as_raw_fd(),
0,
)
};
if addr == MAP_FAILED {
conn.shm_detach(shmseg)?;
return Err(ConnectionError::InsufficientMemory.into());
}
unsafe {
let slice = std::slice::from_raw_parts_mut(addr as *mut u8, segment_size as _);
slice.copy_from_slice(&TEMP_FILE_CONTENT);
}
use_shared_mem(conn, screen_num, shmseg)?;
conn.shm_detach(shmseg)?;
// Let's ignore the munmap() that we should do here
Ok(())
}
fn main() {
let file = make_file().expect("Failed to create temporary file for FD passing");
match connect(None) {
Err(err) => eprintln!("Failed to connect to the X11 server: {err}"),
Ok((conn, screen_num)) => {
// Check for SHM 1.2 support (needed for fd passing)
if let Some((major, minor)) = check_shm_version(&conn).unwrap() {
if major < 1 || (major == 1 && minor < 2) {
eprintln!(
"X11 server supports version {major}.{minor} of the SHM extension, but version 1.2 \
is needed"
);
return;
}
} else {
eprintln!("X11 server does not support SHM extension");
return;
}
println!("Trying to send an FD");
send_fd(&conn, screen_num, file).unwrap();
println!("Trying to receive an FD");
receive_fd(&conn, screen_num).unwrap();
}
}
}
include!("integration_test_util/connect.rs");

173
vendor/x11rb/examples/simple_window.rs vendored Normal file
View File

@@ -0,0 +1,173 @@
extern crate x11rb;
use x11rb::connection::Connection;
use x11rb::cursor::Handle as CursorHandle;
use x11rb::protocol::xproto::*;
use x11rb::protocol::Event;
use x11rb::resource_manager::new_from_default;
use x11rb::wrapper::ConnectionExt as _;
x11rb::atom_manager! {
pub Atoms: AtomsCookie {
WM_PROTOCOLS,
WM_DELETE_WINDOW,
_NET_WM_NAME,
UTF8_STRING,
}
}
fn init_tracing() {
use tracing_subscriber::prelude::*;
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer())
.with(tracing_subscriber::EnvFilter::from_default_env())
.init();
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
init_tracing();
let (conn, screen_num) = x11rb::connect(None)?;
// The following is only needed for start_timeout_thread(), which is used for 'tests'
let conn1 = std::sync::Arc::new(conn);
let conn = &*conn1;
let screen = &conn.setup().roots[screen_num];
let win_id = conn.generate_id()?;
let gc_id = conn.generate_id()?;
let resource_db = new_from_default(conn)?;
let cursor_handle = CursorHandle::new(conn, screen_num, &resource_db)?;
let atoms = Atoms::new(conn)?.reply()?;
let cursor_handle = cursor_handle.reply()?;
let win_aux = CreateWindowAux::new()
.event_mask(EventMask::EXPOSURE | EventMask::STRUCTURE_NOTIFY | EventMask::NO_EVENT)
.background_pixel(screen.white_pixel)
.win_gravity(Gravity::NORTH_WEST)
// Just because, we set the cursor to "wait"
.cursor(cursor_handle.load_cursor(conn, "wait")?);
let gc_aux = CreateGCAux::new().foreground(screen.black_pixel);
let (mut width, mut height) = (100, 100);
conn.create_window(
screen.root_depth,
win_id,
screen.root,
0,
0,
width,
height,
0,
WindowClass::INPUT_OUTPUT,
0,
&win_aux,
)?;
util::start_timeout_thread(conn1.clone(), win_id);
let title = "Simple Window";
conn.change_property8(
PropMode::REPLACE,
win_id,
AtomEnum::WM_NAME,
AtomEnum::STRING,
title.as_bytes(),
)?;
conn.change_property8(
PropMode::REPLACE,
win_id,
atoms._NET_WM_NAME,
atoms.UTF8_STRING,
title.as_bytes(),
)?;
conn.change_property32(
PropMode::REPLACE,
win_id,
atoms.WM_PROTOCOLS,
AtomEnum::ATOM,
&[atoms.WM_DELETE_WINDOW],
)?;
conn.change_property8(
PropMode::REPLACE,
win_id,
AtomEnum::WM_CLASS,
AtomEnum::STRING,
b"simple_window\0simple_window\0",
)?;
conn.change_property8(
PropMode::REPLACE,
win_id,
AtomEnum::WM_CLIENT_MACHINE,
AtomEnum::STRING,
// Text encoding in X11 is complicated. Let's use UTF-8 and hope for the best.
gethostname::gethostname()
.to_str()
.unwrap_or("[Invalid]")
.as_bytes(),
)?;
let reply = conn
.get_property(false, win_id, AtomEnum::WM_NAME, AtomEnum::STRING, 0, 1024)?
.reply()?;
assert_eq!(reply.value, title.as_bytes());
conn.create_gc(gc_id, win_id, &gc_aux)?;
conn.map_window(win_id)?;
conn.flush()?;
loop {
let event = conn.wait_for_event()?;
tracing::debug!("Got event {event:?}");
match event {
Event::Expose(event) => {
if event.count == 0 {
// There already is a white background because we set background_pixel to white
// when creating the window.
let (width, height): (i16, i16) = (width as _, height as _);
let points = [
Point {
x: width,
y: height,
},
Point { x: -10, y: -10 },
Point {
x: -10,
y: height + 10,
},
Point {
x: width + 10,
y: -10,
},
];
conn.poly_line(CoordMode::ORIGIN, win_id, gc_id, &points)?;
conn.flush()?;
}
}
Event::ConfigureNotify(event) => {
width = event.width;
height = event.height;
}
Event::ClientMessage(event) => {
let data = event.data.as_data32();
if event.format == 32 && event.window == win_id && data[0] == atoms.WM_DELETE_WINDOW
{
tracing::info!("Window was asked to close");
return Ok(());
}
}
Event::Error(err) => {
tracing::error!("Got an unexpected error: {err:?}")
}
event => tracing::info!("Got an unhandled event: {event:?}"),
}
}
}
include!("integration_test_util/util.rs");

View File

@@ -0,0 +1,434 @@
// A very simple reparenting window manager.
// This WM does NOT follow ICCCM!
extern crate x11rb;
use std::cmp::Reverse;
use std::collections::{BinaryHeap, HashSet};
use std::process::exit;
use x11rb::connection::Connection;
use x11rb::errors::{ReplyError, ReplyOrIdError};
use x11rb::protocol::xproto::*;
use x11rb::protocol::{ErrorKind, Event};
use x11rb::{COPY_DEPTH_FROM_PARENT, CURRENT_TIME};
const TITLEBAR_HEIGHT: u16 = 20;
const DRAG_BUTTON: Button = 1;
/// The state of a single window that we manage
#[derive(Debug)]
struct WindowState {
window: Window,
frame_window: Window,
x: i16,
y: i16,
width: u16,
}
impl WindowState {
fn new(window: Window, frame_window: Window, geom: &GetGeometryReply) -> WindowState {
WindowState {
window,
frame_window,
x: geom.x,
y: geom.y,
width: geom.width,
}
}
fn close_x_position(&self) -> i16 {
std::cmp::max(0, self.width - TITLEBAR_HEIGHT) as _
}
}
/// The state of the full WM
#[derive(Debug)]
struct WmState<'a, C: Connection> {
conn: &'a C,
screen_num: usize,
black_gc: Gcontext,
windows: Vec<WindowState>,
pending_expose: HashSet<Window>,
wm_protocols: Atom,
wm_delete_window: Atom,
sequences_to_ignore: BinaryHeap<Reverse<u16>>,
// If this is Some, we are currently dragging the given window with the given offset relative
// to the mouse.
drag_window: Option<(Window, (i16, i16))>,
}
impl<'a, C: Connection> WmState<'a, C> {
fn new(conn: &'a C, screen_num: usize) -> Result<WmState<'a, C>, ReplyOrIdError> {
let screen = &conn.setup().roots[screen_num];
let black_gc = conn.generate_id()?;
let font = conn.generate_id()?;
conn.open_font(font, b"9x15")?;
let gc_aux = CreateGCAux::new()
.graphics_exposures(0)
.background(screen.white_pixel)
.foreground(screen.black_pixel)
.font(font);
conn.create_gc(black_gc, screen.root, &gc_aux)?;
conn.close_font(font)?;
let wm_protocols = conn.intern_atom(false, b"WM_PROTOCOLS")?;
let wm_delete_window = conn.intern_atom(false, b"WM_DELETE_WINDOW")?;
Ok(WmState {
conn,
screen_num,
black_gc,
windows: Vec::default(),
pending_expose: HashSet::default(),
wm_protocols: wm_protocols.reply()?.atom,
wm_delete_window: wm_delete_window.reply()?.atom,
sequences_to_ignore: Default::default(),
drag_window: None,
})
}
/// Scan for already existing windows and manage them
fn scan_windows(&mut self) -> Result<(), ReplyOrIdError> {
// Get the already existing top-level windows.
let screen = &self.conn.setup().roots[self.screen_num];
let tree_reply = self.conn.query_tree(screen.root)?.reply()?;
// For each window, request its attributes and geometry *now*
let mut cookies = Vec::with_capacity(tree_reply.children.len());
for win in tree_reply.children {
let attr = self.conn.get_window_attributes(win)?;
let geom = self.conn.get_geometry(win)?;
cookies.push((win, attr, geom));
}
// Get the replies and manage windows
for (win, attr, geom) in cookies {
if let (Ok(attr), Ok(geom)) = (attr.reply(), geom.reply()) {
if !attr.override_redirect && attr.map_state != MapState::UNMAPPED {
self.manage_window(win, &geom)?;
}
} else {
// Just skip this window
}
}
Ok(())
}
/// Add a new window that should be managed by the WM
fn manage_window(
&mut self,
win: Window,
geom: &GetGeometryReply,
) -> Result<(), ReplyOrIdError> {
println!("Managing window {win:?}");
let screen = &self.conn.setup().roots[self.screen_num];
assert!(self.find_window_by_id(win).is_none());
let frame_win = self.conn.generate_id()?;
let win_aux = CreateWindowAux::new()
.event_mask(
EventMask::EXPOSURE
| EventMask::SUBSTRUCTURE_NOTIFY
| EventMask::BUTTON_PRESS
| EventMask::BUTTON_RELEASE
| EventMask::POINTER_MOTION
| EventMask::ENTER_WINDOW,
)
.background_pixel(screen.white_pixel);
self.conn.create_window(
COPY_DEPTH_FROM_PARENT,
frame_win,
screen.root,
geom.x,
geom.y,
geom.width,
geom.height + TITLEBAR_HEIGHT,
1,
WindowClass::INPUT_OUTPUT,
0,
&win_aux,
)?;
self.conn.grab_server()?;
self.conn.change_save_set(SetMode::INSERT, win)?;
let cookie = self
.conn
.reparent_window(win, frame_win, 0, TITLEBAR_HEIGHT as _)?;
self.conn.map_window(win)?;
self.conn.map_window(frame_win)?;
self.conn.ungrab_server()?;
self.windows.push(WindowState::new(win, frame_win, geom));
// Ignore all events caused by reparent_window(). All those events have the sequence number
// of the reparent_window() request, thus remember its sequence number. The
// grab_server()/ungrab_server() is done so that the server does not handle other clients
// in-between, which could cause other events to get the same sequence number.
self.sequences_to_ignore
.push(Reverse(cookie.sequence_number() as u16));
Ok(())
}
/// Draw the titlebar of a window
fn redraw_titlebar(&self, state: &WindowState) -> Result<(), ReplyError> {
let close_x = state.close_x_position();
self.conn.poly_line(
CoordMode::ORIGIN,
state.frame_window,
self.black_gc,
&[
Point { x: close_x, y: 0 },
Point {
x: state.width as _,
y: TITLEBAR_HEIGHT as _,
},
],
)?;
self.conn.poly_line(
CoordMode::ORIGIN,
state.frame_window,
self.black_gc,
&[
Point {
x: close_x,
y: TITLEBAR_HEIGHT as _,
},
Point {
x: state.width as _,
y: 0,
},
],
)?;
let reply = self
.conn
.get_property(
false,
state.window,
AtomEnum::WM_NAME,
AtomEnum::STRING,
0,
u32::MAX,
)?
.reply()?;
self.conn
.image_text8(state.frame_window, self.black_gc, 1, 10, &reply.value)?;
Ok(())
}
/// Do all pending work that was queued while handling some events
fn refresh(&mut self) {
while let Some(&win) = self.pending_expose.iter().next() {
self.pending_expose.remove(&win);
if let Some(state) = self.find_window_by_id(win) {
if let Err(err) = self.redraw_titlebar(state) {
eprintln!(
"Error while redrawing window {:x?}: {:?}",
state.window, err
);
}
}
}
}
fn find_window_by_id(&self, win: Window) -> Option<&WindowState> {
self.windows
.iter()
.find(|state| state.window == win || state.frame_window == win)
}
fn find_window_by_id_mut(&mut self, win: Window) -> Option<&mut WindowState> {
self.windows
.iter_mut()
.find(|state| state.window == win || state.frame_window == win)
}
/// Handle the given event
fn handle_event(&mut self, event: Event) -> Result<(), ReplyOrIdError> {
let mut should_ignore = false;
if let Some(seqno) = event.wire_sequence_number() {
// Check sequences_to_ignore and remove entries with old (=smaller) numbers.
while let Some(&Reverse(to_ignore)) = self.sequences_to_ignore.peek() {
// Sequence numbers can wrap around, so we cannot simply check for
// "to_ignore <= seqno". This is equivalent to "to_ignore - seqno <= 0", which is what we
// check instead. Since sequence numbers are unsigned, we need a trick: We decide
// that values from [MAX/2, MAX] count as "<= 0" and the rest doesn't.
if to_ignore.wrapping_sub(seqno) <= u16::MAX / 2 {
// If the two sequence numbers are equal, this event should be ignored.
should_ignore = to_ignore == seqno;
break;
}
self.sequences_to_ignore.pop();
}
}
println!("Got event {event:?}");
if should_ignore {
println!(" [ignored]");
return Ok(());
}
match event {
Event::UnmapNotify(event) => self.handle_unmap_notify(event),
Event::ConfigureRequest(event) => self.handle_configure_request(event)?,
Event::MapRequest(event) => self.handle_map_request(event)?,
Event::Expose(event) => self.handle_expose(event),
Event::EnterNotify(event) => self.handle_enter(event)?,
Event::ButtonPress(event) => self.handle_button_press(event),
Event::ButtonRelease(event) => self.handle_button_release(event)?,
Event::MotionNotify(event) => self.handle_motion_notify(event)?,
_ => {}
}
Ok(())
}
fn handle_unmap_notify(&mut self, event: UnmapNotifyEvent) {
let root = self.conn.setup().roots[self.screen_num].root;
let conn = self.conn;
self.windows.retain(|state| {
if state.window != event.window {
return true;
}
conn.change_save_set(SetMode::DELETE, state.window).unwrap();
conn.reparent_window(state.window, root, state.x, state.y)
.unwrap();
conn.destroy_window(state.frame_window).unwrap();
false
});
}
fn handle_configure_request(&mut self, event: ConfigureRequestEvent) -> Result<(), ReplyError> {
if let Some(state) = self.find_window_by_id_mut(event.window) {
let _ = state;
unimplemented!();
}
// Allow clients to change everything, except sibling / stack mode
let aux = ConfigureWindowAux::from_configure_request(&event)
.sibling(None)
.stack_mode(None);
println!("Configure: {aux:?}");
self.conn.configure_window(event.window, &aux)?;
Ok(())
}
fn handle_map_request(&mut self, event: MapRequestEvent) -> Result<(), ReplyOrIdError> {
self.manage_window(
event.window,
&self.conn.get_geometry(event.window)?.reply()?,
)
}
fn handle_expose(&mut self, event: ExposeEvent) {
self.pending_expose.insert(event.window);
}
fn handle_enter(&mut self, event: EnterNotifyEvent) -> Result<(), ReplyError> {
if let Some(state) = self.find_window_by_id(event.event) {
// Set the input focus (ignoring ICCCM's WM_PROTOCOLS / WM_TAKE_FOCUS)
self.conn
.set_input_focus(InputFocus::PARENT, state.window, CURRENT_TIME)?;
// Also raise the window to the top of the stacking order
self.conn.configure_window(
state.frame_window,
&ConfigureWindowAux::new().stack_mode(StackMode::ABOVE),
)?;
}
Ok(())
}
fn handle_button_press(&mut self, event: ButtonPressEvent) {
if event.detail != DRAG_BUTTON || u16::from(event.state) != 0 {
return;
}
if let Some(state) = self.find_window_by_id(event.event) {
if self.drag_window.is_none() && event.event_x < state.close_x_position() {
let (x, y) = (-event.event_x, -event.event_y);
self.drag_window = Some((state.frame_window, (x, y)));
}
}
}
fn handle_button_release(&mut self, event: ButtonReleaseEvent) -> Result<(), ReplyError> {
if event.detail == DRAG_BUTTON {
self.drag_window = None;
}
if let Some(state) = self.find_window_by_id(event.event) {
if event.event_x >= state.close_x_position() {
let event = ClientMessageEvent::new(
32,
state.window,
self.wm_protocols,
[self.wm_delete_window, 0, 0, 0, 0],
);
self.conn
.send_event(false, state.window, EventMask::NO_EVENT, event)?;
}
}
Ok(())
}
fn handle_motion_notify(&mut self, event: MotionNotifyEvent) -> Result<(), ReplyError> {
if let Some((win, (x, y))) = self.drag_window {
let (x, y) = (x + event.root_x, y + event.root_y);
// Sigh, X11 and its mixing up i16 and i32
let (x, y) = (x as i32, y as i32);
self.conn
.configure_window(win, &ConfigureWindowAux::new().x(x).y(y))?;
}
Ok(())
}
}
fn become_wm<C: Connection>(conn: &C, screen: &Screen) -> Result<(), ReplyError> {
// Try to become the window manager. This causes an error if there is already another WM.
let change = ChangeWindowAttributesAux::default()
.event_mask(EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY);
let res = conn.change_window_attributes(screen.root, &change)?.check();
if let Err(ReplyError::X11Error(ref error)) = res {
if error.error_kind == ErrorKind::Access {
eprintln!("Another WM is already running.");
exit(1);
} else {
res
}
} else {
res
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, screen_num) = connect(None)?;
// The following is only needed for start_timeout_thread(), which is used for 'tests'
let conn1 = std::sync::Arc::new(conn);
let conn = &*conn1;
let screen = &conn.setup().roots[screen_num];
become_wm(conn, screen)?;
let mut wm_state = WmState::new(conn, screen_num)?;
wm_state.scan_windows()?;
util::start_timeout_thread(conn1.clone(), screen.root);
loop {
wm_state.refresh();
conn.flush()?;
let event = conn.wait_for_event()?;
let mut event_option = Some(event);
while let Some(event) = event_option {
if let Event::ClientMessage(_) = event {
// This is start_timeout_thread() signaling us to close (most likely).
return Ok(());
}
wm_state.handle_event(event)?;
event_option = conn.poll_for_event()?;
}
}
}
include!("integration_test_util/connect.rs");
include!("integration_test_util/util.rs");

2861
vendor/x11rb/examples/tutorial.rs vendored Normal file

File diff suppressed because it is too large Load Diff

282
vendor/x11rb/examples/xclock_utc.rs vendored Normal file
View File

@@ -0,0 +1,282 @@
use std::num::NonZeroUsize;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use polling::{Event as PollingEvent, Poller};
use x11rb::atom_manager;
use x11rb::connection::Connection;
use x11rb::errors::{ConnectionError, ReplyOrIdError};
use x11rb::protocol::xproto::*;
use x11rb::protocol::Event;
use x11rb::rust_connection::RustConnection;
use x11rb::wrapper::ConnectionExt as _;
atom_manager! {
pub Atoms: AtomsCookie {
UTF8_STRING,
WM_DELETE_WINDOW,
WM_PROTOCOLS,
_NET_WM_NAME,
}
}
fn create_window(
conn: &impl Connection,
screen: &Screen,
atoms: &Atoms,
(width, height): (u16, u16),
) -> Result<Window, ReplyOrIdError> {
let win_id = conn.generate_id()?;
let win_aux =
CreateWindowAux::new().event_mask(EventMask::EXPOSURE | EventMask::STRUCTURE_NOTIFY);
conn.create_window(
screen.root_depth,
win_id,
screen.root,
0,
0,
width,
height,
0,
WindowClass::INPUT_OUTPUT,
0,
&win_aux,
)?;
let title = "xclock";
conn.change_property8(
PropMode::REPLACE,
win_id,
AtomEnum::WM_NAME,
AtomEnum::STRING,
title.as_bytes(),
)?;
conn.change_property8(
PropMode::REPLACE,
win_id,
atoms._NET_WM_NAME,
atoms.UTF8_STRING,
title.as_bytes(),
)?;
conn.change_property32(
PropMode::REPLACE,
win_id,
atoms.WM_PROTOCOLS,
AtomEnum::ATOM,
&[atoms.WM_DELETE_WINDOW],
)?;
conn.map_window(win_id)?;
Ok(win_id)
}
fn redraw(
conn: &impl Connection,
screen: &Screen,
win_id: Window,
gc_id: Gcontext,
(width, height): (u16, u16),
) -> Result<(), ConnectionError> {
let (hour, minute, second) = get_time();
let center = ((width as f32) / 2.0, (height as f32) / 2.0);
let size = (width.min(height) as f32) / 2.0;
// Transform a value between 0 and 60 to a position on the clock (relative to the center)
let minute_to_outer_position = |minute: f32| {
let angle = (30.0 - minute) * 2.0 * std::f32::consts::PI / 60.0;
let (sin, cos) = angle.sin_cos();
(size * sin, size * cos)
};
// Create a line segment
fn create_line(center: (f32, f32), from: (f32, f32), to: (f32, f32)) -> Segment {
Segment {
x1: (center.0 + from.0).round() as _,
y1: (center.1 + from.1).round() as _,
x2: (center.0 + to.0).round() as _,
y2: (center.1 + to.1).round() as _,
}
}
// Draw the background
conn.change_gc(gc_id, &ChangeGCAux::new().foreground(screen.white_pixel))?;
conn.poly_fill_rectangle(
win_id,
gc_id,
&[Rectangle {
x: 0,
y: 0,
width,
height,
}],
)?;
conn.change_gc(gc_id, &ChangeGCAux::new().foreground(screen.black_pixel))?;
// Get a list of lines for the clock's face
let mut lines = (0..60)
.map(|minute| {
let outer = minute_to_outer_position(minute as _);
let length_factor = if minute % 5 == 0 { 0.8 } else { 0.9 };
create_line(
center,
outer,
(outer.0 * length_factor, outer.1 * length_factor),
)
})
.collect::<Vec<_>>();
// ... and also the hand for seconds
lines.push(create_line(
center,
(0.0, 0.0),
minute_to_outer_position(second as _),
));
// Draw everything
conn.poly_segment(win_id, gc_id, &lines)?;
// Now draw the hands
let point = |pos: (f32, f32), factor: f32| Point {
x: (center.0 + pos.0 * factor).round() as _,
y: (center.1 + pos.1 * factor).round() as _,
};
let hour_to_60 = (hour % 12) as f32 * 60.0 / 12.0;
for &(position, hand_length, hand_width) in
&[(hour_to_60, 0.6, 0.08), (minute as f32, 0.8, 0.05)]
{
let outer = minute_to_outer_position(position);
let ortho1 = (outer.1, -outer.0);
let ortho2 = (-outer.1, outer.0);
let opposite = (-outer.0, -outer.1);
let polygon = [
point(ortho1, hand_width),
point(opposite, hand_width),
point(ortho2, hand_width),
point(outer, hand_length),
];
conn.fill_poly(
win_id,
gc_id,
PolyShape::COMPLEX,
CoordMode::ORIGIN,
&polygon,
)?;
}
Ok(())
}
fn poll_with_timeout(
poller: &Poller,
conn: &RustConnection,
timeout: Duration,
) -> Result<(), Box<dyn std::error::Error>> {
// Add interest in the connection's stream.
unsafe {
// SAFETY: The guard bellow guarantees that the source will be removed
// from the poller.
poller.add(conn.stream(), PollingEvent::readable(1))?;
}
// Remove it if we time out.
let _guard = CallOnDrop(|| {
poller.delete(conn.stream()).ok();
});
// Wait for events.
let mut event = polling::Events::with_capacity(NonZeroUsize::new(1).unwrap());
let target = Instant::now() + timeout;
loop {
let remaining = target.saturating_duration_since(Instant::now());
poller.wait(&mut event, Some(remaining))?;
// If we received an event, we're done.
if event.iter().any(|event| event.readable) {
return Ok(());
}
// If our timeout expired, we're done.
if Instant::now() >= target {
// We do not really care about the result of poll. Either there was a timeout, in which case we
// try to handle events (there are none) and then redraw. Or there was an event, in which case
// we handle it and then still redraw.
return Ok(());
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, screen_num) = RustConnection::connect(None)?;
// The following is only needed for start_timeout_thread(), which is used for 'tests'
let conn1 = std::sync::Arc::new(conn);
let conn = &*conn1;
let poller = Poller::new()?;
let screen = &conn.setup().roots[screen_num];
let atoms = Atoms::new(conn)?.reply()?;
let (mut width, mut height) = (100, 100);
let win_id = create_window(conn, screen, &atoms, (width, height))?;
let gc_id = conn.generate_id().unwrap();
conn.create_gc(gc_id, win_id, &CreateGCAux::default())?;
util::start_timeout_thread(conn1.clone(), win_id);
conn.flush()?;
loop {
poll_with_timeout(&poller, conn, Duration::from_millis(1_000))?;
while let Some(event) = conn.poll_for_event()? {
println!("{event:?})");
match event {
Event::ConfigureNotify(event) => {
width = event.width;
height = event.height;
}
Event::ClientMessage(event) => {
let data = event.data.as_data32();
if event.format == 32
&& event.window == win_id
&& data[0] == atoms.WM_DELETE_WINDOW
{
println!("Window was asked to close");
return Ok(());
}
}
Event::Error(_) => println!("Got an unexpected error"),
_ => println!("Got an unknown event"),
}
}
redraw(conn, screen, win_id, gc_id, (width, height))?;
conn.flush()?;
}
}
/// Get the current time as (hour, minute, second)
fn get_time() -> (u8, u8, u8) {
let total_secs = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
let (second, total_minutes) = (total_secs % 60, total_secs / 60);
let (minute, total_hours) = (total_minutes % 60, total_minutes / 60);
let hour = total_hours % 24;
// This is in UTC. Getting local time is complicated and not important for us.
(hour as _, minute as _, second as _)
}
include!("integration_test_util/util.rs");
struct CallOnDrop<F: FnMut()>(F);
impl<F: FnMut()> Drop for CallOnDrop<F> {
fn drop(&mut self) {
(self.0)();
}
}

372
vendor/x11rb/examples/xeyes.rs vendored Normal file
View File

@@ -0,0 +1,372 @@
// This is (quite loosely) based on the original xeyes
extern crate x11rb;
use x11rb::connection::{Connection, RequestConnection as _};
use x11rb::errors::{ConnectionError, ReplyOrIdError};
use x11rb::protocol::shape::{self, ConnectionExt as _};
use x11rb::protocol::xproto::*;
use x11rb::protocol::Event;
use x11rb::wrapper::ConnectionExt as _;
use x11rb::COPY_DEPTH_FROM_PARENT;
const PUPIL_SIZE: i16 = 50;
const EYE_SIZE: i16 = 50;
// Draw the big background of the eyes
fn draw_eyes<C: Connection>(
conn: &C,
win_id: Window,
black: Gcontext,
white: Gcontext,
window_size: (u16, u16),
) -> Result<(), ConnectionError> {
// Draw the black outlines
let mut arc1 = Arc {
x: 0,
y: 0,
width: window_size.0 / 2,
height: window_size.1,
angle1: 0,
angle2: 360 * 64,
};
let mut arc2 = arc1;
arc2.x = arc2.width as _;
conn.poly_fill_arc(win_id, black, &[arc1, arc2])?;
// Draw the white inner part
for arc in [&mut arc1, &mut arc2].iter_mut() {
arc.x += EYE_SIZE;
arc.y += EYE_SIZE;
arc.width -= 2 * EYE_SIZE as u16;
arc.height -= 2 * EYE_SIZE as u16;
}
conn.poly_fill_arc(win_id, white, &[arc1, arc2])?;
Ok(())
}
// Draw the pupils inside the eye
fn draw_pupils<C: Connection>(
conn: &C,
win_id: Window,
gc: Gcontext,
((x1, y1), (x2, y2)): ((i16, i16), (i16, i16)),
) -> Result<(), ConnectionError> {
// Transform center to top left corner
let (x1, y1) = (x1 - PUPIL_SIZE / 2, y1 - PUPIL_SIZE / 2);
let (x2, y2) = (x2 - PUPIL_SIZE / 2, y2 - PUPIL_SIZE / 2);
let arc1 = Arc {
x: x1,
y: y1,
width: PUPIL_SIZE as _,
height: PUPIL_SIZE as _,
angle1: 90 * 64,
angle2: 360 * 64,
};
let mut arc2 = arc1;
arc2.x = x2;
arc2.y = y2;
// Do the drawing
conn.poly_fill_arc(win_id, gc, &[arc1, arc2])?;
Ok(())
}
// Given two points, return their squared distance
fn distance_squared(p1: (f64, f64), p2: (f64, f64)) -> f64 {
let dx = p1.0 - p2.0;
let dy = p1.1 - p2.1;
dx * dx + dy * dy
}
// Compute the position of a pupil inside of the given area.
fn compute_pupil(area: (i16, i16, i16, i16), mouse: (i16, i16)) -> (i16, i16) {
// What is the center of the eye?
let center_x = area.0 + area.2 / 2;
let center_y = area.1 + area.3 / 2;
let (w, h) = (f64::from(area.2) / 2.0, f64::from(area.3) / 2.0);
// Is the mouse exactly on the center?
if (center_x, center_y) == mouse {
return mouse;
}
let center = (f64::from(center_x), f64::from(center_y));
let mouse = (f64::from(mouse.0), f64::from(mouse.1));
// Calculate the offset of the mouse position from the center
let diff = (mouse.0 - center.0, mouse.1 - center.1);
// An eclipse is described by this equation, where the angle 'a' is varied over all values, but
// does not actually describe the angle from the center due to the different scaling in x and y
// direction.
//
// x = w * cos(a)
// y = h * sin(a)
//
// With tan(a) = sin(a)/cos(a), we get
//
// tan(a) * x = w * sin(a) => sin(a) = tan(a) * x / w
// y = h * sin(a) => sin(a) = y / h
//
// and thus
//
// tan(a) * x / w = y / h
//
// which we can rearrange to
//
// tan(a) = (y * w) / (x * h)
//
// And thus, the angle we are looking for is:
//
// a = arctan((y * w) / (x * h))
//
// However, due to tan() being the way it is, we actually need:
let angle = (diff.1 * w).atan2(diff.0 * h);
// Now compute the corresponding point on the ellipse (relative to the center)
let (cx, cy) = (w * angle.cos(), h * angle.sin());
// ...and also compute the actual point
let (x, y) = ((center.0 + cx) as _, (center.1 + cy) as _);
// Return the point that is closer to the center
if distance_squared(center, mouse) < distance_squared(center, (x, y)) {
(mouse.0 as _, mouse.1 as _)
} else {
(x as _, y as _)
}
}
// Compute the position of both pupils.
fn compute_pupils(window_size: (u16, u16), mouse_position: (i16, i16)) -> ((i16, i16), (i16, i16)) {
let border = PUPIL_SIZE + EYE_SIZE;
let half_width = window_size.0 as i16 / 2;
let width = half_width - 2 * border;
let height = window_size.1 as i16 - 2 * border;
(
compute_pupil((border, border, width, height), mouse_position),
compute_pupil((border + half_width, border, width, height), mouse_position),
)
}
fn shape_window<C: Connection>(
conn: &C,
win_id: Window,
window_size: (u16, u16),
) -> Result<(), ReplyOrIdError> {
// Create a pixmap for the shape
let pixmap = PixmapWrapper::create_pixmap(conn, 1, win_id, window_size.0, window_size.1)?;
// Fill the pixmap with what will indicate "transparent"
let gc = create_gc_with_foreground(conn, pixmap.pixmap(), 0)?;
let rect = Rectangle {
x: 0,
y: 0,
width: window_size.0,
height: window_size.1,
};
conn.poly_fill_rectangle(pixmap.pixmap(), gc.gcontext(), &[rect])?;
// Draw the eyes as "not transparent"
let values = ChangeGCAux::new().foreground(1);
conn.change_gc(gc.gcontext(), &values)?;
draw_eyes(
conn,
pixmap.pixmap(),
gc.gcontext(),
gc.gcontext(),
window_size,
)?;
// Set the shape of the window
conn.shape_mask(shape::SO::SET, shape::SK::BOUNDING, win_id, 0, 0, &pixmap)?;
Ok(())
}
fn setup_window<C: Connection>(
conn: &C,
screen: &Screen,
window_size: (u16, u16),
wm_protocols: Atom,
wm_delete_window: Atom,
) -> Result<Window, ReplyOrIdError> {
let win_id = conn.generate_id()?;
let win_aux = CreateWindowAux::new()
.event_mask(EventMask::EXPOSURE | EventMask::STRUCTURE_NOTIFY | EventMask::POINTER_MOTION)
.background_pixel(screen.white_pixel);
conn.create_window(
COPY_DEPTH_FROM_PARENT,
win_id,
screen.root,
0,
0,
window_size.0,
window_size.1,
0,
WindowClass::INPUT_OUTPUT,
0,
&win_aux,
)?;
let title = "xeyes";
conn.change_property8(
PropMode::REPLACE,
win_id,
AtomEnum::WM_NAME,
AtomEnum::STRING,
title.as_bytes(),
)?;
conn.change_property32(
PropMode::REPLACE,
win_id,
wm_protocols,
AtomEnum::ATOM,
&[wm_delete_window],
)?;
conn.map_window(win_id)?;
Ok(win_id)
}
fn create_gc_with_foreground<C: Connection>(
conn: C,
win_id: Window,
foreground: u32,
) -> Result<GcontextWrapper<C>, ReplyOrIdError> {
GcontextWrapper::create_gc(
conn,
win_id,
&CreateGCAux::new()
.graphics_exposures(0)
.foreground(foreground),
)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (conn, screen_num) = connect(None).expect("Failed to connect to the X11 server");
// The following is only needed for start_timeout_thread(), which is used for 'tests'
let conn = std::sync::Arc::new(conn);
let screen = &conn.setup().roots[screen_num];
let wm_protocols = conn.intern_atom(false, b"WM_PROTOCOLS")?;
let wm_delete_window = conn.intern_atom(false, b"WM_DELETE_WINDOW")?;
let mut window_size = (700, 500);
let has_shape = conn
.extension_information(shape::X11_EXTENSION_NAME)
.expect("failed to get extension information")
.is_some();
let (wm_protocols, wm_delete_window) =
(wm_protocols.reply()?.atom, wm_delete_window.reply()?.atom);
let win_id = setup_window(&conn, screen, window_size, wm_protocols, wm_delete_window)?;
let mut pixmap = PixmapWrapper::create_pixmap(
conn.clone(),
screen.root_depth,
win_id,
window_size.0,
window_size.1,
)?;
let black_gc = create_gc_with_foreground(&conn, win_id, screen.black_pixel)?;
let white_gc = create_gc_with_foreground(&conn, win_id, screen.white_pixel)?;
conn.flush()?;
let mut need_repaint = false;
let mut need_reshape = false;
let mut mouse_position = (0, 0);
util::start_timeout_thread(conn.clone(), win_id);
loop {
let event = conn.wait_for_event()?;
let mut event_option = Some(event);
while let Some(event) = event_option {
match event {
Event::Expose(event) => {
if event.count == 0 {
need_repaint = true;
}
}
Event::ConfigureNotify(event) => {
window_size = (event.width, event.height);
pixmap = PixmapWrapper::create_pixmap(
conn.clone(),
screen.root_depth,
win_id,
window_size.0,
window_size.1,
)?;
need_reshape = true;
}
Event::MotionNotify(event) => {
mouse_position = (event.event_x, event.event_y);
need_repaint = true;
}
Event::MapNotify(_) => {
need_reshape = true;
}
Event::ClientMessage(event) => {
let data = event.data.as_data32();
if event.format == 32 && event.window == win_id && data[0] == wm_delete_window {
println!("Window was asked to close");
return Ok(());
}
}
Event::Error(error) => {
println!("Unknown error {error:?}");
}
event => {
println!("Unknown event {event:?}");
}
}
event_option = conn.poll_for_event()?;
}
if need_reshape && has_shape {
shape_window(&conn, win_id, window_size)?;
need_reshape = false;
}
if need_repaint {
// Draw new pupils
let pos = compute_pupils(window_size, mouse_position);
draw_eyes(
&conn,
pixmap.pixmap(),
black_gc.gcontext(),
white_gc.gcontext(),
window_size,
)?;
draw_pupils(&conn, pixmap.pixmap(), black_gc.gcontext(), pos)?;
// Copy drawing from pixmap to window
conn.copy_area(
pixmap.pixmap(),
win_id,
white_gc.gcontext(),
0,
0,
0,
0,
window_size.0,
window_size.1,
)?;
conn.flush()?;
need_repaint = false;
}
}
}
include!("integration_test_util/connect.rs");
include!("integration_test_util/util.rs");

253
vendor/x11rb/src/connection/impls.rs vendored Normal file
View File

@@ -0,0 +1,253 @@
//! Implement RequestConnection for wrappers around other connection types, e.g.
//! `Box<Connection>`.
use std::io::IoSlice;
use x11rb_protocol::x11_utils::{ReplyFDsRequest, ReplyRequest, VoidRequest};
use x11rb_protocol::{DiscardMode, RawEventAndSeqNumber, SequenceNumber};
use crate::connection::{
BufWithFds, Connection, EventAndSeqNumber, ReplyOrError, RequestConnection, RequestKind,
};
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::{ConnectionError, ParseError, ReplyError, ReplyOrIdError};
use crate::protocol::xproto::Setup;
use crate::protocol::Event;
use crate::utils::RawFdContainer;
use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd, X11Error};
macro_rules! impl_deref_request_connection_inner {
() => {
type Buf = C::Buf;
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
(**self)
.send_request_with_reply(bufs, fds)
.map(|cookie| cookie.replace_connection(self))
}
fn send_trait_request_with_reply<R>(
&self,
request: R,
) -> Result<Cookie<'_, Self, <R as ReplyRequest>::Reply>, ConnectionError>
where
R: ReplyRequest,
{
(**self)
.send_trait_request_with_reply(request)
.map(|cookie| cookie.replace_connection(self))
}
fn send_request_with_reply_with_fds<R>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
(**self)
.send_request_with_reply_with_fds(bufs, fds)
.map(|cookie| cookie.replace_connection(self))
}
fn send_trait_request_with_reply_with_fds<R>(
&self,
request: R,
) -> Result<CookieWithFds<'_, Self, R::Reply>, ConnectionError>
where
R: ReplyFDsRequest,
{
(**self)
.send_trait_request_with_reply_with_fds(request)
.map(|cookie| cookie.replace_connection(self))
}
fn send_request_without_reply(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
(**self)
.send_request_without_reply(bufs, fds)
.map(|cookie| cookie.replace_connection(self))
}
fn send_trait_request_without_reply<R>(
&self,
request: R,
) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
R: VoidRequest,
{
(**self)
.send_trait_request_without_reply(request)
.map(|cookie| cookie.replace_connection(self))
}
fn discard_reply(&self, sequence: SequenceNumber, kind: RequestKind, mode: DiscardMode) {
(**self).discard_reply(sequence, kind, mode)
}
fn prefetch_extension_information(
&self,
extension_name: &'static str,
) -> Result<(), ConnectionError> {
(**self).prefetch_extension_information(extension_name)
}
fn extension_information(
&self,
extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
(**self).extension_information(extension_name)
}
fn wait_for_reply_or_error(
&self,
sequence: SequenceNumber,
) -> Result<Self::Buf, ReplyError> {
(**self).wait_for_reply_or_error(sequence)
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<Self::Buf>, ConnectionError> {
(**self).wait_for_reply_or_raw_error(sequence)
}
fn wait_for_reply(
&self,
sequence: SequenceNumber,
) -> Result<Option<Self::Buf>, ConnectionError> {
(**self).wait_for_reply(sequence)
}
fn wait_for_reply_with_fds(
&self,
sequence: SequenceNumber,
) -> Result<BufWithFds<Self::Buf>, ReplyError> {
(**self).wait_for_reply_with_fds(sequence)
}
fn wait_for_reply_with_fds_raw(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Self::Buf>, Self::Buf>, ConnectionError> {
(**self).wait_for_reply_with_fds_raw(sequence)
}
fn check_for_error(&self, sequence: SequenceNumber) -> Result<(), ReplyError> {
(**self).check_for_error(sequence)
}
fn check_for_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<Option<Self::Buf>, ConnectionError> {
(**self).check_for_raw_error(sequence)
}
fn prefetch_maximum_request_bytes(&self) {
(**self).prefetch_maximum_request_bytes()
}
fn maximum_request_bytes(&self) -> usize {
(**self).maximum_request_bytes()
}
fn parse_error(&self, error: &[u8]) -> Result<X11Error, ParseError> {
(**self).parse_error(error)
}
fn parse_event(&self, event: &[u8]) -> Result<Event, ParseError> {
(**self).parse_event(event)
}
};
}
macro_rules! impl_deref_connection_inner {
() => {
fn wait_for_event(&self) -> Result<Event, ConnectionError> {
(**self).wait_for_event()
}
fn wait_for_raw_event(&self) -> Result<Self::Buf, ConnectionError> {
(**self).wait_for_raw_event()
}
fn wait_for_event_with_sequence(&self) -> Result<EventAndSeqNumber, ConnectionError> {
(**self).wait_for_event_with_sequence()
}
fn wait_for_raw_event_with_sequence(
&self,
) -> Result<RawEventAndSeqNumber<Self::Buf>, ConnectionError> {
(**self).wait_for_raw_event_with_sequence()
}
fn poll_for_event(&self) -> Result<Option<Event>, ConnectionError> {
(**self).poll_for_event()
}
fn poll_for_raw_event(&self) -> Result<Option<Self::Buf>, ConnectionError> {
(**self).poll_for_raw_event()
}
fn poll_for_event_with_sequence(
&self,
) -> Result<Option<EventAndSeqNumber>, ConnectionError> {
(**self).poll_for_event_with_sequence()
}
fn poll_for_raw_event_with_sequence(
&self,
) -> Result<Option<RawEventAndSeqNumber<Self::Buf>>, ConnectionError> {
(**self).poll_for_raw_event_with_sequence()
}
fn flush(&self) -> Result<(), ConnectionError> {
(**self).flush()
}
fn setup(&self) -> &Setup {
(**self).setup()
}
fn generate_id(&self) -> Result<u32, ReplyOrIdError> {
(**self).generate_id()
}
};
}
macro_rules! impl_deref_connection {
($type:ty) => {
impl<C: RequestConnection + ?Sized> RequestConnection for $type {
impl_deref_request_connection_inner!();
}
impl<C: Connection + ?Sized> Connection for $type {
impl_deref_connection_inner!();
}
};
}
impl_deref_connection!(&C);
impl_deref_connection!(&mut C);
impl_deref_connection!(Box<C>);
impl_deref_connection!(std::sync::Arc<C>);
impl_deref_connection!(std::rc::Rc<C>);
impl<C: RequestConnection + ToOwned + ?Sized> RequestConnection for std::borrow::Cow<'_, C> {
impl_deref_request_connection_inner!();
}
impl<C: Connection + ToOwned + ?Sized> Connection for std::borrow::Cow<'_, C> {
impl_deref_connection_inner!();
}

610
vendor/x11rb/src/connection/mod.rs vendored Normal file
View File

@@ -0,0 +1,610 @@
//! Generic connection-related types and definitions.
//!
//! This module contains the `Connection` trait and related definitions. The code in this module is
//! used by each concrete implementation of the X11 protocol.
use std::io::IoSlice;
use x11rb_protocol::x11_utils::{ReplyFDsRequest, ReplyRequest, VoidRequest};
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::{ConnectionError, ParseError, ReplyError, ReplyOrIdError};
use crate::protocol::xproto::Setup;
use crate::protocol::Event;
use crate::utils::RawFdContainer;
use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd, X11Error};
pub use x11rb_protocol::{DiscardMode, RawEventAndSeqNumber, SequenceNumber};
mod impls;
// Used to avoid too-complex types.
/// A combination of a buffer and a list of file descriptors.
pub type BufWithFds<B> = (B, Vec<RawFdContainer>);
/// An event and its sequence number.
pub type EventAndSeqNumber = (Event, SequenceNumber);
/// Either a raw reply or a raw error response to an X11 request.
#[derive(Debug)]
pub enum ReplyOrError<R, E = R>
where
R: std::fmt::Debug,
E: AsRef<[u8]> + std::fmt::Debug,
{
/// The reply to an X11 request.
Reply(R),
/// An error caused by an X11 request.
Error(E),
}
/// A connection to an X11 server for sending requests.
///
/// This trait only contains functions that are used by other parts of this library. This means
/// that users of this library will most likely not need these functions, unless they want to
/// implement their own X11 connection.
pub trait RequestConnection {
/// Type used as buffer to store raw replies or events before
/// they are parsed.
type Buf: AsRef<[u8]> + std::fmt::Debug + Send + Sync + 'static;
/// Send a request with a reply to the server.
///
/// The `bufs` parameter describes the raw bytes that should be sent. The returned cookie
/// allows to get the response.
///
/// The `fds` parameter contains a list of file descriptors that should be sent with the
/// request. Ownership of these FDs is transferred to the connection. This means that the
/// connection will close the FDs after they were sent.
///
/// Users of this library will most likely not want to use this function directly. Instead, the
/// generated code will take the supplied arguments, construct byte buffers, and call this
/// method.
///
/// The provided buffers must contain at least a single element and the first buffer must have
/// at least four bytes. The length field must be set correctly, unless the request is larger
/// than 2^18 bytes, because in this case, the length field would overflow. The connection
/// automatically uses the BIG-REQUESTS extension for such large requests.
///
/// In any case, the request may not be larger than the server's maximum request length.
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse;
/// Send a request with a reply to the server.
///
/// This function is a wrapper around [`RequestConnection::send_request_with_reply`]. This
/// function gets a [`ReplyRequest`] as its argument to specify the request to send.
fn send_trait_request_with_reply<R>(
&self,
request: R,
) -> Result<Cookie<'_, Self, <R as ReplyRequest>::Reply>, ConnectionError>
where
R: ReplyRequest,
{
let opcode = match R::EXTENSION_NAME {
None => 0,
Some(extension) => {
self.extension_information(extension)?
.ok_or(ConnectionError::UnsupportedExtension)?
.major_opcode
}
};
let (buf, fds) = request.serialize(opcode);
self.send_request_with_reply(&[IoSlice::new(&buf)], fds)
}
/// Send a request with a reply containing file descriptors to the server.
///
/// The `bufs` parameter describes the raw bytes that should be sent. The returned cookie
/// allows to get the response.
///
/// The `fds` parameter contains a list of file descriptors that should be sent with the
/// request. Ownership of these FDs is transferred to the connection. This means that the
/// connection will close the FDs after they were sent.
///
/// Users of this library will most likely not want to use this function directly. Instead, the
/// generated code will take the supplied arguments, construct byte buffers, and call this
/// method.
///
/// The provided buffers must contain at least a single element and the first buffer must have
/// at least four bytes. The length field must be set correctly, unless the request is larger
/// than 2^18 bytes, because in this case, the length field would overflow. The connection
/// automatically uses the BIG-REQUESTS extension for such large requests.
///
/// In any case, the request may not be larger than the server's maximum request length.
fn send_request_with_reply_with_fds<R>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd;
/// Send a request with a reply containing file descriptors to the server.
///
/// This function is a wrapper around [`RequestConnection::send_request_with_reply_with_fds`].
/// This function gets a [`ReplyFDsRequest`] as its argument to specify the request to send.
fn send_trait_request_with_reply_with_fds<R>(
&self,
request: R,
) -> Result<CookieWithFds<'_, Self, R::Reply>, ConnectionError>
where
R: ReplyFDsRequest,
{
let opcode = match R::EXTENSION_NAME {
None => 0,
Some(extension) => {
self.extension_information(extension)?
.ok_or(ConnectionError::UnsupportedExtension)?
.major_opcode
}
};
let (buf, fds) = request.serialize(opcode);
self.send_request_with_reply_with_fds(&[IoSlice::new(&buf)], fds)
}
/// Send a request without a reply to the server.
///
/// The `bufs` parameter describes the raw bytes that should be sent. The sequence number of
/// the request is returned, but most likely not useful to users.
///
/// The `fds` parameter contains a list of file descriptors that should be sent with the
/// request. Ownership of these FDs is transferred to the connection. This means that the
/// connection will close the FDs after they were sent.
///
/// Users of this library will most likely not want to use this function directly. Instead, the
/// generated code will take the supplied arguments, construct byte buffers, and call this
/// method.
///
/// The provided buffers must contain at least a single element and the first buffer must have
/// at least four bytes. The length field must be set correctly, unless the request is larger
/// than 2^18 bytes, because in this case, the length field would overflow. The connection
/// automatically uses the BIG-REQUESTS extension for such large requests.
///
/// In any case, the request may not be larger than the server's maximum request length.
fn send_request_without_reply(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError>;
/// Send a request without a reply to the server.
///
/// This function is a wrapper around [`RequestConnection::send_request_without_reply`]. This
/// function gets a [`VoidRequest`] as its argument to specify the request to send.
fn send_trait_request_without_reply<R>(
&self,
request: R,
) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
R: VoidRequest,
{
let opcode = match R::EXTENSION_NAME {
None => 0,
Some(extension) => {
self.extension_information(extension)?
.ok_or(ConnectionError::UnsupportedExtension)?
.major_opcode
}
};
let (buf, fds) = request.serialize(opcode);
self.send_request_without_reply(&[IoSlice::new(&buf)], fds)
}
/// A reply to an error should be discarded.
///
/// This method is automatically called by the `Drop` implementation on `Cookie` so that any
/// replies that are received later can be ignored.
///
/// Users of this library will most likely not want to use this function directly.
fn discard_reply(&self, sequence: SequenceNumber, kind: RequestKind, mode: DiscardMode);
/// Prefetches information about an extension.
///
/// If the information of a extension is not cached yet, this function sends a
/// `QueryExtension` request, but it does not wait for the reply.
///
/// You can use `extension_information()` to get the reply of such request.
///
/// Using this function can help to reduce round-trip latency, but you can use
/// `extension_information()` directly without calling this function first.
fn prefetch_extension_information(
&self,
extension_name: &'static str,
) -> Result<(), ConnectionError>;
/// Get information about an extension.
///
/// To send a request for some extension, information about the extension (major opcode,
/// first event code and first error code) is necessary. This function provides this
/// information.
///
/// The returned object is guaranteed to have a non-zero `present` field. Extensions that are
/// not present are instead returned as `None`.
fn extension_information(
&self,
extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError>;
/// Wait for the reply to a request.
///
/// The given sequence number identifies the request for which replies are expected. If the X11
/// server answered the request with an error, that error is returned as an `Err`.
///
/// Users of this library will most likely not want to use this function directly.
fn wait_for_reply_or_error(&self, sequence: SequenceNumber) -> Result<Self::Buf, ReplyError> {
match self.wait_for_reply_or_raw_error(sequence)? {
ReplyOrError::Reply(reply) => Ok(reply),
ReplyOrError::Error(error) => {
Err(ReplyError::X11Error(self.parse_error(error.as_ref())?))
}
}
}
/// Wait for the reply to a request.
///
/// The given sequence number identifies the request for which replies are expected. If the X11
/// server answered the request with an error, that error is returned as an `Err`.
///
/// Users of this library will most likely not want to use this function directly.
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<Self::Buf>, ConnectionError>;
/// Wait for the reply to a request.
///
/// The given sequence number identifies the request for which replies are expected. If the X11
/// server answered the request with an error, this function returns `None` and the error is
/// instead returned by `wait_for_event()` or `poll_for_event()`.
///
/// Users of this library will most likely not want to use this function directly.
fn wait_for_reply(
&self,
sequence: SequenceNumber,
) -> Result<Option<Self::Buf>, ConnectionError>;
/// Wait for the reply to a request that has FDs.
///
/// The given sequence number identifies the request for which replies are expected.
///
/// Users of this library will most likely not want to use this function directly.
fn wait_for_reply_with_fds(
&self,
sequence: SequenceNumber,
) -> Result<BufWithFds<Self::Buf>, ReplyError> {
match self.wait_for_reply_with_fds_raw(sequence)? {
ReplyOrError::Reply(reply) => Ok(reply),
ReplyOrError::Error(error) => {
Err(ReplyError::X11Error(self.parse_error(error.as_ref())?))
}
}
}
/// Wait for the reply to a request that has FDs.
///
/// The given sequence number identifies the request for which replies are expected.
///
/// Users of this library will most likely not want to use this function directly.
fn wait_for_reply_with_fds_raw(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Self::Buf>, Self::Buf>, ConnectionError>;
/// Check whether a request that does not have a reply caused an X11 error.
///
/// The given sequence number identifies the request for which the check should be performed.
///
/// Users of this library will most likely not want to use this function directly.
fn check_for_error(&self, sequence: SequenceNumber) -> Result<(), ReplyError> {
match self.check_for_raw_error(sequence)? {
Some(err) => Err(self.parse_error(err.as_ref())?.into()),
None => Ok(()),
}
}
/// Check whether a request that does not have a reply caused an X11 error.
///
/// The given sequence number identifies the request for which the check should be performed.
///
/// Users of this library will most likely not want to use this function directly.
fn check_for_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<Option<Self::Buf>, ConnectionError>;
/// Prefetches the maximum request length.
///
/// If the maximum request length is not cached yet, this function sends a `BigRequests::Enable`
/// request, but it does not wait for the reply.
///
/// You can use `maximum_request_bytes()` to get the result of this request.
///
/// Using this function can help to reduce round-trip latency, but you can use
/// `maximum_request_bytes()` directly without calling this function first.
///
/// Since this uses the `BigRequests` extension, the information about that extension needs to
/// available. Otherwise, this has to wait for the reply when calling
/// `extension_information()`.
///
/// To prefetch the necessary information, you can do the following:
/// ```no_run
/// use x11rb::connection::RequestConnection;
/// use x11rb::errors::ConnectionError;
/// use x11rb::protocol::bigreq;
/// # fn do_it(conn: impl RequestConnection) -> Result<(), ConnectionError> {
/// // conn is a RequestConnection
/// conn.prefetch_extension_information(bigreq::X11_EXTENSION_NAME)?;
/// # Ok(())
/// # }
/// ```
fn prefetch_maximum_request_bytes(&self);
/// The maximum number of bytes that the X11 server accepts in a request.
fn maximum_request_bytes(&self) -> usize;
/// Parse a generic error.
fn parse_error(&self, error: &[u8]) -> Result<X11Error, ParseError>;
/// Parse a generic event.
fn parse_event(&self, event: &[u8]) -> Result<Event, ParseError>;
}
/// A connection to an X11 server.
pub trait Connection: RequestConnection {
/// Wait for a new event from the X11 server.
fn wait_for_event(&self) -> Result<Event, ConnectionError> {
Ok(self.wait_for_event_with_sequence()?.0)
}
/// Wait for a new raw/unparsed event from the X11 server.
fn wait_for_raw_event(&self) -> Result<Self::Buf, ConnectionError> {
Ok(self.wait_for_raw_event_with_sequence()?.0)
}
/// Wait for a new event from the X11 server.
fn wait_for_event_with_sequence(&self) -> Result<EventAndSeqNumber, ConnectionError> {
let (event, seq) = self.wait_for_raw_event_with_sequence()?;
let event = self.parse_event(event.as_ref())?;
Ok((event, seq))
}
/// Wait for a new raw/unparsed event from the X11 server.
fn wait_for_raw_event_with_sequence(
&self,
) -> Result<RawEventAndSeqNumber<Self::Buf>, ConnectionError>;
/// Poll for a new event from the X11 server.
fn poll_for_event(&self) -> Result<Option<Event>, ConnectionError> {
Ok(self.poll_for_event_with_sequence()?.map(|r| r.0))
}
/// Poll for a new raw/unparsed event from the X11 server.
fn poll_for_raw_event(&self) -> Result<Option<Self::Buf>, ConnectionError> {
Ok(self.poll_for_raw_event_with_sequence()?.map(|r| r.0))
}
/// Poll for a new event from the X11 server.
fn poll_for_event_with_sequence(&self) -> Result<Option<EventAndSeqNumber>, ConnectionError> {
Ok(match self.poll_for_raw_event_with_sequence()? {
Some((event, seq)) => Some((self.parse_event(event.as_ref())?, seq)),
None => None,
})
}
/// Poll for a new unparsed/raw event from the X11 server.
fn poll_for_raw_event_with_sequence(
&self,
) -> Result<Option<RawEventAndSeqNumber<Self::Buf>>, ConnectionError>;
/// Send all pending requests to the server.
///
/// Implementations of this trait may buffer requests for batched sending. When this method is
/// called, all pending requests are sent.
///
/// You do not have to call this method before `wait_for_reply()`. If the request you want to
/// wait for was not yet sent, it will be sent by `wait_for_reply()`.
fn flush(&self) -> Result<(), ConnectionError>;
/// Get the setup information sent by the X11 server.
///
/// The setup information contains X11 server, for example the window id of the root window.
fn setup(&self) -> &Setup;
/// Generate a new X11 identifier.
///
/// This method can, for example, be used for creating a new window. First, this method is
/// called to generate an identifier. Next, `xproto::create_window` can be called to
/// actually create the window.
fn generate_id(&self) -> Result<u32, ReplyOrIdError>;
}
/// Does a request have a response?
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum RequestKind {
/// The request has no response, i.e. its type is "void".
IsVoid,
/// The request has a response.
HasResponse,
}
/// Check the request length and use BIG-REQUESTS if necessary.
///
/// Users of this library will most likely not want to use this function directly.
///
/// This function is used by implementations of `RequestConnection` for sending requests. It
/// examines the given request buffers and checks that the length field is set correctly.
///
/// If the request has more than 2^18 bytes, this function handles using the BIG-REQUESTS
/// extension. The request is rewritten to include the correct length field. For this case, the
/// `storage` parameter is needed. This function uses it to store the necessary buffers.
///
/// When using this function, it is recommended to allocate the `storage` parameter with
/// `Default::default()`.
///
/// Example usage:
/// ```
/// use std::io::IoSlice;
/// use x11rb::connection::{BufWithFds, RequestConnection, compute_length_field};
/// use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie};
/// use x11rb::errors::{ParseError, ConnectionError};
/// use x11rb::utils::RawFdContainer;
/// use x11rb::x11_utils::{ExtensionInformation, TryParse, TryParseFd};
/// use x11rb_protocol::SequenceNumber;
/// # use x11rb::connection::ReplyOrError;
///
/// struct MyConnection();
///
/// impl RequestConnection for MyConnection {
/// type Buf = Vec<u8>;
///
/// // [snip, other functions here]
/// # fn discard_reply(&self, sequence: SequenceNumber,
/// # kind: x11rb::connection::RequestKind,
/// # mode: x11rb_protocol::DiscardMode) {
/// # unimplemented!()
/// # }
/// # fn prefetch_extension_information(
/// # &self,
/// # extension_name: &'static str,
/// # ) -> Result<(), ConnectionError> {
/// # unimplemented!()
/// # }
/// # fn extension_information(&self, ext: &'static str)
/// # -> Result<Option<ExtensionInformation>, ConnectionError> {
/// # unimplemented!()
/// # }
/// # fn wait_for_reply_or_raw_error(&self, sequence: SequenceNumber)
/// # -> Result<ReplyOrError<Vec<u8>>, ConnectionError> {
/// # unimplemented!()
/// # }
/// # fn wait_for_reply(&self, sequence: SequenceNumber)
/// # -> Result<Option<Vec<u8>>, x11rb::errors::ConnectionError> {
/// # unimplemented!()
/// # }
/// # fn wait_for_reply_with_fds_raw(&self, sequence: SequenceNumber)
/// # -> Result<ReplyOrError<BufWithFds<Vec<u8>>, Vec<u8>>, ConnectionError> {
/// # unimplemented!()
/// # }
/// # fn check_for_raw_error(&self, sequence: SequenceNumber)
/// # ->Result<Option<Vec<u8>>, ConnectionError> {
/// # unimplemented!()
/// # }
/// # fn maximum_request_bytes(&self) -> usize {
/// # unimplemented!()
/// # }
/// # fn prefetch_maximum_request_bytes(&self) {
/// # unimplemented!()
/// # }
/// # fn parse_error(&self, _error: &[u8]) -> Result<x11rb::x11_utils::X11Error, ParseError> {
/// # unimplemented!()
/// # }
/// # fn parse_event(&self, _event: &[u8]) -> Result<x11rb::protocol::Event, ParseError> {
/// # unimplemented!()
/// # }
///
/// fn send_request_with_reply<R>(&self, bufs: &[IoSlice], fds: Vec<RawFdContainer>)
/// -> Result<Cookie<Self, R>, ConnectionError>
/// where R: TryParse {
/// Ok(Cookie::new(self, self.send_request(bufs, fds, true, false)?))
/// }
///
/// fn send_request_with_reply_with_fds<R>(&self, bufs: &[IoSlice], fds: Vec<RawFdContainer>)
/// -> Result<CookieWithFds<Self, R>, ConnectionError>
/// where R: TryParseFd {
/// Ok(CookieWithFds::new(self, self.send_request(bufs, fds, true, true)?))
/// }
///
/// fn send_request_without_reply(&self, bufs: &[IoSlice], fds: Vec<RawFdContainer>)
/// -> Result<VoidCookie<Self>, ConnectionError> {
/// Ok(VoidCookie::new(self, self.send_request(bufs, fds, false, false)?))
/// }
/// }
///
/// impl MyConnection {
/// fn send_request(&self, bufs: &[IoSlice], fds: Vec<RawFdContainer>,
/// has_reply: bool, reply_has_fds: bool)
/// -> Result<SequenceNumber, ConnectionError>
/// {
/// let mut storage = Default::default();
/// let bufs = compute_length_field(self, bufs, &mut storage)?;
/// unimplemented!("Now send bufs and fds to the X11 server");
/// }
/// }
/// ```
pub fn compute_length_field<'b>(
conn: &impl RequestConnection,
request_buffers: &'b [IoSlice<'b>],
storage: &'b mut (Vec<IoSlice<'b>>, [u8; 8]),
) -> Result<&'b [IoSlice<'b>], ConnectionError> {
// Compute the total length of the request
let length: usize = request_buffers.iter().map(|buf| buf.len()).sum();
assert_eq!(
length % 4,
0,
"The length of X11 requests must be a multiple of 4, got {length}"
);
let wire_length = length / 4;
let first_buf = &request_buffers[0];
// If the length fits into an u16, just return the request as-is
if let Ok(wire_length) = u16::try_from(wire_length) {
// Check that the request contains the correct length field
let length_field = u16::from_ne_bytes([first_buf[2], first_buf[3]]);
assert_eq!(
wire_length, length_field,
"Length field contains incorrect value"
);
return Ok(request_buffers);
}
// Check that the total length is not too large
if length > conn.maximum_request_bytes() {
return Err(ConnectionError::MaximumRequestLengthExceeded);
}
// Okay, we need to use big requests (thus four extra bytes, "+1" below)
let wire_length: u32 = wire_length
.checked_add(1)
.ok_or(ConnectionError::MaximumRequestLengthExceeded)?
.try_into()
.expect("X11 request larger than 2^34 bytes?!?");
let wire_length = wire_length.to_ne_bytes();
// Now construct the new IoSlices
// Replacement for the first four bytes of the request
storage.1.copy_from_slice(&[
// First part of the request
first_buf[0],
first_buf[1],
// length field zero indicates big requests
0,
0,
// New bytes: extended length
wire_length[0],
wire_length[1],
wire_length[2],
wire_length[3],
]);
storage.0.push(IoSlice::new(&storage.1));
// The remaining part of the first buffer of the request
storage.0.push(IoSlice::new(&first_buf[4..]));
// and the rest of the request
storage.0.extend(
request_buffers[1..]
.iter()
.map(std::ops::Deref::deref)
.map(IoSlice::new),
);
Ok(&storage.0[..])
}

464
vendor/x11rb/src/cookie.rs vendored Normal file
View File

@@ -0,0 +1,464 @@
//! Cookies are handles to future replies or errors from the X11 server.
//!
//! When sending a request, you get back a cookie. There are different cookies for different
//! kinds of requests.
//!
//! For requests without a reply, you get a [`VoidCookie`]. Requests with a reply are represented
//! by a [`Cookie`] or a [`CookieWithFds`] if the reply also contains file descriptors.
//! Additionally, there are two special cases for requests which generate more than one reply:
//! [`ListFontsWithInfoCookie`] and [`RecordEnableContextCookie`].
//!
//! # Handling X11 errors
//!
//! The X11 server can answer requests with an error packet for various reasons, e.g. because an
//! invalid window ID was given. There are three options what can be done with errors:
//!
//! - Errors can appear as X11 events in `wait_for_event()` (in XCB, this is called "unchecked")
//! - Errors can be checked for locally after a request was sent (in XCB, this is called "checked")
//! - Errors can be completely ignored (the closest analog in XCB would be `xcb_discard_reply()`)
//!
//! There is an additional difference between requests with and without replies.
//!
//! ## Requests without a reply
//!
//! For requests that do not have a reply, you get an instance of `VoidCookie` after sending the
//! request. The different behaviors can be achieved via interacting with this cookie as foolows:
//!
//! | What? | How? |
//! | --------------- | -------------------------- |
//! | Treat as events | Just drop the cookie |
//! | Check locally | `VoidCookie::check` |
//! | Ignore | `VoidCookie::ignore_error` |
//!
//! ## Requests with a reply
//!
//! For requests with a reply, an additional option is what should happen to the reply. You can get
//! the reply, but any errors are still treated as events. This allows to centralise X11 error
//! handling a bit in case you only want to log errors.
//!
//! The following things can be done with the `Cookie` that you get after sending a request with an
//! error.
//!
//! | Reply | Errors locally/ignored | Errors as events |
//! | ------ | ---------------------------------- | ------------------------- |
//! | Get | `Cookie::reply` | `Cookie::reply_unchecked` |
//! | Ignore | `Cookie::discard_reply_and_errors` | Just drop the cookie |
use std::marker::PhantomData;
use crate::connection::{BufWithFds, RequestConnection, RequestKind};
use crate::errors::{ConnectionError, ReplyError};
#[cfg(feature = "record")]
use crate::protocol::record::EnableContextReply;
use crate::protocol::xproto::ListFontsWithInfoReply;
use crate::x11_utils::{TryParse, TryParseFd};
use x11rb_protocol::{DiscardMode, SequenceNumber};
/// A handle to a possible error from the X11 server.
///
/// When sending a request for which no reply is expected, this library returns a `VoidCookie`.
/// This `VoidCookie` can then later be used to check if the X11 server sent an error.
///
/// See [crate::cookie#requests-without-a-reply] for infos on the different ways to handle X11
/// errors in response to a request.
#[derive(Debug)]
pub struct VoidCookie<'a, C>
where
C: RequestConnection + ?Sized,
{
connection: &'a C,
sequence_number: SequenceNumber,
}
impl<'a, C> VoidCookie<'a, C>
where
C: RequestConnection + ?Sized,
{
/// Construct a new cookie.
///
/// This function should only be used by implementations of
/// `Connection::send_request_without_reply`.
pub fn new(connection: &C, sequence_number: SequenceNumber) -> VoidCookie<'_, C> {
VoidCookie {
connection,
sequence_number,
}
}
/// Get the sequence number of the request that generated this cookie.
pub fn sequence_number(&self) -> SequenceNumber {
self.sequence_number
}
fn consume(self) -> (&'a C, SequenceNumber) {
let result = (self.connection, self.sequence_number);
std::mem::forget(self);
result
}
/// Check if the original request caused an X11 error.
pub fn check(self) -> Result<(), ReplyError> {
let (connection, sequence) = self.consume();
connection.check_for_error(sequence)
}
/// Ignore all errors to this request.
///
/// Without calling this method, an error becomes available on the connection as an event after
/// this cookie was dropped. This function causes errors to be ignored instead.
pub fn ignore_error(self) {
let (connection, sequence) = self.consume();
connection.discard_reply(
sequence,
RequestKind::IsVoid,
DiscardMode::DiscardReplyAndError,
)
}
/// Move this cookie to refer to another connection instance.
///
/// This function may only be used if both connections are "basically the same". For example, a
/// Cookie for a connection `C` can be moved to `Rc<C>` since that still refers to the same
/// underlying connection.
pub(crate) fn replace_connection<C2: RequestConnection + ?Sized>(
self,
connection: &C2,
) -> VoidCookie<'_, C2> {
let (_, sequence_number) = self.consume();
VoidCookie {
connection,
sequence_number,
}
}
}
impl<C> Drop for VoidCookie<'_, C>
where
C: RequestConnection + ?Sized,
{
fn drop(&mut self) {
self.connection.discard_reply(
self.sequence_number,
RequestKind::IsVoid,
DiscardMode::DiscardReply,
)
}
}
/// Internal helper for a cookie with an response
#[derive(Debug)]
struct RawCookie<'a, C>
where
C: RequestConnection + ?Sized,
{
connection: &'a C,
sequence_number: SequenceNumber,
}
impl<C> RawCookie<'_, C>
where
C: RequestConnection + ?Sized,
{
/// Construct a new raw cookie.
///
/// This function should only be used by implementations of
/// `RequestConnection::send_request_with_reply`.
fn new(connection: &C, sequence_number: SequenceNumber) -> RawCookie<'_, C> {
RawCookie {
connection,
sequence_number,
}
}
/// Consume this instance and get the contained sequence number out.
fn into_sequence_number(self) -> SequenceNumber {
let number = self.sequence_number;
// Prevent drop() from running
std::mem::forget(self);
number
}
/// Move this cookie to refer to another connection instance.
///
/// This function may only be used if both connections are "basically the same". For example, a
/// Cookie for a connection `C` can be moved to `Rc<C>` since that still refers to the same
/// underlying connection.
fn replace_connection<C2: RequestConnection + ?Sized>(
self,
connection: &C2,
) -> RawCookie<'_, C2> {
RawCookie {
connection,
sequence_number: self.into_sequence_number(),
}
}
}
impl<C> Drop for RawCookie<'_, C>
where
C: RequestConnection + ?Sized,
{
fn drop(&mut self) {
self.connection.discard_reply(
self.sequence_number,
RequestKind::HasResponse,
DiscardMode::DiscardReply,
);
}
}
/// A handle to a response from the X11 server.
///
/// When sending a request to the X11 server, this library returns a `Cookie`. This `Cookie` can
/// then later be used to get the response that the server sent.
///
/// See [crate::cookie#requests-with-a-reply] for infos on the different ways to handle X11
/// errors in response to a request.
#[derive(Debug)]
pub struct Cookie<'a, C, R>
where
C: RequestConnection + ?Sized,
{
raw_cookie: RawCookie<'a, C>,
phantom: PhantomData<R>,
}
impl<C, R> Cookie<'_, C, R>
where
R: TryParse,
C: RequestConnection + ?Sized,
{
/// Construct a new cookie.
///
/// This function should only be used by implementations of
/// `RequestConnection::send_request_with_reply`.
pub fn new(connection: &C, sequence_number: SequenceNumber) -> Cookie<'_, C, R> {
Cookie {
raw_cookie: RawCookie::new(connection, sequence_number),
phantom: PhantomData,
}
}
/// Get the sequence number of the request that generated this cookie.
pub fn sequence_number(&self) -> SequenceNumber {
self.raw_cookie.sequence_number
}
/// Get the raw reply that the server sent.
pub fn raw_reply(self) -> Result<C::Buf, ReplyError> {
let conn = self.raw_cookie.connection;
conn.wait_for_reply_or_error(self.raw_cookie.into_sequence_number())
}
/// Get the raw reply that the server sent, but have errors handled as events.
pub fn raw_reply_unchecked(self) -> Result<Option<C::Buf>, ConnectionError> {
let conn = self.raw_cookie.connection;
conn.wait_for_reply(self.raw_cookie.into_sequence_number())
}
/// Get the reply that the server sent.
pub fn reply(self) -> Result<R, ReplyError> {
Ok(R::try_parse(self.raw_reply()?.as_ref())?.0)
}
/// Get the reply that the server sent, but have errors handled as events.
pub fn reply_unchecked(self) -> Result<Option<R>, ConnectionError> {
self.raw_reply_unchecked()?
.map(|buf| R::try_parse(buf.as_ref()).map(|r| r.0))
.transpose()
.map_err(Into::into)
}
/// Discard all responses to the request this cookie represents, even errors.
///
/// Without this function, errors are treated as events after the cookie is dropped.
pub fn discard_reply_and_errors(self) {
let conn = self.raw_cookie.connection;
conn.discard_reply(
self.raw_cookie.into_sequence_number(),
RequestKind::HasResponse,
DiscardMode::DiscardReplyAndError,
)
}
/// Consume this instance and get the contained sequence number out.
pub(crate) fn into_sequence_number(self) -> SequenceNumber {
self.raw_cookie.into_sequence_number()
}
/// Move this cookie to refer to another connection instance.
///
/// This function may only be used if both connections are "basically the same". For example, a
/// Cookie for a connection `C` can be moved to `Rc<C>` since that still refers to the same
/// underlying connection.
pub(crate) fn replace_connection<C2: RequestConnection + ?Sized>(
self,
connection: &C2,
) -> Cookie<'_, C2, R> {
Cookie {
raw_cookie: self.raw_cookie.replace_connection(connection),
phantom: PhantomData,
}
}
}
/// A handle to a response containing `RawFd` from the X11 server.
///
/// When sending a request to the X11 server, this library returns a `Cookie`. This `Cookie` can
/// then later be used to get the response that the server sent.
///
/// This variant of `Cookie` represents a response that can contain `RawFd`s.
///
/// See [crate::cookie#requests-with-a-reply] for infos on the different ways to handle X11
/// errors in response to a request.
#[derive(Debug)]
pub struct CookieWithFds<'a, C, R>
where
C: RequestConnection + ?Sized,
{
raw_cookie: RawCookie<'a, C>,
phantom: PhantomData<R>,
}
impl<C, R> CookieWithFds<'_, C, R>
where
R: TryParseFd,
C: RequestConnection + ?Sized,
{
/// Construct a new cookie.
///
/// This function should only be used by implementations of
/// `RequestConnection::send_request_with_reply`.
pub fn new(connection: &C, sequence_number: SequenceNumber) -> CookieWithFds<'_, C, R> {
CookieWithFds {
raw_cookie: RawCookie::new(connection, sequence_number),
phantom: PhantomData,
}
}
/// Get the sequence number of the request that generated this cookie.
pub fn sequence_number(&self) -> SequenceNumber {
self.raw_cookie.sequence_number
}
/// Get the raw reply that the server sent.
pub fn raw_reply(self) -> Result<BufWithFds<C::Buf>, ReplyError> {
let conn = self.raw_cookie.connection;
conn.wait_for_reply_with_fds(self.raw_cookie.into_sequence_number())
}
/// Get the reply that the server sent.
pub fn reply(self) -> Result<R, ReplyError> {
let (buffer, mut fds) = self.raw_reply()?;
Ok(R::try_parse_fd(buffer.as_ref(), &mut fds)?.0)
}
/// Move this cookie to refer to another connection instance.
///
/// This function may only be used if both connections are "basically the same". For example, a
/// Cookie for a connection `C` can be moved to `Rc<C>` since that still refers to the same
/// underlying connection.
pub(crate) fn replace_connection<C2: RequestConnection + ?Sized>(
self,
connection: &C2,
) -> CookieWithFds<'_, C2, R> {
CookieWithFds {
raw_cookie: self.raw_cookie.replace_connection(connection),
phantom: PhantomData,
}
}
}
macro_rules! multiple_reply_cookie {
(
$(#[$meta:meta])*
pub struct $name:ident for $reply:ident
) => {
$(#[$meta])*
#[derive(Debug)]
pub struct $name<'a, C: RequestConnection + ?Sized>(Option<RawCookie<'a, C>>);
impl<'c, C> $name<'c, C>
where
C: RequestConnection + ?Sized,
{
pub(crate) fn new(
cookie: Cookie<'c, C, $reply>,
) -> Self {
Self(Some(cookie.raw_cookie))
}
/// Get the sequence number of the request that generated this cookie.
pub fn sequence_number(&self) -> Option<SequenceNumber> {
self.0.as_ref().map(|x| x.sequence_number)
}
}
impl<C> Iterator for $name<'_, C>
where
C: RequestConnection + ?Sized,
{
type Item = Result<$reply, ReplyError>;
fn next(&mut self) -> Option<Self::Item> {
let cookie = self.0.take()?;
let reply = cookie
.connection
.wait_for_reply_or_error(cookie.sequence_number);
let reply = match reply {
Err(e) => return Some(Err(e)),
Ok(v) => v,
};
let reply = $reply::try_parse(reply.as_ref());
match reply {
// Is this an indicator that no more replies follow?
Ok(ref reply) if Self::is_last(&reply.0) => None,
Ok(reply) => {
self.0 = Some(cookie);
Some(Ok(reply.0))
}
Err(e) => Some(Err(e.into())),
}
}
}
}
}
multiple_reply_cookie!(
/// A handle to the replies to a `ListFontsWithInfo` request.
///
/// `ListFontsWithInfo` generated more than one reply, but `Cookie` only allows getting one reply.
/// This structure implements `Iterator` and allows to get all the replies.
pub struct ListFontsWithInfoCookie for ListFontsWithInfoReply
);
impl<C> ListFontsWithInfoCookie<'_, C>
where
C: RequestConnection + ?Sized,
{
fn is_last(reply: &ListFontsWithInfoReply) -> bool {
reply.name.is_empty()
}
}
#[cfg(feature = "record")]
multiple_reply_cookie!(
/// A handle to the replies to a `record::EnableContext` request.
///
/// `EnableContext` generated more than one reply, but `Cookie` only allows getting one reply.
/// This structure implements `Iterator` and allows to get all the replies.
pub struct RecordEnableContextCookie for EnableContextReply
);
#[cfg(feature = "record")]
impl<C> RecordEnableContextCookie<'_, C>
where
C: RequestConnection + ?Sized,
{
fn is_last(reply: &EnableContextReply) -> bool {
// FIXME: There does not seem to be an enumeration of the category values, (value 5 is
// EndOfData)
reply.category == 5
}
}

136
vendor/x11rb/src/cursor/find_cursor.rs vendored Normal file
View File

@@ -0,0 +1,136 @@
//! Find the right cursor file from a cursor name
// Based on libxcb-cursor's load_cursor.c which has:
//
// Copyright © 2013 Michael Stapelberg
// Copyright © 2002 Keith Packard
//
// and is licensed under MIT/X Consortium License
use std::fs::File;
use xcursor::CursorTheme;
static CORE_CURSORS: &[(&str, u16)] = &[
("X_cursor", 0),
("arrow", 1),
("based_arrow_down", 2),
("based_arrow_up", 3),
("boat", 4),
("bogosity", 5),
("bottom_left_corner", 6),
("bottom_right_corner", 7),
("bottom_side", 8),
("bottom_tee", 9),
("box_spiral", 10),
("center_ptr", 11),
("circle", 12),
("clock", 13),
("coffee_mug", 14),
("cross", 15),
("cross_reverse", 16),
("crosshair", 17),
("diamond_cross", 18),
("dot", 19),
("dotbox", 20),
("double_arrow", 21),
("draft_large", 22),
("draft_small", 23),
("draped_box", 24),
("exchange", 25),
("fleur", 26),
("gobbler", 27),
("gumby", 28),
("hand1", 29),
("hand2", 30),
("heart", 31),
("icon", 32),
("iron_cross", 33),
("left_ptr", 34),
("left_side", 35),
("left_tee", 36),
("leftbutton", 37),
("ll_angle", 38),
("lr_angle", 39),
("man", 40),
("middlebutton", 41),
("mouse", 42),
("pencil", 43),
("pirate", 44),
("plus", 45),
("question_arrow", 46),
("right_ptr", 47),
("right_side", 48),
("right_tee", 49),
("rightbutton", 50),
("rtl_logo", 51),
("sailboat", 52),
("sb_down_arrow", 53),
("sb_h_double_arrow", 54),
("sb_left_arrow", 55),
("sb_right_arrow", 56),
("sb_up_arrow", 57),
("sb_v_double_arrow", 58),
("shuttle", 59),
("sizing", 60),
("spider", 61),
("spraycan", 62),
("star", 63),
("target", 64),
("tcross", 65),
("top_left_arrow", 66),
("top_left_corner", 67),
("top_right_corner", 68),
("top_side", 69),
("top_tee", 70),
("trek", 71),
("ul_angle", 72),
("umbrella", 73),
("ur_angle", 74),
("watch", 75),
("xterm", 76),
];
/// Find a core cursor based on its name
///
/// This function checks a built-in list of known names.
fn cursor_shape_to_id(name: &str) -> Option<u16> {
CORE_CURSORS
.iter()
.find(|&(name2, _)| name == *name2)
.map(|&(_, id)| id)
}
#[cfg(test)]
mod test_cursor_shape_to_id {
use super::cursor_shape_to_id;
#[test]
fn test_cursor_shape_to_id() {
assert_eq!(cursor_shape_to_id("heart"), Some(31));
}
}
/// The result of finding a cursor
#[derive(Debug)]
pub(crate) enum Cursor {
/// The cursor is a core cursor that can be created with xproto's `CreateGlyphCursor`
CoreChar(u16),
/// A cursor file was opened
File(File),
}
/// Find a cursor file based on the name of a cursor theme and the name of the cursor.
pub(crate) fn find_cursor(theme: &str, name: &str) -> Option<Cursor> {
if theme == "core" {
if let Some(id) = cursor_shape_to_id(name) {
return Some(Cursor::CoreChar(id));
}
}
if let Some(path) = CursorTheme::load(theme).load_icon(name) {
if let Ok(file) = File::open(path) {
return Some(Cursor::File(file));
}
}
None
}

357
vendor/x11rb/src/cursor/mod.rs vendored Normal file
View File

@@ -0,0 +1,357 @@
//! Utility functions for working with X11 cursors
//!
//! The code in this module is only available when the `cursor` feature of the library is enabled.
use crate::connection::Connection;
use crate::cookie::Cookie as X11Cookie;
use crate::errors::{ConnectionError, ReplyOrIdError};
use crate::protocol::render::{self, Pictformat};
use crate::protocol::xproto::{self, FontWrapper, Window};
use crate::resource_manager::Database;
use crate::NONE;
use xcursor::parser::Image;
mod find_cursor;
mod parse_cursor;
/// The level of cursor support of the X11 server
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum RenderSupport {
/// Render extension not available
None,
/// Static cursor support (CreateCursor added in RENDER 0.5)
StaticCursor,
/// Animated cursor support (CreateAnimCursor added in RENDER 0.8)
AnimatedCursor,
}
/// A cookie for creating a `Handle`
#[derive(Debug)]
pub struct Cookie<'a, 'b, C: Connection> {
screen: &'a xproto::Screen,
resource_database: &'b Database,
render_info: Option<(
X11Cookie<'a, C, render::QueryVersionReply>,
X11Cookie<'a, C, render::QueryPictFormatsReply>,
)>,
}
impl<C: Connection> Cookie<'_, '_, C> {
/// Get the handle from the replies from the X11 server
pub fn reply(self) -> Result<Handle, ReplyOrIdError> {
let mut render_version = (0, 0);
let mut picture_format = NONE;
if let Some((version, formats)) = self.render_info {
let version = version.reply()?;
render_version = (version.major_version, version.minor_version);
picture_format = find_format(&formats.reply()?);
}
Self::from_replies(
self.screen,
self.resource_database,
render_version,
picture_format,
)
}
/// Get the handle from the replies from the X11 server
pub fn reply_unchecked(self) -> Result<Option<Handle>, ReplyOrIdError> {
let mut render_version = (0, 0);
let mut picture_format = NONE;
if let Some((version, formats)) = self.render_info {
match (version.reply_unchecked()?, formats.reply_unchecked()?) {
(Some(version), Some(formats)) => {
render_version = (version.major_version, version.minor_version);
picture_format = find_format(&formats);
}
_ => return Ok(None),
}
}
Ok(Some(Self::from_replies(
self.screen,
self.resource_database,
render_version,
picture_format,
)?))
}
fn from_replies(
screen: &xproto::Screen,
resource_database: &Database,
render_version: (u32, u32),
picture_format: Pictformat,
) -> Result<Handle, ReplyOrIdError> {
let render_support = if render_version.0 >= 1 || render_version.1 >= 8 {
RenderSupport::AnimatedCursor
} else if render_version.0 >= 1 || render_version.1 >= 5 {
RenderSupport::StaticCursor
} else {
RenderSupport::None
};
let theme = std::env::var("XCURSOR_THEME").ok().or_else(|| {
resource_database
.get_string("Xcursor.theme", "")
.map(|theme| theme.to_string())
});
let cursor_size = match resource_database.get_value("Xcursor.size", "") {
Ok(Some(value)) => value,
_ => 0,
};
let xft_dpi = match resource_database.get_value("Xft.dpi", "") {
Ok(Some(value)) => value,
_ => 0,
};
let cursor_size = get_cursor_size(cursor_size, xft_dpi, screen);
Ok(Handle {
root: screen.root,
picture_format,
render_support,
theme,
cursor_size,
})
}
}
/// A handle necessary for loading cursors
#[derive(Debug)]
pub struct Handle {
root: Window,
picture_format: Pictformat,
render_support: RenderSupport,
theme: Option<String>,
cursor_size: u32,
}
impl Handle {
/// Create a new cursor handle for creating cursors on the given screen.
///
/// The `resource_database` is used to look up settings like the current cursor theme and the
/// cursor size to use.
///
/// This function returns a cookie that can be used to later get the actual handle.
///
/// If you want this function not to block, you should prefetch the RENDER extension's data on
/// the connection.
#[allow(clippy::new_ret_no_self)]
pub fn new<'a, 'b, C: Connection>(
conn: &'a C,
screen: usize,
resource_database: &'b Database,
) -> Result<Cookie<'a, 'b, C>, ConnectionError> {
let screen = &conn.setup().roots[screen];
let render_info = if conn
.extension_information(render::X11_EXTENSION_NAME)?
.is_some()
{
let render_version = render::query_version(conn, 0, 8)?;
let render_pict_format = render::query_pict_formats(conn)?;
Some((render_version, render_pict_format))
} else {
None
};
Ok(Cookie {
screen,
resource_database,
render_info,
})
}
/// Loads the specified cursor, either from the cursor theme or by falling back to the X11
/// "cursor" font.
pub fn load_cursor<C>(&self, conn: &C, name: &str) -> Result<xproto::Cursor, ReplyOrIdError>
where
C: Connection,
{
load_cursor(conn, self, name)
}
}
fn open_cursor(theme: &Option<String>, name: &str) -> Option<find_cursor::Cursor> {
theme
.as_ref()
.and_then(|theme| find_cursor::find_cursor(theme, name))
.or_else(|| find_cursor::find_cursor("default", name))
}
fn create_core_cursor<C: Connection>(
conn: &C,
cursor: u16,
) -> Result<xproto::Cursor, ReplyOrIdError> {
let result = conn.generate_id()?;
let cursor_font = FontWrapper::open_font(conn, b"cursor")?;
let _ = xproto::create_glyph_cursor(
conn,
result,
cursor_font.font(),
cursor_font.font(),
cursor,
cursor + 1,
// foreground color
0,
0,
0,
// background color
u16::MAX,
u16::MAX,
u16::MAX,
)?;
Ok(result)
}
fn create_render_cursor<C: Connection>(
conn: &C,
handle: &Handle,
image: &Image,
storage: &mut Option<(xproto::Pixmap, xproto::Gcontext, u16, u16)>,
) -> Result<render::Animcursorelt, ReplyOrIdError> {
let to_u16 = |input: u32| {
u16::try_from(input).expect(
"xcursor-rs has a 16 bit limit on cursor size, but some number does not fit into u16?!",
)
};
let (width, height) = (to_u16(image.width), to_u16(image.height));
// Get a pixmap of the right size and a gc for it
let (pixmap, gc) = match *storage {
Some((pixmap, gc, w, h)) if (w, h) == (width, height) => (pixmap, gc),
_ => {
let (pixmap, gc) = if let Some((pixmap, gc, _, _)) = storage {
let _ = xproto::free_gc(conn, *gc)?;
let _ = xproto::free_pixmap(conn, *pixmap)?;
(*pixmap, *gc)
} else {
(conn.generate_id()?, conn.generate_id()?)
};
let _ = xproto::create_pixmap(conn, 32, pixmap, handle.root, width, height)?;
let _ = xproto::create_gc(conn, gc, pixmap, &Default::default())?;
*storage = Some((pixmap, gc, width, height));
(pixmap, gc)
}
};
let _ = xproto::put_image(
conn,
xproto::ImageFormat::Z_PIXMAP,
pixmap,
gc,
width,
height,
0,
0,
0,
32,
&image.pixels_rgba,
)?;
let picture = render::PictureWrapper::create_picture(
conn,
pixmap,
handle.picture_format,
&Default::default(),
)?;
let cursor = conn.generate_id()?;
let _ = render::create_cursor(
conn,
cursor,
picture.picture(),
to_u16(image.xhot),
to_u16(image.yhot),
)?;
Ok(render::Animcursorelt {
cursor,
delay: image.delay,
})
}
fn load_cursor<C: Connection>(
conn: &C,
handle: &Handle,
name: &str,
) -> Result<xproto::Cursor, ReplyOrIdError> {
// Find the right cursor, load it directly if it is a core cursor
let cursor_file = match open_cursor(&handle.theme, name) {
None => return Ok(NONE),
Some(find_cursor::Cursor::CoreChar(c)) => return create_core_cursor(conn, c),
Some(find_cursor::Cursor::File(f)) => f,
};
// We have to load a file and use RENDER to create a cursor
if handle.render_support == RenderSupport::None {
return Ok(NONE);
}
// Load the cursor from the file
use std::io::BufReader;
let images = parse_cursor::parse_cursor(&mut BufReader::new(cursor_file), handle.cursor_size)
.or(Err(crate::errors::ParseError::InvalidValue))?;
let mut images = &images[..];
// No animated cursor support? Only use the first image
if handle.render_support == RenderSupport::StaticCursor {
images = &images[0..1];
}
// Now transfer the cursors to the X11 server
let mut storage = None;
let cursors = images
.iter()
.map(|image| create_render_cursor(conn, handle, image, &mut storage))
.collect::<Result<Vec<_>, _>>()?;
if let Some((pixmap, gc, _, _)) = storage {
let _ = xproto::free_gc(conn, gc)?;
let _ = xproto::free_pixmap(conn, pixmap)?;
}
if cursors.len() == 1 {
Ok(cursors[0].cursor)
} else {
let result = conn.generate_id()?;
let _ = render::create_anim_cursor(conn, result, &cursors)?;
for elem in cursors {
let _ = xproto::free_cursor(conn, elem.cursor)?;
}
Ok(result)
}
}
fn find_format(reply: &render::QueryPictFormatsReply) -> Pictformat {
reply
.formats
.iter()
.filter(|format| {
format.type_ == render::PictType::DIRECT
&& format.depth == 32
&& format.direct.red_shift == 16
&& format.direct.red_mask == 0xff
&& format.direct.green_shift == 8
&& format.direct.green_mask == 0xff
&& format.direct.blue_shift == 0
&& format.direct.blue_mask == 0xff
&& format.direct.alpha_shift == 24
&& format.direct.alpha_mask == 0xff
})
.map(|format| format.id)
.next()
.expect("The X11 server is missing the RENDER ARGB_32 standard format!")
}
fn get_cursor_size(rm_cursor_size: u32, rm_xft_dpi: u32, screen: &xproto::Screen) -> u32 {
if let Some(size) = std::env::var("XCURSOR_SIZE")
.ok()
.and_then(|s| s.parse().ok())
{
return size;
}
if rm_cursor_size > 0 {
return rm_cursor_size;
}
if rm_xft_dpi > 0 {
return rm_xft_dpi * 16 / 72;
}
u32::from(screen.height_in_pixels.min(screen.width_in_pixels) / 48)
}

102
vendor/x11rb/src/cursor/parse_cursor.rs vendored Normal file
View File

@@ -0,0 +1,102 @@
//! Parse the contents of a cursor file
// This code is loosely based on parse_cursor_file.c from libxcb-cursor, which is:
// Copyright © 2013 Michael Stapelberg
// and is covered by MIT/X Consortium License
use std::io::{Read, Seek};
use xcursor::parser::{parse_xcursor_stream, Image};
/// An error that occurred while parsing
#[derive(Debug)]
pub(crate) enum Error {
/// An I/O error occurred
Io,
/// The file contains no images
NoImages,
}
impl From<std::io::Error> for Error {
fn from(_: std::io::Error) -> Self {
Error::Io
}
}
/// Find the size of the image in the toc with a size as close as possible to the desired size.
fn find_best_size(images: &[Image], desired_size: u32) -> Result<u32, Error> {
fn distance(a: u32, b: u32) -> u32 {
a.max(b) - a.min(b)
}
fn is_better(desired_size: u32, entry: &Image, result: &Result<u32, Error>) -> bool {
match result {
Err(_) => true,
Ok(size) => distance(entry.size, desired_size) < distance(*size, desired_size),
}
}
let mut result = Err(Error::NoImages);
for entry in images {
// If this is better than the best so far, replace best
if is_better(desired_size, entry, &result) {
result = Ok(entry.size)
}
}
result
}
/// Parse a complete cursor file
pub(crate) fn parse_cursor<R: Read + Seek>(
input: &mut R,
desired_size: u32,
) -> Result<Vec<Image>, Error> {
let mut cursors = parse_xcursor_stream(input)?;
let size = find_best_size(&cursors, desired_size)?;
cursors.retain(|image| image.size == size);
Ok(cursors)
}
#[cfg(test)]
mod test {
use super::{find_best_size, Error, Image};
#[test]
fn find_best_size_empty_input() {
let res = find_best_size(&[], 42);
match res {
Err(Error::NoImages) => {}
r => panic!("Unexpected result {r:?}"),
}
}
fn fake_image_with_size(size: u32) -> Image {
Image {
size,
width: 42,
height: 42,
xhot: 0,
yhot: 0,
delay: 0,
pixels_rgba: Vec::new(),
pixels_argb: Vec::new(),
}
}
#[test]
fn find_best_size_one_input() {
let input = [fake_image_with_size(42)];
assert_eq!(42, find_best_size(&input, 10).unwrap());
}
#[test]
fn find_best_size_selects_better() {
let input = [
fake_image_with_size(42),
fake_image_with_size(32),
fake_image_with_size(3),
fake_image_with_size(22),
];
assert_eq!(3, find_best_size(&input, 10).unwrap());
}
}

205
vendor/x11rb/src/errors.rs vendored Normal file
View File

@@ -0,0 +1,205 @@
//! This module contains the current mess that is error handling.
use crate::x11_utils::X11Error;
pub use x11rb_protocol::errors::{ConnectError, DisplayParsingError, IdsExhausted, ParseError};
/// An error occurred while dynamically loading libxcb.
#[cfg(feature = "dl-libxcb")]
#[derive(Debug, Clone)]
pub enum LibxcbLoadError {
/// Could not open the library. The `OsString` is the library
/// file name and the string is the reason.
OpenLibError(std::ffi::OsString, String),
/// Could not get a symbol from the library. The byte vector is the
/// symbol name and the string is the reason.
GetSymbolError(Vec<u8>, String),
}
#[cfg(feature = "dl-libxcb")]
impl std::fmt::Display for LibxcbLoadError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LibxcbLoadError::OpenLibError(lib_name, e) => {
write!(f, "failed to open library {lib_name:?}: {e}")
}
LibxcbLoadError::GetSymbolError(symbol, e) => write!(
f,
"failed to get symbol \"{}\": {}",
symbol.escape_ascii(),
e,
),
}
}
}
#[cfg(feature = "dl-libxcb")]
impl std::error::Error for LibxcbLoadError {}
/// An error that occurred on an already established X11 connection
#[derive(Debug)]
#[non_exhaustive]
pub enum ConnectionError {
/// An unknown error occurred.
///
/// One situation were this error is used when libxcb indicates an error that does not match
/// any of the defined error conditions. Thus, libxcb is violating its own API (or new error
/// cases were defined, but are not yet handled by x11rb).
UnknownError,
/// An X11 extension was not supported by the server.
///
/// This corresponds to `XCB_CONN_CLOSED_EXT_NOTSUPPORTED`.
UnsupportedExtension,
/// A request larger than the maximum request length was sent.
///
/// This corresponds to `XCB_CONN_CLOSED_REQ_LEN_EXCEED`.
MaximumRequestLengthExceeded,
/// File descriptor passing failed.
///
/// This corresponds to `XCB_CONN_CLOSED_FDPASSING_FAILED`.
FdPassingFailed,
/// Error while parsing some data, see `ParseError`.
ParseError(ParseError),
/// Out of memory.
///
/// This is `XCB_CONN_CLOSED_MEM_INSUFFICIENT`.
InsufficientMemory,
/// An I/O error occurred on the connection.
IoError(std::io::Error),
}
impl std::error::Error for ConnectionError {}
impl std::fmt::Display for ConnectionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConnectionError::UnknownError => write!(f, "Unknown connection error"),
ConnectionError::UnsupportedExtension => write!(f, "Unsupported extension"),
ConnectionError::InsufficientMemory => write!(f, "Insufficient memory"),
ConnectionError::MaximumRequestLengthExceeded => {
write!(f, "Maximum request length exceeded")
}
ConnectionError::FdPassingFailed => write!(f, "FD passing failed"),
ConnectionError::ParseError(err) => err.fmt(f),
ConnectionError::IoError(err) => err.fmt(f),
}
}
}
impl From<ParseError> for ConnectionError {
fn from(err: ParseError) -> Self {
ConnectionError::ParseError(err)
}
}
impl From<std::io::Error> for ConnectionError {
fn from(err: std::io::Error) -> Self {
ConnectionError::IoError(err)
}
}
/// An error that occurred with some request.
#[derive(Debug)]
pub enum ReplyError {
/// Some error occurred on the X11 connection.
ConnectionError(ConnectionError),
/// The X11 server sent an error in response to a request.
X11Error(X11Error),
}
impl std::error::Error for ReplyError {}
impl std::fmt::Display for ReplyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReplyError::ConnectionError(e) => write!(f, "{e}"),
ReplyError::X11Error(e) => write!(f, "X11 error {e:?}"),
}
}
}
impl From<ParseError> for ReplyError {
fn from(err: ParseError) -> Self {
Self::from(ConnectionError::from(err))
}
}
impl From<std::io::Error> for ReplyError {
fn from(err: std::io::Error) -> Self {
ConnectionError::from(err).into()
}
}
impl From<ConnectionError> for ReplyError {
fn from(err: ConnectionError) -> Self {
Self::ConnectionError(err)
}
}
impl From<X11Error> for ReplyError {
fn from(err: X11Error) -> Self {
Self::X11Error(err)
}
}
/// An error caused by some request or by the exhaustion of IDs.
#[derive(Debug)]
pub enum ReplyOrIdError {
/// All available IDs have been exhausted.
IdsExhausted,
/// Some error occurred on the X11 connection.
ConnectionError(ConnectionError),
/// The X11 server sent an error in response to a request.
X11Error(X11Error),
}
impl std::fmt::Display for ReplyOrIdError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReplyOrIdError::IdsExhausted => f.write_str("X11 IDs have been exhausted"),
ReplyOrIdError::ConnectionError(e) => write!(f, "{e}"),
ReplyOrIdError::X11Error(e) => write!(f, "X11 error {e:?}"),
}
}
}
impl std::error::Error for ReplyOrIdError {}
impl From<ParseError> for ReplyOrIdError {
fn from(err: ParseError) -> Self {
ConnectionError::from(err).into()
}
}
impl From<ConnectionError> for ReplyOrIdError {
fn from(err: ConnectionError) -> Self {
ReplyOrIdError::ConnectionError(err)
}
}
impl From<X11Error> for ReplyOrIdError {
fn from(err: X11Error) -> Self {
ReplyOrIdError::X11Error(err)
}
}
impl From<ReplyError> for ReplyOrIdError {
fn from(err: ReplyError) -> Self {
match err {
ReplyError::ConnectionError(err) => ReplyOrIdError::ConnectionError(err),
ReplyError::X11Error(err) => ReplyOrIdError::X11Error(err),
}
}
}
impl From<IdsExhausted> for ReplyOrIdError {
fn from(_: IdsExhausted) -> Self {
ReplyOrIdError::IdsExhausted
}
}

View File

@@ -0,0 +1,82 @@
//! # Integrating x11rb with an Event Loop
//!
//! To integrate x11rb with an event loop,
//! [`std::os::unix::io::AsRawFd`](https://doc.rust-lang.org/std/os/unix/io/trait.AsRawFd.html) is
//! implemented by [`RustConnection`](../rust_connection/struct.RustConnection.html)'s
//! [`DefaultStream`](../rust_connection/struct.DefaultStream.html#impl-AsRawFd) and
//! [`XCBConnection`](../xcb_ffi/struct.XCBConnection.html#impl-AsRawFd). This allows to integrate
//! with an event loop that also handles timeouts or network I/O. See
//! [`xclock_utc`](https://github.com/psychon/x11rb/blob/master/x11rb/examples/xclock_utc.rs) for an
//! example.
//!
//! The general form of such an integration could be as follows:
//! ```no_run
//! #[cfg(unix)]
//! use std::os::unix::io::{AsRawFd, RawFd};
//! #[cfg(windows)]
//! use std::os::windows::io::{AsRawSocket, RawSocket};
//! use x11rb::connection::Connection;
//! use x11rb::rust_connection::RustConnection;
//! use x11rb::errors::ConnectionError;
//!
//! fn main_loop(conn: &RustConnection) -> Result<(), ConnectionError> {
//! #[cfg(unix)]
//! let raw_handle = conn.stream().as_raw_fd();
//! #[cfg(windows)]
//! let raw_handle = conn.stream().as_raw_socket();
//! loop {
//! while let Some(event) = conn.poll_for_event()? {
//! handle_event(event);
//! }
//!
//! poll_for_readable(raw_handle);
//!
//! // Do other work here.
//! }
//! }
//! # fn handle_event<T>(event: T) {}
//! # fn poll_for_readable<T>(event: T) {}
//! ```
//! The function `poll_for_readable` could wait for any number of I/O streams (besides the one from
//! x11rb) to become readable. It can also implement timeouts, as seen in the
//! [`xclock_utc` example](https://github.com/psychon/x11rb/blob/master/x11rb/examples/xclock_utc.rs).
//!
//!
//! ## Threads and Races
//!
//! Both [`RustConnection`](../rust_connection/struct.RustConnection.html) and
//! [`XCBConnection`](../xcb_ffi/struct.XCBConnection.html) are `Sync+Send`. However, it is still
//! possible to see races in the presence of threads and an event loop.
//!
//! The underlying problem is that the following two points are not equivalent:
//!
//! 1. A new event is available and can be returned from `conn.poll_for_event()`.
//! 2. The underlying I/O stream is readable.
//!
//! The reason for this is an internal buffer that is required: When an event is received from the
//! X11 server, but we are currently not in `conn.poll_for_event()`, then this event is added to an
//! internal buffer. Thus, it can happen that there is an event available, but the stream is not
//! readable.
//!
//! An example for such an other function is `conn.get_input_focus()?.reply()?`: The
//! `GetInputFocus` request is sent to the server and then `reply()` waits for the reply. It does
//! so by reading X11 packets from the X11 server until the right reply arrives. Any events that
//! are read during this are buffered internally in the `Connection`.
//!
//! If this race occurs, the main loop would sit in `poll_for_readable` and wait, while the already
//! buffered event is available. When something else wakes up the main loop and
//! `conn.poll_for_event()` is called the next time, the event is finally processed.
//!
//! There are two ways around this:
//!
//! 1. Only interact with x11rb from one thread.
//! 2. Use a dedicated thread for waiting for event.
//!
//! In case (1), one can call `conn.poll_for_event()` before waiting for the underlying I/O stream
//! to be readable. Since there are no other threads, nothing can read a new event from the stream
//! after `conn.poll_for_event()` returned `None`.
//!
//! Option (2) is to start a thread that calls `conn.wait_for_event()` in a loop. This is basically
//! a dedicated event loop for fetching events from the X11 server. All other threads can now
//! freely use the X11 connection without events possibly getting stuck and only being processed
//! later.

346
vendor/x11rb/src/extension_manager.rs vendored Normal file
View File

@@ -0,0 +1,346 @@
//! Helper for implementing `RequestConnection::extension_information()`.
use std::collections::{hash_map::Entry as HashMapEntry, HashMap};
use crate::connection::RequestConnection;
use crate::cookie::Cookie;
use crate::errors::{ConnectionError, ReplyError};
use crate::protocol::xproto::{ConnectionExt, QueryExtensionReply};
use crate::x11_utils::{ExtInfoProvider, ExtensionInformation};
use x11rb_protocol::SequenceNumber;
/// Helper for implementing `RequestConnection::extension_information()`.
///
/// This helps with implementing `RequestConnection`. Most likely, you do not need this in your own
/// code, unless you really want to implement your own X11 connection.
#[derive(Debug, Default)]
pub struct ExtensionManager(HashMap<&'static str, CheckState>);
#[derive(Debug)]
enum CheckState {
Prefetched(SequenceNumber),
Present(ExtensionInformation),
Missing,
Error,
}
impl ExtensionManager {
/// If the extension has not prefetched yet, sends a `QueryExtension`
/// requests, adds a field to the hash map and returns a reference to it.
fn prefetch_extension_information_aux<C: RequestConnection>(
&mut self,
conn: &C,
extension_name: &'static str,
) -> Result<&mut CheckState, ConnectionError> {
match self.0.entry(extension_name) {
// Extension already checked, return the cached value
HashMapEntry::Occupied(entry) => Ok(entry.into_mut()),
HashMapEntry::Vacant(entry) => {
crate::debug!(
"Prefetching information about '{}' extension",
extension_name
);
let cookie = conn.query_extension(extension_name.as_bytes())?;
Ok(entry.insert(CheckState::Prefetched(cookie.into_sequence_number())))
}
}
}
/// Prefetchs an extension sending a `QueryExtension` without waiting for
/// the reply.
pub fn prefetch_extension_information<C: RequestConnection>(
&mut self,
conn: &C,
extension_name: &'static str,
) -> Result<(), ConnectionError> {
// We are not interested on the reference to the entry.
let _ = self.prefetch_extension_information_aux(conn, extension_name)?;
Ok(())
}
/// Insert an extension if you already have the information.
pub fn insert_extension_information(
&mut self,
extension_name: &'static str,
info: Option<ExtensionInformation>,
) {
crate::debug!(
"Inserting '{}' extension information directly: {:?}",
extension_name,
info
);
let state = match info {
Some(info) => CheckState::Present(info),
None => CheckState::Missing,
};
let _ = self.0.insert(extension_name, state);
}
/// An implementation of `RequestConnection::extension_information()`.
///
/// The given connection is used for sending a `QueryExtension` request if needed.
pub fn extension_information<C: RequestConnection>(
&mut self,
conn: &C,
extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
let _guard = crate::debug_span!("extension_information", extension_name).entered();
let entry = self.prefetch_extension_information_aux(conn, extension_name)?;
match entry {
CheckState::Prefetched(sequence_number) => {
crate::debug!(
"Waiting for QueryInfo reply for '{}' extension",
extension_name
);
match Cookie::<C, QueryExtensionReply>::new(conn, *sequence_number).reply() {
Err(err) => {
crate::warning!(
"Got error {:?} for QueryInfo reply for '{}' extension",
err,
extension_name
);
*entry = CheckState::Error;
match err {
ReplyError::ConnectionError(e) => Err(e),
// The X11 protocol specification does not specify any error
// for the QueryExtension request, so this should not happen.
ReplyError::X11Error(_) => Err(ConnectionError::UnknownError),
}
}
Ok(info) => {
if info.present {
let info = ExtensionInformation {
major_opcode: info.major_opcode,
first_event: info.first_event,
first_error: info.first_error,
};
crate::debug!("Extension '{}' is present: {:?}", extension_name, info);
*entry = CheckState::Present(info);
Ok(Some(info))
} else {
crate::debug!("Extension '{}' is not present", extension_name);
*entry = CheckState::Missing;
Ok(None)
}
}
}
}
CheckState::Present(info) => Ok(Some(*info)),
CheckState::Missing => Ok(None),
CheckState::Error => Err(ConnectionError::UnknownError),
}
}
}
impl ExtInfoProvider for ExtensionManager {
fn get_from_major_opcode(&self, major_opcode: u8) -> Option<(&str, ExtensionInformation)> {
self.0
.iter()
.filter_map(|(name, state)| {
if let CheckState::Present(info) = state {
Some((*name, *info))
} else {
None
}
})
.find(|(_, info)| info.major_opcode == major_opcode)
}
fn get_from_event_code(&self, event_code: u8) -> Option<(&str, ExtensionInformation)> {
self.0
.iter()
.filter_map(|(name, state)| {
if let CheckState::Present(info) = state {
if info.first_event <= event_code {
Some((*name, *info))
} else {
None
}
} else {
None
}
})
.max_by_key(|(_, info)| info.first_event)
}
fn get_from_error_code(&self, error_code: u8) -> Option<(&str, ExtensionInformation)> {
self.0
.iter()
.filter_map(|(name, state)| {
if let CheckState::Present(info) = state {
if info.first_error <= error_code {
Some((*name, *info))
} else {
None
}
} else {
None
}
})
.max_by_key(|(_, info)| info.first_error)
}
}
#[cfg(test)]
mod test {
use std::cell::RefCell;
use std::io::IoSlice;
use crate::connection::{BufWithFds, ReplyOrError, RequestConnection, RequestKind};
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::{ConnectionError, ParseError};
use crate::utils::RawFdContainer;
use crate::x11_utils::{ExtInfoProvider, ExtensionInformation, TryParse, TryParseFd};
use x11rb_protocol::{DiscardMode, SequenceNumber};
use super::{CheckState, ExtensionManager};
struct FakeConnection(RefCell<SequenceNumber>);
impl RequestConnection for FakeConnection {
type Buf = Vec<u8>;
fn send_request_with_reply<R>(
&self,
_bufs: &[IoSlice<'_>],
_fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
Ok(Cookie::new(self, 1))
}
fn send_request_with_reply_with_fds<R>(
&self,
_bufs: &[IoSlice<'_>],
_fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
_bufs: &[IoSlice<'_>],
_fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
unimplemented!()
}
fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) {
unimplemented!()
}
fn prefetch_extension_information(
&self,
_extension_name: &'static str,
) -> Result<(), ConnectionError> {
unimplemented!();
}
fn extension_information(
&self,
_extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<Vec<u8>>, ConnectionError> {
// Code should only ask once for the reply to a request. Check that this is the case
// (by requiring monotonically increasing sequence numbers here).
let mut last = self.0.borrow_mut();
assert!(
*last < sequence,
"Last sequence number that was awaited was {}, but now {}",
*last,
sequence
);
*last = sequence;
// Then return an error, because that's what the #[test] below needs.
Err(ConnectionError::UnknownError)
}
fn wait_for_reply(
&self,
_sequence: SequenceNumber,
) -> Result<Option<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Vec<u8>>, Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_sequence: SequenceNumber,
) -> Result<Option<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
0
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn parse_error(&self, _error: &[u8]) -> Result<crate::x11_utils::X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _event: &[u8]) -> Result<crate::protocol::Event, ParseError> {
unimplemented!()
}
}
#[test]
fn test_double_await() {
let conn = FakeConnection(RefCell::new(0));
let mut ext_info = ExtensionManager::default();
// Ask for an extension info. FakeConnection will return an error.
match ext_info.extension_information(&conn, "whatever") {
Err(ConnectionError::UnknownError) => {}
r => panic!("Unexpected result: {r:?}"),
}
// Ask again for the extension information. ExtensionInformation should not try to get the
// reply again, because that would just hang. Once upon a time, this caused a hang.
match ext_info.extension_information(&conn, "whatever") {
Err(ConnectionError::UnknownError) => {}
r => panic!("Unexpected result: {r:?}"),
}
}
#[test]
fn test_info_provider() {
let info = ExtensionInformation {
major_opcode: 4,
first_event: 5,
first_error: 6,
};
let mut ext_info = ExtensionManager::default();
let _ = ext_info.0.insert("prefetched", CheckState::Prefetched(42));
let _ = ext_info.0.insert("present", CheckState::Present(info));
let _ = ext_info.0.insert("missing", CheckState::Missing);
let _ = ext_info.0.insert("error", CheckState::Error);
assert_eq!(ext_info.get_from_major_opcode(4), Some(("present", info)));
assert_eq!(ext_info.get_from_event_code(5), Some(("present", info)));
assert_eq!(ext_info.get_from_error_code(6), Some(("present", info)));
}
}

1298
vendor/x11rb/src/image.rs vendored Normal file

File diff suppressed because it is too large Load Diff

215
vendor/x11rb/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,215 @@
//! X11 rust bindings.
//!
//! This library allows to interact with an X11 server from rust code. A connection to an X11
//! server is represented by an implementation of the `Connection` trait.
//!
//! The client can interact with the server by sending requests. The server can answer requests and
//! can also generate events.
//!
//! The examples that come with this library might be a good starting point for new users.
//!
//!
//! # Getting started with X11
//!
//! X11 is a big protocol. I would claim that most of it is not actually that complicated, but it
//! is still difficult to get into it. A good starting point might be some [libxcb
//! tutorial](https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html). This tutorial
//! was adapted in this crate [as an
//! example](https://github.com/psychon/x11rb/blob/master/x11rb/examples/tutorial.rs). A more in-depth
//! look at the X11 protocol can be gained from the [protocol reference
//! manual](https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html), but this requires some
//! existing basic understanding of X11. If you want to figure out what some specific request does,
//! be sure to look it up in the specification!
//!
//! Most extensions can be understood by reading their specification. Most of them can be found
//! [here](https://www.x.org/releases/current/doc/index.html#protocol). For example, [the
//! specification of Composite
//! 0.4](https://www.x.org/releases/X11R7.5/doc/compositeproto/compositeproto.txt) consists of
//! about six pages of text.
//!
//! The notable exception is the X keyboard extension, which is documented in a [PDF file with 168
//! pages](https://www.x.org/releases/current/doc/kbproto/xkbproto.pdf) which I am never going to
//! read completely.
//!
//!
//! # Getting started with x11rb
//!
//! Most code in this code is automatically generated from an XML description of the protocol. This
//! is the same approach as taken by [libxcb](https://xcb.freedesktop.org/) (and in fact this uses
//! the same XML description). This means that if you know your way around X11, most things should
//! be obvious to you.
//!
//! For example, here is how to create a new window with x11rb:
//! ```no_run
//! use x11rb::connection::Connection;
//! use x11rb::errors::ReplyOrIdError;
//! use x11rb::protocol::xproto::*;
//! use x11rb::COPY_DEPTH_FROM_PARENT;
//!
//! fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let (conn, screen_num) = x11rb::connect(None).unwrap();
//! let screen = &conn.setup().roots[screen_num];
//! let win_id = conn.generate_id()?;
//! conn.create_window(
//! COPY_DEPTH_FROM_PARENT,
//! win_id,
//! screen.root,
//! 0,
//! 0,
//! 100,
//! 100,
//! 0,
//! WindowClass::INPUT_OUTPUT,
//! 0,
//! &CreateWindowAux::new().background_pixel(screen.white_pixel),
//! )?;
//! conn.map_window(win_id)?;
//! conn.flush();
//! loop {
//! println!("Event: {:?}", conn.wait_for_event()?);
//! }
//! }
//! ```
//! More examples can be found in the
//! [examples](https://github.com/psychon/x11rb/tree/master/x11rb/examples) directory.
//!
//! ## Feature flags
//!
//! This crate uses [feature
//! flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section) to reduce
//! the amount of compiled code. There are two kinds of feature flags available:
//!
//! * Feature flags for specific X11 extensions
//! * Feature flags for additional functionality
//!
//! ### Feature flags for specific X11 extensions
//!
//! By default, only the core X11 protocol and X11 extensions that are needed internally are
//! enabled. These are the `bigreq`, `ge` and `xc_misc` extensions. Further extensions need to be
//! explicitly enabled via their feature flag:
//!
//! `composite`, `damage`, `dpms`, `dri2`, `dri3`, `glx`, `present`, `randr`, `record`, `render`,
//! `res`, `screensaver`, `shape`, `shm`, `sync`, `xevie`, `xf86dri`, `xf86vidmode`, `xfixes`,
//! `xinerama`, `xinput`, `xkb`, `xprint`, `xselinux`, `xtest`, `xv`, `xvmc`.
//!
//! If you want to take the "I do not want to think about this"-approach, you can enable the
//! `all-extensions` feature to just enable, well, all extensions.
//!
//! ### Feature flags for additional functionality
//!
//! Additionally, the following flags exist:
//! * `allow-unsafe-code`: Enable features that require `unsafe`. Without this flag,
//! [`xcb_ffi::XCBConnection`] and some support code for it are unavailable.
//! * `cursor`: Enable the code in [cursor] for loading cursor files.
//! * `resource_manager`: Enable the code in [resource_manager] for loading and querying the
//! X11 resource database.
//! * `image`: Enable the code in [image] for working with pixel image data.
//! * `dl-libxcb`: Enabling this feature will prevent from libxcb being linked to the
//! resulting executable. Instead libxcb will be dynamically loaded at runtime.
//! This feature adds the [`xcb_ffi::load_libxcb`] function, that allows to load
//! libxcb and check for success or failure.
//! * `extra-traits`: Enable some additional traits for generated code, like `Eq`, `Ord` and
//! `Hash`. This is not needed by default and adds a large amount of code that bloats codegen
//! time
//! * `request-parsing`: Add the ability to parse X11 requests. Not normally needed.
//! * `extra-traits`: Implement extra traits for X11 types. This improves the output of the `Debug`
//! impl and adds `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` where possible.
//!
//! # Integrating x11rb with an Event Loop
//!
//! The [event_loop_integration](event_loop_integration/index.html) module contains some hints for
//! integrating x11rb with an event loop as doc comments.
// A list of lints that are only #![deny] and not the stronger #![forbid]. Each one has a comment
// explaining why it gets the weaker treatment.
#![deny(
// Contains unreachable_code and "?" generates an #[allow] for this
unused,
// #[derive] generates an #[allow] for this; not part of "unused"
unused_qualifications,
// Not everything in x11rb::protocol has doc comments
missing_docs,
)]
#![forbid(
missing_copy_implementations,
missing_debug_implementations,
rustdoc::private_doc_tests,
rust_2018_idioms,
//single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
unreachable_pub,
unused_must_use,
unused_results,
clippy::cast_lossless,
clippy::needless_pass_by_value,
)]
#![cfg_attr(not(feature = "allow-unsafe-code"), forbid(unsafe_code))]
// Only contains documentation, but no "actual rust"
pub mod event_loop_integration;
/// Reexports of dependencies
pub mod reexports {
pub use x11rb_protocol;
}
mod tracing;
pub(crate) use crate::tracing::*;
pub mod utils;
#[cfg(feature = "allow-unsafe-code")]
pub mod xcb_ffi;
#[macro_use]
pub mod x11_utils;
pub mod connection;
pub mod cookie;
#[cfg(feature = "cursor")]
pub mod cursor;
pub mod errors;
pub mod extension_manager;
#[cfg(feature = "image")]
pub mod image;
pub mod properties;
pub mod rust_connection;
pub mod wrapper;
#[rustfmt::skip]
#[allow(missing_docs)]
pub mod protocol;
#[cfg(feature = "resource_manager")]
pub mod resource_manager;
#[cfg(test)]
mod test;
use errors::ConnectError;
use protocol::xproto::{Keysym, Timestamp};
/// Establish a new connection to an X11 server.
///
/// This function is identical to
/// [RustConnection::connect](crate::rust_connection::RustConnection::connect).
pub fn connect(
dpy_name: Option<&str>,
) -> Result<(rust_connection::RustConnection, usize), ConnectError> {
rust_connection::RustConnection::connect(dpy_name)
}
/// The universal null resource or null atom parameter value for many core X requests
pub const NONE: u32 = 0;
/// This constant can be used for many parameters in `create_window`
pub const COPY_FROM_PARENT: u32 = 0;
/// This constant can be used for the depth parameter in `create_window`. It indicates to use the
/// parent window's depth.
pub const COPY_DEPTH_FROM_PARENT: u8 = 0;
/// This constant can be used for the class parameter in `create_window`. It indicates to use the
/// parent window's class.
pub const COPY_CLASS_FROM_PARENT: u16 = 0;
/// This constant can be used in most request that take a timestamp argument
pub const CURRENT_TIME: Timestamp = 0;
/// This constant can be used to fill unused entries in `Keysym` tables
pub const NO_SYMBOL: Keysym = 0;

823
vendor/x11rb/src/properties.rs vendored Normal file
View File

@@ -0,0 +1,823 @@
//! Utility functions for working with X11 properties
use crate::connection::RequestConnection;
use crate::cookie::{Cookie, VoidCookie};
use crate::errors::{ConnectionError, ParseError, ReplyError};
use crate::protocol::xproto::{self, Atom, AtomEnum, GetPropertyReply, Window};
use crate::x11_utils::{Serialize, TryParse};
macro_rules! property_cookie {
{
$(#[$meta:meta])*
pub struct $cookie_name:ident: $struct_name:ident,
$from_reply:expr,
} => {
$(#[$meta])*
#[derive(Debug)]
pub struct $cookie_name<'a, Conn: RequestConnection + ?Sized>(Cookie<'a, Conn, GetPropertyReply>);
impl<'a, Conn> $cookie_name<'a, Conn>
where
Conn: RequestConnection + ?Sized,
{
/// Get the reply that the server sent.
pub fn reply(self) -> Result<Option<$struct_name>, ReplyError> {
#[allow(clippy::redundant_closure_call)]
Ok($from_reply(self.0.reply()?)?)
}
/// Get the reply that the server sent, but have errors handled as events.
pub fn reply_unchecked(self) -> Result<Option<$struct_name>, ConnectionError> {
self.0
.reply_unchecked()?
.map($from_reply)
.transpose()
.map(|e| e.flatten())
.map_err(Into::into)
}
}
}
}
// WM_CLASS
property_cookie! {
/// A cookie for getting a window's `WM_CLASS` property.
///
/// See `WmClass`.
pub struct WmClassCookie: WmClass,
WmClass::from_reply,
}
impl<'a, Conn> WmClassCookie<'a, Conn>
where
Conn: RequestConnection + ?Sized,
{
/// Send a `GetProperty` request for the `WM_CLASS` property of the given window
pub fn new(conn: &'a Conn, window: Window) -> Result<Self, ConnectionError> {
Ok(Self(xproto::get_property(
conn,
false,
window,
AtomEnum::WM_CLASS,
AtomEnum::STRING,
0,
2048,
)?))
}
}
/// The value of a window's `WM_CLASS` property.
///
/// Usage example:
/// ```
/// use x11rb::connection::Connection;
/// use x11rb::errors::ConnectionError;
/// use x11rb::properties::WmClass;
/// use x11rb::protocol::xproto::Window;
///
/// fn print_class_instance(
/// conn: &impl Connection,
/// window: Window,
/// ) -> Result<bool, ConnectionError> {
/// let wm_class = match WmClass::get(conn, window)?.reply_unchecked()? {
/// Some(wm_class) => wm_class,
/// None => return Ok(false), // Getting the property failed
/// };
/// // Note that the WM_CLASS property is not actually encoded in utf8.
/// // ASCII values are most common and for these from_utf8() should be fine.
/// let class = std::str::from_utf8(wm_class.class());
/// let instance = std::str::from_utf8(wm_class.instance());
/// println!(
/// "For window {:x}, class is '{:?}' and instance is '{:?}'",
/// window, class, instance,
/// );
/// Ok(true)
/// }
/// ```
#[derive(Debug)]
pub struct WmClass(GetPropertyReply, usize);
impl WmClass {
/// Send a `GetProperty` request for the `WM_CLASS` property of the given window
pub fn get<C: RequestConnection>(
conn: &C,
window: Window,
) -> Result<WmClassCookie<'_, C>, ConnectionError> {
WmClassCookie::new(conn, window)
}
/// Construct a new `WmClass` instance from a `GetPropertyReply`.
///
/// The original `GetProperty` request must have been for a `WM_CLASS` property for this
/// function to return sensible results.
pub fn from_reply(reply: GetPropertyReply) -> Result<Option<Self>, ParseError> {
if reply.type_ == AtomEnum::NONE.into() {
return Ok(None);
}
if reply.type_ != AtomEnum::STRING.into() || reply.format != 8 {
return Err(ParseError::InvalidValue);
}
// Find the first zero byte in the value
let offset = reply
.value
.iter()
.position(|&v| v == 0)
.unwrap_or(reply.value.len());
Ok(Some(WmClass(reply, offset)))
}
/// Get the instance contained in this `WM_CLASS` property
pub fn instance(&self) -> &[u8] {
&self.0.value[0..self.1]
}
/// Get the class contained in this `WM_CLASS` property
pub fn class(&self) -> &[u8] {
let start = self.1 + 1;
if start >= self.0.value.len() {
return &[];
};
let end = if self.0.value.last() == Some(&0) {
self.0.value.len() - 1
} else {
self.0.value.len()
};
&self.0.value[start..end]
}
}
// WM_SIZE_HINTS
/// Representation of whether some part of `WM_SIZE_HINTS` was user/program specified.
#[derive(Debug, Copy, Clone)]
pub enum WmSizeHintsSpecification {
/// The user specified the values.
UserSpecified,
/// The program specified the values.
ProgramSpecified,
}
property_cookie! {
/// A cookie for getting a window's `WM_SIZE_HINTS` property.
pub struct WmSizeHintsCookie: WmSizeHints,
|reply| WmSizeHints::from_reply(&reply),
}
const NUM_WM_SIZE_HINTS_ELEMENTS: u16 = 18;
impl<'a, Conn> WmSizeHintsCookie<'a, Conn>
where
Conn: RequestConnection + ?Sized,
{
/// Send a `GetProperty` request for the given property of the given window
pub fn new(
conn: &'a Conn,
window: Window,
property: impl Into<Atom>,
) -> Result<Self, ConnectionError> {
Ok(Self(xproto::get_property(
conn,
false,
window,
property,
AtomEnum::WM_SIZE_HINTS,
0,
NUM_WM_SIZE_HINTS_ELEMENTS.into(),
)?))
}
}
// Possible flags for `WM_SIZE_HINTS`.
const U_S_POSITION: u32 = 1;
const U_S_SIZE: u32 = 1 << 1;
const P_S_POSITION: u32 = 1 << 2;
const P_S_SIZE: u32 = 1 << 3;
const P_MIN_SIZE: u32 = 1 << 4;
const P_MAX_SIZE: u32 = 1 << 5;
const P_RESIZE_INCREMENT: u32 = 1 << 6;
const P_ASPECT: u32 = 1 << 7;
const P_BASE_SIZE: u32 = 1 << 8;
const P_WIN_GRAVITY: u32 = 1 << 9;
/// An aspect ratio `numerator` / `denominator`.
#[derive(Debug, Copy, Clone)]
pub struct AspectRatio {
/// The numerator of the aspect ratio.
pub numerator: i32,
/// The denominator of the aspect ratio.
pub denominator: i32,
}
impl AspectRatio {
/// Create a new aspect ratio with the given values.
pub fn new(numerator: i32, denominator: i32) -> Self {
Self {
numerator,
denominator,
}
}
}
impl TryParse for AspectRatio {
fn try_parse(value: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let ((numerator, denominator), remaining) = TryParse::try_parse(value)?;
let result = AspectRatio::new(numerator, denominator);
Ok((result, remaining))
}
}
#[allow(clippy::many_single_char_names)]
impl Serialize for AspectRatio {
type Bytes = [u8; 8];
fn serialize(&self) -> Self::Bytes {
let [a, b, c, d] = self.numerator.serialize();
let [e, f, g, h] = self.denominator.serialize();
[a, b, c, d, e, f, g, h]
}
fn serialize_into(&self, bytes: &mut Vec<u8>) {
(self.numerator, self.denominator).serialize_into(bytes);
}
}
/// A structure representing a `WM_SIZE_HINTS` property.
#[derive(Debug, Default, Copy, Clone)]
pub struct WmSizeHints {
/// The position that the window should be assigned.
///
/// Note that current versions of ICCCM only make use of the `WmSizeHintsSpecification` field.
/// The later two fields exist only for backwards compatibility.
pub position: Option<(WmSizeHintsSpecification, i32, i32)>,
/// The size that the window should be assigned.
///
/// Note that current versions of ICCCM only make use of the `WmSizeHintsSpecification` field.
/// The later two fields exist only for backwards compatibility.
pub size: Option<(WmSizeHintsSpecification, i32, i32)>,
/// The minimum size that the window may be assigned.
pub min_size: Option<(i32, i32)>,
/// The maximum size that the window may be assigned.
pub max_size: Option<(i32, i32)>,
/// The increment to be used for sizing the window together with `base_size`.
pub size_increment: Option<(i32, i32)>,
/// The minimum and maximum aspect ratio.
pub aspect: Option<(AspectRatio, AspectRatio)>,
/// The base size of the window.
///
/// This is used together with `size_increment`.
pub base_size: Option<(i32, i32)>,
/// The gravity that is used to make room for window decorations.
pub win_gravity: Option<xproto::Gravity>,
}
impl WmSizeHints {
/// Get a new, empty `WmSizeHints` structure.
pub fn new() -> Self {
Default::default()
}
/// Send a `GetProperty` request for the given property of the given window
pub fn get<C: RequestConnection>(
conn: &C,
window: Window,
property: impl Into<Atom>,
) -> Result<WmSizeHintsCookie<'_, C>, ConnectionError> {
WmSizeHintsCookie::new(conn, window, property)
}
/// Send a `GetProperty` request for the `WM_NORMAL_HINTS` property of the given window
pub fn get_normal_hints<C: RequestConnection>(
conn: &C,
window: Window,
) -> Result<WmSizeHintsCookie<'_, C>, ConnectionError> {
Self::get(conn, window, AtomEnum::WM_NORMAL_HINTS)
}
/// Construct a new `WmSizeHints` instance from a `GetPropertyReply`.
///
/// The original `WmSizeHints` request must have been for a `WM_SIZE_HINTS` property for this
/// function to return sensible results.
pub fn from_reply(reply: &GetPropertyReply) -> Result<Option<Self>, ParseError> {
if reply.type_ == AtomEnum::NONE.into() {
return Ok(None);
}
if reply.type_ != AtomEnum::WM_SIZE_HINTS.into() || reply.format != 32 {
return Err(ParseError::InvalidValue);
}
Ok(Some(Self::try_parse(&reply.value)?.0))
}
/// Set these `WM_SIZE_HINTS` on some window as the `WM_NORMAL_HINTS` property.
pub fn set_normal_hints<'a, C: RequestConnection + ?Sized>(
&self,
conn: &'a C,
window: Window,
) -> Result<VoidCookie<'a, C>, ConnectionError> {
self.set(conn, window, AtomEnum::WM_NORMAL_HINTS)
}
/// Set these `WM_SIZE_HINTS` on some window as the given property.
pub fn set<'a, C: RequestConnection + ?Sized>(
&self,
conn: &'a C,
window: Window,
property: impl Into<Atom>,
) -> Result<VoidCookie<'a, C>, ConnectionError> {
let data = self.serialize();
xproto::change_property(
conn,
xproto::PropMode::REPLACE,
window,
property.into(),
AtomEnum::WM_SIZE_HINTS,
32,
NUM_WM_SIZE_HINTS_ELEMENTS.into(),
&data,
)
}
}
impl TryParse for WmSizeHints {
fn try_parse(remaining: &[u8]) -> Result<(Self, &[u8]), ParseError> {
// Implemented based on what xcb_icccm does. At least a bit. This stuff makes no sense...
let (flags, remaining) = u32::try_parse(remaining)?;
let (x, remaining) = i32::try_parse(remaining)?;
let (y, remaining) = i32::try_parse(remaining)?;
let (width, remaining) = i32::try_parse(remaining)?;
let (height, remaining) = i32::try_parse(remaining)?;
let (min_size, remaining) = parse_with_flag::<(i32, i32)>(remaining, flags, P_MIN_SIZE)?;
let (max_size, remaining) = parse_with_flag::<(i32, i32)>(remaining, flags, P_MAX_SIZE)?;
let (size_increment, remaining) =
parse_with_flag::<(i32, i32)>(remaining, flags, P_RESIZE_INCREMENT)?;
let (aspect, remaining) =
parse_with_flag::<(AspectRatio, AspectRatio)>(remaining, flags, P_ASPECT)?;
// Apparently, some older version of ICCCM didn't have these...?
let (base_size, win_gravity, remaining) = if remaining.is_empty() {
(min_size, Some(xproto::Gravity::NORTH_WEST), remaining)
} else {
let (base_size, remaining) =
parse_with_flag::<(i32, i32)>(remaining, flags, P_BASE_SIZE)?;
let (win_gravity, remaining) = parse_with_flag::<u32>(remaining, flags, P_WIN_GRAVITY)?;
(base_size, win_gravity.map(Into::into), remaining)
};
let position = if flags & U_S_POSITION != 0 {
Some((WmSizeHintsSpecification::UserSpecified, x, y))
} else if flags & P_S_POSITION != 0 {
Some((WmSizeHintsSpecification::ProgramSpecified, x, y))
} else {
None
};
let size = if flags & U_S_SIZE != 0 {
Some((WmSizeHintsSpecification::UserSpecified, width, height))
} else if flags & P_S_SIZE != 0 {
Some((WmSizeHintsSpecification::ProgramSpecified, width, height))
} else {
None
};
Ok((
WmSizeHints {
position,
size,
min_size,
max_size,
size_increment,
aspect,
base_size,
win_gravity,
},
remaining,
))
}
}
impl Serialize for WmSizeHints {
type Bytes = Vec<u8>;
fn serialize(&self) -> Self::Bytes {
let mut result = Vec::with_capacity((NUM_WM_SIZE_HINTS_ELEMENTS * 4).into());
self.serialize_into(&mut result);
result
}
fn serialize_into(&self, bytes: &mut Vec<u8>) {
let mut flags = 0;
match self.position {
Some((WmSizeHintsSpecification::UserSpecified, _, _)) => flags |= U_S_POSITION,
Some((WmSizeHintsSpecification::ProgramSpecified, _, _)) => flags |= P_S_POSITION,
None => {}
}
match self.size {
Some((WmSizeHintsSpecification::UserSpecified, _, _)) => flags |= U_S_SIZE,
Some((WmSizeHintsSpecification::ProgramSpecified, _, _)) => flags |= P_S_SIZE,
None => {}
}
flags |= self.min_size.map_or(0, |_| P_MIN_SIZE);
flags |= self.max_size.map_or(0, |_| P_MAX_SIZE);
flags |= self.size_increment.map_or(0, |_| P_RESIZE_INCREMENT);
flags |= self.aspect.map_or(0, |_| P_ASPECT);
flags |= self.base_size.map_or(0, |_| P_BASE_SIZE);
flags |= self.win_gravity.map_or(0, |_| P_WIN_GRAVITY);
flags.serialize_into(bytes);
match self.position {
Some((_, x, y)) => (x, y),
None => (0, 0),
}
.serialize_into(bytes);
match self.size {
Some((_, width, height)) => (width, height),
None => (0, 0),
}
.serialize_into(bytes);
self.min_size.unwrap_or((0, 0)).serialize_into(bytes);
self.max_size.unwrap_or((0, 0)).serialize_into(bytes);
self.size_increment.unwrap_or((0, 0)).serialize_into(bytes);
self.aspect
.unwrap_or((AspectRatio::new(0, 0), AspectRatio::new(0, 0)))
.serialize_into(bytes);
self.base_size.unwrap_or((0, 0)).serialize_into(bytes);
self.win_gravity.map_or(0, u32::from).serialize_into(bytes);
}
}
// WM_HINTS
//
property_cookie! {
/// A cookie for getting a window's `WM_HINTS` property.
///
/// See `WmHints`.
pub struct WmHintsCookie: WmHints,
|reply| WmHints::from_reply(&reply),
}
const NUM_WM_HINTS_ELEMENTS: u32 = 9;
impl<'a, Conn> WmHintsCookie<'a, Conn>
where
Conn: RequestConnection + ?Sized,
{
/// Send a `GetProperty` request for the `WM_CLASS` property of the given window
pub fn new(conn: &'a Conn, window: Window) -> Result<Self, ConnectionError> {
Ok(Self(xproto::get_property(
conn,
false,
window,
AtomEnum::WM_HINTS,
AtomEnum::WM_HINTS,
0,
NUM_WM_HINTS_ELEMENTS,
)?))
}
}
/// The possible values for a `WM_STATE`'s state field.
#[derive(Debug, Copy, Clone)]
pub enum WmHintsState {
/// The window should be in Normal state.
Normal,
/// The window should be in Iconic state.
Iconic,
}
// Possible flags for `WM_HINTS`.
const HINT_INPUT: u32 = 1;
const HINT_STATE: u32 = 1 << 1;
const HINT_ICON_PIXMAP: u32 = 1 << 2;
const HINT_ICON_WINDOW: u32 = 1 << 3;
const HINT_ICON_POSITION: u32 = 1 << 4;
const HINT_ICON_MASK: u32 = 1 << 5;
const HINT_WINDOW_GROUP: u32 = 1 << 6;
// This bit is obsolete, according to ICCCM
//const HINT_MESSAGE: u32 = 1 << 7;
const HINT_URGENCY: u32 = 1 << 8;
/// A structure representing a `WM_HINTS` property.
#[derive(Debug, Default, Copy, Clone)]
pub struct WmHints {
/// Whether the window manager may set the input focus to this window.
///
/// See ICCCM §4.1.7 for details.
pub input: Option<bool>,
/// The state that the window should be when it leaves the Withdrawn state.
pub initial_state: Option<WmHintsState>,
/// A pixmap that represents the icon of this window.
pub icon_pixmap: Option<xproto::Pixmap>,
/// A window that should be used as icon.
pub icon_window: Option<Window>,
/// The position where the icon should be shown.
pub icon_position: Option<(i32, i32)>,
/// A mask for `icon_pixmap`.
///
/// This allows nonrectangular icons.
pub icon_mask: Option<xproto::Pixmap>,
/// A window that represents a group of windows.
///
/// The specified window is called the "group leader". All windows with the same group leader
/// are part of the same group.
pub window_group: Option<Window>,
/// Indication that the window contents are urgent.
///
/// Urgency means that a timely response of the user is required. The window manager must make
/// some effort to draw the user's attention to this window while this flag is set.
pub urgent: bool,
}
impl WmHints {
/// Get a new, empty `WmSizeHints` structure.
pub fn new() -> Self {
Default::default()
}
/// Send a `GetProperty` request for the `WM_HINTS` property of the given window
pub fn get<C: RequestConnection>(
conn: &C,
window: Window,
) -> Result<WmHintsCookie<'_, C>, ConnectionError> {
WmHintsCookie::new(conn, window)
}
/// Construct a new `WmHints` instance from a `GetPropertyReply`.
///
/// The original `WmHints` request must have been for a `WM_HINTS` property for this
/// function to return sensible results.
pub fn from_reply(reply: &GetPropertyReply) -> Result<Option<Self>, ParseError> {
if reply.type_ == AtomEnum::NONE.into() {
return Ok(None);
}
if reply.type_ != AtomEnum::WM_HINTS.into() || reply.format != 32 {
return Err(ParseError::InvalidValue);
}
Ok(Some(Self::try_parse(&reply.value)?.0))
}
/// Set these `WM_HINTS` on some window.
pub fn set<'a, C: RequestConnection + ?Sized>(
&self,
conn: &'a C,
window: Window,
) -> Result<VoidCookie<'a, C>, ConnectionError> {
let data = self.serialize();
xproto::change_property(
conn,
xproto::PropMode::REPLACE,
window,
AtomEnum::WM_HINTS,
AtomEnum::WM_HINTS,
32,
NUM_WM_HINTS_ELEMENTS,
&data,
)
}
}
impl TryParse for WmHints {
fn try_parse(remaining: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let (flags, remaining) = u32::try_parse(remaining)?;
let (input, remaining) = parse_with_flag::<u32>(remaining, flags, HINT_INPUT)?;
let (initial_state, remaining) = parse_with_flag::<u32>(remaining, flags, HINT_STATE)?;
let (icon_pixmap, remaining) = parse_with_flag::<u32>(remaining, flags, HINT_ICON_PIXMAP)?;
let (icon_window, remaining) = parse_with_flag::<u32>(remaining, flags, HINT_ICON_WINDOW)?;
let (icon_position, remaining) =
parse_with_flag::<(i32, i32)>(remaining, flags, HINT_ICON_POSITION)?;
let (icon_mask, remaining) = parse_with_flag::<u32>(remaining, flags, HINT_ICON_MASK)?;
// Apparently, some older version of ICCCM didn't have this...?
let (window_group, remaining) = if remaining.is_empty() {
(None, remaining)
} else {
let (window_group, remaining) =
parse_with_flag::<u32>(remaining, flags, HINT_WINDOW_GROUP)?;
(window_group, remaining)
};
let input = input.map(|input| input != 0);
let initial_state = match initial_state {
None => None,
Some(1) => Some(WmHintsState::Normal),
Some(3) => Some(WmHintsState::Iconic),
_ => return Err(ParseError::InvalidValue),
};
let urgent = flags & HINT_URGENCY != 0;
Ok((
WmHints {
input,
initial_state,
icon_pixmap,
icon_window,
icon_position,
icon_mask,
window_group,
urgent,
},
remaining,
))
}
}
impl Serialize for WmHints {
type Bytes = Vec<u8>;
fn serialize(&self) -> Self::Bytes {
// 9*4 surely fits into an usize, so this unwrap() cannot trigger
let mut result = Vec::with_capacity((NUM_WM_HINTS_ELEMENTS * 4).try_into().unwrap());
self.serialize_into(&mut result);
result
}
fn serialize_into(&self, bytes: &mut Vec<u8>) {
let mut flags = 0;
flags |= self.input.map_or(0, |_| HINT_INPUT);
flags |= self.initial_state.map_or(0, |_| HINT_STATE);
flags |= self.icon_pixmap.map_or(0, |_| HINT_ICON_PIXMAP);
flags |= self.icon_window.map_or(0, |_| HINT_ICON_WINDOW);
flags |= self.icon_position.map_or(0, |_| HINT_ICON_POSITION);
flags |= self.icon_mask.map_or(0, |_| HINT_ICON_MASK);
flags |= self.window_group.map_or(0, |_| HINT_WINDOW_GROUP);
if self.urgent {
flags |= HINT_URGENCY;
}
flags.serialize_into(bytes);
u32::from(self.input.unwrap_or(false)).serialize_into(bytes);
match self.initial_state {
Some(WmHintsState::Normal) => 1,
Some(WmHintsState::Iconic) => 3,
None => 0,
}
.serialize_into(bytes);
self.icon_pixmap.unwrap_or(0).serialize_into(bytes);
self.icon_window.unwrap_or(0).serialize_into(bytes);
self.icon_position.unwrap_or((0, 0)).serialize_into(bytes);
self.icon_mask.unwrap_or(0).serialize_into(bytes);
self.window_group.unwrap_or(0).serialize_into(bytes);
}
}
/// Parse an element of type `T` and turn it into an `Option` by checking if the given `bit` is set
/// in `flags`.
fn parse_with_flag<T: TryParse>(
remaining: &[u8],
flags: u32,
bit: u32,
) -> Result<(Option<T>, &[u8]), ParseError> {
let (value, remaining) = T::try_parse(remaining)?;
if flags & bit != 0 {
Ok((Some(value), remaining))
} else {
Ok((None, remaining))
}
}
#[cfg(test)]
mod test {
use super::{WmClass, WmHints, WmHintsState, WmSizeHints};
use crate::protocol::xproto::{Atom, AtomEnum, GetPropertyReply, Gravity};
use crate::x11_utils::Serialize;
fn get_property_reply(value: &[u8], format: u8, type_: impl Into<Atom>) -> GetPropertyReply {
GetPropertyReply {
format,
sequence: 0,
length: 0,
type_: type_.into(),
bytes_after: 0,
value_len: value.len().try_into().unwrap(),
value: value.to_vec(),
}
}
#[test]
fn test_wm_class() {
for (input, instance, class) in &[
(&b""[..], &b""[..], &b""[..]),
(b"\0", b"", b""),
(b"\0\0", b"", b""),
(b"\0\0\0", b"", b"\0"),
(b"Hello World", b"Hello World", b""),
(b"Hello World\0", b"Hello World", b""),
(b"Hello\0World\0", b"Hello", b"World"),
(b"Hello\0World", b"Hello", b"World"),
(b"Hello\0World\0Good\0Day", b"Hello", b"World\0Good\0Day"),
] {
let wm_class = WmClass::from_reply(get_property_reply(input, 8, AtomEnum::STRING))
.unwrap()
.unwrap();
assert_eq!((wm_class.instance(), wm_class.class()), (*instance, *class));
}
}
#[test]
fn test_wm_class_missing() {
let wm_class = WmClass::from_reply(get_property_reply(&[], 0, AtomEnum::NONE)).unwrap();
assert!(wm_class.is_none());
}
#[test]
fn test_wm_normal_hints() {
// This is the value of some random xterm window.
// It was acquired via 'xtrace xprop WM_NORMAL_HINTS'.
let input = [
0x0000_0350,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0000_0015,
0x0000_0017,
0x0000_0000,
0x0000_0000,
0x0000_000a,
0x0000_0013,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0000_000b,
0x0000_0004,
0x0000_0001,
];
let input = input
.iter()
.flat_map(|v| u32::serialize(v).to_vec())
.collect::<Vec<u8>>();
let wm_size_hints =
WmSizeHints::from_reply(&get_property_reply(&input, 32, AtomEnum::WM_SIZE_HINTS))
.unwrap()
.unwrap();
assert!(
wm_size_hints.position.is_none(),
"{:?}",
wm_size_hints.position,
);
assert!(wm_size_hints.size.is_none(), "{:?}", wm_size_hints.size);
assert_eq!(wm_size_hints.min_size, Some((21, 23)));
assert_eq!(wm_size_hints.max_size, None);
assert_eq!(wm_size_hints.size_increment, Some((10, 19)));
assert!(wm_size_hints.aspect.is_none(), "{:?}", wm_size_hints.aspect);
assert_eq!(wm_size_hints.base_size, Some((11, 4)));
assert_eq!(wm_size_hints.win_gravity, Some(Gravity::NORTH_WEST));
assert_eq!(input, wm_size_hints.serialize());
}
#[test]
fn test_wm_normal_hints_missing() {
let wm_size_hints =
WmSizeHints::from_reply(&get_property_reply(&[], 0, AtomEnum::NONE)).unwrap();
assert!(wm_size_hints.is_none());
}
#[test]
fn test_wm_hints() {
// This is the value of some random xterm window.
// It was acquired via 'xtrace xprop WM_HINTS'.
let input = [
0x0000_0043,
0x0000_0001,
0x0000_0001,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0000_0000,
0x0060_0009,
];
let input = input
.iter()
.flat_map(|v| u32::serialize(v).to_vec())
.collect::<Vec<u8>>();
let wm_hints = WmHints::from_reply(&get_property_reply(&input, 32, AtomEnum::WM_HINTS))
.unwrap()
.unwrap();
assert_eq!(wm_hints.input, Some(true));
match wm_hints.initial_state {
Some(WmHintsState::Normal) => {}
value => panic!("Expected Some(Normal), but got {value:?}"),
}
assert_eq!(wm_hints.icon_pixmap, None);
assert_eq!(wm_hints.icon_window, None);
assert_eq!(wm_hints.icon_position, None);
assert_eq!(wm_hints.icon_mask, None);
assert_eq!(wm_hints.window_group, Some(0x0060_0009));
assert!(!wm_hints.urgent);
assert_eq!(input, wm_hints.serialize());
}
#[test]
fn test_wm_hints_missing() {
let wm_hints = WmHints::from_reply(&get_property_reply(&[], 0, AtomEnum::NONE)).unwrap();
assert!(wm_hints.is_none());
}
}

66
vendor/x11rb/src/protocol/bigreq.rs vendored Normal file
View File

@@ -0,0 +1,66 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `BigRequests` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::bigreq::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
/// Enable the BIG-REQUESTS extension.
///
/// This enables the BIG-REQUESTS extension, which allows for requests larger than
/// 262140 bytes in length. When enabled, if the 16-bit length field is zero, it
/// is immediately followed by a 32-bit length field specifying the length of the
/// request in 4-byte units.
pub fn enable<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, EnableReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = EnableRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
/// Enable the BIG-REQUESTS extension.
///
/// This enables the BIG-REQUESTS extension, which allows for requests larger than
/// 262140 bytes in length. When enabled, if the 16-bit length field is zero, it
/// is immediately followed by a 32-bit length field specifying the length of the
/// request in 4-byte units.
fn bigreq_enable(&self) -> Result<Cookie<'_, Self, EnableReply>, ConnectionError>
{
enable(self)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

321
vendor/x11rb/src/protocol/composite.rs vendored Normal file
View File

@@ -0,0 +1,321 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Composite` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xfixes;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::composite::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
/// Negotiate the version of Composite.
///
/// This negotiates the version of the Composite extension. It must be precede all
/// other requests using Composite. Failure to do so will cause a BadRequest error.
///
/// # Fields
///
/// * `client_major_version` - The major version supported by the client.
/// * `client_minor_version` - The minor version supported by the client.
pub fn query_version<Conn>(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Redirect the hierarchy starting at "window" to off-screen storage..
///
/// The hierarchy starting at 'window' is directed to off-screen
/// storage. When all clients enabling redirection terminate,
/// the redirection will automatically be disabled.
///
/// The root window may not be redirected. Doing so results in a Match
/// error.
///
/// # Fields
///
/// * `window` - The root of the hierarchy to redirect to off-screen storage.
/// * `update` - Whether contents are automatically mirrored to the parent window. If one client
/// already specifies an update type of Manual, any attempt by another to specify a
/// mode of Manual so will result in an Access error.
pub fn redirect_window<Conn>(conn: &Conn, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = RedirectWindowRequest {
window,
update,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Redirect all current and future children of window.
///
/// Hierarchies starting at all current and future children of window
/// will be redirected as in RedirectWindow. If update is Manual,
/// then painting of the window background during window manipulation
/// and ClearArea requests is inhibited.
///
/// # Fields
///
/// * `window` - The root of the hierarchy to redirect to off-screen storage.
/// * `update` - Whether contents are automatically mirrored to the parent window. If one client
/// already specifies an update type of Manual, any attempt by another to specify a
/// mode of Manual so will result in an Access error.
pub fn redirect_subwindows<Conn>(conn: &Conn, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = RedirectSubwindowsRequest {
window,
update,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Terminate redirection of the specified window..
///
/// Redirection of the specified window will be terminated. This cannot be
/// used if the window was redirected with RedirectSubwindows.
///
/// # Fields
///
/// * `window` - The window to terminate redirection of. Must be redirected by the
/// current client, or a Value error results.
/// * `update` - The update type passed to RedirectWindows. If this does not match the
/// previously requested update type, a Value error results.
pub fn unredirect_window<Conn>(conn: &Conn, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = UnredirectWindowRequest {
window,
update,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Terminate redirection of the specified windows children.
///
/// Redirection of all children of window will be terminated.
///
/// # Fields
///
/// * `window` - The window to terminate redirection of. Must have previously been
/// selected for sub-redirection by the current client, or a Value error
/// results.
/// * `update` - The update type passed to RedirectSubWindows. If this does not match
/// the previously requested update type, a Value error results.
pub fn unredirect_subwindows<Conn>(conn: &Conn, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = UnredirectSubwindowsRequest {
window,
update,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_region_from_border_clip<Conn>(conn: &Conn, region: xfixes::Region, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRegionFromBorderClipRequest {
region,
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn name_window_pixmap<Conn>(conn: &Conn, window: xproto::Window, pixmap: xproto::Pixmap) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = NameWindowPixmapRequest {
window,
pixmap,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_overlay_window<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetOverlayWindowReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetOverlayWindowRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn release_overlay_window<Conn>(conn: &Conn, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ReleaseOverlayWindowRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
/// Negotiate the version of Composite.
///
/// This negotiates the version of the Composite extension. It must be precede all
/// other requests using Composite. Failure to do so will cause a BadRequest error.
///
/// # Fields
///
/// * `client_major_version` - The major version supported by the client.
/// * `client_minor_version` - The minor version supported by the client.
fn composite_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
/// Redirect the hierarchy starting at "window" to off-screen storage..
///
/// The hierarchy starting at 'window' is directed to off-screen
/// storage. When all clients enabling redirection terminate,
/// the redirection will automatically be disabled.
///
/// The root window may not be redirected. Doing so results in a Match
/// error.
///
/// # Fields
///
/// * `window` - The root of the hierarchy to redirect to off-screen storage.
/// * `update` - Whether contents are automatically mirrored to the parent window. If one client
/// already specifies an update type of Manual, any attempt by another to specify a
/// mode of Manual so will result in an Access error.
fn composite_redirect_window(&self, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
redirect_window(self, window, update)
}
/// Redirect all current and future children of window.
///
/// Hierarchies starting at all current and future children of window
/// will be redirected as in RedirectWindow. If update is Manual,
/// then painting of the window background during window manipulation
/// and ClearArea requests is inhibited.
///
/// # Fields
///
/// * `window` - The root of the hierarchy to redirect to off-screen storage.
/// * `update` - Whether contents are automatically mirrored to the parent window. If one client
/// already specifies an update type of Manual, any attempt by another to specify a
/// mode of Manual so will result in an Access error.
fn composite_redirect_subwindows(&self, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
redirect_subwindows(self, window, update)
}
/// Terminate redirection of the specified window..
///
/// Redirection of the specified window will be terminated. This cannot be
/// used if the window was redirected with RedirectSubwindows.
///
/// # Fields
///
/// * `window` - The window to terminate redirection of. Must be redirected by the
/// current client, or a Value error results.
/// * `update` - The update type passed to RedirectWindows. If this does not match the
/// previously requested update type, a Value error results.
fn composite_unredirect_window(&self, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
unredirect_window(self, window, update)
}
/// Terminate redirection of the specified windows children.
///
/// Redirection of all children of window will be terminated.
///
/// # Fields
///
/// * `window` - The window to terminate redirection of. Must have previously been
/// selected for sub-redirection by the current client, or a Value error
/// results.
/// * `update` - The update type passed to RedirectSubWindows. If this does not match
/// the previously requested update type, a Value error results.
fn composite_unredirect_subwindows(&self, window: xproto::Window, update: Redirect) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
unredirect_subwindows(self, window, update)
}
fn composite_create_region_from_border_clip(&self, region: xfixes::Region, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_region_from_border_clip(self, region, window)
}
fn composite_name_window_pixmap(&self, window: xproto::Window, pixmap: xproto::Pixmap) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
name_window_pixmap(self, window, pixmap)
}
fn composite_get_overlay_window(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetOverlayWindowReply>, ConnectionError>
{
get_overlay_window(self, window)
}
fn composite_release_overlay_window(&self, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
release_overlay_window(self, window)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

356
vendor/x11rb/src/protocol/damage.rs vendored Normal file
View File

@@ -0,0 +1,356 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Damage` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xfixes;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::damage::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
/// Negotiate the version of the DAMAGE extension.
///
/// This negotiates the version of the DAMAGE extension. It must precede any other
/// request using the DAMAGE extension. Failure to do so will cause a BadRequest
/// error for those requests.
///
/// # Fields
///
/// * `client_major_version` - The major version supported by the client.
/// * `client_minor_version` - The minor version supported by the client.
pub fn query_version<Conn>(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Creates a Damage object to monitor changes to a drawable..
///
/// This creates a Damage object to monitor changes to a drawable, and specifies
/// the level of detail to be reported for changes.
///
/// We call changes made to pixel contents of windows and pixmaps 'damage'
/// throughout this extension.
///
/// Damage accumulates as drawing occurs in the drawable. Each drawing operation
/// 'damages' one or more rectangular areas within the drawable. The rectangles
/// are guaranteed to include the set of pixels modified by each operation, but
/// may include significantly more than just those pixels. The desire is for
/// the damage to strike a balance between the number of rectangles reported and
/// the extraneous area included. A reasonable goal is for each primitive
/// object drawn (line, string, rectangle) to be represented as a single
/// rectangle and for the damage area of the operation to be the union of these
/// rectangles.
///
/// The DAMAGE extension allows applications to either receive the raw
/// rectangles as a stream of events, or to have them partially processed within
/// the X server to reduce the amount of data transmitted as well as reduce the
/// processing latency once the repaint operation has started.
///
/// The Damage object holds any accumulated damage region and reflects the
/// relationship between the drawable selected for damage notification and the
/// drawable for which damage is tracked.
///
/// # Fields
///
/// * `damage` - The ID with which you will refer to the new Damage object, created by
/// `xcb_generate_id`.
/// * `drawable` - The ID of the drawable to be monitored.
/// * `level` - The level of detail to be provided in Damage events.
pub fn create<Conn>(conn: &Conn, damage: Damage, drawable: xproto::Drawable, level: ReportLevel) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRequest {
damage,
drawable,
level,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Destroys a previously created Damage object..
///
/// This destroys a Damage object and requests the X server stop reporting
/// the changes it was tracking.
///
/// # Fields
///
/// * `damage` - The ID you provided to `xcb_create_damage`.
pub fn destroy<Conn>(conn: &Conn, damage: Damage) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyRequest {
damage,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Remove regions from a previously created Damage object..
///
/// This updates the regions of damage recorded in a a Damage object.
/// See <https://www.x.org/releases/current/doc/damageproto/damageproto.txt>
/// for details.
///
/// # Fields
///
/// * `damage` - The ID you provided to `xcb_create_damage`.
pub fn subtract<Conn, A, B>(conn: &Conn, damage: Damage, repair: A, parts: B) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<xfixes::Region>,
B: Into<xfixes::Region>,
{
let repair: xfixes::Region = repair.into();
let parts: xfixes::Region = parts.into();
let request0 = SubtractRequest {
damage,
repair,
parts,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Add a region to a previously created Damage object..
///
/// This updates the regions of damage recorded in a a Damage object.
/// See <https://www.x.org/releases/current/doc/damageproto/damageproto.txt>
/// for details.
///
/// # Fields
///
/// * `damage` - The ID you provided to `xcb_create_damage`.
pub fn add<Conn>(conn: &Conn, drawable: xproto::Drawable, region: xfixes::Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AddRequest {
drawable,
region,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
/// Negotiate the version of the DAMAGE extension.
///
/// This negotiates the version of the DAMAGE extension. It must precede any other
/// request using the DAMAGE extension. Failure to do so will cause a BadRequest
/// error for those requests.
///
/// # Fields
///
/// * `client_major_version` - The major version supported by the client.
/// * `client_minor_version` - The minor version supported by the client.
fn damage_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
/// Creates a Damage object to monitor changes to a drawable..
///
/// This creates a Damage object to monitor changes to a drawable, and specifies
/// the level of detail to be reported for changes.
///
/// We call changes made to pixel contents of windows and pixmaps 'damage'
/// throughout this extension.
///
/// Damage accumulates as drawing occurs in the drawable. Each drawing operation
/// 'damages' one or more rectangular areas within the drawable. The rectangles
/// are guaranteed to include the set of pixels modified by each operation, but
/// may include significantly more than just those pixels. The desire is for
/// the damage to strike a balance between the number of rectangles reported and
/// the extraneous area included. A reasonable goal is for each primitive
/// object drawn (line, string, rectangle) to be represented as a single
/// rectangle and for the damage area of the operation to be the union of these
/// rectangles.
///
/// The DAMAGE extension allows applications to either receive the raw
/// rectangles as a stream of events, or to have them partially processed within
/// the X server to reduce the amount of data transmitted as well as reduce the
/// processing latency once the repaint operation has started.
///
/// The Damage object holds any accumulated damage region and reflects the
/// relationship between the drawable selected for damage notification and the
/// drawable for which damage is tracked.
///
/// # Fields
///
/// * `damage` - The ID with which you will refer to the new Damage object, created by
/// `xcb_generate_id`.
/// * `drawable` - The ID of the drawable to be monitored.
/// * `level` - The level of detail to be provided in Damage events.
fn damage_create(&self, damage: Damage, drawable: xproto::Drawable, level: ReportLevel) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create(self, damage, drawable, level)
}
/// Destroys a previously created Damage object..
///
/// This destroys a Damage object and requests the X server stop reporting
/// the changes it was tracking.
///
/// # Fields
///
/// * `damage` - The ID you provided to `xcb_create_damage`.
fn damage_destroy(&self, damage: Damage) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy(self, damage)
}
/// Remove regions from a previously created Damage object..
///
/// This updates the regions of damage recorded in a a Damage object.
/// See <https://www.x.org/releases/current/doc/damageproto/damageproto.txt>
/// for details.
///
/// # Fields
///
/// * `damage` - The ID you provided to `xcb_create_damage`.
fn damage_subtract<A, B>(&self, damage: Damage, repair: A, parts: B) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<xfixes::Region>,
B: Into<xfixes::Region>,
{
subtract(self, damage, repair, parts)
}
/// Add a region to a previously created Damage object..
///
/// This updates the regions of damage recorded in a a Damage object.
/// See <https://www.x.org/releases/current/doc/damageproto/damageproto.txt>
/// for details.
///
/// # Fields
///
/// * `damage` - The ID you provided to `xcb_create_damage`.
fn damage_add(&self, drawable: xproto::Drawable, region: xfixes::Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
add(self, drawable, region)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around a [Damage].
///
/// Instances of this struct represent a Damage that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct DamageWrapper<C: RequestConnection>(C, Damage);
impl<C: RequestConnection> DamageWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_damage(conn: C, id: Damage) -> Self {
DamageWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn damage(&self) -> Damage {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_damage(self) -> Damage {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> DamageWrapper<&'c C>
{
/// Create a new Damage and return a Damage wrapper and a cookie.
///
/// This is a thin wrapper around [create] that allocates an id for the Damage.
/// This function returns the resulting `DamageWrapper` that owns the created Damage and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create].
pub fn create_and_get_cookie(conn: &'c C, drawable: xproto::Drawable, level: ReportLevel) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let damage = conn.generate_id()?;
let cookie = create(conn, damage, drawable, level)?;
Ok((Self::for_damage(conn, damage), cookie))
}
}
impl<C: X11Connection> DamageWrapper<C>
{
/// Create a new Damage and return a Damage wrapper
///
/// This is a thin wrapper around [create] that allocates an id for the Damage.
/// This function returns the resulting `DamageWrapper` that owns the created Damage and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create].
pub fn create(conn: C, drawable: xproto::Drawable, level: ReportLevel) -> Result<Self, ReplyOrIdError>
{
let damage = conn.generate_id()?;
let _ = create(&conn, damage, drawable, level)?;
Ok(Self::for_damage(conn, damage))
}
}
impl<C: RequestConnection> From<&DamageWrapper<C>> for Damage {
fn from(from: &DamageWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for DamageWrapper<C> {
fn drop(&mut self) {
let _ = destroy(&self.0, self.1);
}
}

266
vendor/x11rb/src/protocol/dbe.rs vendored Normal file
View File

@@ -0,0 +1,266 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Dbe` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::dbe::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
/// Queries the version of this extension.
///
/// Queries the version of this extension. You must do this before using any functionality it provides.
///
/// # Fields
///
/// * `major_version` - The major version of the extension. Check that it is compatible with the XCB_DBE_MAJOR_VERSION that your code is compiled with.
/// * `minor_version` - The minor version of the extension. Check that it is compatible with the XCB_DBE_MINOR_VERSION that your code is compiled with.
pub fn query_version<Conn>(conn: &Conn, major_version: u8, minor_version: u8) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Allocates a back buffer.
///
/// Associates `buffer` with the back buffer of `window`. Multiple ids may be associated with the back buffer, which is created by the first allocate call and destroyed by the last deallocate.
///
/// # Fields
///
/// * `window` - The window to which to add the back buffer.
/// * `buffer` - The buffer id to associate with the back buffer.
/// * `swap_action` - The swap action most likely to be used to present this back buffer. This is only a hint, and does not preclude the use of other swap actions.
pub fn allocate_back_buffer<Conn>(conn: &Conn, window: xproto::Window, buffer: BackBuffer, swap_action: u8) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AllocateBackBufferRequest {
window,
buffer,
swap_action,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Deallocates a back buffer.
///
/// Deallocates the given `buffer`. If `buffer` is an invalid id, a `BadBuffer` error is returned. Because a window may have allocated multiple back buffer ids, the back buffer itself is not deleted until all these ids are deallocated by this call.
///
/// # Fields
///
/// * `buffer` - The back buffer to deallocate.
pub fn deallocate_back_buffer<Conn>(conn: &Conn, buffer: BackBuffer) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeallocateBackBufferRequest {
buffer,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Swaps front and back buffers.
///
/// Swaps the front and back buffers on the specified windows. The front and back buffers retain their ids, so that the window id continues to refer to the front buffer, while the back buffer id created by this extension continues to refer to the back buffer. Back buffer contents is moved to the front buffer. Back buffer contents after the operation depends on the given swap action. The optimal swap action depends on how each frame is rendered. For example, if the buffer is cleared and fully overwritten on every frame, the "untouched" action, which throws away the buffer contents, would provide the best performance. To eliminate visual artifacts, the swap will occure during the monitor VSync, if the X server supports detecting it.
///
/// # Fields
///
/// * `n_actions` - Number of swap actions in `actions`.
/// * `actions` - List of windows on which to swap buffers.
pub fn swap_buffers<'c, 'input, Conn>(conn: &'c Conn, actions: &'input [SwapInfo]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SwapBuffersRequest {
actions: Cow::Borrowed(actions),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Begins a logical swap block.
///
/// Creates a block of operations intended to occur together. This may be needed if window presentation requires changing buffers unknown to this extension, such as depth or stencil buffers.
pub fn begin_idiom<Conn>(conn: &Conn) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = BeginIdiomRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Ends a logical swap block.
pub fn end_idiom<Conn>(conn: &Conn) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = EndIdiomRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Requests visuals that support double buffering.
pub fn get_visual_info<'c, 'input, Conn>(conn: &'c Conn, drawables: &'input [xproto::Drawable]) -> Result<Cookie<'c, Conn, GetVisualInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetVisualInfoRequest {
drawables: Cow::Borrowed(drawables),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Gets back buffer attributes.
///
/// Returns the attributes of the specified `buffer`.
///
/// # Fields
///
/// * `buffer` - The back buffer to query.
/// * `attributes` - The attributes of `buffer`.
pub fn get_back_buffer_attributes<Conn>(conn: &Conn, buffer: BackBuffer) -> Result<Cookie<'_, Conn, GetBackBufferAttributesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetBackBufferAttributesRequest {
buffer,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
/// Queries the version of this extension.
///
/// Queries the version of this extension. You must do this before using any functionality it provides.
///
/// # Fields
///
/// * `major_version` - The major version of the extension. Check that it is compatible with the XCB_DBE_MAJOR_VERSION that your code is compiled with.
/// * `minor_version` - The minor version of the extension. Check that it is compatible with the XCB_DBE_MINOR_VERSION that your code is compiled with.
fn dbe_query_version(&self, major_version: u8, minor_version: u8) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major_version, minor_version)
}
/// Allocates a back buffer.
///
/// Associates `buffer` with the back buffer of `window`. Multiple ids may be associated with the back buffer, which is created by the first allocate call and destroyed by the last deallocate.
///
/// # Fields
///
/// * `window` - The window to which to add the back buffer.
/// * `buffer` - The buffer id to associate with the back buffer.
/// * `swap_action` - The swap action most likely to be used to present this back buffer. This is only a hint, and does not preclude the use of other swap actions.
fn dbe_allocate_back_buffer(&self, window: xproto::Window, buffer: BackBuffer, swap_action: u8) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
allocate_back_buffer(self, window, buffer, swap_action)
}
/// Deallocates a back buffer.
///
/// Deallocates the given `buffer`. If `buffer` is an invalid id, a `BadBuffer` error is returned. Because a window may have allocated multiple back buffer ids, the back buffer itself is not deleted until all these ids are deallocated by this call.
///
/// # Fields
///
/// * `buffer` - The back buffer to deallocate.
fn dbe_deallocate_back_buffer(&self, buffer: BackBuffer) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
deallocate_back_buffer(self, buffer)
}
/// Swaps front and back buffers.
///
/// Swaps the front and back buffers on the specified windows. The front and back buffers retain their ids, so that the window id continues to refer to the front buffer, while the back buffer id created by this extension continues to refer to the back buffer. Back buffer contents is moved to the front buffer. Back buffer contents after the operation depends on the given swap action. The optimal swap action depends on how each frame is rendered. For example, if the buffer is cleared and fully overwritten on every frame, the "untouched" action, which throws away the buffer contents, would provide the best performance. To eliminate visual artifacts, the swap will occure during the monitor VSync, if the X server supports detecting it.
///
/// # Fields
///
/// * `n_actions` - Number of swap actions in `actions`.
/// * `actions` - List of windows on which to swap buffers.
fn dbe_swap_buffers<'c, 'input>(&'c self, actions: &'input [SwapInfo]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
swap_buffers(self, actions)
}
/// Begins a logical swap block.
///
/// Creates a block of operations intended to occur together. This may be needed if window presentation requires changing buffers unknown to this extension, such as depth or stencil buffers.
fn dbe_begin_idiom(&self) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
begin_idiom(self)
}
/// Ends a logical swap block.
fn dbe_end_idiom(&self) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
end_idiom(self)
}
/// Requests visuals that support double buffering.
fn dbe_get_visual_info<'c, 'input>(&'c self, drawables: &'input [xproto::Drawable]) -> Result<Cookie<'c, Self, GetVisualInfoReply>, ConnectionError>
{
get_visual_info(self, drawables)
}
/// Gets back buffer attributes.
///
/// Returns the attributes of the specified `buffer`.
///
/// # Fields
///
/// * `buffer` - The back buffer to query.
/// * `attributes` - The attributes of `buffer`.
fn dbe_get_back_buffer_attributes(&self, buffer: BackBuffer) -> Result<Cookie<'_, Self, GetBackBufferAttributesReply>, ConnectionError>
{
get_back_buffer_attributes(self, buffer)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

187
vendor/x11rb/src/protocol/dpms.rs vendored Normal file
View File

@@ -0,0 +1,187 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `DPMS` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::dpms::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn get_version<Conn>(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Conn, GetVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn capable<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, CapableReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CapableRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_timeouts<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetTimeoutsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetTimeoutsRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_timeouts<Conn>(conn: &Conn, standby_timeout: u16, suspend_timeout: u16, off_timeout: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetTimeoutsRequest {
standby_timeout,
suspend_timeout,
off_timeout,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn enable<Conn>(conn: &Conn) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = EnableRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn disable<Conn>(conn: &Conn) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DisableRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn force_level<Conn>(conn: &Conn, power_level: DPMSMode) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ForceLevelRequest {
power_level,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn info<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, InfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = InfoRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn select_input<Conn>(conn: &Conn, event_mask: EventMask) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn dpms_get_version(&self, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Self, GetVersionReply>, ConnectionError>
{
get_version(self, client_major_version, client_minor_version)
}
fn dpms_capable(&self) -> Result<Cookie<'_, Self, CapableReply>, ConnectionError>
{
capable(self)
}
fn dpms_get_timeouts(&self) -> Result<Cookie<'_, Self, GetTimeoutsReply>, ConnectionError>
{
get_timeouts(self)
}
fn dpms_set_timeouts(&self, standby_timeout: u16, suspend_timeout: u16, off_timeout: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_timeouts(self, standby_timeout, suspend_timeout, off_timeout)
}
fn dpms_enable(&self) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
enable(self)
}
fn dpms_disable(&self) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
disable(self)
}
fn dpms_force_level(&self, power_level: DPMSMode) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
force_level(self, power_level)
}
fn dpms_info(&self) -> Result<Cookie<'_, Self, InfoReply>, ConnectionError>
{
info(self)
}
fn dpms_select_input(&self, event_mask: EventMask) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_input(self, event_mask)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

305
vendor/x11rb/src/protocol/dri2.rs vendored Normal file
View File

@@ -0,0 +1,305 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `DRI2` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::dri2::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn connect<Conn>(conn: &Conn, window: xproto::Window, driver_type: DriverType) -> Result<Cookie<'_, Conn, ConnectReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ConnectRequest {
window,
driver_type,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn authenticate<Conn>(conn: &Conn, window: xproto::Window, magic: u32) -> Result<Cookie<'_, Conn, AuthenticateReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AuthenticateRequest {
window,
magic,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_drawable<Conn>(conn: &Conn, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateDrawableRequest {
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn destroy_drawable<Conn>(conn: &Conn, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyDrawableRequest {
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_buffers<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, count: u32, attachments: &'input [u32]) -> Result<Cookie<'c, Conn, GetBuffersReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetBuffersRequest {
drawable,
count,
attachments: Cow::Borrowed(attachments),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn copy_region<Conn>(conn: &Conn, drawable: xproto::Drawable, region: u32, dest: u32, src: u32) -> Result<Cookie<'_, Conn, CopyRegionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CopyRegionRequest {
drawable,
region,
dest,
src,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_buffers_with_format<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, count: u32, attachments: &'input [AttachFormat]) -> Result<Cookie<'c, Conn, GetBuffersWithFormatReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetBuffersWithFormatRequest {
drawable,
count,
attachments: Cow::Borrowed(attachments),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn swap_buffers<Conn>(conn: &Conn, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result<Cookie<'_, Conn, SwapBuffersReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SwapBuffersRequest {
drawable,
target_msc_hi,
target_msc_lo,
divisor_hi,
divisor_lo,
remainder_hi,
remainder_lo,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_msc<Conn>(conn: &Conn, drawable: xproto::Drawable) -> Result<Cookie<'_, Conn, GetMSCReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetMSCRequest {
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn wait_msc<Conn>(conn: &Conn, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result<Cookie<'_, Conn, WaitMSCReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = WaitMSCRequest {
drawable,
target_msc_hi,
target_msc_lo,
divisor_hi,
divisor_lo,
remainder_hi,
remainder_lo,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn wait_sbc<Conn>(conn: &Conn, drawable: xproto::Drawable, target_sbc_hi: u32, target_sbc_lo: u32) -> Result<Cookie<'_, Conn, WaitSBCReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = WaitSBCRequest {
drawable,
target_sbc_hi,
target_sbc_lo,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn swap_interval<Conn>(conn: &Conn, drawable: xproto::Drawable, interval: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SwapIntervalRequest {
drawable,
interval,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_param<Conn>(conn: &Conn, drawable: xproto::Drawable, param: u32) -> Result<Cookie<'_, Conn, GetParamReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetParamRequest {
drawable,
param,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn dri2_query_version(&self, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major_version, minor_version)
}
fn dri2_connect(&self, window: xproto::Window, driver_type: DriverType) -> Result<Cookie<'_, Self, ConnectReply>, ConnectionError>
{
connect(self, window, driver_type)
}
fn dri2_authenticate(&self, window: xproto::Window, magic: u32) -> Result<Cookie<'_, Self, AuthenticateReply>, ConnectionError>
{
authenticate(self, window, magic)
}
fn dri2_create_drawable(&self, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_drawable(self, drawable)
}
fn dri2_destroy_drawable(&self, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_drawable(self, drawable)
}
fn dri2_get_buffers<'c, 'input>(&'c self, drawable: xproto::Drawable, count: u32, attachments: &'input [u32]) -> Result<Cookie<'c, Self, GetBuffersReply>, ConnectionError>
{
get_buffers(self, drawable, count, attachments)
}
fn dri2_copy_region(&self, drawable: xproto::Drawable, region: u32, dest: u32, src: u32) -> Result<Cookie<'_, Self, CopyRegionReply>, ConnectionError>
{
copy_region(self, drawable, region, dest, src)
}
fn dri2_get_buffers_with_format<'c, 'input>(&'c self, drawable: xproto::Drawable, count: u32, attachments: &'input [AttachFormat]) -> Result<Cookie<'c, Self, GetBuffersWithFormatReply>, ConnectionError>
{
get_buffers_with_format(self, drawable, count, attachments)
}
fn dri2_swap_buffers(&self, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result<Cookie<'_, Self, SwapBuffersReply>, ConnectionError>
{
swap_buffers(self, drawable, target_msc_hi, target_msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo)
}
fn dri2_get_msc(&self, drawable: xproto::Drawable) -> Result<Cookie<'_, Self, GetMSCReply>, ConnectionError>
{
get_msc(self, drawable)
}
fn dri2_wait_msc(&self, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result<Cookie<'_, Self, WaitMSCReply>, ConnectionError>
{
wait_msc(self, drawable, target_msc_hi, target_msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo)
}
fn dri2_wait_sbc(&self, drawable: xproto::Drawable, target_sbc_hi: u32, target_sbc_lo: u32) -> Result<Cookie<'_, Self, WaitSBCReply>, ConnectionError>
{
wait_sbc(self, drawable, target_sbc_hi, target_sbc_lo)
}
fn dri2_swap_interval(&self, drawable: xproto::Drawable, interval: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
swap_interval(self, drawable, interval)
}
fn dri2_get_param(&self, drawable: xproto::Drawable, param: u32) -> Result<Cookie<'_, Self, GetParamReply>, ConnectionError>
{
get_param(self, drawable, param)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

292
vendor/x11rb/src/protocol/dri3.rs vendored Normal file
View File

@@ -0,0 +1,292 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `DRI3` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::dri3::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn open<Conn>(conn: &Conn, drawable: xproto::Drawable, provider: u32) -> Result<CookieWithFds<'_, Conn, OpenReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = OpenRequest {
drawable,
provider,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply_with_fds(&slices, fds)
}
pub fn pixmap_from_buffer<Conn, A>(conn: &Conn, pixmap: xproto::Pixmap, drawable: xproto::Drawable, size: u32, width: u16, height: u16, stride: u16, depth: u8, bpp: u8, pixmap_fd: A) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<RawFdContainer>,
{
let pixmap_fd: RawFdContainer = pixmap_fd.into();
let request0 = PixmapFromBufferRequest {
pixmap,
drawable,
size,
width,
height,
stride,
depth,
bpp,
pixmap_fd,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn buffer_from_pixmap<Conn>(conn: &Conn, pixmap: xproto::Pixmap) -> Result<CookieWithFds<'_, Conn, BufferFromPixmapReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = BufferFromPixmapRequest {
pixmap,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply_with_fds(&slices, fds)
}
pub fn fence_from_fd<Conn, A>(conn: &Conn, drawable: xproto::Drawable, fence: u32, initially_triggered: bool, fence_fd: A) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<RawFdContainer>,
{
let fence_fd: RawFdContainer = fence_fd.into();
let request0 = FenceFromFDRequest {
drawable,
fence,
initially_triggered,
fence_fd,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn fd_from_fence<Conn>(conn: &Conn, drawable: xproto::Drawable, fence: u32) -> Result<CookieWithFds<'_, Conn, FDFromFenceReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FDFromFenceRequest {
drawable,
fence,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply_with_fds(&slices, fds)
}
pub fn get_supported_modifiers<Conn>(conn: &Conn, window: u32, depth: u8, bpp: u8) -> Result<Cookie<'_, Conn, GetSupportedModifiersReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetSupportedModifiersRequest {
window,
depth,
bpp,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn pixmap_from_buffers<Conn>(conn: &Conn, pixmap: xproto::Pixmap, window: xproto::Window, width: u16, height: u16, stride0: u32, offset0: u32, stride1: u32, offset1: u32, stride2: u32, offset2: u32, stride3: u32, offset3: u32, depth: u8, bpp: u8, modifier: u64, buffers: Vec<RawFdContainer>) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PixmapFromBuffersRequest {
pixmap,
window,
width,
height,
stride0,
offset0,
stride1,
offset1,
stride2,
offset2,
stride3,
offset3,
depth,
bpp,
modifier,
buffers,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn buffers_from_pixmap<Conn>(conn: &Conn, pixmap: xproto::Pixmap) -> Result<CookieWithFds<'_, Conn, BuffersFromPixmapReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = BuffersFromPixmapRequest {
pixmap,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply_with_fds(&slices, fds)
}
pub fn set_drm_device_in_use<Conn>(conn: &Conn, window: xproto::Window, drm_major: u32, drm_minor: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetDRMDeviceInUseRequest {
window,
drm_major,
drm_minor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn import_syncobj<Conn, A>(conn: &Conn, syncobj: Syncobj, drawable: xproto::Drawable, syncobj_fd: A) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<RawFdContainer>,
{
let syncobj_fd: RawFdContainer = syncobj_fd.into();
let request0 = ImportSyncobjRequest {
syncobj,
drawable,
syncobj_fd,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn free_syncobj<Conn>(conn: &Conn, syncobj: Syncobj) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FreeSyncobjRequest {
syncobj,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn dri3_query_version(&self, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major_version, minor_version)
}
fn dri3_open(&self, drawable: xproto::Drawable, provider: u32) -> Result<CookieWithFds<'_, Self, OpenReply>, ConnectionError>
{
open(self, drawable, provider)
}
fn dri3_pixmap_from_buffer<A>(&self, pixmap: xproto::Pixmap, drawable: xproto::Drawable, size: u32, width: u16, height: u16, stride: u16, depth: u8, bpp: u8, pixmap_fd: A) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<RawFdContainer>,
{
pixmap_from_buffer(self, pixmap, drawable, size, width, height, stride, depth, bpp, pixmap_fd)
}
fn dri3_buffer_from_pixmap(&self, pixmap: xproto::Pixmap) -> Result<CookieWithFds<'_, Self, BufferFromPixmapReply>, ConnectionError>
{
buffer_from_pixmap(self, pixmap)
}
fn dri3_fence_from_fd<A>(&self, drawable: xproto::Drawable, fence: u32, initially_triggered: bool, fence_fd: A) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<RawFdContainer>,
{
fence_from_fd(self, drawable, fence, initially_triggered, fence_fd)
}
fn dri3_fd_from_fence(&self, drawable: xproto::Drawable, fence: u32) -> Result<CookieWithFds<'_, Self, FDFromFenceReply>, ConnectionError>
{
fd_from_fence(self, drawable, fence)
}
fn dri3_get_supported_modifiers(&self, window: u32, depth: u8, bpp: u8) -> Result<Cookie<'_, Self, GetSupportedModifiersReply>, ConnectionError>
{
get_supported_modifiers(self, window, depth, bpp)
}
fn dri3_pixmap_from_buffers(&self, pixmap: xproto::Pixmap, window: xproto::Window, width: u16, height: u16, stride0: u32, offset0: u32, stride1: u32, offset1: u32, stride2: u32, offset2: u32, stride3: u32, offset3: u32, depth: u8, bpp: u8, modifier: u64, buffers: Vec<RawFdContainer>) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
pixmap_from_buffers(self, pixmap, window, width, height, stride0, offset0, stride1, offset1, stride2, offset2, stride3, offset3, depth, bpp, modifier, buffers)
}
fn dri3_buffers_from_pixmap(&self, pixmap: xproto::Pixmap) -> Result<CookieWithFds<'_, Self, BuffersFromPixmapReply>, ConnectionError>
{
buffers_from_pixmap(self, pixmap)
}
fn dri3_set_drm_device_in_use(&self, window: xproto::Window, drm_major: u32, drm_minor: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_drm_device_in_use(self, window, drm_major, drm_minor)
}
fn dri3_import_syncobj<A>(&self, syncobj: Syncobj, drawable: xproto::Drawable, syncobj_fd: A) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<RawFdContainer>,
{
import_syncobj(self, syncobj, drawable, syncobj_fd)
}
fn dri3_free_syncobj(&self, syncobj: Syncobj) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
free_syncobj(self, syncobj)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

57
vendor/x11rb/src/protocol/ge.rs vendored Normal file
View File

@@ -0,0 +1,57 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `GenericEvent` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::ge::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn ge_query_version(&self, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

1945
vendor/x11rb/src/protocol/glx.rs vendored Normal file

File diff suppressed because it is too large Load Diff

77
vendor/x11rb/src/protocol/mod.rs vendored Normal file
View File

@@ -0,0 +1,77 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the X11 protocol.
//!
//! Each sub-module of this module corresponds to one X11 extension. It contains all the
//! definitions from that extension. The core X11 protocol is in [`xproto`](xproto/index.html).
// Clippy does not like some names from the XML.
#![allow(clippy::upper_case_acronyms)]
// This is not easy to fix, so ignore it.
#![allow(clippy::needless_borrow, clippy::needless_lifetimes)]
pub mod xproto;
pub mod bigreq;
#[cfg(feature = "composite")]
pub mod composite;
#[cfg(feature = "damage")]
pub mod damage;
#[cfg(feature = "dbe")]
pub mod dbe;
#[cfg(feature = "dpms")]
pub mod dpms;
#[cfg(feature = "dri2")]
pub mod dri2;
#[cfg(feature = "dri3")]
pub mod dri3;
pub mod ge;
#[cfg(feature = "glx")]
pub mod glx;
#[cfg(feature = "present")]
pub mod present;
#[cfg(feature = "randr")]
pub mod randr;
#[cfg(feature = "record")]
pub mod record;
#[cfg(feature = "render")]
pub mod render;
#[cfg(feature = "res")]
pub mod res;
#[cfg(feature = "screensaver")]
pub mod screensaver;
#[cfg(feature = "shape")]
pub mod shape;
#[cfg(feature = "shm")]
pub mod shm;
#[cfg(feature = "sync")]
pub mod sync;
pub mod xc_misc;
#[cfg(feature = "xevie")]
pub mod xevie;
#[cfg(feature = "xf86dri")]
pub mod xf86dri;
#[cfg(feature = "xf86vidmode")]
pub mod xf86vidmode;
#[cfg(feature = "xfixes")]
pub mod xfixes;
#[cfg(feature = "xinerama")]
pub mod xinerama;
#[cfg(feature = "xinput")]
pub mod xinput;
#[cfg(feature = "xkb")]
pub mod xkb;
#[cfg(feature = "xprint")]
pub mod xprint;
#[cfg(feature = "xselinux")]
pub mod xselinux;
#[cfg(feature = "xtest")]
pub mod xtest;
#[cfg(feature = "xv")]
pub mod xv;
#[cfg(feature = "xvmc")]
pub mod xvmc;
pub use x11rb_protocol::protocol::Request;
pub use x11rb_protocol::protocol::Reply;
pub use x11rb_protocol::protocol::ErrorKind;
pub use x11rb_protocol::protocol::Event;

188
vendor/x11rb/src/protocol/present.rs vendored Normal file
View File

@@ -0,0 +1,188 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Present` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::dri3;
#[allow(unused_imports)]
use super::randr;
#[allow(unused_imports)]
use super::sync;
#[allow(unused_imports)]
use super::xfixes;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::present::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn pixmap<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, pixmap: xproto::Pixmap, serial: u32, valid: xfixes::Region, update: xfixes::Region, x_off: i16, y_off: i16, target_crtc: randr::Crtc, wait_fence: sync::Fence, idle_fence: sync::Fence, options: u32, target_msc: u64, divisor: u64, remainder: u64, notifies: &'input [Notify]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PixmapRequest {
window,
pixmap,
serial,
valid,
update,
x_off,
y_off,
target_crtc,
wait_fence,
idle_fence,
options,
target_msc,
divisor,
remainder,
notifies: Cow::Borrowed(notifies),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn notify_msc<Conn>(conn: &Conn, window: xproto::Window, serial: u32, target_msc: u64, divisor: u64, remainder: u64) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = NotifyMSCRequest {
window,
serial,
target_msc,
divisor,
remainder,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn select_input<Conn>(conn: &Conn, eid: Event, window: xproto::Window, event_mask: EventMask) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
eid,
window,
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_capabilities<Conn>(conn: &Conn, target: u32) -> Result<Cookie<'_, Conn, QueryCapabilitiesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryCapabilitiesRequest {
target,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn pixmap_synced<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, pixmap: xproto::Pixmap, serial: u32, valid: xfixes::Region, update: xfixes::Region, x_off: i16, y_off: i16, target_crtc: randr::Crtc, acquire_syncobj: dri3::Syncobj, release_syncobj: dri3::Syncobj, acquire_point: u64, release_point: u64, options: u32, target_msc: u64, divisor: u64, remainder: u64, notifies: &'input [Notify]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PixmapSyncedRequest {
window,
pixmap,
serial,
valid,
update,
x_off,
y_off,
target_crtc,
acquire_syncobj,
release_syncobj,
acquire_point,
release_point,
options,
target_msc,
divisor,
remainder,
notifies: Cow::Borrowed(notifies),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn present_query_version(&self, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major_version, minor_version)
}
fn present_pixmap<'c, 'input>(&'c self, window: xproto::Window, pixmap: xproto::Pixmap, serial: u32, valid: xfixes::Region, update: xfixes::Region, x_off: i16, y_off: i16, target_crtc: randr::Crtc, wait_fence: sync::Fence, idle_fence: sync::Fence, options: u32, target_msc: u64, divisor: u64, remainder: u64, notifies: &'input [Notify]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
self::pixmap(self, window, pixmap, serial, valid, update, x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc, divisor, remainder, notifies)
}
fn present_notify_msc(&self, window: xproto::Window, serial: u32, target_msc: u64, divisor: u64, remainder: u64) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
notify_msc(self, window, serial, target_msc, divisor, remainder)
}
fn present_select_input(&self, eid: Event, window: xproto::Window, event_mask: EventMask) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_input(self, eid, window, event_mask)
}
fn present_query_capabilities(&self, target: u32) -> Result<Cookie<'_, Self, QueryCapabilitiesReply>, ConnectionError>
{
query_capabilities(self, target)
}
fn present_pixmap_synced<'c, 'input>(&'c self, window: xproto::Window, pixmap: xproto::Pixmap, serial: u32, valid: xfixes::Region, update: xfixes::Region, x_off: i16, y_off: i16, target_crtc: randr::Crtc, acquire_syncobj: dri3::Syncobj, release_syncobj: dri3::Syncobj, acquire_point: u64, release_point: u64, options: u32, target_msc: u64, divisor: u64, remainder: u64, notifies: &'input [Notify]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
pixmap_synced(self, window, pixmap, serial, valid, update, x_off, y_off, target_crtc, acquire_syncobj, release_syncobj, acquire_point, release_point, options, target_msc, divisor, remainder, notifies)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

904
vendor/x11rb/src/protocol/randr.rs vendored Normal file
View File

@@ -0,0 +1,904 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `RandR` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::render;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::randr::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_screen_config<Conn>(conn: &Conn, window: xproto::Window, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, size_id: u16, rotation: Rotation, rate: u16) -> Result<Cookie<'_, Conn, SetScreenConfigReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetScreenConfigRequest {
window,
timestamp,
config_timestamp,
size_id,
rotation,
rate,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn select_input<Conn>(conn: &Conn, window: xproto::Window, enable: NotifyMask) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
window,
enable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_screen_info<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetScreenInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetScreenInfoRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_screen_size_range<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetScreenSizeRangeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetScreenSizeRangeRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_screen_size<Conn>(conn: &Conn, window: xproto::Window, width: u16, height: u16, mm_width: u32, mm_height: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetScreenSizeRequest {
window,
width,
height,
mm_width,
mm_height,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_screen_resources<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetScreenResourcesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetScreenResourcesRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_output_info<Conn>(conn: &Conn, output: Output, config_timestamp: xproto::Timestamp) -> Result<Cookie<'_, Conn, GetOutputInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetOutputInfoRequest {
output,
config_timestamp,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_output_properties<Conn>(conn: &Conn, output: Output) -> Result<Cookie<'_, Conn, ListOutputPropertiesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListOutputPropertiesRequest {
output,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_output_property<Conn>(conn: &Conn, output: Output, property: xproto::Atom) -> Result<Cookie<'_, Conn, QueryOutputPropertyReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryOutputPropertyRequest {
output,
property,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn configure_output_property<'c, 'input, Conn>(conn: &'c Conn, output: Output, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ConfigureOutputPropertyRequest {
output,
property,
pending,
range,
values: Cow::Borrowed(values),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn change_output_property<'c, 'input, Conn>(conn: &'c Conn, output: Output, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: xproto::PropMode, num_units: u32, data: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeOutputPropertyRequest {
output,
property,
type_,
format,
mode,
num_units,
data: Cow::Borrowed(data),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn delete_output_property<Conn>(conn: &Conn, output: Output, property: xproto::Atom) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeleteOutputPropertyRequest {
output,
property,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_output_property<Conn, A>(conn: &Conn, output: Output, property: xproto::Atom, type_: A, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result<Cookie<'_, Conn, GetOutputPropertyReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<xproto::Atom>,
{
let type_: xproto::Atom = type_.into();
let request0 = GetOutputPropertyRequest {
output,
property,
type_,
long_offset,
long_length,
delete,
pending,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_mode<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, mode_info: ModeInfo, name: &'input [u8]) -> Result<Cookie<'c, Conn, CreateModeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateModeRequest {
window,
mode_info,
name: Cow::Borrowed(name),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn destroy_mode<Conn>(conn: &Conn, mode: Mode) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyModeRequest {
mode,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn add_output_mode<Conn>(conn: &Conn, output: Output, mode: Mode) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AddOutputModeRequest {
output,
mode,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn delete_output_mode<Conn>(conn: &Conn, output: Output, mode: Mode) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeleteOutputModeRequest {
output,
mode,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_crtc_info<Conn>(conn: &Conn, crtc: Crtc, config_timestamp: xproto::Timestamp) -> Result<Cookie<'_, Conn, GetCrtcInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCrtcInfoRequest {
crtc,
config_timestamp,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_crtc_config<'c, 'input, Conn>(conn: &'c Conn, crtc: Crtc, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, x: i16, y: i16, mode: Mode, rotation: Rotation, outputs: &'input [Output]) -> Result<Cookie<'c, Conn, SetCrtcConfigReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetCrtcConfigRequest {
crtc,
timestamp,
config_timestamp,
x,
y,
mode,
rotation,
outputs: Cow::Borrowed(outputs),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_crtc_gamma_size<Conn>(conn: &Conn, crtc: Crtc) -> Result<Cookie<'_, Conn, GetCrtcGammaSizeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCrtcGammaSizeRequest {
crtc,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_crtc_gamma<Conn>(conn: &Conn, crtc: Crtc) -> Result<Cookie<'_, Conn, GetCrtcGammaReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCrtcGammaRequest {
crtc,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_crtc_gamma<'c, 'input, Conn>(conn: &'c Conn, crtc: Crtc, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetCrtcGammaRequest {
crtc,
red: Cow::Borrowed(red),
green: Cow::Borrowed(green),
blue: Cow::Borrowed(blue),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_screen_resources_current<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetScreenResourcesCurrentReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetScreenResourcesCurrentRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_crtc_transform<'c, 'input, Conn>(conn: &'c Conn, crtc: Crtc, transform: render::Transform, filter_name: &'input [u8], filter_params: &'input [render::Fixed]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetCrtcTransformRequest {
crtc,
transform,
filter_name: Cow::Borrowed(filter_name),
filter_params: Cow::Borrowed(filter_params),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_crtc_transform<Conn>(conn: &Conn, crtc: Crtc) -> Result<Cookie<'_, Conn, GetCrtcTransformReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCrtcTransformRequest {
crtc,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_panning<Conn>(conn: &Conn, crtc: Crtc) -> Result<Cookie<'_, Conn, GetPanningReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPanningRequest {
crtc,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_panning<Conn>(conn: &Conn, crtc: Crtc, timestamp: xproto::Timestamp, left: u16, top: u16, width: u16, height: u16, track_left: u16, track_top: u16, track_width: u16, track_height: u16, border_left: i16, border_top: i16, border_right: i16, border_bottom: i16) -> Result<Cookie<'_, Conn, SetPanningReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPanningRequest {
crtc,
timestamp,
left,
top,
width,
height,
track_left,
track_top,
track_width,
track_height,
border_left,
border_top,
border_right,
border_bottom,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_output_primary<Conn>(conn: &Conn, window: xproto::Window, output: Output) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetOutputPrimaryRequest {
window,
output,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_output_primary<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetOutputPrimaryReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetOutputPrimaryRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_providers<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetProvidersReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetProvidersRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_provider_info<Conn>(conn: &Conn, provider: Provider, config_timestamp: xproto::Timestamp) -> Result<Cookie<'_, Conn, GetProviderInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetProviderInfoRequest {
provider,
config_timestamp,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_provider_offload_sink<Conn>(conn: &Conn, provider: Provider, sink_provider: Provider, config_timestamp: xproto::Timestamp) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetProviderOffloadSinkRequest {
provider,
sink_provider,
config_timestamp,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_provider_output_source<Conn>(conn: &Conn, provider: Provider, source_provider: Provider, config_timestamp: xproto::Timestamp) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetProviderOutputSourceRequest {
provider,
source_provider,
config_timestamp,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn list_provider_properties<Conn>(conn: &Conn, provider: Provider) -> Result<Cookie<'_, Conn, ListProviderPropertiesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListProviderPropertiesRequest {
provider,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_provider_property<Conn>(conn: &Conn, provider: Provider, property: xproto::Atom) -> Result<Cookie<'_, Conn, QueryProviderPropertyReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryProviderPropertyRequest {
provider,
property,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn configure_provider_property<'c, 'input, Conn>(conn: &'c Conn, provider: Provider, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ConfigureProviderPropertyRequest {
provider,
property,
pending,
range,
values: Cow::Borrowed(values),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn change_provider_property<'c, 'input, Conn>(conn: &'c Conn, provider: Provider, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: u8, num_items: u32, data: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeProviderPropertyRequest {
provider,
property,
type_,
format,
mode,
num_items,
data: Cow::Borrowed(data),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn delete_provider_property<Conn>(conn: &Conn, provider: Provider, property: xproto::Atom) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeleteProviderPropertyRequest {
provider,
property,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_provider_property<Conn>(conn: &Conn, provider: Provider, property: xproto::Atom, type_: xproto::Atom, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result<Cookie<'_, Conn, GetProviderPropertyReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetProviderPropertyRequest {
provider,
property,
type_,
long_offset,
long_length,
delete,
pending,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_monitors<Conn>(conn: &Conn, window: xproto::Window, get_active: bool) -> Result<Cookie<'_, Conn, GetMonitorsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetMonitorsRequest {
window,
get_active,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_monitor<Conn>(conn: &Conn, window: xproto::Window, monitorinfo: MonitorInfo) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetMonitorRequest {
window,
monitorinfo,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn delete_monitor<Conn>(conn: &Conn, window: xproto::Window, name: xproto::Atom) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeleteMonitorRequest {
window,
name,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_lease<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, lid: Lease, crtcs: &'input [Crtc], outputs: &'input [Output]) -> Result<CookieWithFds<'c, Conn, CreateLeaseReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateLeaseRequest {
window,
lid,
crtcs: Cow::Borrowed(crtcs),
outputs: Cow::Borrowed(outputs),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply_with_fds(&slices, fds)
}
pub fn free_lease<Conn>(conn: &Conn, lid: Lease, terminate: u8) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FreeLeaseRequest {
lid,
terminate,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn randr_query_version(&self, major_version: u32, minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major_version, minor_version)
}
fn randr_set_screen_config(&self, window: xproto::Window, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, size_id: u16, rotation: Rotation, rate: u16) -> Result<Cookie<'_, Self, SetScreenConfigReply>, ConnectionError>
{
set_screen_config(self, window, timestamp, config_timestamp, size_id, rotation, rate)
}
fn randr_select_input(&self, window: xproto::Window, enable: NotifyMask) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_input(self, window, enable)
}
fn randr_get_screen_info(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetScreenInfoReply>, ConnectionError>
{
get_screen_info(self, window)
}
fn randr_get_screen_size_range(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetScreenSizeRangeReply>, ConnectionError>
{
get_screen_size_range(self, window)
}
fn randr_set_screen_size(&self, window: xproto::Window, width: u16, height: u16, mm_width: u32, mm_height: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_screen_size(self, window, width, height, mm_width, mm_height)
}
fn randr_get_screen_resources(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetScreenResourcesReply>, ConnectionError>
{
get_screen_resources(self, window)
}
fn randr_get_output_info(&self, output: Output, config_timestamp: xproto::Timestamp) -> Result<Cookie<'_, Self, GetOutputInfoReply>, ConnectionError>
{
get_output_info(self, output, config_timestamp)
}
fn randr_list_output_properties(&self, output: Output) -> Result<Cookie<'_, Self, ListOutputPropertiesReply>, ConnectionError>
{
list_output_properties(self, output)
}
fn randr_query_output_property(&self, output: Output, property: xproto::Atom) -> Result<Cookie<'_, Self, QueryOutputPropertyReply>, ConnectionError>
{
query_output_property(self, output, property)
}
fn randr_configure_output_property<'c, 'input>(&'c self, output: Output, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
configure_output_property(self, output, property, pending, range, values)
}
fn randr_change_output_property<'c, 'input>(&'c self, output: Output, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: xproto::PropMode, num_units: u32, data: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
change_output_property(self, output, property, type_, format, mode, num_units, data)
}
fn randr_delete_output_property(&self, output: Output, property: xproto::Atom) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
delete_output_property(self, output, property)
}
fn randr_get_output_property<A>(&self, output: Output, property: xproto::Atom, type_: A, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result<Cookie<'_, Self, GetOutputPropertyReply>, ConnectionError>
where
A: Into<xproto::Atom>,
{
get_output_property(self, output, property, type_, long_offset, long_length, delete, pending)
}
fn randr_create_mode<'c, 'input>(&'c self, window: xproto::Window, mode_info: ModeInfo, name: &'input [u8]) -> Result<Cookie<'c, Self, CreateModeReply>, ConnectionError>
{
create_mode(self, window, mode_info, name)
}
fn randr_destroy_mode(&self, mode: Mode) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_mode(self, mode)
}
fn randr_add_output_mode(&self, output: Output, mode: Mode) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
add_output_mode(self, output, mode)
}
fn randr_delete_output_mode(&self, output: Output, mode: Mode) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
delete_output_mode(self, output, mode)
}
fn randr_get_crtc_info(&self, crtc: Crtc, config_timestamp: xproto::Timestamp) -> Result<Cookie<'_, Self, GetCrtcInfoReply>, ConnectionError>
{
get_crtc_info(self, crtc, config_timestamp)
}
fn randr_set_crtc_config<'c, 'input>(&'c self, crtc: Crtc, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, x: i16, y: i16, mode: Mode, rotation: Rotation, outputs: &'input [Output]) -> Result<Cookie<'c, Self, SetCrtcConfigReply>, ConnectionError>
{
set_crtc_config(self, crtc, timestamp, config_timestamp, x, y, mode, rotation, outputs)
}
fn randr_get_crtc_gamma_size(&self, crtc: Crtc) -> Result<Cookie<'_, Self, GetCrtcGammaSizeReply>, ConnectionError>
{
get_crtc_gamma_size(self, crtc)
}
fn randr_get_crtc_gamma(&self, crtc: Crtc) -> Result<Cookie<'_, Self, GetCrtcGammaReply>, ConnectionError>
{
get_crtc_gamma(self, crtc)
}
fn randr_set_crtc_gamma<'c, 'input>(&'c self, crtc: Crtc, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_crtc_gamma(self, crtc, red, green, blue)
}
fn randr_get_screen_resources_current(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetScreenResourcesCurrentReply>, ConnectionError>
{
get_screen_resources_current(self, window)
}
fn randr_set_crtc_transform<'c, 'input>(&'c self, crtc: Crtc, transform: render::Transform, filter_name: &'input [u8], filter_params: &'input [render::Fixed]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_crtc_transform(self, crtc, transform, filter_name, filter_params)
}
fn randr_get_crtc_transform(&self, crtc: Crtc) -> Result<Cookie<'_, Self, GetCrtcTransformReply>, ConnectionError>
{
get_crtc_transform(self, crtc)
}
fn randr_get_panning(&self, crtc: Crtc) -> Result<Cookie<'_, Self, GetPanningReply>, ConnectionError>
{
get_panning(self, crtc)
}
fn randr_set_panning(&self, crtc: Crtc, timestamp: xproto::Timestamp, left: u16, top: u16, width: u16, height: u16, track_left: u16, track_top: u16, track_width: u16, track_height: u16, border_left: i16, border_top: i16, border_right: i16, border_bottom: i16) -> Result<Cookie<'_, Self, SetPanningReply>, ConnectionError>
{
set_panning(self, crtc, timestamp, left, top, width, height, track_left, track_top, track_width, track_height, border_left, border_top, border_right, border_bottom)
}
fn randr_set_output_primary(&self, window: xproto::Window, output: Output) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_output_primary(self, window, output)
}
fn randr_get_output_primary(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetOutputPrimaryReply>, ConnectionError>
{
get_output_primary(self, window)
}
fn randr_get_providers(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetProvidersReply>, ConnectionError>
{
get_providers(self, window)
}
fn randr_get_provider_info(&self, provider: Provider, config_timestamp: xproto::Timestamp) -> Result<Cookie<'_, Self, GetProviderInfoReply>, ConnectionError>
{
get_provider_info(self, provider, config_timestamp)
}
fn randr_set_provider_offload_sink(&self, provider: Provider, sink_provider: Provider, config_timestamp: xproto::Timestamp) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_provider_offload_sink(self, provider, sink_provider, config_timestamp)
}
fn randr_set_provider_output_source(&self, provider: Provider, source_provider: Provider, config_timestamp: xproto::Timestamp) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_provider_output_source(self, provider, source_provider, config_timestamp)
}
fn randr_list_provider_properties(&self, provider: Provider) -> Result<Cookie<'_, Self, ListProviderPropertiesReply>, ConnectionError>
{
list_provider_properties(self, provider)
}
fn randr_query_provider_property(&self, provider: Provider, property: xproto::Atom) -> Result<Cookie<'_, Self, QueryProviderPropertyReply>, ConnectionError>
{
query_provider_property(self, provider, property)
}
fn randr_configure_provider_property<'c, 'input>(&'c self, provider: Provider, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
configure_provider_property(self, provider, property, pending, range, values)
}
fn randr_change_provider_property<'c, 'input>(&'c self, provider: Provider, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: u8, num_items: u32, data: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
change_provider_property(self, provider, property, type_, format, mode, num_items, data)
}
fn randr_delete_provider_property(&self, provider: Provider, property: xproto::Atom) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
delete_provider_property(self, provider, property)
}
fn randr_get_provider_property(&self, provider: Provider, property: xproto::Atom, type_: xproto::Atom, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result<Cookie<'_, Self, GetProviderPropertyReply>, ConnectionError>
{
get_provider_property(self, provider, property, type_, long_offset, long_length, delete, pending)
}
fn randr_get_monitors(&self, window: xproto::Window, get_active: bool) -> Result<Cookie<'_, Self, GetMonitorsReply>, ConnectionError>
{
get_monitors(self, window, get_active)
}
fn randr_set_monitor(&self, window: xproto::Window, monitorinfo: MonitorInfo) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_monitor(self, window, monitorinfo)
}
fn randr_delete_monitor(&self, window: xproto::Window, name: xproto::Atom) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
delete_monitor(self, window, name)
}
fn randr_create_lease<'c, 'input>(&'c self, window: xproto::Window, lid: Lease, crtcs: &'input [Crtc], outputs: &'input [Output]) -> Result<CookieWithFds<'c, Self, CreateLeaseReply>, ConnectionError>
{
create_lease(self, window, lid, crtcs, outputs)
}
fn randr_free_lease(&self, lid: Lease, terminate: u8) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
free_lease(self, lid, terminate)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

261
vendor/x11rb/src/protocol/record.rs vendored Normal file
View File

@@ -0,0 +1,261 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Record` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::cookie::RecordEnableContextCookie;
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::record::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, major_version: u16, minor_version: u16) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_context<'c, 'input, Conn>(conn: &'c Conn, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateContextRequest {
context,
element_header,
client_specs: Cow::Borrowed(client_specs),
ranges: Cow::Borrowed(ranges),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn register_clients<'c, 'input, Conn>(conn: &'c Conn, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = RegisterClientsRequest {
context,
element_header,
client_specs: Cow::Borrowed(client_specs),
ranges: Cow::Borrowed(ranges),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn unregister_clients<'c, 'input, Conn>(conn: &'c Conn, context: Context, client_specs: &'input [ClientSpec]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = UnregisterClientsRequest {
context,
client_specs: Cow::Borrowed(client_specs),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_context<Conn>(conn: &Conn, context: Context) -> Result<Cookie<'_, Conn, GetContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetContextRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn enable_context<Conn>(conn: &Conn, context: Context) -> Result<RecordEnableContextCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = EnableContextRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
Ok(RecordEnableContextCookie::new(conn.send_request_with_reply(&slices, fds)?))
}
pub fn disable_context<Conn>(conn: &Conn, context: Context) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DisableContextRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn free_context<Conn>(conn: &Conn, context: Context) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FreeContextRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn record_query_version(&self, major_version: u16, minor_version: u16) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major_version, minor_version)
}
fn record_create_context<'c, 'input>(&'c self, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_context(self, context, element_header, client_specs, ranges)
}
fn record_register_clients<'c, 'input>(&'c self, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
register_clients(self, context, element_header, client_specs, ranges)
}
fn record_unregister_clients<'c, 'input>(&'c self, context: Context, client_specs: &'input [ClientSpec]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
unregister_clients(self, context, client_specs)
}
fn record_get_context(&self, context: Context) -> Result<Cookie<'_, Self, GetContextReply>, ConnectionError>
{
get_context(self, context)
}
fn record_enable_context(&self, context: Context) -> Result<RecordEnableContextCookie<'_, Self>, ConnectionError>
{
enable_context(self, context)
}
fn record_disable_context(&self, context: Context) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
disable_context(self, context)
}
fn record_free_context(&self, context: Context) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
free_context(self, context)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around a [Context].
///
/// Instances of this struct represent a Context that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct ContextWrapper<C: RequestConnection>(C, Context);
impl<C: RequestConnection> ContextWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_context(conn: C, id: Context) -> Self {
ContextWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn context(&self) -> Context {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_context(self) -> Context {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> ContextWrapper<&'c C>
{
/// Create a new Context and return a Context wrapper and a cookie.
///
/// This is a thin wrapper around [create_context] that allocates an id for the Context.
/// This function returns the resulting `ContextWrapper` that owns the created Context and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_context].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_context].
pub fn create_context_and_get_cookie(conn: &'c C, element_header: ElementHeader, client_specs: &[ClientSpec], ranges: &[Range]) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let context = conn.generate_id()?;
let cookie = create_context(conn, context, element_header, client_specs, ranges)?;
Ok((Self::for_context(conn, context), cookie))
}
}
impl<C: X11Connection> ContextWrapper<C>
{
/// Create a new Context and return a Context wrapper
///
/// This is a thin wrapper around [create_context] that allocates an id for the Context.
/// This function returns the resulting `ContextWrapper` that owns the created Context and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_context].
pub fn create_context(conn: C, element_header: ElementHeader, client_specs: &[ClientSpec], ranges: &[Range]) -> Result<Self, ReplyOrIdError>
{
let context = conn.generate_id()?;
let _ = create_context(&conn, context, element_header, client_specs, ranges)?;
Ok(Self::for_context(conn, context))
}
}
impl<C: RequestConnection> From<&ContextWrapper<C>> for Context {
fn from(from: &ContextWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for ContextWrapper<C> {
fn drop(&mut self) {
let _ = free_context(&self.0, self.1);
}
}

958
vendor/x11rb/src/protocol/render.rs vendored Normal file
View File

@@ -0,0 +1,958 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Render` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::render::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_pict_formats<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryPictFormatsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryPictFormatsRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_pict_index_values<Conn>(conn: &Conn, format: Pictformat) -> Result<Cookie<'_, Conn, QueryPictIndexValuesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryPictIndexValuesRequest {
format,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_picture<'c, 'input, Conn>(conn: &'c Conn, pid: Picture, drawable: xproto::Drawable, format: Pictformat, value_list: &'input CreatePictureAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreatePictureRequest {
pid,
drawable,
format,
value_list: Cow::Borrowed(value_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn change_picture<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, value_list: &'input ChangePictureAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangePictureRequest {
picture,
value_list: Cow::Borrowed(value_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_picture_clip_rectangles<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPictureClipRectanglesRequest {
picture,
clip_x_origin,
clip_y_origin,
rectangles: Cow::Borrowed(rectangles),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn free_picture<Conn>(conn: &Conn, picture: Picture) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FreePictureRequest {
picture,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn composite<Conn, A>(conn: &Conn, op: PictOp, src: Picture, mask: A, dst: Picture, src_x: i16, src_y: i16, mask_x: i16, mask_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<Picture>,
{
let mask: Picture = mask.into();
let request0 = CompositeRequest {
op,
src,
mask,
dst,
src_x,
src_y,
mask_x,
mask_y,
dst_x,
dst_y,
width,
height,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn trapezoids<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, traps: &'input [Trapezoid]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = TrapezoidsRequest {
op,
src,
dst,
mask_format,
src_x,
src_y,
traps: Cow::Borrowed(traps),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn triangles<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, triangles: &'input [Triangle]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = TrianglesRequest {
op,
src,
dst,
mask_format,
src_x,
src_y,
triangles: Cow::Borrowed(triangles),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn tri_strip<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = TriStripRequest {
op,
src,
dst,
mask_format,
src_x,
src_y,
points: Cow::Borrowed(points),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn tri_fan<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = TriFanRequest {
op,
src,
dst,
mask_format,
src_x,
src_y,
points: Cow::Borrowed(points),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_glyph_set<Conn>(conn: &Conn, gsid: Glyphset, format: Pictformat) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateGlyphSetRequest {
gsid,
format,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn reference_glyph_set<Conn>(conn: &Conn, gsid: Glyphset, existing: Glyphset) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ReferenceGlyphSetRequest {
gsid,
existing,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn free_glyph_set<Conn>(conn: &Conn, glyphset: Glyphset) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FreeGlyphSetRequest {
glyphset,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn add_glyphs<'c, 'input, Conn>(conn: &'c Conn, glyphset: Glyphset, glyphids: &'input [u32], glyphs: &'input [Glyphinfo], data: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AddGlyphsRequest {
glyphset,
glyphids: Cow::Borrowed(glyphids),
glyphs: Cow::Borrowed(glyphs),
data: Cow::Borrowed(data),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn free_glyphs<'c, 'input, Conn>(conn: &'c Conn, glyphset: Glyphset, glyphs: &'input [Glyph]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FreeGlyphsRequest {
glyphset,
glyphs: Cow::Borrowed(glyphs),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn composite_glyphs8<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CompositeGlyphs8Request {
op,
src,
dst,
mask_format,
glyphset,
src_x,
src_y,
glyphcmds: Cow::Borrowed(glyphcmds),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn composite_glyphs16<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CompositeGlyphs16Request {
op,
src,
dst,
mask_format,
glyphset,
src_x,
src_y,
glyphcmds: Cow::Borrowed(glyphcmds),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn composite_glyphs32<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CompositeGlyphs32Request {
op,
src,
dst,
mask_format,
glyphset,
src_x,
src_y,
glyphcmds: Cow::Borrowed(glyphcmds),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn fill_rectangles<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, dst: Picture, color: Color, rects: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FillRectanglesRequest {
op,
dst,
color,
rects: Cow::Borrowed(rects),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_cursor<Conn>(conn: &Conn, cid: xproto::Cursor, source: Picture, x: u16, y: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateCursorRequest {
cid,
source,
x,
y,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_picture_transform<Conn>(conn: &Conn, picture: Picture, transform: Transform) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPictureTransformRequest {
picture,
transform,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_filters<Conn>(conn: &Conn, drawable: xproto::Drawable) -> Result<Cookie<'_, Conn, QueryFiltersReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryFiltersRequest {
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_picture_filter<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, filter: &'input [u8], values: &'input [Fixed]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPictureFilterRequest {
picture,
filter: Cow::Borrowed(filter),
values: Cow::Borrowed(values),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_anim_cursor<'c, 'input, Conn>(conn: &'c Conn, cid: xproto::Cursor, cursors: &'input [Animcursorelt]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateAnimCursorRequest {
cid,
cursors: Cow::Borrowed(cursors),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn add_traps<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, x_off: i16, y_off: i16, traps: &'input [Trap]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AddTrapsRequest {
picture,
x_off,
y_off,
traps: Cow::Borrowed(traps),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_solid_fill<Conn>(conn: &Conn, picture: Picture, color: Color) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateSolidFillRequest {
picture,
color,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_linear_gradient<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, p1: Pointfix, p2: Pointfix, stops: &'input [Fixed], colors: &'input [Color]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateLinearGradientRequest {
picture,
p1,
p2,
stops: Cow::Borrowed(stops),
colors: Cow::Borrowed(colors),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_radial_gradient<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, inner: Pointfix, outer: Pointfix, inner_radius: Fixed, outer_radius: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRadialGradientRequest {
picture,
inner,
outer,
inner_radius,
outer_radius,
stops: Cow::Borrowed(stops),
colors: Cow::Borrowed(colors),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_conical_gradient<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, center: Pointfix, angle: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateConicalGradientRequest {
picture,
center,
angle,
stops: Cow::Borrowed(stops),
colors: Cow::Borrowed(colors),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn render_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
fn render_query_pict_formats(&self) -> Result<Cookie<'_, Self, QueryPictFormatsReply>, ConnectionError>
{
query_pict_formats(self)
}
fn render_query_pict_index_values(&self, format: Pictformat) -> Result<Cookie<'_, Self, QueryPictIndexValuesReply>, ConnectionError>
{
query_pict_index_values(self, format)
}
fn render_create_picture<'c, 'input>(&'c self, pid: Picture, drawable: xproto::Drawable, format: Pictformat, value_list: &'input CreatePictureAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_picture(self, pid, drawable, format, value_list)
}
fn render_change_picture<'c, 'input>(&'c self, picture: Picture, value_list: &'input ChangePictureAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
change_picture(self, picture, value_list)
}
fn render_set_picture_clip_rectangles<'c, 'input>(&'c self, picture: Picture, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_picture_clip_rectangles(self, picture, clip_x_origin, clip_y_origin, rectangles)
}
fn render_free_picture(&self, picture: Picture) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
free_picture(self, picture)
}
fn render_composite<A>(&self, op: PictOp, src: Picture, mask: A, dst: Picture, src_x: i16, src_y: i16, mask_x: i16, mask_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Picture>,
{
composite(self, op, src, mask, dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height)
}
fn render_trapezoids<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, traps: &'input [Trapezoid]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
trapezoids(self, op, src, dst, mask_format, src_x, src_y, traps)
}
fn render_triangles<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, triangles: &'input [Triangle]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
self::triangles(self, op, src, dst, mask_format, src_x, src_y, triangles)
}
fn render_tri_strip<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
tri_strip(self, op, src, dst, mask_format, src_x, src_y, points)
}
fn render_tri_fan<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
tri_fan(self, op, src, dst, mask_format, src_x, src_y, points)
}
fn render_create_glyph_set(&self, gsid: Glyphset, format: Pictformat) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_glyph_set(self, gsid, format)
}
fn render_reference_glyph_set(&self, gsid: Glyphset, existing: Glyphset) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
reference_glyph_set(self, gsid, existing)
}
fn render_free_glyph_set(&self, glyphset: Glyphset) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
free_glyph_set(self, glyphset)
}
fn render_add_glyphs<'c, 'input>(&'c self, glyphset: Glyphset, glyphids: &'input [u32], glyphs: &'input [Glyphinfo], data: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
add_glyphs(self, glyphset, glyphids, glyphs, data)
}
fn render_free_glyphs<'c, 'input>(&'c self, glyphset: Glyphset, glyphs: &'input [Glyph]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
free_glyphs(self, glyphset, glyphs)
}
fn render_composite_glyphs8<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
composite_glyphs8(self, op, src, dst, mask_format, glyphset, src_x, src_y, glyphcmds)
}
fn render_composite_glyphs16<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
composite_glyphs16(self, op, src, dst, mask_format, glyphset, src_x, src_y, glyphcmds)
}
fn render_composite_glyphs32<'c, 'input>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
composite_glyphs32(self, op, src, dst, mask_format, glyphset, src_x, src_y, glyphcmds)
}
fn render_fill_rectangles<'c, 'input>(&'c self, op: PictOp, dst: Picture, color: Color, rects: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
fill_rectangles(self, op, dst, color, rects)
}
fn render_create_cursor(&self, cid: xproto::Cursor, source: Picture, x: u16, y: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_cursor(self, cid, source, x, y)
}
fn render_set_picture_transform(&self, picture: Picture, transform: Transform) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_picture_transform(self, picture, transform)
}
fn render_query_filters(&self, drawable: xproto::Drawable) -> Result<Cookie<'_, Self, QueryFiltersReply>, ConnectionError>
{
query_filters(self, drawable)
}
fn render_set_picture_filter<'c, 'input>(&'c self, picture: Picture, filter: &'input [u8], values: &'input [Fixed]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_picture_filter(self, picture, filter, values)
}
fn render_create_anim_cursor<'c, 'input>(&'c self, cid: xproto::Cursor, cursors: &'input [Animcursorelt]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_anim_cursor(self, cid, cursors)
}
fn render_add_traps<'c, 'input>(&'c self, picture: Picture, x_off: i16, y_off: i16, traps: &'input [Trap]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
add_traps(self, picture, x_off, y_off, traps)
}
fn render_create_solid_fill(&self, picture: Picture, color: Color) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_solid_fill(self, picture, color)
}
fn render_create_linear_gradient<'c, 'input>(&'c self, picture: Picture, p1: Pointfix, p2: Pointfix, stops: &'input [Fixed], colors: &'input [Color]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_linear_gradient(self, picture, p1, p2, stops, colors)
}
fn render_create_radial_gradient<'c, 'input>(&'c self, picture: Picture, inner: Pointfix, outer: Pointfix, inner_radius: Fixed, outer_radius: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_radial_gradient(self, picture, inner, outer, inner_radius, outer_radius, stops, colors)
}
fn render_create_conical_gradient<'c, 'input>(&'c self, picture: Picture, center: Pointfix, angle: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_conical_gradient(self, picture, center, angle, stops, colors)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around a [Picture].
///
/// Instances of this struct represent a Picture that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct PictureWrapper<C: RequestConnection>(C, Picture);
impl<C: RequestConnection> PictureWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_picture(conn: C, id: Picture) -> Self {
PictureWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn picture(&self) -> Picture {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_picture(self) -> Picture {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> PictureWrapper<&'c C>
{
/// Create a new Picture and return a Picture wrapper and a cookie.
///
/// This is a thin wrapper around [create_picture] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_picture].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_picture].
pub fn create_picture_and_get_cookie(conn: &'c C, drawable: xproto::Drawable, format: Pictformat, value_list: &CreatePictureAux) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let pid = conn.generate_id()?;
let cookie = create_picture(conn, pid, drawable, format, value_list)?;
Ok((Self::for_picture(conn, pid), cookie))
}
}
impl<C: X11Connection> PictureWrapper<C>
{
/// Create a new Picture and return a Picture wrapper
///
/// This is a thin wrapper around [create_picture] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_picture].
pub fn create_picture(conn: C, drawable: xproto::Drawable, format: Pictformat, value_list: &CreatePictureAux) -> Result<Self, ReplyOrIdError>
{
let pid = conn.generate_id()?;
let _ = create_picture(&conn, pid, drawable, format, value_list)?;
Ok(Self::for_picture(conn, pid))
}
}
impl<'c, C: X11Connection> PictureWrapper<&'c C>
{
/// Create a new Picture and return a Picture wrapper and a cookie.
///
/// This is a thin wrapper around [create_solid_fill] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_solid_fill].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_solid_fill].
pub fn create_solid_fill_and_get_cookie(conn: &'c C, color: Color) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let picture = conn.generate_id()?;
let cookie = create_solid_fill(conn, picture, color)?;
Ok((Self::for_picture(conn, picture), cookie))
}
}
impl<C: X11Connection> PictureWrapper<C>
{
/// Create a new Picture and return a Picture wrapper
///
/// This is a thin wrapper around [create_solid_fill] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_solid_fill].
pub fn create_solid_fill(conn: C, color: Color) -> Result<Self, ReplyOrIdError>
{
let picture = conn.generate_id()?;
let _ = create_solid_fill(&conn, picture, color)?;
Ok(Self::for_picture(conn, picture))
}
}
impl<'c, C: X11Connection> PictureWrapper<&'c C>
{
/// Create a new Picture and return a Picture wrapper and a cookie.
///
/// This is a thin wrapper around [create_linear_gradient] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_linear_gradient].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_linear_gradient].
pub fn create_linear_gradient_and_get_cookie(conn: &'c C, p1: Pointfix, p2: Pointfix, stops: &[Fixed], colors: &[Color]) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let picture = conn.generate_id()?;
let cookie = create_linear_gradient(conn, picture, p1, p2, stops, colors)?;
Ok((Self::for_picture(conn, picture), cookie))
}
}
impl<C: X11Connection> PictureWrapper<C>
{
/// Create a new Picture and return a Picture wrapper
///
/// This is a thin wrapper around [create_linear_gradient] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_linear_gradient].
pub fn create_linear_gradient(conn: C, p1: Pointfix, p2: Pointfix, stops: &[Fixed], colors: &[Color]) -> Result<Self, ReplyOrIdError>
{
let picture = conn.generate_id()?;
let _ = create_linear_gradient(&conn, picture, p1, p2, stops, colors)?;
Ok(Self::for_picture(conn, picture))
}
}
impl<'c, C: X11Connection> PictureWrapper<&'c C>
{
/// Create a new Picture and return a Picture wrapper and a cookie.
///
/// This is a thin wrapper around [create_radial_gradient] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_radial_gradient].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_radial_gradient].
pub fn create_radial_gradient_and_get_cookie(conn: &'c C, inner: Pointfix, outer: Pointfix, inner_radius: Fixed, outer_radius: Fixed, stops: &[Fixed], colors: &[Color]) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let picture = conn.generate_id()?;
let cookie = create_radial_gradient(conn, picture, inner, outer, inner_radius, outer_radius, stops, colors)?;
Ok((Self::for_picture(conn, picture), cookie))
}
}
impl<C: X11Connection> PictureWrapper<C>
{
/// Create a new Picture and return a Picture wrapper
///
/// This is a thin wrapper around [create_radial_gradient] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_radial_gradient].
pub fn create_radial_gradient(conn: C, inner: Pointfix, outer: Pointfix, inner_radius: Fixed, outer_radius: Fixed, stops: &[Fixed], colors: &[Color]) -> Result<Self, ReplyOrIdError>
{
let picture = conn.generate_id()?;
let _ = create_radial_gradient(&conn, picture, inner, outer, inner_radius, outer_radius, stops, colors)?;
Ok(Self::for_picture(conn, picture))
}
}
impl<'c, C: X11Connection> PictureWrapper<&'c C>
{
/// Create a new Picture and return a Picture wrapper and a cookie.
///
/// This is a thin wrapper around [create_conical_gradient] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_conical_gradient].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_conical_gradient].
pub fn create_conical_gradient_and_get_cookie(conn: &'c C, center: Pointfix, angle: Fixed, stops: &[Fixed], colors: &[Color]) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let picture = conn.generate_id()?;
let cookie = create_conical_gradient(conn, picture, center, angle, stops, colors)?;
Ok((Self::for_picture(conn, picture), cookie))
}
}
impl<C: X11Connection> PictureWrapper<C>
{
/// Create a new Picture and return a Picture wrapper
///
/// This is a thin wrapper around [create_conical_gradient] that allocates an id for the Picture.
/// This function returns the resulting `PictureWrapper` that owns the created Picture and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_conical_gradient].
pub fn create_conical_gradient(conn: C, center: Pointfix, angle: Fixed, stops: &[Fixed], colors: &[Color]) -> Result<Self, ReplyOrIdError>
{
let picture = conn.generate_id()?;
let _ = create_conical_gradient(&conn, picture, center, angle, stops, colors)?;
Ok(Self::for_picture(conn, picture))
}
}
impl<C: RequestConnection> From<&PictureWrapper<C>> for Picture {
fn from(from: &PictureWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for PictureWrapper<C> {
fn drop(&mut self) {
let _ = free_picture(&self.0, self.1);
}
}
/// A RAII-like wrapper around a [Glyphset].
///
/// Instances of this struct represent a Glyphset that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct GlyphsetWrapper<C: RequestConnection>(C, Glyphset);
impl<C: RequestConnection> GlyphsetWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_glyphset(conn: C, id: Glyphset) -> Self {
GlyphsetWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn glyphset(&self) -> Glyphset {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_glyphset(self) -> Glyphset {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> GlyphsetWrapper<&'c C>
{
/// Create a new Glyphset and return a Glyphset wrapper and a cookie.
///
/// This is a thin wrapper around [create_glyph_set] that allocates an id for the Glyphset.
/// This function returns the resulting `GlyphsetWrapper` that owns the created Glyphset and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_glyph_set].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_glyph_set].
pub fn create_glyph_set_and_get_cookie(conn: &'c C, format: Pictformat) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let gsid = conn.generate_id()?;
let cookie = create_glyph_set(conn, gsid, format)?;
Ok((Self::for_glyphset(conn, gsid), cookie))
}
}
impl<C: X11Connection> GlyphsetWrapper<C>
{
/// Create a new Glyphset and return a Glyphset wrapper
///
/// This is a thin wrapper around [create_glyph_set] that allocates an id for the Glyphset.
/// This function returns the resulting `GlyphsetWrapper` that owns the created Glyphset and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_glyph_set].
pub fn create_glyph_set(conn: C, format: Pictformat) -> Result<Self, ReplyOrIdError>
{
let gsid = conn.generate_id()?;
let _ = create_glyph_set(&conn, gsid, format)?;
Ok(Self::for_glyphset(conn, gsid))
}
}
impl<C: RequestConnection> From<&GlyphsetWrapper<C>> for Glyphset {
fn from(from: &GlyphsetWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for GlyphsetWrapper<C> {
fn drop(&mut self) {
let _ = free_glyph_set(&self.0, self.1);
}
}

143
vendor/x11rb/src/protocol/res.rs vendored Normal file
View File

@@ -0,0 +1,143 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Res` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::res::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major: u8, client_minor: u8) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major,
client_minor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_clients<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryClientsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryClientsRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_client_resources<Conn>(conn: &Conn, xid: u32) -> Result<Cookie<'_, Conn, QueryClientResourcesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryClientResourcesRequest {
xid,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_client_pixmap_bytes<Conn>(conn: &Conn, xid: u32) -> Result<Cookie<'_, Conn, QueryClientPixmapBytesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryClientPixmapBytesRequest {
xid,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_client_ids<'c, 'input, Conn>(conn: &'c Conn, specs: &'input [ClientIdSpec]) -> Result<Cookie<'c, Conn, QueryClientIdsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryClientIdsRequest {
specs: Cow::Borrowed(specs),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_resource_bytes<'c, 'input, Conn>(conn: &'c Conn, client: u32, specs: &'input [ResourceIdSpec]) -> Result<Cookie<'c, Conn, QueryResourceBytesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryResourceBytesRequest {
client,
specs: Cow::Borrowed(specs),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn res_query_version(&self, client_major: u8, client_minor: u8) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major, client_minor)
}
fn res_query_clients(&self) -> Result<Cookie<'_, Self, QueryClientsReply>, ConnectionError>
{
query_clients(self)
}
fn res_query_client_resources(&self, xid: u32) -> Result<Cookie<'_, Self, QueryClientResourcesReply>, ConnectionError>
{
query_client_resources(self, xid)
}
fn res_query_client_pixmap_bytes(&self, xid: u32) -> Result<Cookie<'_, Self, QueryClientPixmapBytesReply>, ConnectionError>
{
query_client_pixmap_bytes(self, xid)
}
fn res_query_client_ids<'c, 'input>(&'c self, specs: &'input [ClientIdSpec]) -> Result<Cookie<'c, Self, QueryClientIdsReply>, ConnectionError>
{
query_client_ids(self, specs)
}
fn res_query_resource_bytes<'c, 'input>(&'c self, client: u32, specs: &'input [ResourceIdSpec]) -> Result<Cookie<'c, Self, QueryResourceBytesReply>, ConnectionError>
{
query_resource_bytes(self, client, specs)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

154
vendor/x11rb/src/protocol/screensaver.rs vendored Normal file
View File

@@ -0,0 +1,154 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `ScreenSaver` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::screensaver::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major_version: u8, client_minor_version: u8) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_info<Conn>(conn: &Conn, drawable: xproto::Drawable) -> Result<Cookie<'_, Conn, QueryInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryInfoRequest {
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn select_input<Conn>(conn: &Conn, drawable: xproto::Drawable, event_mask: Event) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
drawable,
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_attributes<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: xproto::WindowClass, depth: u8, visual: xproto::Visualid, value_list: &'input SetAttributesAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetAttributesRequest {
drawable,
x,
y,
width,
height,
border_width,
class,
depth,
visual,
value_list: Cow::Borrowed(value_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn unset_attributes<Conn>(conn: &Conn, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = UnsetAttributesRequest {
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn suspend<Conn>(conn: &Conn, suspend: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SuspendRequest {
suspend,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn screensaver_query_version(&self, client_major_version: u8, client_minor_version: u8) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
fn screensaver_query_info(&self, drawable: xproto::Drawable) -> Result<Cookie<'_, Self, QueryInfoReply>, ConnectionError>
{
query_info(self, drawable)
}
fn screensaver_select_input(&self, drawable: xproto::Drawable, event_mask: Event) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_input(self, drawable, event_mask)
}
fn screensaver_set_attributes<'c, 'input>(&'c self, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: xproto::WindowClass, depth: u8, visual: xproto::Visualid, value_list: &'input SetAttributesAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_attributes(self, drawable, x, y, width, height, border_width, class, depth, visual, value_list)
}
fn screensaver_unset_attributes(&self, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
unset_attributes(self, drawable)
}
fn screensaver_suspend(&self, suspend: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
self::suspend(self, suspend)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

218
vendor/x11rb/src/protocol/shape.rs vendored Normal file
View File

@@ -0,0 +1,218 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Shape` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::shape::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn rectangles<'c, 'input, Conn>(conn: &'c Conn, operation: SO, destination_kind: SK, ordering: xproto::ClipOrdering, destination_window: xproto::Window, x_offset: i16, y_offset: i16, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = RectanglesRequest {
operation,
destination_kind,
ordering,
destination_window,
x_offset,
y_offset,
rectangles: Cow::Borrowed(rectangles),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn mask<Conn, A>(conn: &Conn, operation: SO, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_bitmap: A) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<xproto::Pixmap>,
{
let source_bitmap: xproto::Pixmap = source_bitmap.into();
let request0 = MaskRequest {
operation,
destination_kind,
destination_window,
x_offset,
y_offset,
source_bitmap,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn combine<Conn>(conn: &Conn, operation: SO, destination_kind: SK, source_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CombineRequest {
operation,
destination_kind,
source_kind,
destination_window,
x_offset,
y_offset,
source_window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn offset<Conn>(conn: &Conn, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = OffsetRequest {
destination_kind,
destination_window,
x_offset,
y_offset,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_extents<Conn>(conn: &Conn, destination_window: xproto::Window) -> Result<Cookie<'_, Conn, QueryExtentsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryExtentsRequest {
destination_window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn select_input<Conn>(conn: &Conn, destination_window: xproto::Window, enable: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
destination_window,
enable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn input_selected<Conn>(conn: &Conn, destination_window: xproto::Window) -> Result<Cookie<'_, Conn, InputSelectedReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = InputSelectedRequest {
destination_window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_rectangles<Conn>(conn: &Conn, window: xproto::Window, source_kind: SK) -> Result<Cookie<'_, Conn, GetRectanglesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetRectanglesRequest {
window,
source_kind,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn shape_query_version(&self) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self)
}
fn shape_rectangles<'c, 'input>(&'c self, operation: SO, destination_kind: SK, ordering: xproto::ClipOrdering, destination_window: xproto::Window, x_offset: i16, y_offset: i16, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
self::rectangles(self, operation, destination_kind, ordering, destination_window, x_offset, y_offset, rectangles)
}
fn shape_mask<A>(&self, operation: SO, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_bitmap: A) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<xproto::Pixmap>,
{
mask(self, operation, destination_kind, destination_window, x_offset, y_offset, source_bitmap)
}
fn shape_combine(&self, operation: SO, destination_kind: SK, source_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
combine(self, operation, destination_kind, source_kind, destination_window, x_offset, y_offset, source_window)
}
fn shape_offset(&self, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
offset(self, destination_kind, destination_window, x_offset, y_offset)
}
fn shape_query_extents(&self, destination_window: xproto::Window) -> Result<Cookie<'_, Self, QueryExtentsReply>, ConnectionError>
{
query_extents(self, destination_window)
}
fn shape_select_input(&self, destination_window: xproto::Window, enable: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_input(self, destination_window, enable)
}
fn shape_input_selected(&self, destination_window: xproto::Window) -> Result<Cookie<'_, Self, InputSelectedReply>, ConnectionError>
{
input_selected(self, destination_window)
}
fn shape_get_rectangles(&self, window: xproto::Window, source_kind: SK) -> Result<Cookie<'_, Self, GetRectanglesReply>, ConnectionError>
{
get_rectangles(self, window, source_kind)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

546
vendor/x11rb/src/protocol/shm.rs vendored Normal file
View File

@@ -0,0 +1,546 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Shm` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::shm::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
/// Query the version of the MIT-SHM extension..
///
/// This is used to determine the version of the MIT-SHM extension supported by the
/// X server. Clients MUST NOT make other requests in this extension until a reply
/// to this requests indicates the X server supports them.
pub fn query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Attach a System V shared memory segment..
///
/// Attach a System V shared memory segment to the server. This will fail unless
/// the server has permission to map the segment. The client may destroy the segment
/// as soon as it receives a XCB_SHM_COMPLETION event with the shmseg value in this
/// request and with the appropriate serial number.
///
/// # Fields
///
/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
/// * `shmid` - The System V shared memory segment the server should map.
/// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
pub fn attach<Conn>(conn: &Conn, shmseg: Seg, shmid: u32, read_only: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AttachRequest {
shmseg,
shmid,
read_only,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Destroys the specified shared memory segment..
///
/// Destroys the specified shared memory segment. This will never fail unless the
/// segment number is incorrect.
///
/// # Fields
///
/// * `shmseg` - The segment to be destroyed.
pub fn detach<Conn>(conn: &Conn, shmseg: Seg) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DetachRequest {
shmseg,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Copy data from the shared memory to the specified drawable..
///
/// Copy data from the shared memory to the specified drawable. The amount of bytes
/// written to the destination image is always equal to the number of bytes read
/// from the shared memory segment.
///
/// # Fields
///
/// * `drawable` - The drawable to draw to.
/// * `gc` - The graphics context to use.
/// * `total_width` - The total width of the source image.
/// * `total_height` - The total height of the source image.
/// * `src_x` - The source X coordinate of the sub-image to copy.
/// * `src_y` - The source Y coordinate of the sub-image to copy.
/// * `src_width` - The width, in source image coordinates, of the data to copy from the source.
/// The X server will use this to determine the amount of data to copy. The amount
/// of the destination image that is overwritten is determined automatically.
/// * `src_height` - The height, in source image coordinates, of the data to copy from the source.
/// The X server will use this to determine the amount of data to copy. The amount
/// of the destination image that is overwritten is determined automatically.
/// * `dst_x` - The X coordinate on the destination drawable to copy to.
/// * `dst_y` - The Y coordinate on the destination drawable to copy to.
/// * `depth` - The depth to use.
/// * `format` - The format of the image being drawn. If it is XYBitmap, depth must be 1, or a
/// "BadMatch" error results. The foreground pixel in the GC determines the source
/// for the one bits in the image, and the background pixel determines the source
/// for the zero bits. For XYPixmap and ZPixmap, the depth must match the depth of
/// the drawable, or a "BadMatch" error results.
/// * `send_event` - True if the server should send an XCB_SHM_COMPLETION event when the blit
/// completes.
/// * `offset` - The offset that the source image starts at.
pub fn put_image<Conn>(conn: &Conn, drawable: xproto::Drawable, gc: xproto::Gcontext, total_width: u16, total_height: u16, src_x: u16, src_y: u16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16, depth: u8, format: u8, send_event: bool, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PutImageRequest {
drawable,
gc,
total_width,
total_height,
src_x,
src_y,
src_width,
src_height,
dst_x,
dst_y,
depth,
format,
send_event,
shmseg,
offset,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Copies data from the specified drawable to the shared memory segment..
///
/// Copy data from the specified drawable to the shared memory segment. The amount
/// of bytes written to the destination image is always equal to the number of bytes
/// read from the shared memory segment.
///
/// # Fields
///
/// * `drawable` - The drawable to copy the image out of.
/// * `x` - The X coordinate in the drawable to begin copying at.
/// * `y` - The Y coordinate in the drawable to begin copying at.
/// * `width` - The width of the image to copy.
/// * `height` - The height of the image to copy.
/// * `plane_mask` - A mask that determines which planes are used.
/// * `format` - The format to use for the copy (???).
/// * `shmseg` - The destination shared memory segment.
/// * `offset` - The offset in the shared memory segment to copy data to.
pub fn get_image<Conn>(conn: &Conn, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Result<Cookie<'_, Conn, GetImageReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetImageRequest {
drawable,
x,
y,
width,
height,
plane_mask,
format,
shmseg,
offset,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Create a pixmap backed by shared memory..
///
/// Create a pixmap backed by shared memory. Writes to the shared memory will be
/// reflected in the contents of the pixmap, and writes to the pixmap will be
/// reflected in the contents of the shared memory.
///
/// # Fields
///
/// * `pid` - A pixmap ID created with xcb_generate_id().
/// * `drawable` - The drawable to create the pixmap in.
/// * `width` - The width of the pixmap to create. Must be nonzero, or a Value error results.
/// * `height` - The height of the pixmap to create. Must be nonzero, or a Value error results.
/// * `depth` - The depth of the pixmap to create. Must be nonzero, or a Value error results.
/// * `shmseg` - The shared memory segment to use to create the pixmap.
/// * `offset` - The offset in the segment to create the pixmap at.
pub fn create_pixmap<Conn>(conn: &Conn, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreatePixmapRequest {
pid,
drawable,
width,
height,
depth,
shmseg,
offset,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Create a shared memory segment.
///
/// Create a shared memory segment. The file descriptor will be mapped at offset
/// zero, and the size will be obtained using fstat(). A zero size will result in a
/// Value error.
///
/// # Fields
///
/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
/// * `shm_fd` - The file descriptor the server should mmap().
/// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
pub fn attach_fd<Conn, A>(conn: &Conn, shmseg: Seg, shm_fd: A, read_only: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<RawFdContainer>,
{
let shm_fd: RawFdContainer = shm_fd.into();
let request0 = AttachFdRequest {
shmseg,
shm_fd,
read_only,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Asks the server to allocate a shared memory segment..
///
/// Asks the server to allocate a shared memory segment. The servers reply will
/// include a file descriptor for the client to pass to mmap().
///
/// # Fields
///
/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
/// * `size` - The size of the segment to create.
/// * `read_only` - True if the server should map the segment read-only; otherwise false.
pub fn create_segment<Conn>(conn: &Conn, shmseg: Seg, size: u32, read_only: bool) -> Result<CookieWithFds<'_, Conn, CreateSegmentReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateSegmentRequest {
shmseg,
size,
read_only,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply_with_fds(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
/// Query the version of the MIT-SHM extension..
///
/// This is used to determine the version of the MIT-SHM extension supported by the
/// X server. Clients MUST NOT make other requests in this extension until a reply
/// to this requests indicates the X server supports them.
fn shm_query_version(&self) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self)
}
/// Attach a System V shared memory segment..
///
/// Attach a System V shared memory segment to the server. This will fail unless
/// the server has permission to map the segment. The client may destroy the segment
/// as soon as it receives a XCB_SHM_COMPLETION event with the shmseg value in this
/// request and with the appropriate serial number.
///
/// # Fields
///
/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
/// * `shmid` - The System V shared memory segment the server should map.
/// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
fn shm_attach(&self, shmseg: Seg, shmid: u32, read_only: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
attach(self, shmseg, shmid, read_only)
}
/// Destroys the specified shared memory segment..
///
/// Destroys the specified shared memory segment. This will never fail unless the
/// segment number is incorrect.
///
/// # Fields
///
/// * `shmseg` - The segment to be destroyed.
fn shm_detach(&self, shmseg: Seg) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
detach(self, shmseg)
}
/// Copy data from the shared memory to the specified drawable..
///
/// Copy data from the shared memory to the specified drawable. The amount of bytes
/// written to the destination image is always equal to the number of bytes read
/// from the shared memory segment.
///
/// # Fields
///
/// * `drawable` - The drawable to draw to.
/// * `gc` - The graphics context to use.
/// * `total_width` - The total width of the source image.
/// * `total_height` - The total height of the source image.
/// * `src_x` - The source X coordinate of the sub-image to copy.
/// * `src_y` - The source Y coordinate of the sub-image to copy.
/// * `src_width` - The width, in source image coordinates, of the data to copy from the source.
/// The X server will use this to determine the amount of data to copy. The amount
/// of the destination image that is overwritten is determined automatically.
/// * `src_height` - The height, in source image coordinates, of the data to copy from the source.
/// The X server will use this to determine the amount of data to copy. The amount
/// of the destination image that is overwritten is determined automatically.
/// * `dst_x` - The X coordinate on the destination drawable to copy to.
/// * `dst_y` - The Y coordinate on the destination drawable to copy to.
/// * `depth` - The depth to use.
/// * `format` - The format of the image being drawn. If it is XYBitmap, depth must be 1, or a
/// "BadMatch" error results. The foreground pixel in the GC determines the source
/// for the one bits in the image, and the background pixel determines the source
/// for the zero bits. For XYPixmap and ZPixmap, the depth must match the depth of
/// the drawable, or a "BadMatch" error results.
/// * `send_event` - True if the server should send an XCB_SHM_COMPLETION event when the blit
/// completes.
/// * `offset` - The offset that the source image starts at.
fn shm_put_image(&self, drawable: xproto::Drawable, gc: xproto::Gcontext, total_width: u16, total_height: u16, src_x: u16, src_y: u16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16, depth: u8, format: u8, send_event: bool, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
put_image(self, drawable, gc, total_width, total_height, src_x, src_y, src_width, src_height, dst_x, dst_y, depth, format, send_event, shmseg, offset)
}
/// Copies data from the specified drawable to the shared memory segment..
///
/// Copy data from the specified drawable to the shared memory segment. The amount
/// of bytes written to the destination image is always equal to the number of bytes
/// read from the shared memory segment.
///
/// # Fields
///
/// * `drawable` - The drawable to copy the image out of.
/// * `x` - The X coordinate in the drawable to begin copying at.
/// * `y` - The Y coordinate in the drawable to begin copying at.
/// * `width` - The width of the image to copy.
/// * `height` - The height of the image to copy.
/// * `plane_mask` - A mask that determines which planes are used.
/// * `format` - The format to use for the copy (???).
/// * `shmseg` - The destination shared memory segment.
/// * `offset` - The offset in the shared memory segment to copy data to.
fn shm_get_image(&self, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Result<Cookie<'_, Self, GetImageReply>, ConnectionError>
{
get_image(self, drawable, x, y, width, height, plane_mask, format, shmseg, offset)
}
/// Create a pixmap backed by shared memory..
///
/// Create a pixmap backed by shared memory. Writes to the shared memory will be
/// reflected in the contents of the pixmap, and writes to the pixmap will be
/// reflected in the contents of the shared memory.
///
/// # Fields
///
/// * `pid` - A pixmap ID created with xcb_generate_id().
/// * `drawable` - The drawable to create the pixmap in.
/// * `width` - The width of the pixmap to create. Must be nonzero, or a Value error results.
/// * `height` - The height of the pixmap to create. Must be nonzero, or a Value error results.
/// * `depth` - The depth of the pixmap to create. Must be nonzero, or a Value error results.
/// * `shmseg` - The shared memory segment to use to create the pixmap.
/// * `offset` - The offset in the segment to create the pixmap at.
fn shm_create_pixmap(&self, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_pixmap(self, pid, drawable, width, height, depth, shmseg, offset)
}
/// Create a shared memory segment.
///
/// Create a shared memory segment. The file descriptor will be mapped at offset
/// zero, and the size will be obtained using fstat(). A zero size will result in a
/// Value error.
///
/// # Fields
///
/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
/// * `shm_fd` - The file descriptor the server should mmap().
/// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
fn shm_attach_fd<A>(&self, shmseg: Seg, shm_fd: A, read_only: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<RawFdContainer>,
{
attach_fd(self, shmseg, shm_fd, read_only)
}
/// Asks the server to allocate a shared memory segment..
///
/// Asks the server to allocate a shared memory segment. The servers reply will
/// include a file descriptor for the client to pass to mmap().
///
/// # Fields
///
/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
/// * `size` - The size of the segment to create.
/// * `read_only` - True if the server should map the segment read-only; otherwise false.
fn shm_create_segment(&self, shmseg: Seg, size: u32, read_only: bool) -> Result<CookieWithFds<'_, Self, CreateSegmentReply>, ConnectionError>
{
create_segment(self, shmseg, size, read_only)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around a [Seg].
///
/// Instances of this struct represent a Seg that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct SegWrapper<C: RequestConnection>(C, Seg);
impl<C: RequestConnection> SegWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_seg(conn: C, id: Seg) -> Self {
SegWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn seg(&self) -> Seg {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_seg(self) -> Seg {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> SegWrapper<&'c C>
{
/// Create a new Seg and return a Seg wrapper and a cookie.
///
/// This is a thin wrapper around [attach] that allocates an id for the Seg.
/// This function returns the resulting `SegWrapper` that owns the created Seg and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [attach].
///
/// Errors can come from the call to [X11Connection::generate_id] or [attach].
pub fn attach_and_get_cookie(conn: &'c C, shmid: u32, read_only: bool) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let shmseg = conn.generate_id()?;
let cookie = attach(conn, shmseg, shmid, read_only)?;
Ok((Self::for_seg(conn, shmseg), cookie))
}
}
impl<C: X11Connection> SegWrapper<C>
{
/// Create a new Seg and return a Seg wrapper
///
/// This is a thin wrapper around [attach] that allocates an id for the Seg.
/// This function returns the resulting `SegWrapper` that owns the created Seg and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [attach].
pub fn attach(conn: C, shmid: u32, read_only: bool) -> Result<Self, ReplyOrIdError>
{
let shmseg = conn.generate_id()?;
let _ = attach(&conn, shmseg, shmid, read_only)?;
Ok(Self::for_seg(conn, shmseg))
}
}
impl<'c, C: X11Connection> SegWrapper<&'c C>
{
/// Create a new Seg and return a Seg wrapper and a cookie.
///
/// This is a thin wrapper around [attach_fd] that allocates an id for the Seg.
/// This function returns the resulting `SegWrapper` that owns the created Seg and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [attach_fd].
///
/// Errors can come from the call to [X11Connection::generate_id] or [attach_fd].
pub fn attach_fd_and_get_cookie<A>(conn: &'c C, shm_fd: A, read_only: bool) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
where
A: Into<RawFdContainer>,
{
let shmseg = conn.generate_id()?;
let cookie = attach_fd(conn, shmseg, shm_fd, read_only)?;
Ok((Self::for_seg(conn, shmseg), cookie))
}
}
impl<C: X11Connection> SegWrapper<C>
{
/// Create a new Seg and return a Seg wrapper
///
/// This is a thin wrapper around [attach_fd] that allocates an id for the Seg.
/// This function returns the resulting `SegWrapper` that owns the created Seg and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [attach_fd].
pub fn attach_fd<A>(conn: C, shm_fd: A, read_only: bool) -> Result<Self, ReplyOrIdError>
where
A: Into<RawFdContainer>,
{
let shmseg = conn.generate_id()?;
let _ = attach_fd(&conn, shmseg, shm_fd, read_only)?;
Ok(Self::for_seg(conn, shmseg))
}
}
impl<C: RequestConnection> From<&SegWrapper<C>> for Seg {
fn from(from: &SegWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for SegWrapper<C> {
fn drop(&mut self) {
let _ = detach(&self.0, self.1);
}
}

662
vendor/x11rb/src/protocol/sync.rs vendored Normal file
View File

@@ -0,0 +1,662 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Sync` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::sync::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn initialize<Conn>(conn: &Conn, desired_major_version: u8, desired_minor_version: u8) -> Result<Cookie<'_, Conn, InitializeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = InitializeRequest {
desired_major_version,
desired_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_system_counters<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, ListSystemCountersReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListSystemCountersRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_counter<Conn>(conn: &Conn, id: Counter, initial_value: Int64) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateCounterRequest {
id,
initial_value,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn destroy_counter<Conn>(conn: &Conn, counter: Counter) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyCounterRequest {
counter,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_counter<Conn>(conn: &Conn, counter: Counter) -> Result<Cookie<'_, Conn, QueryCounterReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryCounterRequest {
counter,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn await_<'c, 'input, Conn>(conn: &'c Conn, wait_list: &'input [Waitcondition]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AwaitRequest {
wait_list: Cow::Borrowed(wait_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn change_counter<Conn>(conn: &Conn, counter: Counter, amount: Int64) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeCounterRequest {
counter,
amount,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_counter<Conn>(conn: &Conn, counter: Counter, value: Int64) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetCounterRequest {
counter,
value,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_alarm<'c, 'input, Conn>(conn: &'c Conn, id: Alarm, value_list: &'input CreateAlarmAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateAlarmRequest {
id,
value_list: Cow::Borrowed(value_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn change_alarm<'c, 'input, Conn>(conn: &'c Conn, id: Alarm, value_list: &'input ChangeAlarmAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeAlarmRequest {
id,
value_list: Cow::Borrowed(value_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn destroy_alarm<Conn>(conn: &Conn, alarm: Alarm) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyAlarmRequest {
alarm,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_alarm<Conn>(conn: &Conn, alarm: Alarm) -> Result<Cookie<'_, Conn, QueryAlarmReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryAlarmRequest {
alarm,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_priority<Conn>(conn: &Conn, id: u32, priority: i32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPriorityRequest {
id,
priority,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_priority<Conn>(conn: &Conn, id: u32) -> Result<Cookie<'_, Conn, GetPriorityReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPriorityRequest {
id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_fence<Conn>(conn: &Conn, drawable: xproto::Drawable, fence: Fence, initially_triggered: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateFenceRequest {
drawable,
fence,
initially_triggered,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn trigger_fence<Conn>(conn: &Conn, fence: Fence) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = TriggerFenceRequest {
fence,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn reset_fence<Conn>(conn: &Conn, fence: Fence) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ResetFenceRequest {
fence,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn destroy_fence<Conn>(conn: &Conn, fence: Fence) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyFenceRequest {
fence,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_fence<Conn>(conn: &Conn, fence: Fence) -> Result<Cookie<'_, Conn, QueryFenceReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryFenceRequest {
fence,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn await_fence<'c, 'input, Conn>(conn: &'c Conn, fence_list: &'input [Fence]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AwaitFenceRequest {
fence_list: Cow::Borrowed(fence_list),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn sync_initialize(&self, desired_major_version: u8, desired_minor_version: u8) -> Result<Cookie<'_, Self, InitializeReply>, ConnectionError>
{
initialize(self, desired_major_version, desired_minor_version)
}
fn sync_list_system_counters(&self) -> Result<Cookie<'_, Self, ListSystemCountersReply>, ConnectionError>
{
list_system_counters(self)
}
fn sync_create_counter(&self, id: Counter, initial_value: Int64) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_counter(self, id, initial_value)
}
fn sync_destroy_counter(&self, counter: Counter) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_counter(self, counter)
}
fn sync_query_counter(&self, counter: Counter) -> Result<Cookie<'_, Self, QueryCounterReply>, ConnectionError>
{
query_counter(self, counter)
}
fn sync_await_<'c, 'input>(&'c self, wait_list: &'input [Waitcondition]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
await_(self, wait_list)
}
fn sync_change_counter(&self, counter: Counter, amount: Int64) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
change_counter(self, counter, amount)
}
fn sync_set_counter(&self, counter: Counter, value: Int64) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_counter(self, counter, value)
}
fn sync_create_alarm<'c, 'input>(&'c self, id: Alarm, value_list: &'input CreateAlarmAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_alarm(self, id, value_list)
}
fn sync_change_alarm<'c, 'input>(&'c self, id: Alarm, value_list: &'input ChangeAlarmAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
change_alarm(self, id, value_list)
}
fn sync_destroy_alarm(&self, alarm: Alarm) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_alarm(self, alarm)
}
fn sync_query_alarm(&self, alarm: Alarm) -> Result<Cookie<'_, Self, QueryAlarmReply>, ConnectionError>
{
query_alarm(self, alarm)
}
fn sync_set_priority(&self, id: u32, priority: i32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_priority(self, id, priority)
}
fn sync_get_priority(&self, id: u32) -> Result<Cookie<'_, Self, GetPriorityReply>, ConnectionError>
{
get_priority(self, id)
}
fn sync_create_fence(&self, drawable: xproto::Drawable, fence: Fence, initially_triggered: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_fence(self, drawable, fence, initially_triggered)
}
fn sync_trigger_fence(&self, fence: Fence) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
trigger_fence(self, fence)
}
fn sync_reset_fence(&self, fence: Fence) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
reset_fence(self, fence)
}
fn sync_destroy_fence(&self, fence: Fence) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_fence(self, fence)
}
fn sync_query_fence(&self, fence: Fence) -> Result<Cookie<'_, Self, QueryFenceReply>, ConnectionError>
{
query_fence(self, fence)
}
fn sync_await_fence<'c, 'input>(&'c self, fence_list: &'input [Fence]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
await_fence(self, fence_list)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around a [Counter].
///
/// Instances of this struct represent a Counter that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct CounterWrapper<C: RequestConnection>(C, Counter);
impl<C: RequestConnection> CounterWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_counter(conn: C, id: Counter) -> Self {
CounterWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn counter(&self) -> Counter {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_counter(self) -> Counter {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> CounterWrapper<&'c C>
{
/// Create a new Counter and return a Counter wrapper and a cookie.
///
/// This is a thin wrapper around [create_counter] that allocates an id for the Counter.
/// This function returns the resulting `CounterWrapper` that owns the created Counter and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_counter].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_counter].
pub fn create_counter_and_get_cookie(conn: &'c C, initial_value: Int64) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let id = conn.generate_id()?;
let cookie = create_counter(conn, id, initial_value)?;
Ok((Self::for_counter(conn, id), cookie))
}
}
impl<C: X11Connection> CounterWrapper<C>
{
/// Create a new Counter and return a Counter wrapper
///
/// This is a thin wrapper around [create_counter] that allocates an id for the Counter.
/// This function returns the resulting `CounterWrapper` that owns the created Counter and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_counter].
pub fn create_counter(conn: C, initial_value: Int64) -> Result<Self, ReplyOrIdError>
{
let id = conn.generate_id()?;
let _ = create_counter(&conn, id, initial_value)?;
Ok(Self::for_counter(conn, id))
}
}
impl<C: RequestConnection> From<&CounterWrapper<C>> for Counter {
fn from(from: &CounterWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for CounterWrapper<C> {
fn drop(&mut self) {
let _ = destroy_counter(&self.0, self.1);
}
}
/// A RAII-like wrapper around a [Alarm].
///
/// Instances of this struct represent a Alarm that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct AlarmWrapper<C: RequestConnection>(C, Alarm);
impl<C: RequestConnection> AlarmWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_alarm(conn: C, id: Alarm) -> Self {
AlarmWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn alarm(&self) -> Alarm {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_alarm(self) -> Alarm {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> AlarmWrapper<&'c C>
{
/// Create a new Alarm and return a Alarm wrapper and a cookie.
///
/// This is a thin wrapper around [create_alarm] that allocates an id for the Alarm.
/// This function returns the resulting `AlarmWrapper` that owns the created Alarm and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_alarm].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_alarm].
pub fn create_alarm_and_get_cookie(conn: &'c C, value_list: &CreateAlarmAux) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let id = conn.generate_id()?;
let cookie = create_alarm(conn, id, value_list)?;
Ok((Self::for_alarm(conn, id), cookie))
}
}
impl<C: X11Connection> AlarmWrapper<C>
{
/// Create a new Alarm and return a Alarm wrapper
///
/// This is a thin wrapper around [create_alarm] that allocates an id for the Alarm.
/// This function returns the resulting `AlarmWrapper` that owns the created Alarm and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_alarm].
pub fn create_alarm(conn: C, value_list: &CreateAlarmAux) -> Result<Self, ReplyOrIdError>
{
let id = conn.generate_id()?;
let _ = create_alarm(&conn, id, value_list)?;
Ok(Self::for_alarm(conn, id))
}
}
impl<C: RequestConnection> From<&AlarmWrapper<C>> for Alarm {
fn from(from: &AlarmWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for AlarmWrapper<C> {
fn drop(&mut self) {
let _ = destroy_alarm(&self.0, self.1);
}
}
/// A RAII-like wrapper around a [Fence].
///
/// Instances of this struct represent a Fence that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct FenceWrapper<C: RequestConnection>(C, Fence);
impl<C: RequestConnection> FenceWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_fence(conn: C, id: Fence) -> Self {
FenceWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn fence(&self) -> Fence {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_fence(self) -> Fence {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> FenceWrapper<&'c C>
{
/// Create a new Fence and return a Fence wrapper and a cookie.
///
/// This is a thin wrapper around [create_fence] that allocates an id for the Fence.
/// This function returns the resulting `FenceWrapper` that owns the created Fence and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_fence].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_fence].
pub fn create_fence_and_get_cookie(conn: &'c C, drawable: xproto::Drawable, initially_triggered: bool) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let fence = conn.generate_id()?;
let cookie = create_fence(conn, drawable, fence, initially_triggered)?;
Ok((Self::for_fence(conn, fence), cookie))
}
}
impl<C: X11Connection> FenceWrapper<C>
{
/// Create a new Fence and return a Fence wrapper
///
/// This is a thin wrapper around [create_fence] that allocates an id for the Fence.
/// This function returns the resulting `FenceWrapper` that owns the created Fence and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_fence].
pub fn create_fence(conn: C, drawable: xproto::Drawable, initially_triggered: bool) -> Result<Self, ReplyOrIdError>
{
let fence = conn.generate_id()?;
let _ = create_fence(&conn, drawable, fence, initially_triggered)?;
Ok(Self::for_fence(conn, fence))
}
}
impl<'c, C: X11Connection> FenceWrapper<&'c C>
{
/// Create a new Fence and return a Fence wrapper and a cookie.
///
/// This is a thin wrapper around [super::dri3::fence_from_fd] that allocates an id for the Fence.
/// This function returns the resulting `FenceWrapper` that owns the created Fence and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [super::dri3::fence_from_fd].
///
/// Errors can come from the call to [X11Connection::generate_id] or [super::dri3::fence_from_fd].
#[cfg(feature = "dri3")]
pub fn dri3_fence_from_fd_and_get_cookie<A>(conn: &'c C, drawable: xproto::Drawable, initially_triggered: bool, fence_fd: A) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
where
A: Into<RawFdContainer>,
{
let fence = conn.generate_id()?;
let cookie = super::dri3::fence_from_fd(conn, drawable, fence, initially_triggered, fence_fd)?;
Ok((Self::for_fence(conn, fence), cookie))
}
}
impl<C: X11Connection> FenceWrapper<C>
{
/// Create a new Fence and return a Fence wrapper
///
/// This is a thin wrapper around [super::dri3::fence_from_fd] that allocates an id for the Fence.
/// This function returns the resulting `FenceWrapper` that owns the created Fence and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [super::dri3::fence_from_fd].
#[cfg(feature = "dri3")]
pub fn dri3_fence_from_fd<A>(conn: C, drawable: xproto::Drawable, initially_triggered: bool, fence_fd: A) -> Result<Self, ReplyOrIdError>
where
A: Into<RawFdContainer>,
{
let fence = conn.generate_id()?;
let _ = super::dri3::fence_from_fd(&conn, drawable, fence, initially_triggered, fence_fd)?;
Ok(Self::for_fence(conn, fence))
}
}
#[cfg(feature = "dri3")]
#[allow(unused_imports)]
use super::dri3;
impl<C: RequestConnection> From<&FenceWrapper<C>> for Fence {
fn from(from: &FenceWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for FenceWrapper<C> {
fn drop(&mut self) {
let _ = destroy_fence(&self.0, self.1);
}
}

89
vendor/x11rb/src/protocol/xc_misc.rs vendored Normal file
View File

@@ -0,0 +1,89 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `XCMisc` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::xc_misc::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn get_version<Conn>(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Conn, GetVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_xid_range<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetXIDRangeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetXIDRangeRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_xid_list<Conn>(conn: &Conn, count: u32) -> Result<Cookie<'_, Conn, GetXIDListReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetXIDListRequest {
count,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xc_misc_get_version(&self, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Self, GetVersionReply>, ConnectionError>
{
get_version(self, client_major_version, client_minor_version)
}
fn xc_misc_get_xid_range(&self) -> Result<Cookie<'_, Self, GetXIDRangeReply>, ConnectionError>
{
get_xid_range(self)
}
fn xc_misc_get_xid_list(&self, count: u32) -> Result<Cookie<'_, Self, GetXIDListReply>, ConnectionError>
{
get_xid_list(self, count)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

126
vendor/x11rb/src/protocol/xevie.rs vendored Normal file
View File

@@ -0,0 +1,126 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Xevie` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::xevie::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn start<Conn>(conn: &Conn, screen: u32) -> Result<Cookie<'_, Conn, StartReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = StartRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn end<Conn>(conn: &Conn, cmap: u32) -> Result<Cookie<'_, Conn, EndReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = EndRequest {
cmap,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn send<Conn>(conn: &Conn, event: Event, data_type: u32) -> Result<Cookie<'_, Conn, SendReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SendRequest {
event,
data_type,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn select_input<Conn>(conn: &Conn, event_mask: u32) -> Result<Cookie<'_, Conn, SelectInputReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xevie_query_version(&self, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
fn xevie_start(&self, screen: u32) -> Result<Cookie<'_, Self, StartReply>, ConnectionError>
{
start(self, screen)
}
fn xevie_end(&self, cmap: u32) -> Result<Cookie<'_, Self, EndReply>, ConnectionError>
{
end(self, cmap)
}
fn xevie_send(&self, event: Event, data_type: u32) -> Result<Cookie<'_, Self, SendReply>, ConnectionError>
{
send(self, event, data_type)
}
fn xevie_select_input(&self, event_mask: u32) -> Result<Cookie<'_, Self, SelectInputReply>, ConnectionError>
{
select_input(self, event_mask)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

248
vendor/x11rb/src/protocol/xf86dri.rs vendored Normal file
View File

@@ -0,0 +1,248 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `XF86Dri` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::xf86dri::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_direct_rendering_capable<Conn>(conn: &Conn, screen: u32) -> Result<Cookie<'_, Conn, QueryDirectRenderingCapableReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryDirectRenderingCapableRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn open_connection<Conn>(conn: &Conn, screen: u32) -> Result<Cookie<'_, Conn, OpenConnectionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = OpenConnectionRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn close_connection<Conn>(conn: &Conn, screen: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CloseConnectionRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_client_driver_name<Conn>(conn: &Conn, screen: u32) -> Result<Cookie<'_, Conn, GetClientDriverNameReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetClientDriverNameRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_context<Conn>(conn: &Conn, screen: u32, visual: u32, context: u32) -> Result<Cookie<'_, Conn, CreateContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateContextRequest {
screen,
visual,
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn destroy_context<Conn>(conn: &Conn, screen: u32, context: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyContextRequest {
screen,
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_drawable<Conn>(conn: &Conn, screen: u32, drawable: u32) -> Result<Cookie<'_, Conn, CreateDrawableReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateDrawableRequest {
screen,
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn destroy_drawable<Conn>(conn: &Conn, screen: u32, drawable: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyDrawableRequest {
screen,
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_drawable_info<Conn>(conn: &Conn, screen: u32, drawable: u32) -> Result<Cookie<'_, Conn, GetDrawableInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetDrawableInfoRequest {
screen,
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_device_info<Conn>(conn: &Conn, screen: u32) -> Result<Cookie<'_, Conn, GetDeviceInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetDeviceInfoRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn auth_connection<Conn>(conn: &Conn, screen: u32, magic: u32) -> Result<Cookie<'_, Conn, AuthConnectionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AuthConnectionRequest {
screen,
magic,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xf86dri_query_version(&self) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self)
}
fn xf86dri_query_direct_rendering_capable(&self, screen: u32) -> Result<Cookie<'_, Self, QueryDirectRenderingCapableReply>, ConnectionError>
{
query_direct_rendering_capable(self, screen)
}
fn xf86dri_open_connection(&self, screen: u32) -> Result<Cookie<'_, Self, OpenConnectionReply>, ConnectionError>
{
open_connection(self, screen)
}
fn xf86dri_close_connection(&self, screen: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
close_connection(self, screen)
}
fn xf86dri_get_client_driver_name(&self, screen: u32) -> Result<Cookie<'_, Self, GetClientDriverNameReply>, ConnectionError>
{
get_client_driver_name(self, screen)
}
fn xf86dri_create_context(&self, screen: u32, visual: u32, context: u32) -> Result<Cookie<'_, Self, CreateContextReply>, ConnectionError>
{
create_context(self, screen, visual, context)
}
fn xf86dri_destroy_context(&self, screen: u32, context: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_context(self, screen, context)
}
fn xf86dri_create_drawable(&self, screen: u32, drawable: u32) -> Result<Cookie<'_, Self, CreateDrawableReply>, ConnectionError>
{
create_drawable(self, screen, drawable)
}
fn xf86dri_destroy_drawable(&self, screen: u32, drawable: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_drawable(self, screen, drawable)
}
fn xf86dri_get_drawable_info(&self, screen: u32, drawable: u32) -> Result<Cookie<'_, Self, GetDrawableInfoReply>, ConnectionError>
{
get_drawable_info(self, screen, drawable)
}
fn xf86dri_get_device_info(&self, screen: u32) -> Result<Cookie<'_, Self, GetDeviceInfoReply>, ConnectionError>
{
get_device_info(self, screen)
}
fn xf86dri_auth_connection(&self, screen: u32, magic: u32) -> Result<Cookie<'_, Self, AuthConnectionReply>, ConnectionError>
{
auth_connection(self, screen, magic)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

477
vendor/x11rb/src/protocol/xf86vidmode.rs vendored Normal file
View File

@@ -0,0 +1,477 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `XF86VidMode` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub use x11rb_protocol::protocol::xf86vidmode::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_mode_line<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetModeLineReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetModeLineRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn mod_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ModModeLineRequest {
screen,
hdisplay,
hsyncstart,
hsyncend,
htotal,
hskew,
vdisplay,
vsyncstart,
vsyncend,
vtotal,
flags,
private: Cow::Borrowed(private),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn switch_mode<Conn>(conn: &Conn, screen: u16, zoom: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SwitchModeRequest {
screen,
zoom,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_monitor<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetMonitorReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetMonitorRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn lock_mode_switch<Conn>(conn: &Conn, screen: u16, lock: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = LockModeSwitchRequest {
screen,
lock,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_all_mode_lines<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetAllModeLinesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetAllModeLinesRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn add_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, after_dotclock: Dotclock, after_hdisplay: u16, after_hsyncstart: u16, after_hsyncend: u16, after_htotal: u16, after_hskew: u16, after_vdisplay: u16, after_vsyncstart: u16, after_vsyncend: u16, after_vtotal: u16, after_flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = AddModeLineRequest {
screen,
dotclock,
hdisplay,
hsyncstart,
hsyncend,
htotal,
hskew,
vdisplay,
vsyncstart,
vsyncend,
vtotal,
flags,
after_dotclock,
after_hdisplay,
after_hsyncstart,
after_hsyncend,
after_htotal,
after_hskew,
after_vdisplay,
after_vsyncstart,
after_vsyncend,
after_vtotal,
after_flags,
private: Cow::Borrowed(private),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn delete_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeleteModeLineRequest {
screen,
dotclock,
hdisplay,
hsyncstart,
hsyncend,
htotal,
hskew,
vdisplay,
vsyncstart,
vsyncend,
vtotal,
flags,
private: Cow::Borrowed(private),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn validate_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<Cookie<'c, Conn, ValidateModeLineReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ValidateModeLineRequest {
screen,
dotclock,
hdisplay,
hsyncstart,
hsyncend,
htotal,
hskew,
vdisplay,
vsyncstart,
vsyncend,
vtotal,
flags,
private: Cow::Borrowed(private),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn switch_to_mode<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SwitchToModeRequest {
screen,
dotclock,
hdisplay,
hsyncstart,
hsyncend,
htotal,
hskew,
vdisplay,
vsyncstart,
vsyncend,
vtotal,
flags,
private: Cow::Borrowed(private),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_view_port<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetViewPortReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetViewPortRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_view_port<Conn>(conn: &Conn, screen: u16, x: u32, y: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetViewPortRequest {
screen,
x,
y,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_dot_clocks<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetDotClocksReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetDotClocksRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_client_version<Conn>(conn: &Conn, major: u16, minor: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetClientVersionRequest {
major,
minor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_gamma<Conn>(conn: &Conn, screen: u16, red: u32, green: u32, blue: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetGammaRequest {
screen,
red,
green,
blue,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_gamma<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetGammaReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetGammaRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_gamma_ramp<Conn>(conn: &Conn, screen: u16, size: u16) -> Result<Cookie<'_, Conn, GetGammaRampReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetGammaRampRequest {
screen,
size,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_gamma_ramp<'c, 'input, Conn>(conn: &'c Conn, screen: u16, size: u16, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetGammaRampRequest {
screen,
size,
red: Cow::Borrowed(red),
green: Cow::Borrowed(green),
blue: Cow::Borrowed(blue),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_gamma_ramp_size<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetGammaRampSizeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetGammaRampSizeRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_permissions<Conn>(conn: &Conn, screen: u16) -> Result<Cookie<'_, Conn, GetPermissionsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPermissionsRequest {
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xf86vidmode_query_version(&self) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self)
}
fn xf86vidmode_get_mode_line(&self, screen: u16) -> Result<Cookie<'_, Self, GetModeLineReply>, ConnectionError>
{
get_mode_line(self, screen)
}
fn xf86vidmode_mod_mode_line<'c, 'input>(&'c self, screen: u32, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
mod_mode_line(self, screen, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)
}
fn xf86vidmode_switch_mode(&self, screen: u16, zoom: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
switch_mode(self, screen, zoom)
}
fn xf86vidmode_get_monitor(&self, screen: u16) -> Result<Cookie<'_, Self, GetMonitorReply>, ConnectionError>
{
get_monitor(self, screen)
}
fn xf86vidmode_lock_mode_switch(&self, screen: u16, lock: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
lock_mode_switch(self, screen, lock)
}
fn xf86vidmode_get_all_mode_lines(&self, screen: u16) -> Result<Cookie<'_, Self, GetAllModeLinesReply>, ConnectionError>
{
get_all_mode_lines(self, screen)
}
fn xf86vidmode_add_mode_line<'c, 'input>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, after_dotclock: Dotclock, after_hdisplay: u16, after_hsyncstart: u16, after_hsyncend: u16, after_htotal: u16, after_hskew: u16, after_vdisplay: u16, after_vsyncstart: u16, after_vsyncend: u16, after_vtotal: u16, after_flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
add_mode_line(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, after_dotclock, after_hdisplay, after_hsyncstart, after_hsyncend, after_htotal, after_hskew, after_vdisplay, after_vsyncstart, after_vsyncend, after_vtotal, after_flags, private)
}
fn xf86vidmode_delete_mode_line<'c, 'input>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
delete_mode_line(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)
}
fn xf86vidmode_validate_mode_line<'c, 'input>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<Cookie<'c, Self, ValidateModeLineReply>, ConnectionError>
{
validate_mode_line(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)
}
fn xf86vidmode_switch_to_mode<'c, 'input>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
switch_to_mode(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)
}
fn xf86vidmode_get_view_port(&self, screen: u16) -> Result<Cookie<'_, Self, GetViewPortReply>, ConnectionError>
{
get_view_port(self, screen)
}
fn xf86vidmode_set_view_port(&self, screen: u16, x: u32, y: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_view_port(self, screen, x, y)
}
fn xf86vidmode_get_dot_clocks(&self, screen: u16) -> Result<Cookie<'_, Self, GetDotClocksReply>, ConnectionError>
{
get_dot_clocks(self, screen)
}
fn xf86vidmode_set_client_version(&self, major: u16, minor: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_client_version(self, major, minor)
}
fn xf86vidmode_set_gamma(&self, screen: u16, red: u32, green: u32, blue: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_gamma(self, screen, red, green, blue)
}
fn xf86vidmode_get_gamma(&self, screen: u16) -> Result<Cookie<'_, Self, GetGammaReply>, ConnectionError>
{
get_gamma(self, screen)
}
fn xf86vidmode_get_gamma_ramp(&self, screen: u16, size: u16) -> Result<Cookie<'_, Self, GetGammaRampReply>, ConnectionError>
{
get_gamma_ramp(self, screen, size)
}
fn xf86vidmode_set_gamma_ramp<'c, 'input>(&'c self, screen: u16, size: u16, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_gamma_ramp(self, screen, size, red, green, blue)
}
fn xf86vidmode_get_gamma_ramp_size(&self, screen: u16) -> Result<Cookie<'_, Self, GetGammaRampSizeReply>, ConnectionError>
{
get_gamma_ramp_size(self, screen)
}
fn xf86vidmode_get_permissions(&self, screen: u16) -> Result<Cookie<'_, Self, GetPermissionsReply>, ConnectionError>
{
get_permissions(self, screen)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

959
vendor/x11rb/src/protocol/xfixes.rs vendored Normal file
View File

@@ -0,0 +1,959 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `XFixes` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::render;
#[allow(unused_imports)]
use super::shape;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xfixes::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn change_save_set<Conn>(conn: &Conn, mode: SaveSetMode, target: SaveSetTarget, map: SaveSetMapping, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeSaveSetRequest {
mode,
target,
map,
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn select_selection_input<Conn>(conn: &Conn, window: xproto::Window, selection: xproto::Atom, event_mask: SelectionEventMask) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectSelectionInputRequest {
window,
selection,
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn select_cursor_input<Conn>(conn: &Conn, window: xproto::Window, event_mask: CursorNotifyMask) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectCursorInputRequest {
window,
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_cursor_image<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetCursorImageReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCursorImageRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_region<'c, 'input, Conn>(conn: &'c Conn, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRegionRequest {
region,
rectangles: Cow::Borrowed(rectangles),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_region_from_bitmap<Conn>(conn: &Conn, region: Region, bitmap: xproto::Pixmap) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRegionFromBitmapRequest {
region,
bitmap,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_region_from_window<Conn>(conn: &Conn, region: Region, window: xproto::Window, kind: shape::SK) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRegionFromWindowRequest {
region,
window,
kind,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_region_from_gc<Conn>(conn: &Conn, region: Region, gc: xproto::Gcontext) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRegionFromGCRequest {
region,
gc,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_region_from_picture<Conn>(conn: &Conn, region: Region, picture: render::Picture) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateRegionFromPictureRequest {
region,
picture,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn destroy_region<Conn>(conn: &Conn, region: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyRegionRequest {
region,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_region<'c, 'input, Conn>(conn: &'c Conn, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetRegionRequest {
region,
rectangles: Cow::Borrowed(rectangles),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn copy_region<Conn>(conn: &Conn, source: Region, destination: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CopyRegionRequest {
source,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn union_region<Conn>(conn: &Conn, source1: Region, source2: Region, destination: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = UnionRegionRequest {
source1,
source2,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn intersect_region<Conn>(conn: &Conn, source1: Region, source2: Region, destination: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = IntersectRegionRequest {
source1,
source2,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn subtract_region<Conn>(conn: &Conn, source1: Region, source2: Region, destination: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SubtractRegionRequest {
source1,
source2,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn invert_region<Conn>(conn: &Conn, source: Region, bounds: xproto::Rectangle, destination: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = InvertRegionRequest {
source,
bounds,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn translate_region<Conn>(conn: &Conn, region: Region, dx: i16, dy: i16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = TranslateRegionRequest {
region,
dx,
dy,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn region_extents<Conn>(conn: &Conn, source: Region, destination: Region) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = RegionExtentsRequest {
source,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn fetch_region<Conn>(conn: &Conn, region: Region) -> Result<Cookie<'_, Conn, FetchRegionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FetchRegionRequest {
region,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_gc_clip_region<Conn, A>(conn: &Conn, gc: xproto::Gcontext, region: A, x_origin: i16, y_origin: i16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<Region>,
{
let region: Region = region.into();
let request0 = SetGCClipRegionRequest {
gc,
region,
x_origin,
y_origin,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_window_shape_region<Conn, A>(conn: &Conn, dest: xproto::Window, dest_kind: shape::SK, x_offset: i16, y_offset: i16, region: A) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<Region>,
{
let region: Region = region.into();
let request0 = SetWindowShapeRegionRequest {
dest,
dest_kind,
x_offset,
y_offset,
region,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_picture_clip_region<Conn, A>(conn: &Conn, picture: render::Picture, region: A, x_origin: i16, y_origin: i16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<Region>,
{
let region: Region = region.into();
let request0 = SetPictureClipRegionRequest {
picture,
region,
x_origin,
y_origin,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_cursor_name<'c, 'input, Conn>(conn: &'c Conn, cursor: xproto::Cursor, name: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetCursorNameRequest {
cursor,
name: Cow::Borrowed(name),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_cursor_name<Conn>(conn: &Conn, cursor: xproto::Cursor) -> Result<Cookie<'_, Conn, GetCursorNameReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCursorNameRequest {
cursor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_cursor_image_and_name<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetCursorImageAndNameReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCursorImageAndNameRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn change_cursor<Conn>(conn: &Conn, source: xproto::Cursor, destination: xproto::Cursor) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeCursorRequest {
source,
destination,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn change_cursor_by_name<'c, 'input, Conn>(conn: &'c Conn, src: xproto::Cursor, name: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ChangeCursorByNameRequest {
src,
name: Cow::Borrowed(name),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn expand_region<Conn>(conn: &Conn, source: Region, destination: Region, left: u16, right: u16, top: u16, bottom: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ExpandRegionRequest {
source,
destination,
left,
right,
top,
bottom,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn hide_cursor<Conn>(conn: &Conn, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = HideCursorRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn show_cursor<Conn>(conn: &Conn, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ShowCursorRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_pointer_barrier<'c, 'input, Conn>(conn: &'c Conn, barrier: Barrier, window: xproto::Window, x1: u16, y1: u16, x2: u16, y2: u16, directions: BarrierDirections, devices: &'input [u16]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreatePointerBarrierRequest {
barrier,
window,
x1,
y1,
x2,
y2,
directions,
devices: Cow::Borrowed(devices),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn delete_pointer_barrier<Conn>(conn: &Conn, barrier: Barrier) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DeletePointerBarrierRequest {
barrier,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Sets the disconnect mode for the client..
///
/// # Fields
///
/// * `disconnect_mode` - The new disconnect mode.
pub fn set_client_disconnect_mode<Conn>(conn: &Conn, disconnect_mode: ClientDisconnectFlags) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetClientDisconnectModeRequest {
disconnect_mode,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_client_disconnect_mode<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetClientDisconnectModeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetClientDisconnectModeRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xfixes_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
fn xfixes_change_save_set(&self, mode: SaveSetMode, target: SaveSetTarget, map: SaveSetMapping, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
change_save_set(self, mode, target, map, window)
}
fn xfixes_select_selection_input(&self, window: xproto::Window, selection: xproto::Atom, event_mask: SelectionEventMask) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_selection_input(self, window, selection, event_mask)
}
fn xfixes_select_cursor_input(&self, window: xproto::Window, event_mask: CursorNotifyMask) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_cursor_input(self, window, event_mask)
}
fn xfixes_get_cursor_image(&self) -> Result<Cookie<'_, Self, GetCursorImageReply>, ConnectionError>
{
get_cursor_image(self)
}
fn xfixes_create_region<'c, 'input>(&'c self, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_region(self, region, rectangles)
}
fn xfixes_create_region_from_bitmap(&self, region: Region, bitmap: xproto::Pixmap) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_region_from_bitmap(self, region, bitmap)
}
fn xfixes_create_region_from_window(&self, region: Region, window: xproto::Window, kind: shape::SK) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_region_from_window(self, region, window, kind)
}
fn xfixes_create_region_from_gc(&self, region: Region, gc: xproto::Gcontext) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_region_from_gc(self, region, gc)
}
fn xfixes_create_region_from_picture(&self, region: Region, picture: render::Picture) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
create_region_from_picture(self, region, picture)
}
fn xfixes_destroy_region(&self, region: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_region(self, region)
}
fn xfixes_set_region<'c, 'input>(&'c self, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_region(self, region, rectangles)
}
fn xfixes_copy_region(&self, source: Region, destination: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
copy_region(self, source, destination)
}
fn xfixes_union_region(&self, source1: Region, source2: Region, destination: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
union_region(self, source1, source2, destination)
}
fn xfixes_intersect_region(&self, source1: Region, source2: Region, destination: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
intersect_region(self, source1, source2, destination)
}
fn xfixes_subtract_region(&self, source1: Region, source2: Region, destination: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
subtract_region(self, source1, source2, destination)
}
fn xfixes_invert_region(&self, source: Region, bounds: xproto::Rectangle, destination: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
invert_region(self, source, bounds, destination)
}
fn xfixes_translate_region(&self, region: Region, dx: i16, dy: i16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
translate_region(self, region, dx, dy)
}
fn xfixes_region_extents(&self, source: Region, destination: Region) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
region_extents(self, source, destination)
}
fn xfixes_fetch_region(&self, region: Region) -> Result<Cookie<'_, Self, FetchRegionReply>, ConnectionError>
{
fetch_region(self, region)
}
fn xfixes_set_gc_clip_region<A>(&self, gc: xproto::Gcontext, region: A, x_origin: i16, y_origin: i16) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Region>,
{
set_gc_clip_region(self, gc, region, x_origin, y_origin)
}
fn xfixes_set_window_shape_region<A>(&self, dest: xproto::Window, dest_kind: shape::SK, x_offset: i16, y_offset: i16, region: A) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Region>,
{
set_window_shape_region(self, dest, dest_kind, x_offset, y_offset, region)
}
fn xfixes_set_picture_clip_region<A>(&self, picture: render::Picture, region: A, x_origin: i16, y_origin: i16) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Region>,
{
set_picture_clip_region(self, picture, region, x_origin, y_origin)
}
fn xfixes_set_cursor_name<'c, 'input>(&'c self, cursor: xproto::Cursor, name: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_cursor_name(self, cursor, name)
}
fn xfixes_get_cursor_name(&self, cursor: xproto::Cursor) -> Result<Cookie<'_, Self, GetCursorNameReply>, ConnectionError>
{
get_cursor_name(self, cursor)
}
fn xfixes_get_cursor_image_and_name(&self) -> Result<Cookie<'_, Self, GetCursorImageAndNameReply>, ConnectionError>
{
get_cursor_image_and_name(self)
}
fn xfixes_change_cursor(&self, source: xproto::Cursor, destination: xproto::Cursor) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
change_cursor(self, source, destination)
}
fn xfixes_change_cursor_by_name<'c, 'input>(&'c self, src: xproto::Cursor, name: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
change_cursor_by_name(self, src, name)
}
fn xfixes_expand_region(&self, source: Region, destination: Region, left: u16, right: u16, top: u16, bottom: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
expand_region(self, source, destination, left, right, top, bottom)
}
fn xfixes_hide_cursor(&self, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
hide_cursor(self, window)
}
fn xfixes_show_cursor(&self, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
show_cursor(self, window)
}
fn xfixes_create_pointer_barrier<'c, 'input>(&'c self, barrier: Barrier, window: xproto::Window, x1: u16, y1: u16, x2: u16, y2: u16, directions: BarrierDirections, devices: &'input [u16]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_pointer_barrier(self, barrier, window, x1, y1, x2, y2, directions, devices)
}
fn xfixes_delete_pointer_barrier(&self, barrier: Barrier) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
delete_pointer_barrier(self, barrier)
}
/// Sets the disconnect mode for the client..
///
/// # Fields
///
/// * `disconnect_mode` - The new disconnect mode.
fn xfixes_set_client_disconnect_mode(&self, disconnect_mode: ClientDisconnectFlags) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_client_disconnect_mode(self, disconnect_mode)
}
fn xfixes_get_client_disconnect_mode(&self) -> Result<Cookie<'_, Self, GetClientDisconnectModeReply>, ConnectionError>
{
get_client_disconnect_mode(self)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around a [Region].
///
/// Instances of this struct represent a Region that is freed in `Drop`.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct RegionWrapper<C: RequestConnection>(C, Region);
impl<C: RequestConnection> RegionWrapper<C>
{
/// Assume ownership of the given resource and destroy it in `Drop`.
pub fn for_region(conn: C, id: Region) -> Self {
RegionWrapper(conn, id)
}
/// Get the XID of the wrapped resource
pub fn region(&self) -> Region {
self.1
}
/// Assume ownership of the XID of the wrapped resource
///
/// This function destroys this wrapper without freeing the underlying resource.
pub fn into_region(self) -> Region {
let id = self.1;
std::mem::forget(self);
id
}
}
impl<'c, C: X11Connection> RegionWrapper<&'c C>
{
/// Create a new Region and return a Region wrapper and a cookie.
///
/// This is a thin wrapper around [create_region] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_region].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region].
pub fn create_region_and_get_cookie(conn: &'c C, rectangles: &[xproto::Rectangle]) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let region = conn.generate_id()?;
let cookie = create_region(conn, region, rectangles)?;
Ok((Self::for_region(conn, region), cookie))
}
}
impl<C: X11Connection> RegionWrapper<C>
{
/// Create a new Region and return a Region wrapper
///
/// This is a thin wrapper around [create_region] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region].
pub fn create_region(conn: C, rectangles: &[xproto::Rectangle]) -> Result<Self, ReplyOrIdError>
{
let region = conn.generate_id()?;
let _ = create_region(&conn, region, rectangles)?;
Ok(Self::for_region(conn, region))
}
}
impl<'c, C: X11Connection> RegionWrapper<&'c C>
{
/// Create a new Region and return a Region wrapper and a cookie.
///
/// This is a thin wrapper around [create_region_from_bitmap] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_region_from_bitmap].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_bitmap].
pub fn create_region_from_bitmap_and_get_cookie(conn: &'c C, bitmap: xproto::Pixmap) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let region = conn.generate_id()?;
let cookie = create_region_from_bitmap(conn, region, bitmap)?;
Ok((Self::for_region(conn, region), cookie))
}
}
impl<C: X11Connection> RegionWrapper<C>
{
/// Create a new Region and return a Region wrapper
///
/// This is a thin wrapper around [create_region_from_bitmap] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_bitmap].
pub fn create_region_from_bitmap(conn: C, bitmap: xproto::Pixmap) -> Result<Self, ReplyOrIdError>
{
let region = conn.generate_id()?;
let _ = create_region_from_bitmap(&conn, region, bitmap)?;
Ok(Self::for_region(conn, region))
}
}
impl<'c, C: X11Connection> RegionWrapper<&'c C>
{
/// Create a new Region and return a Region wrapper and a cookie.
///
/// This is a thin wrapper around [create_region_from_window] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_region_from_window].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_window].
pub fn create_region_from_window_and_get_cookie(conn: &'c C, window: xproto::Window, kind: shape::SK) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let region = conn.generate_id()?;
let cookie = create_region_from_window(conn, region, window, kind)?;
Ok((Self::for_region(conn, region), cookie))
}
}
impl<C: X11Connection> RegionWrapper<C>
{
/// Create a new Region and return a Region wrapper
///
/// This is a thin wrapper around [create_region_from_window] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_window].
pub fn create_region_from_window(conn: C, window: xproto::Window, kind: shape::SK) -> Result<Self, ReplyOrIdError>
{
let region = conn.generate_id()?;
let _ = create_region_from_window(&conn, region, window, kind)?;
Ok(Self::for_region(conn, region))
}
}
impl<'c, C: X11Connection> RegionWrapper<&'c C>
{
/// Create a new Region and return a Region wrapper and a cookie.
///
/// This is a thin wrapper around [create_region_from_gc] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_region_from_gc].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_gc].
pub fn create_region_from_gc_and_get_cookie(conn: &'c C, gc: xproto::Gcontext) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let region = conn.generate_id()?;
let cookie = create_region_from_gc(conn, region, gc)?;
Ok((Self::for_region(conn, region), cookie))
}
}
impl<C: X11Connection> RegionWrapper<C>
{
/// Create a new Region and return a Region wrapper
///
/// This is a thin wrapper around [create_region_from_gc] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_gc].
pub fn create_region_from_gc(conn: C, gc: xproto::Gcontext) -> Result<Self, ReplyOrIdError>
{
let region = conn.generate_id()?;
let _ = create_region_from_gc(&conn, region, gc)?;
Ok(Self::for_region(conn, region))
}
}
impl<'c, C: X11Connection> RegionWrapper<&'c C>
{
/// Create a new Region and return a Region wrapper and a cookie.
///
/// This is a thin wrapper around [create_region_from_picture] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [create_region_from_picture].
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_picture].
pub fn create_region_from_picture_and_get_cookie(conn: &'c C, picture: render::Picture) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let region = conn.generate_id()?;
let cookie = create_region_from_picture(conn, region, picture)?;
Ok((Self::for_region(conn, region), cookie))
}
}
impl<C: X11Connection> RegionWrapper<C>
{
/// Create a new Region and return a Region wrapper
///
/// This is a thin wrapper around [create_region_from_picture] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [create_region_from_picture].
pub fn create_region_from_picture(conn: C, picture: render::Picture) -> Result<Self, ReplyOrIdError>
{
let region = conn.generate_id()?;
let _ = create_region_from_picture(&conn, region, picture)?;
Ok(Self::for_region(conn, region))
}
}
impl<'c, C: X11Connection> RegionWrapper<&'c C>
{
/// Create a new Region and return a Region wrapper and a cookie.
///
/// This is a thin wrapper around [super::composite::create_region_from_border_clip] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
/// [super::composite::create_region_from_border_clip].
///
/// Errors can come from the call to [X11Connection::generate_id] or [super::composite::create_region_from_border_clip].
#[cfg(feature = "composite")]
pub fn composite_create_region_from_border_clip_and_get_cookie(conn: &'c C, window: xproto::Window) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
{
let region = conn.generate_id()?;
let cookie = super::composite::create_region_from_border_clip(conn, region, window)?;
Ok((Self::for_region(conn, region), cookie))
}
}
impl<C: X11Connection> RegionWrapper<C>
{
/// Create a new Region and return a Region wrapper
///
/// This is a thin wrapper around [super::composite::create_region_from_border_clip] that allocates an id for the Region.
/// This function returns the resulting `RegionWrapper` that owns the created Region and frees
/// it in `Drop`.
///
/// Errors can come from the call to [X11Connection::generate_id] or [super::composite::create_region_from_border_clip].
#[cfg(feature = "composite")]
pub fn composite_create_region_from_border_clip(conn: C, window: xproto::Window) -> Result<Self, ReplyOrIdError>
{
let region = conn.generate_id()?;
let _ = super::composite::create_region_from_border_clip(&conn, region, window)?;
Ok(Self::for_region(conn, region))
}
}
#[cfg(feature = "composite")]
#[allow(unused_imports)]
use super::composite;
impl<C: RequestConnection> From<&RegionWrapper<C>> for Region {
fn from(from: &RegionWrapper<C>) -> Self {
from.1
}
}
impl<C: RequestConnection> Drop for RegionWrapper<C> {
fn drop(&mut self) {
let _ = destroy_region(&self.0, self.1);
}
}

141
vendor/x11rb/src/protocol/xinerama.rs vendored Normal file
View File

@@ -0,0 +1,141 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Xinerama` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xinerama::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, major: u8, minor: u8) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
major,
minor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_state<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetStateReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetStateRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_screen_count<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetScreenCountReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetScreenCountRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_screen_size<Conn>(conn: &Conn, window: xproto::Window, screen: u32) -> Result<Cookie<'_, Conn, GetScreenSizeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetScreenSizeRequest {
window,
screen,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn is_active<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, IsActiveReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = IsActiveRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_screens<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryScreensReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryScreensRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xinerama_query_version(&self, major: u8, minor: u8) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, major, minor)
}
fn xinerama_get_state(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetStateReply>, ConnectionError>
{
get_state(self, window)
}
fn xinerama_get_screen_count(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetScreenCountReply>, ConnectionError>
{
get_screen_count(self, window)
}
fn xinerama_get_screen_size(&self, window: xproto::Window, screen: u32) -> Result<Cookie<'_, Self, GetScreenSizeReply>, ConnectionError>
{
get_screen_size(self, window, screen)
}
fn xinerama_is_active(&self) -> Result<Cookie<'_, Self, IsActiveReply>, ConnectionError>
{
is_active(self)
}
fn xinerama_query_screens(&self) -> Result<Cookie<'_, Self, QueryScreensReply>, ConnectionError>
{
query_screens(self)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

1339
vendor/x11rb/src/protocol/xinput.rs vendored Normal file

File diff suppressed because it is too large Load Diff

621
vendor/x11rb/src/protocol/xkb.rs vendored Normal file
View File

@@ -0,0 +1,621 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `xkb` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xkb::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn use_extension<Conn>(conn: &Conn, wanted_major: u16, wanted_minor: u16) -> Result<Cookie<'_, Conn, UseExtensionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = UseExtensionRequest {
wanted_major,
wanted_minor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn select_events<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, clear: EventType, select_all: EventType, affect_map: MapPart, map: MapPart, details: &'input SelectEventsAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectEventsRequest {
device_spec,
clear,
select_all,
affect_map,
map,
details: Cow::Borrowed(details),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn bell<Conn>(conn: &Conn, device_spec: DeviceSpec, bell_class: BellClassSpec, bell_id: IDSpec, percent: i8, force_sound: bool, event_only: bool, pitch: i16, duration: i16, name: xproto::Atom, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = BellRequest {
device_spec,
bell_class,
bell_id,
percent,
force_sound,
event_only,
pitch,
duration,
name,
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_state<Conn>(conn: &Conn, device_spec: DeviceSpec) -> Result<Cookie<'_, Conn, GetStateReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetStateRequest {
device_spec,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn latch_lock_state<Conn>(conn: &Conn, device_spec: DeviceSpec, affect_mod_locks: xproto::ModMask, mod_locks: xproto::ModMask, lock_group: bool, group_lock: Group, affect_mod_latches: xproto::ModMask, latch_group: bool, group_latch: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = LatchLockStateRequest {
device_spec,
affect_mod_locks,
mod_locks,
lock_group,
group_lock,
affect_mod_latches,
latch_group,
group_latch,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_controls<Conn>(conn: &Conn, device_spec: DeviceSpec) -> Result<Cookie<'_, Conn, GetControlsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetControlsRequest {
device_spec,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_controls<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, affect_internal_real_mods: xproto::ModMask, internal_real_mods: xproto::ModMask, affect_ignore_lock_real_mods: xproto::ModMask, ignore_lock_real_mods: xproto::ModMask, affect_internal_virtual_mods: VMod, internal_virtual_mods: VMod, affect_ignore_lock_virtual_mods: VMod, ignore_lock_virtual_mods: VMod, mouse_keys_dflt_btn: u8, groups_wrap: u8, access_x_options: AXOption, affect_enabled_controls: BoolCtrl, enabled_controls: BoolCtrl, change_controls: Control, repeat_delay: u16, repeat_interval: u16, slow_keys_delay: u16, debounce_delay: u16, mouse_keys_delay: u16, mouse_keys_interval: u16, mouse_keys_time_to_max: u16, mouse_keys_max_speed: u16, mouse_keys_curve: i16, access_x_timeout: u16, access_x_timeout_mask: BoolCtrl, access_x_timeout_values: BoolCtrl, access_x_timeout_options_mask: AXOption, access_x_timeout_options_values: AXOption, per_key_repeat: &'input [u8; 32]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetControlsRequest {
device_spec,
affect_internal_real_mods,
internal_real_mods,
affect_ignore_lock_real_mods,
ignore_lock_real_mods,
affect_internal_virtual_mods,
internal_virtual_mods,
affect_ignore_lock_virtual_mods,
ignore_lock_virtual_mods,
mouse_keys_dflt_btn,
groups_wrap,
access_x_options,
affect_enabled_controls,
enabled_controls,
change_controls,
repeat_delay,
repeat_interval,
slow_keys_delay,
debounce_delay,
mouse_keys_delay,
mouse_keys_interval,
mouse_keys_time_to_max,
mouse_keys_max_speed,
mouse_keys_curve,
access_x_timeout,
access_x_timeout_mask,
access_x_timeout_values,
access_x_timeout_options_mask,
access_x_timeout_options_values,
per_key_repeat: Cow::Borrowed(per_key_repeat),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_map<Conn>(conn: &Conn, device_spec: DeviceSpec, full: MapPart, partial: MapPart, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, first_key_action: xproto::Keycode, n_key_actions: u8, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, virtual_mods: VMod, first_key_explicit: xproto::Keycode, n_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8) -> Result<Cookie<'_, Conn, GetMapReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetMapRequest {
device_spec,
full,
partial,
first_type,
n_types,
first_key_sym,
n_key_syms,
first_key_action,
n_key_actions,
first_key_behavior,
n_key_behaviors,
virtual_mods,
first_key_explicit,
n_key_explicit,
first_mod_map_key,
n_mod_map_keys,
first_v_mod_map_key,
n_v_mod_map_keys,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_map<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, flags: SetMapFlags, min_key_code: xproto::Keycode, max_key_code: xproto::Keycode, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, total_syms: u16, first_key_action: xproto::Keycode, n_key_actions: u8, total_actions: u16, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, total_key_behaviors: u8, first_key_explicit: xproto::Keycode, n_key_explicit: u8, total_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, total_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8, total_v_mod_map_keys: u8, virtual_mods: VMod, values: &'input SetMapAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetMapRequest {
device_spec,
flags,
min_key_code,
max_key_code,
first_type,
n_types,
first_key_sym,
n_key_syms,
total_syms,
first_key_action,
n_key_actions,
total_actions,
first_key_behavior,
n_key_behaviors,
total_key_behaviors,
first_key_explicit,
n_key_explicit,
total_key_explicit,
first_mod_map_key,
n_mod_map_keys,
total_mod_map_keys,
first_v_mod_map_key,
n_v_mod_map_keys,
total_v_mod_map_keys,
virtual_mods,
values: Cow::Borrowed(values),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_compat_map<Conn>(conn: &Conn, device_spec: DeviceSpec, groups: SetOfGroup, get_all_si: bool, first_si: u16, n_si: u16) -> Result<Cookie<'_, Conn, GetCompatMapReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetCompatMapRequest {
device_spec,
groups,
get_all_si,
first_si,
n_si,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_compat_map<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, recompute_actions: bool, truncate_si: bool, groups: SetOfGroup, first_si: u16, si: &'input [SymInterpret], group_maps: &'input [ModDef]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetCompatMapRequest {
device_spec,
recompute_actions,
truncate_si,
groups,
first_si,
si: Cow::Borrowed(si),
group_maps: Cow::Borrowed(group_maps),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_indicator_state<Conn>(conn: &Conn, device_spec: DeviceSpec) -> Result<Cookie<'_, Conn, GetIndicatorStateReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetIndicatorStateRequest {
device_spec,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_indicator_map<Conn>(conn: &Conn, device_spec: DeviceSpec, which: u32) -> Result<Cookie<'_, Conn, GetIndicatorMapReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetIndicatorMapRequest {
device_spec,
which,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_indicator_map<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, which: u32, maps: &'input [IndicatorMap]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetIndicatorMapRequest {
device_spec,
which,
maps: Cow::Borrowed(maps),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_named_indicator<Conn, A>(conn: &Conn, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom) -> Result<Cookie<'_, Conn, GetNamedIndicatorReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<IDSpec>,
{
let led_id: IDSpec = led_id.into();
let request0 = GetNamedIndicatorRequest {
device_spec,
led_class,
led_id,
indicator,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_named_indicator<Conn, A>(conn: &Conn, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom, set_state: bool, on: bool, set_map: bool, create_map: bool, map_flags: IMFlag, map_which_groups: IMGroupsWhich, map_groups: SetOfGroups, map_which_mods: IMModsWhich, map_real_mods: xproto::ModMask, map_vmods: VMod, map_ctrls: BoolCtrl) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<IDSpec>,
{
let led_id: IDSpec = led_id.into();
let request0 = SetNamedIndicatorRequest {
device_spec,
led_class,
led_id,
indicator,
set_state,
on,
set_map,
create_map,
map_flags,
map_which_groups,
map_groups,
map_which_mods,
map_real_mods,
map_vmods,
map_ctrls,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_names<Conn>(conn: &Conn, device_spec: DeviceSpec, which: NameDetail) -> Result<Cookie<'_, Conn, GetNamesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetNamesRequest {
device_spec,
which,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_names<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, virtual_mods: VMod, first_type: u8, n_types: u8, first_kt_levelt: u8, n_kt_levels: u8, indicators: u32, group_names: SetOfGroup, n_radio_groups: u8, first_key: xproto::Keycode, n_keys: u8, n_key_aliases: u8, total_kt_level_names: u16, values: &'input SetNamesAux) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetNamesRequest {
device_spec,
virtual_mods,
first_type,
n_types,
first_kt_levelt,
n_kt_levels,
indicators,
group_names,
n_radio_groups,
first_key,
n_keys,
n_key_aliases,
total_kt_level_names,
values: Cow::Borrowed(values),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn per_client_flags<Conn>(conn: &Conn, device_spec: DeviceSpec, change: PerClientFlag, value: PerClientFlag, ctrls_to_change: BoolCtrl, auto_ctrls: BoolCtrl, auto_ctrls_values: BoolCtrl) -> Result<Cookie<'_, Conn, PerClientFlagsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PerClientFlagsRequest {
device_spec,
change,
value,
ctrls_to_change,
auto_ctrls,
auto_ctrls_values,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_components<Conn>(conn: &Conn, device_spec: DeviceSpec, max_names: u16) -> Result<Cookie<'_, Conn, ListComponentsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListComponentsRequest {
device_spec,
max_names,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_kbd_by_name<Conn>(conn: &Conn, device_spec: DeviceSpec, need: GBNDetail, want: GBNDetail, load: bool) -> Result<Cookie<'_, Conn, GetKbdByNameReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetKbdByNameRequest {
device_spec,
need,
want,
load,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_device_info<Conn, A>(conn: &Conn, device_spec: DeviceSpec, wanted: XIFeature, all_buttons: bool, first_button: u8, n_buttons: u8, led_class: LedClass, led_id: A) -> Result<Cookie<'_, Conn, GetDeviceInfoReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<IDSpec>,
{
let led_id: IDSpec = led_id.into();
let request0 = GetDeviceInfoRequest {
device_spec,
wanted,
all_buttons,
first_button,
n_buttons,
led_class,
led_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_device_info<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, first_btn: u8, change: XIFeature, btn_actions: &'input [Action], leds: &'input [DeviceLedInfo]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetDeviceInfoRequest {
device_spec,
first_btn,
change,
btn_actions: Cow::Borrowed(btn_actions),
leds: Cow::Borrowed(leds),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn set_debugging_flags<'c, 'input, Conn>(conn: &'c Conn, affect_flags: u32, flags: u32, affect_ctrls: u32, ctrls: u32, message: &'input [String8]) -> Result<Cookie<'c, Conn, SetDebuggingFlagsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetDebuggingFlagsRequest {
affect_flags,
flags,
affect_ctrls,
ctrls,
message: Cow::Borrowed(message),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xkb_use_extension(&self, wanted_major: u16, wanted_minor: u16) -> Result<Cookie<'_, Self, UseExtensionReply>, ConnectionError>
{
use_extension(self, wanted_major, wanted_minor)
}
fn xkb_select_events<'c, 'input>(&'c self, device_spec: DeviceSpec, clear: EventType, select_all: EventType, affect_map: MapPart, map: MapPart, details: &'input SelectEventsAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
select_events(self, device_spec, clear, select_all, affect_map, map, details)
}
fn xkb_bell(&self, device_spec: DeviceSpec, bell_class: BellClassSpec, bell_id: IDSpec, percent: i8, force_sound: bool, event_only: bool, pitch: i16, duration: i16, name: xproto::Atom, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
bell(self, device_spec, bell_class, bell_id, percent, force_sound, event_only, pitch, duration, name, window)
}
fn xkb_get_state(&self, device_spec: DeviceSpec) -> Result<Cookie<'_, Self, GetStateReply>, ConnectionError>
{
get_state(self, device_spec)
}
fn xkb_latch_lock_state(&self, device_spec: DeviceSpec, affect_mod_locks: xproto::ModMask, mod_locks: xproto::ModMask, lock_group: bool, group_lock: Group, affect_mod_latches: xproto::ModMask, latch_group: bool, group_latch: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
latch_lock_state(self, device_spec, affect_mod_locks, mod_locks, lock_group, group_lock, affect_mod_latches, latch_group, group_latch)
}
fn xkb_get_controls(&self, device_spec: DeviceSpec) -> Result<Cookie<'_, Self, GetControlsReply>, ConnectionError>
{
get_controls(self, device_spec)
}
fn xkb_set_controls<'c, 'input>(&'c self, device_spec: DeviceSpec, affect_internal_real_mods: xproto::ModMask, internal_real_mods: xproto::ModMask, affect_ignore_lock_real_mods: xproto::ModMask, ignore_lock_real_mods: xproto::ModMask, affect_internal_virtual_mods: VMod, internal_virtual_mods: VMod, affect_ignore_lock_virtual_mods: VMod, ignore_lock_virtual_mods: VMod, mouse_keys_dflt_btn: u8, groups_wrap: u8, access_x_options: AXOption, affect_enabled_controls: BoolCtrl, enabled_controls: BoolCtrl, change_controls: Control, repeat_delay: u16, repeat_interval: u16, slow_keys_delay: u16, debounce_delay: u16, mouse_keys_delay: u16, mouse_keys_interval: u16, mouse_keys_time_to_max: u16, mouse_keys_max_speed: u16, mouse_keys_curve: i16, access_x_timeout: u16, access_x_timeout_mask: BoolCtrl, access_x_timeout_values: BoolCtrl, access_x_timeout_options_mask: AXOption, access_x_timeout_options_values: AXOption, per_key_repeat: &'input [u8; 32]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_controls(self, device_spec, affect_internal_real_mods, internal_real_mods, affect_ignore_lock_real_mods, ignore_lock_real_mods, affect_internal_virtual_mods, internal_virtual_mods, affect_ignore_lock_virtual_mods, ignore_lock_virtual_mods, mouse_keys_dflt_btn, groups_wrap, access_x_options, affect_enabled_controls, enabled_controls, change_controls, repeat_delay, repeat_interval, slow_keys_delay, debounce_delay, mouse_keys_delay, mouse_keys_interval, mouse_keys_time_to_max, mouse_keys_max_speed, mouse_keys_curve, access_x_timeout, access_x_timeout_mask, access_x_timeout_values, access_x_timeout_options_mask, access_x_timeout_options_values, per_key_repeat)
}
fn xkb_get_map(&self, device_spec: DeviceSpec, full: MapPart, partial: MapPart, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, first_key_action: xproto::Keycode, n_key_actions: u8, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, virtual_mods: VMod, first_key_explicit: xproto::Keycode, n_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8) -> Result<Cookie<'_, Self, GetMapReply>, ConnectionError>
{
get_map(self, device_spec, full, partial, first_type, n_types, first_key_sym, n_key_syms, first_key_action, n_key_actions, first_key_behavior, n_key_behaviors, virtual_mods, first_key_explicit, n_key_explicit, first_mod_map_key, n_mod_map_keys, first_v_mod_map_key, n_v_mod_map_keys)
}
fn xkb_set_map<'c, 'input>(&'c self, device_spec: DeviceSpec, flags: SetMapFlags, min_key_code: xproto::Keycode, max_key_code: xproto::Keycode, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, total_syms: u16, first_key_action: xproto::Keycode, n_key_actions: u8, total_actions: u16, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, total_key_behaviors: u8, first_key_explicit: xproto::Keycode, n_key_explicit: u8, total_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, total_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8, total_v_mod_map_keys: u8, virtual_mods: VMod, values: &'input SetMapAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_map(self, device_spec, flags, min_key_code, max_key_code, first_type, n_types, first_key_sym, n_key_syms, total_syms, first_key_action, n_key_actions, total_actions, first_key_behavior, n_key_behaviors, total_key_behaviors, first_key_explicit, n_key_explicit, total_key_explicit, first_mod_map_key, n_mod_map_keys, total_mod_map_keys, first_v_mod_map_key, n_v_mod_map_keys, total_v_mod_map_keys, virtual_mods, values)
}
fn xkb_get_compat_map(&self, device_spec: DeviceSpec, groups: SetOfGroup, get_all_si: bool, first_si: u16, n_si: u16) -> Result<Cookie<'_, Self, GetCompatMapReply>, ConnectionError>
{
get_compat_map(self, device_spec, groups, get_all_si, first_si, n_si)
}
fn xkb_set_compat_map<'c, 'input>(&'c self, device_spec: DeviceSpec, recompute_actions: bool, truncate_si: bool, groups: SetOfGroup, first_si: u16, si: &'input [SymInterpret], group_maps: &'input [ModDef]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_compat_map(self, device_spec, recompute_actions, truncate_si, groups, first_si, si, group_maps)
}
fn xkb_get_indicator_state(&self, device_spec: DeviceSpec) -> Result<Cookie<'_, Self, GetIndicatorStateReply>, ConnectionError>
{
get_indicator_state(self, device_spec)
}
fn xkb_get_indicator_map(&self, device_spec: DeviceSpec, which: u32) -> Result<Cookie<'_, Self, GetIndicatorMapReply>, ConnectionError>
{
get_indicator_map(self, device_spec, which)
}
fn xkb_set_indicator_map<'c, 'input>(&'c self, device_spec: DeviceSpec, which: u32, maps: &'input [IndicatorMap]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_indicator_map(self, device_spec, which, maps)
}
fn xkb_get_named_indicator<A>(&self, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom) -> Result<Cookie<'_, Self, GetNamedIndicatorReply>, ConnectionError>
where
A: Into<IDSpec>,
{
get_named_indicator(self, device_spec, led_class, led_id, indicator)
}
fn xkb_set_named_indicator<A>(&self, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom, set_state: bool, on: bool, set_map: bool, create_map: bool, map_flags: IMFlag, map_which_groups: IMGroupsWhich, map_groups: SetOfGroups, map_which_mods: IMModsWhich, map_real_mods: xproto::ModMask, map_vmods: VMod, map_ctrls: BoolCtrl) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<IDSpec>,
{
set_named_indicator(self, device_spec, led_class, led_id, indicator, set_state, on, set_map, create_map, map_flags, map_which_groups, map_groups, map_which_mods, map_real_mods, map_vmods, map_ctrls)
}
fn xkb_get_names(&self, device_spec: DeviceSpec, which: NameDetail) -> Result<Cookie<'_, Self, GetNamesReply>, ConnectionError>
{
get_names(self, device_spec, which)
}
fn xkb_set_names<'c, 'input>(&'c self, device_spec: DeviceSpec, virtual_mods: VMod, first_type: u8, n_types: u8, first_kt_levelt: u8, n_kt_levels: u8, indicators: u32, group_names: SetOfGroup, n_radio_groups: u8, first_key: xproto::Keycode, n_keys: u8, n_key_aliases: u8, total_kt_level_names: u16, values: &'input SetNamesAux) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_names(self, device_spec, virtual_mods, first_type, n_types, first_kt_levelt, n_kt_levels, indicators, group_names, n_radio_groups, first_key, n_keys, n_key_aliases, total_kt_level_names, values)
}
fn xkb_per_client_flags(&self, device_spec: DeviceSpec, change: PerClientFlag, value: PerClientFlag, ctrls_to_change: BoolCtrl, auto_ctrls: BoolCtrl, auto_ctrls_values: BoolCtrl) -> Result<Cookie<'_, Self, PerClientFlagsReply>, ConnectionError>
{
per_client_flags(self, device_spec, change, value, ctrls_to_change, auto_ctrls, auto_ctrls_values)
}
fn xkb_list_components(&self, device_spec: DeviceSpec, max_names: u16) -> Result<Cookie<'_, Self, ListComponentsReply>, ConnectionError>
{
list_components(self, device_spec, max_names)
}
fn xkb_get_kbd_by_name(&self, device_spec: DeviceSpec, need: GBNDetail, want: GBNDetail, load: bool) -> Result<Cookie<'_, Self, GetKbdByNameReply>, ConnectionError>
{
get_kbd_by_name(self, device_spec, need, want, load)
}
fn xkb_get_device_info<A>(&self, device_spec: DeviceSpec, wanted: XIFeature, all_buttons: bool, first_button: u8, n_buttons: u8, led_class: LedClass, led_id: A) -> Result<Cookie<'_, Self, GetDeviceInfoReply>, ConnectionError>
where
A: Into<IDSpec>,
{
get_device_info(self, device_spec, wanted, all_buttons, first_button, n_buttons, led_class, led_id)
}
fn xkb_set_device_info<'c, 'input>(&'c self, device_spec: DeviceSpec, first_btn: u8, change: XIFeature, btn_actions: &'input [Action], leds: &'input [DeviceLedInfo]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_device_info(self, device_spec, first_btn, change, btn_actions, leds)
}
fn xkb_set_debugging_flags<'c, 'input>(&'c self, affect_flags: u32, flags: u32, affect_ctrls: u32, ctrls: u32, message: &'input [String8]) -> Result<Cookie<'c, Self, SetDebuggingFlagsReply>, ConnectionError>
{
set_debugging_flags(self, affect_flags, flags, affect_ctrls, ctrls, message)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

472
vendor/x11rb/src/protocol/xprint.rs vendored Normal file
View File

@@ -0,0 +1,472 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `XPrint` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xprint::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn print_query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, PrintQueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintQueryVersionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_get_printer_list<'c, 'input, Conn>(conn: &'c Conn, printer_name: &'input [String8], locale: &'input [String8]) -> Result<Cookie<'c, Conn, PrintGetPrinterListReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetPrinterListRequest {
printer_name: Cow::Borrowed(printer_name),
locale: Cow::Borrowed(locale),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_rehash_printer_list<Conn>(conn: &Conn) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintRehashPrinterListRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_context<'c, 'input, Conn>(conn: &'c Conn, context_id: u32, printer_name: &'input [String8], locale: &'input [String8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateContextRequest {
context_id,
printer_name: Cow::Borrowed(printer_name),
locale: Cow::Borrowed(locale),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_set_context<Conn>(conn: &Conn, context: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintSetContextRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_get_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, PrintGetContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_destroy_context<Conn>(conn: &Conn, context: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintDestroyContextRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_get_screen_of_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, PrintGetScreenOfContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetScreenOfContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_start_job<Conn>(conn: &Conn, output_mode: u8) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintStartJobRequest {
output_mode,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_end_job<Conn>(conn: &Conn, cancel: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintEndJobRequest {
cancel,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_start_doc<Conn>(conn: &Conn, driver_mode: u8) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintStartDocRequest {
driver_mode,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_end_doc<Conn>(conn: &Conn, cancel: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintEndDocRequest {
cancel,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_put_document_data<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, data: &'input [u8], doc_format: &'input [String8], options: &'input [String8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintPutDocumentDataRequest {
drawable,
data: Cow::Borrowed(data),
doc_format: Cow::Borrowed(doc_format),
options: Cow::Borrowed(options),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2]), IoSlice::new(&bytes[3]), IoSlice::new(&bytes[4]), IoSlice::new(&bytes[5]), IoSlice::new(&bytes[6])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_get_document_data<Conn>(conn: &Conn, context: Pcontext, max_bytes: u32) -> Result<Cookie<'_, Conn, PrintGetDocumentDataReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetDocumentDataRequest {
context,
max_bytes,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_start_page<Conn>(conn: &Conn, window: xproto::Window) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintStartPageRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_end_page<Conn>(conn: &Conn, cancel: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintEndPageRequest {
cancel,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_select_input<Conn>(conn: &Conn, context: Pcontext, event_mask: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintSelectInputRequest {
context,
event_mask,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_input_selected<Conn>(conn: &Conn, context: Pcontext) -> Result<Cookie<'_, Conn, PrintInputSelectedReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintInputSelectedRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_get_attributes<Conn>(conn: &Conn, context: Pcontext, pool: u8) -> Result<Cookie<'_, Conn, PrintGetAttributesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetAttributesRequest {
context,
pool,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_get_one_attributes<'c, 'input, Conn>(conn: &'c Conn, context: Pcontext, pool: u8, name: &'input [String8]) -> Result<Cookie<'c, Conn, PrintGetOneAttributesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetOneAttributesRequest {
context,
pool,
name: Cow::Borrowed(name),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_set_attributes<'c, 'input, Conn>(conn: &'c Conn, context: Pcontext, string_len: u32, pool: u8, rule: u8, attributes: &'input [String8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintSetAttributesRequest {
context,
string_len,
pool,
rule,
attributes: Cow::Borrowed(attributes),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn print_get_page_dimensions<Conn>(conn: &Conn, context: Pcontext) -> Result<Cookie<'_, Conn, PrintGetPageDimensionsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetPageDimensionsRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_query_screens<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, PrintQueryScreensReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintQueryScreensRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_set_image_resolution<Conn>(conn: &Conn, context: Pcontext, image_resolution: u16) -> Result<Cookie<'_, Conn, PrintSetImageResolutionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintSetImageResolutionRequest {
context,
image_resolution,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn print_get_image_resolution<Conn>(conn: &Conn, context: Pcontext) -> Result<Cookie<'_, Conn, PrintGetImageResolutionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PrintGetImageResolutionRequest {
context,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xprint_print_query_version(&self) -> Result<Cookie<'_, Self, PrintQueryVersionReply>, ConnectionError>
{
print_query_version(self)
}
fn xprint_print_get_printer_list<'c, 'input>(&'c self, printer_name: &'input [String8], locale: &'input [String8]) -> Result<Cookie<'c, Self, PrintGetPrinterListReply>, ConnectionError>
{
print_get_printer_list(self, printer_name, locale)
}
fn xprint_print_rehash_printer_list(&self) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_rehash_printer_list(self)
}
fn xprint_create_context<'c, 'input>(&'c self, context_id: u32, printer_name: &'input [String8], locale: &'input [String8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
create_context(self, context_id, printer_name, locale)
}
fn xprint_print_set_context(&self, context: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_set_context(self, context)
}
fn xprint_print_get_context(&self) -> Result<Cookie<'_, Self, PrintGetContextReply>, ConnectionError>
{
print_get_context(self)
}
fn xprint_print_destroy_context(&self, context: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_destroy_context(self, context)
}
fn xprint_print_get_screen_of_context(&self) -> Result<Cookie<'_, Self, PrintGetScreenOfContextReply>, ConnectionError>
{
print_get_screen_of_context(self)
}
fn xprint_print_start_job(&self, output_mode: u8) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_start_job(self, output_mode)
}
fn xprint_print_end_job(&self, cancel: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_end_job(self, cancel)
}
fn xprint_print_start_doc(&self, driver_mode: u8) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_start_doc(self, driver_mode)
}
fn xprint_print_end_doc(&self, cancel: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_end_doc(self, cancel)
}
fn xprint_print_put_document_data<'c, 'input>(&'c self, drawable: xproto::Drawable, data: &'input [u8], doc_format: &'input [String8], options: &'input [String8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
print_put_document_data(self, drawable, data, doc_format, options)
}
fn xprint_print_get_document_data(&self, context: Pcontext, max_bytes: u32) -> Result<Cookie<'_, Self, PrintGetDocumentDataReply>, ConnectionError>
{
print_get_document_data(self, context, max_bytes)
}
fn xprint_print_start_page(&self, window: xproto::Window) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_start_page(self, window)
}
fn xprint_print_end_page(&self, cancel: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_end_page(self, cancel)
}
fn xprint_print_select_input(&self, context: Pcontext, event_mask: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
print_select_input(self, context, event_mask)
}
fn xprint_print_input_selected(&self, context: Pcontext) -> Result<Cookie<'_, Self, PrintInputSelectedReply>, ConnectionError>
{
print_input_selected(self, context)
}
fn xprint_print_get_attributes(&self, context: Pcontext, pool: u8) -> Result<Cookie<'_, Self, PrintGetAttributesReply>, ConnectionError>
{
print_get_attributes(self, context, pool)
}
fn xprint_print_get_one_attributes<'c, 'input>(&'c self, context: Pcontext, pool: u8, name: &'input [String8]) -> Result<Cookie<'c, Self, PrintGetOneAttributesReply>, ConnectionError>
{
print_get_one_attributes(self, context, pool, name)
}
fn xprint_print_set_attributes<'c, 'input>(&'c self, context: Pcontext, string_len: u32, pool: u8, rule: u8, attributes: &'input [String8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
print_set_attributes(self, context, string_len, pool, rule, attributes)
}
fn xprint_print_get_page_dimensions(&self, context: Pcontext) -> Result<Cookie<'_, Self, PrintGetPageDimensionsReply>, ConnectionError>
{
print_get_page_dimensions(self, context)
}
fn xprint_print_query_screens(&self) -> Result<Cookie<'_, Self, PrintQueryScreensReply>, ConnectionError>
{
print_query_screens(self)
}
fn xprint_print_set_image_resolution(&self, context: Pcontext, image_resolution: u16) -> Result<Cookie<'_, Self, PrintSetImageResolutionReply>, ConnectionError>
{
print_set_image_resolution(self, context, image_resolution)
}
fn xprint_print_get_image_resolution(&self, context: Pcontext) -> Result<Cookie<'_, Self, PrintGetImageResolutionReply>, ConnectionError>
{
print_get_image_resolution(self, context)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

5980
vendor/x11rb/src/protocol/xproto.rs vendored Normal file

File diff suppressed because it is too large Load Diff

422
vendor/x11rb/src/protocol/xselinux.rs vendored Normal file
View File

@@ -0,0 +1,422 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `SELinux` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xselinux::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn, client_major: u8, client_minor: u8) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major,
client_minor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_device_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetDeviceCreateContextRequest {
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_device_create_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetDeviceCreateContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetDeviceCreateContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_device_context<'c, 'input, Conn>(conn: &'c Conn, device: u32, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetDeviceContextRequest {
device,
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_device_context<Conn>(conn: &Conn, device: u32) -> Result<Cookie<'_, Conn, GetDeviceContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetDeviceContextRequest {
device,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_window_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetWindowCreateContextRequest {
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_window_create_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetWindowCreateContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetWindowCreateContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_window_context<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, GetWindowContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetWindowContextRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_property_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPropertyCreateContextRequest {
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_property_create_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetPropertyCreateContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPropertyCreateContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_property_use_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPropertyUseContextRequest {
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_property_use_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetPropertyUseContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPropertyUseContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_property_context<Conn>(conn: &Conn, window: xproto::Window, property: xproto::Atom) -> Result<Cookie<'_, Conn, GetPropertyContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPropertyContextRequest {
window,
property,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_property_data_context<Conn>(conn: &Conn, window: xproto::Window, property: xproto::Atom) -> Result<Cookie<'_, Conn, GetPropertyDataContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPropertyDataContextRequest {
window,
property,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_properties<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, ListPropertiesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListPropertiesRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_selection_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetSelectionCreateContextRequest {
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_selection_create_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetSelectionCreateContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetSelectionCreateContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_selection_use_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetSelectionUseContextRequest {
context: Cow::Borrowed(context),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_selection_use_context<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, GetSelectionUseContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetSelectionUseContextRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_selection_context<Conn>(conn: &Conn, selection: xproto::Atom) -> Result<Cookie<'_, Conn, GetSelectionContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetSelectionContextRequest {
selection,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_selection_data_context<Conn>(conn: &Conn, selection: xproto::Atom) -> Result<Cookie<'_, Conn, GetSelectionDataContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetSelectionDataContextRequest {
selection,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_selections<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, ListSelectionsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListSelectionsRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn get_client_context<Conn>(conn: &Conn, resource: u32) -> Result<Cookie<'_, Conn, GetClientContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetClientContextRequest {
resource,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xselinux_query_version(&self, client_major: u8, client_minor: u8) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major, client_minor)
}
fn xselinux_set_device_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_device_create_context(self, context)
}
fn xselinux_get_device_create_context(&self) -> Result<Cookie<'_, Self, GetDeviceCreateContextReply>, ConnectionError>
{
get_device_create_context(self)
}
fn xselinux_set_device_context<'c, 'input>(&'c self, device: u32, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_device_context(self, device, context)
}
fn xselinux_get_device_context(&self, device: u32) -> Result<Cookie<'_, Self, GetDeviceContextReply>, ConnectionError>
{
get_device_context(self, device)
}
fn xselinux_set_window_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_window_create_context(self, context)
}
fn xselinux_get_window_create_context(&self) -> Result<Cookie<'_, Self, GetWindowCreateContextReply>, ConnectionError>
{
get_window_create_context(self)
}
fn xselinux_get_window_context(&self, window: xproto::Window) -> Result<Cookie<'_, Self, GetWindowContextReply>, ConnectionError>
{
get_window_context(self, window)
}
fn xselinux_set_property_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_property_create_context(self, context)
}
fn xselinux_get_property_create_context(&self) -> Result<Cookie<'_, Self, GetPropertyCreateContextReply>, ConnectionError>
{
get_property_create_context(self)
}
fn xselinux_set_property_use_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_property_use_context(self, context)
}
fn xselinux_get_property_use_context(&self) -> Result<Cookie<'_, Self, GetPropertyUseContextReply>, ConnectionError>
{
get_property_use_context(self)
}
fn xselinux_get_property_context(&self, window: xproto::Window, property: xproto::Atom) -> Result<Cookie<'_, Self, GetPropertyContextReply>, ConnectionError>
{
get_property_context(self, window, property)
}
fn xselinux_get_property_data_context(&self, window: xproto::Window, property: xproto::Atom) -> Result<Cookie<'_, Self, GetPropertyDataContextReply>, ConnectionError>
{
get_property_data_context(self, window, property)
}
fn xselinux_list_properties(&self, window: xproto::Window) -> Result<Cookie<'_, Self, ListPropertiesReply>, ConnectionError>
{
list_properties(self, window)
}
fn xselinux_set_selection_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_selection_create_context(self, context)
}
fn xselinux_get_selection_create_context(&self) -> Result<Cookie<'_, Self, GetSelectionCreateContextReply>, ConnectionError>
{
get_selection_create_context(self)
}
fn xselinux_set_selection_use_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
set_selection_use_context(self, context)
}
fn xselinux_get_selection_use_context(&self) -> Result<Cookie<'_, Self, GetSelectionUseContextReply>, ConnectionError>
{
get_selection_use_context(self)
}
fn xselinux_get_selection_context(&self, selection: xproto::Atom) -> Result<Cookie<'_, Self, GetSelectionContextReply>, ConnectionError>
{
get_selection_context(self, selection)
}
fn xselinux_get_selection_data_context(&self, selection: xproto::Atom) -> Result<Cookie<'_, Self, GetSelectionDataContextReply>, ConnectionError>
{
get_selection_data_context(self, selection)
}
fn xselinux_list_selections(&self) -> Result<Cookie<'_, Self, ListSelectionsReply>, ConnectionError>
{
list_selections(self)
}
fn xselinux_get_client_context(&self, resource: u32) -> Result<Cookie<'_, Self, GetClientContextReply>, ConnectionError>
{
get_client_context(self, resource)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

117
vendor/x11rb/src/protocol/xtest.rs vendored Normal file
View File

@@ -0,0 +1,117 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Test` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xtest::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn get_version<Conn>(conn: &Conn, major_version: u8, minor_version: u16) -> Result<Cookie<'_, Conn, GetVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetVersionRequest {
major_version,
minor_version,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn compare_cursor<Conn>(conn: &Conn, window: xproto::Window, cursor: xproto::Cursor) -> Result<Cookie<'_, Conn, CompareCursorReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CompareCursorRequest {
window,
cursor,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn fake_input<Conn>(conn: &Conn, type_: u8, detail: u8, time: u32, root: xproto::Window, root_x: i16, root_y: i16, deviceid: u8) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = FakeInputRequest {
type_,
detail,
time,
root,
root_x,
root_y,
deviceid,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn grab_control<Conn>(conn: &Conn, impervious: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GrabControlRequest {
impervious,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xtest_get_version(&self, major_version: u8, minor_version: u16) -> Result<Cookie<'_, Self, GetVersionReply>, ConnectionError>
{
get_version(self, major_version, minor_version)
}
fn xtest_compare_cursor(&self, window: xproto::Window, cursor: xproto::Cursor) -> Result<Cookie<'_, Self, CompareCursorReply>, ConnectionError>
{
compare_cursor(self, window, cursor)
}
fn xtest_fake_input(&self, type_: u8, detail: u8, time: u32, root: xproto::Window, root_x: i16, root_y: i16, deviceid: u8) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
fake_input(self, type_, detail, time, root, root_x, root_y, deviceid)
}
fn xtest_grab_control(&self, impervious: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
grab_control(self, impervious)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

475
vendor/x11rb/src/protocol/xv.rs vendored Normal file
View File

@@ -0,0 +1,475 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `Xv` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::shm;
#[allow(unused_imports)]
use super::xproto;
pub use x11rb_protocol::protocol::xv::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_extension<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryExtensionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryExtensionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_adaptors<Conn>(conn: &Conn, window: xproto::Window) -> Result<Cookie<'_, Conn, QueryAdaptorsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryAdaptorsRequest {
window,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_encodings<Conn>(conn: &Conn, port: Port) -> Result<Cookie<'_, Conn, QueryEncodingsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryEncodingsRequest {
port,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn grab_port<Conn, A>(conn: &Conn, port: Port, time: A) -> Result<Cookie<'_, Conn, GrabPortReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<xproto::Timestamp>,
{
let time: xproto::Timestamp = time.into();
let request0 = GrabPortRequest {
port,
time,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn ungrab_port<Conn, A>(conn: &Conn, port: Port, time: A) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
A: Into<xproto::Timestamp>,
{
let time: xproto::Timestamp = time.into();
let request0 = UngrabPortRequest {
port,
time,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn put_video<Conn>(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PutVideoRequest {
port,
drawable,
gc,
vid_x,
vid_y,
vid_w,
vid_h,
drw_x,
drw_y,
drw_w,
drw_h,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn put_still<Conn>(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PutStillRequest {
port,
drawable,
gc,
vid_x,
vid_y,
vid_w,
vid_h,
drw_x,
drw_y,
drw_w,
drw_h,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_video<Conn>(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetVideoRequest {
port,
drawable,
gc,
vid_x,
vid_y,
vid_w,
vid_h,
drw_x,
drw_y,
drw_w,
drw_h,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_still<Conn>(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetStillRequest {
port,
drawable,
gc,
vid_x,
vid_y,
vid_w,
vid_h,
drw_x,
drw_y,
drw_w,
drw_h,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn stop_video<Conn>(conn: &Conn, port: Port, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = StopVideoRequest {
port,
drawable,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn select_video_notify<Conn>(conn: &Conn, drawable: xproto::Drawable, onoff: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectVideoNotifyRequest {
drawable,
onoff,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn select_port_notify<Conn>(conn: &Conn, port: Port, onoff: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectPortNotifyRequest {
port,
onoff,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn query_best_size<Conn>(conn: &Conn, port: Port, vid_w: u16, vid_h: u16, drw_w: u16, drw_h: u16, motion: bool) -> Result<Cookie<'_, Conn, QueryBestSizeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryBestSizeRequest {
port,
vid_w,
vid_h,
drw_w,
drw_h,
motion,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn set_port_attribute<Conn>(conn: &Conn, port: Port, attribute: xproto::Atom, value: i32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SetPortAttributeRequest {
port,
attribute,
value,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn get_port_attribute<Conn>(conn: &Conn, port: Port, attribute: xproto::Atom) -> Result<Cookie<'_, Conn, GetPortAttributeReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = GetPortAttributeRequest {
port,
attribute,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_port_attributes<Conn>(conn: &Conn, port: Port) -> Result<Cookie<'_, Conn, QueryPortAttributesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryPortAttributesRequest {
port,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_image_formats<Conn>(conn: &Conn, port: Port) -> Result<Cookie<'_, Conn, ListImageFormatsReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListImageFormatsRequest {
port,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn query_image_attributes<Conn>(conn: &Conn, port: Port, id: u32, width: u16, height: u16) -> Result<Cookie<'_, Conn, QueryImageAttributesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryImageAttributesRequest {
port,
id,
width,
height,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn put_image<'c, 'input, Conn>(conn: &'c Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, id: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, data: &'input [u8]) -> Result<VoidCookie<'c, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = PutImageRequest {
port,
drawable,
gc,
id,
src_x,
src_y,
src_w,
src_h,
drw_x,
drw_y,
drw_w,
drw_h,
width,
height,
data: Cow::Borrowed(data),
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn shm_put_image<Conn>(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, shmseg: shm::Seg, id: u32, offset: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, send_event: u8) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ShmPutImageRequest {
port,
drawable,
gc,
shmseg,
id,
offset,
src_x,
src_y,
src_w,
src_h,
drw_x,
drw_y,
drw_w,
drw_h,
width,
height,
send_event,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xv_query_extension(&self) -> Result<Cookie<'_, Self, QueryExtensionReply>, ConnectionError>
{
query_extension(self)
}
fn xv_query_adaptors(&self, window: xproto::Window) -> Result<Cookie<'_, Self, QueryAdaptorsReply>, ConnectionError>
{
query_adaptors(self, window)
}
fn xv_query_encodings(&self, port: Port) -> Result<Cookie<'_, Self, QueryEncodingsReply>, ConnectionError>
{
query_encodings(self, port)
}
fn xv_grab_port<A>(&self, port: Port, time: A) -> Result<Cookie<'_, Self, GrabPortReply>, ConnectionError>
where
A: Into<xproto::Timestamp>,
{
grab_port(self, port, time)
}
fn xv_ungrab_port<A>(&self, port: Port, time: A) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<xproto::Timestamp>,
{
ungrab_port(self, port, time)
}
fn xv_put_video(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
put_video(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)
}
fn xv_put_still(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
put_still(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)
}
fn xv_get_video(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
get_video(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)
}
fn xv_get_still(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
get_still(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)
}
fn xv_stop_video(&self, port: Port, drawable: xproto::Drawable) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
stop_video(self, port, drawable)
}
fn xv_select_video_notify(&self, drawable: xproto::Drawable, onoff: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_video_notify(self, drawable, onoff)
}
fn xv_select_port_notify(&self, port: Port, onoff: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
select_port_notify(self, port, onoff)
}
fn xv_query_best_size(&self, port: Port, vid_w: u16, vid_h: u16, drw_w: u16, drw_h: u16, motion: bool) -> Result<Cookie<'_, Self, QueryBestSizeReply>, ConnectionError>
{
query_best_size(self, port, vid_w, vid_h, drw_w, drw_h, motion)
}
fn xv_set_port_attribute(&self, port: Port, attribute: xproto::Atom, value: i32) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
set_port_attribute(self, port, attribute, value)
}
fn xv_get_port_attribute(&self, port: Port, attribute: xproto::Atom) -> Result<Cookie<'_, Self, GetPortAttributeReply>, ConnectionError>
{
get_port_attribute(self, port, attribute)
}
fn xv_query_port_attributes(&self, port: Port) -> Result<Cookie<'_, Self, QueryPortAttributesReply>, ConnectionError>
{
query_port_attributes(self, port)
}
fn xv_list_image_formats(&self, port: Port) -> Result<Cookie<'_, Self, ListImageFormatsReply>, ConnectionError>
{
list_image_formats(self, port)
}
fn xv_query_image_attributes(&self, port: Port, id: u32, width: u16, height: u16) -> Result<Cookie<'_, Self, QueryImageAttributesReply>, ConnectionError>
{
query_image_attributes(self, port, id, width, height)
}
fn xv_put_image<'c, 'input>(&'c self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, id: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, data: &'input [u8]) -> Result<VoidCookie<'c, Self>, ConnectionError>
{
put_image(self, port, drawable, gc, id, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height, data)
}
fn xv_shm_put_image(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, shmseg: shm::Seg, id: u32, offset: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, send_event: u8) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
shm_put_image(self, port, drawable, gc, shmseg, id, offset, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height, send_event)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

203
vendor/x11rb/src/protocol/xvmc.rs vendored Normal file
View File

@@ -0,0 +1,203 @@
// This file contains generated code. Do not edit directly.
// To regenerate this, run 'make'.
//! Bindings to the `XvMC` X11 extension.
#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
#[allow(unused_imports)]
use std::convert::TryInto;
#[allow(unused_imports)]
use crate::utils::RawFdContainer;
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
use std::io::IoSlice;
use crate::connection::RequestConnection;
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::ConnectionError;
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
#[allow(unused_imports)]
use super::xv;
pub use x11rb_protocol::protocol::xvmc::*;
/// Get the major opcode of this extension
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub fn query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest;
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn list_surface_types<Conn>(conn: &Conn, port_id: xv::Port) -> Result<Cookie<'_, Conn, ListSurfaceTypesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListSurfaceTypesRequest {
port_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn create_context<Conn>(conn: &Conn, context_id: Context, port_id: xv::Port, surface_id: Surface, width: u16, height: u16, flags: u32) -> Result<Cookie<'_, Conn, CreateContextReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateContextRequest {
context_id,
port_id,
surface_id,
width,
height,
flags,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn destroy_context<Conn>(conn: &Conn, context_id: Context) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroyContextRequest {
context_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_surface<Conn>(conn: &Conn, surface_id: Surface, context_id: Context) -> Result<Cookie<'_, Conn, CreateSurfaceReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateSurfaceRequest {
surface_id,
context_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn destroy_surface<Conn>(conn: &Conn, surface_id: Surface) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroySurfaceRequest {
surface_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn create_subpicture<Conn>(conn: &Conn, subpicture_id: Subpicture, context: Context, xvimage_id: u32, width: u16, height: u16) -> Result<Cookie<'_, Conn, CreateSubpictureReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = CreateSubpictureRequest {
subpicture_id,
context,
xvimage_id,
width,
height,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
pub fn destroy_subpicture<Conn>(conn: &Conn, subpicture_id: Subpicture) -> Result<VoidCookie<'_, Conn>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = DestroySubpictureRequest {
subpicture_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_without_reply(&slices, fds)
}
pub fn list_subpicture_types<Conn>(conn: &Conn, port_id: xv::Port, surface_id: Surface) -> Result<Cookie<'_, Conn, ListSubpictureTypesReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = ListSubpictureTypesRequest {
port_id,
surface_id,
};
let (bytes, fds) = request0.serialize(major_opcode(conn)?);
let slices = [IoSlice::new(&bytes[0])];
assert_eq!(slices.len(), bytes.len());
conn.send_request_with_reply(&slices, fds)
}
/// Extension trait defining the requests of this extension.
pub trait ConnectionExt: RequestConnection {
fn xvmc_query_version(&self) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self)
}
fn xvmc_list_surface_types(&self, port_id: xv::Port) -> Result<Cookie<'_, Self, ListSurfaceTypesReply>, ConnectionError>
{
list_surface_types(self, port_id)
}
fn xvmc_create_context(&self, context_id: Context, port_id: xv::Port, surface_id: Surface, width: u16, height: u16, flags: u32) -> Result<Cookie<'_, Self, CreateContextReply>, ConnectionError>
{
create_context(self, context_id, port_id, surface_id, width, height, flags)
}
fn xvmc_destroy_context(&self, context_id: Context) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_context(self, context_id)
}
fn xvmc_create_surface(&self, surface_id: Surface, context_id: Context) -> Result<Cookie<'_, Self, CreateSurfaceReply>, ConnectionError>
{
create_surface(self, surface_id, context_id)
}
fn xvmc_destroy_surface(&self, surface_id: Surface) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_surface(self, surface_id)
}
fn xvmc_create_subpicture(&self, subpicture_id: Subpicture, context: Context, xvimage_id: u32, width: u16, height: u16) -> Result<Cookie<'_, Self, CreateSubpictureReply>, ConnectionError>
{
create_subpicture(self, subpicture_id, context, xvimage_id, width, height)
}
fn xvmc_destroy_subpicture(&self, subpicture_id: Subpicture) -> Result<VoidCookie<'_, Self>, ConnectionError>
{
destroy_subpicture(self, subpicture_id)
}
fn xvmc_list_subpicture_types(&self, port_id: xv::Port, surface_id: Surface) -> Result<Cookie<'_, Self, ListSubpictureTypesReply>, ConnectionError>
{
list_subpicture_types(self, port_id, surface_id)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}

View File

@@ -0,0 +1,69 @@
//! X11 resource manager library.
//!
//! Usage example (please cache the database returned by [`new_from_default`] in real applications
//! instead of re-opening it whenever a value is needed):
//! ```
//! use x11rb::{connection::Connection, errors::ReplyError, resource_manager::new_from_default};
//! fn get_xft_dpi(conn: &impl Connection) -> Result<Option<u32>, ReplyError> {
//! let db = new_from_default(conn)?;
//! let value = db.get_value("Xft.dpi", "");
//! Ok(value.ok().flatten())
//! }
//! ```
//!
//! This functionality is similar to what is available to C code through xcb-util-xrm and Xlib's
//! `Xrm*` function family. Not all their functionality is available in this library. Please open a
//! feature request if you need something that is not available.
//!
//! The code in this module is only available when the `resource_manager` feature of the library is
//! enabled.
use crate::connection::Connection;
use crate::errors::ReplyError;
use crate::protocol::xproto::GetPropertyReply;
pub use x11rb_protocol::resource_manager::Database;
fn send_request(conn: &impl Connection) -> Result<GetPropertyReply, ReplyError> {
let mut request = Database::GET_RESOURCE_DATABASE;
request.window = conn.setup().roots[0].root;
conn.send_trait_request_with_reply(request)?.reply()
}
/// Create a new X11 resource database from the `RESOURCE_MANAGER` property of the first
/// screen's root window.
///
/// This function returns an error if the `GetProperty` request to get the `RESOURCE_MANAGER`
/// property fails. It returns `Ok(None)` if the property does not exist, has the wrong format,
/// or is empty.
pub fn new_from_resource_manager(conn: &impl Connection) -> Result<Option<Database>, ReplyError> {
Ok(Database::new_from_get_property_reply(&send_request(conn)?))
}
/// Create a new X11 resource database from the default locations.
///
/// The default location is a combination of two places. First, the following places are
/// searched for data:
/// - The `RESOURCE_MANAGER` property of the first screen's root window (See
/// [`new_from_resource_manager`]).
/// - If not found, the file `$HOME/.Xresources` is loaded.
/// - If not found, the file `$HOME/.Xdefaults` is loaded.
///
/// The result of the above search of the above search is combined with:
/// - The contents of the file `$XENVIRONMENT`, if this environment variable is set.
/// - Otherwise, the contents of `$HOME/.Xdefaults-[hostname]`.
///
/// This function only returns an error if communication with the X11 server fails. All other
/// errors are ignored. It might be that an empty database is returned.
///
/// The behaviour of this function is mostly equivalent to Xlib's `XGetDefault()`. The
/// exception is that `XGetDefault()` does not load `$HOME/.Xresources`.
///
/// The behaviour of this function is equivalent to xcb-util-xrm's
/// `xcb_xrm_database_from_default()`.
pub fn new_from_default(conn: &impl Connection) -> Result<Database, ReplyError> {
Ok(Database::new_from_default(
&send_request(conn)?,
gethostname::gethostname(),
))
}

851
vendor/x11rb/src/rust_connection/mod.rs vendored Normal file
View File

@@ -0,0 +1,851 @@
//! A pure-rust implementation of a connection to an X11 server.
use std::io::IoSlice;
use std::sync::{Condvar, Mutex, MutexGuard, TryLockError};
use std::time::Instant;
use crate::connection::{
compute_length_field, Connection, ReplyOrError, RequestConnection, RequestKind,
};
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::DisplayParsingError;
pub use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyError, ReplyOrIdError};
use crate::extension_manager::ExtensionManager;
use crate::protocol::bigreq::{ConnectionExt as _, EnableReply};
use crate::protocol::xproto::{Setup, GET_INPUT_FOCUS_REQUEST, QUERY_EXTENSION_REQUEST};
use crate::utils::RawFdContainer;
use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd};
use x11rb_protocol::connect::Connect;
use x11rb_protocol::connection::{Connection as ProtoConnection, PollReply, ReplyFdKind};
use x11rb_protocol::id_allocator::IdAllocator;
use x11rb_protocol::{xauth::get_auth, DiscardMode, RawEventAndSeqNumber, SequenceNumber};
mod packet_reader;
mod stream;
mod write_buffer;
use packet_reader::PacketReader;
pub use stream::{DefaultStream, PollMode, Stream};
use write_buffer::WriteBuffer;
type Buffer = <RustConnection as RequestConnection>::Buf;
/// A combination of a buffer and a list of file descriptors for use by [`RustConnection`].
pub type BufWithFds = crate::connection::BufWithFds<Buffer>;
#[derive(Debug)]
enum MaxRequestBytes {
Unknown,
Requested(Option<SequenceNumber>),
Known(usize),
}
#[derive(Debug)]
struct ConnectionInner {
inner: ProtoConnection,
write_buffer: WriteBuffer,
}
type MutexGuardInner<'a> = MutexGuard<'a, ConnectionInner>;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum BlockingMode {
Blocking,
NonBlocking,
}
/// A connection to an X11 server implemented in pure rust
///
/// This type is generic over `S`, which allows to use a generic stream to communicate with the
/// server. This stream can written to and read from, but it can also be polled, meaning that one
/// checks if new data can be read or written.
///
/// `RustConnection` always used an internal buffer for reading, so `R` does not need
/// to be buffered.
#[derive(Debug)]
pub struct RustConnection<S: Stream = DefaultStream> {
inner: Mutex<ConnectionInner>,
stream: S,
// This mutex is only locked with `try_lock` (never blocks), so a simpler
// lock based only on a atomic variable would be more efficient.
packet_reader: Mutex<PacketReader>,
reader_condition: Condvar,
setup: Setup,
extension_manager: Mutex<ExtensionManager>,
maximum_request_bytes: Mutex<MaxRequestBytes>,
id_allocator: Mutex<IdAllocator>,
}
// Locking rules
// =============
//
// To avoid deadlocks, it is important to have a defined ordering about mutexes:
//
// Mutexes that may be locked when no other mutex is held:
// - maximum_request_bytes
// - extension_manager
// - id_allocator
//
// Then comes `inner`. This mutex protects the information about in-flight requests and packets
// that were already read from the connection but not given out to callers. This mutex also
// contains the write buffer and has to be locked in order to write something to the X11 server.
// In this case, the mutex has to be kept locked until writing the request has finished. This is
// necessary to ensure correct sync insertion without threads interfering with each other. When
// this mutex is locked for operations other than writing, the lock should be kept only for a
// short time.
//
// The inner level is `packet_reader`. This mutex is only locked when `inner` is already held and
// only with `try_lock()`. This ensures that there is only one reader. While actually reading, the
// lock on `inner` is released so that other threads can make progress. If more threads want to
// read while `read` is already locked, they sleep on `reader_condition`. The actual reader will
// then notify this condition variable once it is done reading.
//
// n.b. notgull: write_buffer follows the same rules
//
// The condition variable is necessary since one thread may read packets that another thread waits
// for. Thus, after reading something from the connection, all threads that wait for something have
// to check if they are the intended recipient.
impl RustConnection<DefaultStream> {
/// Establish a new connection.
///
/// If no `dpy_name` is provided, the value from `$DISPLAY` is used.
pub fn connect(dpy_name: Option<&str>) -> Result<(Self, usize), ConnectError> {
// Parse display information
let parsed_display = x11rb_protocol::parse_display::parse_display(dpy_name)?;
let screen = parsed_display.screen.into();
// Establish connection by iterating over ConnectAddresses until we find one that
// works.
let mut error = None;
for addr in parsed_display.connect_instruction() {
let start = Instant::now();
match DefaultStream::connect(&addr) {
Ok((stream, (family, address))) => {
crate::trace!(
"Connected to X11 server via {:?} in {:?}",
addr,
start.elapsed()
);
// we found a stream, get auth information
let (auth_name, auth_data) = get_auth(family, &address, parsed_display.display)
// Ignore all errors while determining auth; instead we just try without auth info.
.unwrap_or(None)
.unwrap_or_else(|| (Vec::new(), Vec::new()));
crate::trace!("Picked authentication via auth mechanism {:?}", auth_name);
// finish connecting to server
return Ok((
Self::connect_to_stream_with_auth_info(
stream, screen, auth_name, auth_data,
)?,
screen,
));
}
Err(e) => {
crate::debug!("Failed to connect to X11 server via {:?}: {:?}", addr, e);
error = Some(e);
continue;
}
}
}
// none of the addresses worked
Err(match error {
Some(e) => ConnectError::IoError(e),
None => DisplayParsingError::Unknown.into(),
})
}
}
impl<S: Stream> RustConnection<S> {
/// Establish a new connection to the given streams.
///
/// `read` is used for reading data from the X11 server and `write` is used for writing.
/// `screen` is the number of the screen that should be used. This function checks that a
/// screen with that number exists.
pub fn connect_to_stream(stream: S, screen: usize) -> Result<Self, ConnectError> {
Self::connect_to_stream_with_auth_info(stream, screen, Vec::new(), Vec::new())
}
/// Establish a new connection to the given streams.
///
/// `read` is used for reading data from the X11 server and `write` is used for writing.
/// `screen` is the number of the screen that should be used. This function checks that a
/// screen with that number exists.
///
/// The parameters `auth_name` and `auth_data` are used for the members
/// `authorization_protocol_name` and `authorization_protocol_data` of the `SetupRequest` that
/// is sent to the X11 server.
pub fn connect_to_stream_with_auth_info(
stream: S,
screen: usize,
auth_name: Vec<u8>,
auth_data: Vec<u8>,
) -> Result<Self, ConnectError> {
let (mut connect, setup_request) = Connect::with_authorization(auth_name, auth_data);
// write the connect() setup request
let mut nwritten = 0;
let mut fds = vec![];
crate::trace!(
"Writing connection setup with {} bytes",
setup_request.len()
);
while nwritten != setup_request.len() {
stream.poll(PollMode::Writable)?;
// poll returned successfully, so the stream is writable.
match stream.write(&setup_request[nwritten..], &mut fds) {
Ok(0) => {
return Err(std::io::Error::new(
std::io::ErrorKind::WriteZero,
"failed to write whole buffer",
)
.into())
}
Ok(n) => nwritten += n,
// Spurious wakeup from poll, try again
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {}
Err(e) => return Err(e.into()),
}
}
// read in the setup
loop {
stream.poll(PollMode::Readable)?;
crate::trace!(
"Reading connection setup with at least {} bytes remaining",
connect.buffer().len()
);
let adv = match stream.read(connect.buffer(), &mut fds) {
Ok(0) => {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"failed to read whole buffer",
)
.into())
}
Ok(n) => n,
// Spurious wakeup from poll, try again
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => continue,
Err(e) => return Err(e.into()),
};
crate::trace!("Read {} bytes", adv);
// advance the internal buffer
if connect.advance(adv) {
break;
}
}
// resolve the setup
let setup = connect.into_setup()?;
// Check that we got a valid screen number
if screen >= setup.roots.len() {
return Err(ConnectError::InvalidScreen);
}
// Success! Set up our state
Self::for_connected_stream(stream, setup)
}
/// Establish a new connection for an already connected stream.
///
/// The given `stream` is used for communicating with the X11 server.
/// It is assumed that `setup` was just received from the server. Thus, the first reply to a
/// request that is sent will have sequence number one.
pub fn for_connected_stream(stream: S, setup: Setup) -> Result<Self, ConnectError> {
let id_allocator = IdAllocator::new(setup.resource_id_base, setup.resource_id_mask)?;
Ok(RustConnection {
inner: Mutex::new(ConnectionInner {
inner: ProtoConnection::new(),
write_buffer: WriteBuffer::new(),
}),
stream,
packet_reader: Mutex::new(PacketReader::new()),
reader_condition: Condvar::new(),
setup,
extension_manager: Default::default(),
maximum_request_bytes: Mutex::new(MaxRequestBytes::Unknown),
id_allocator: Mutex::new(id_allocator),
})
}
/// Internal function for actually sending a request.
///
/// This function "does the actual work" for `send_request_with_reply()` and
/// `send_request_without_reply()`.
fn send_request(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
kind: ReplyFdKind,
) -> Result<SequenceNumber, ConnectionError> {
let _guard = crate::debug_span!("send_request").entered();
let request_info = RequestInfo {
extension_manager: &self.extension_manager,
major_opcode: bufs[0][0],
minor_opcode: bufs[0][1],
};
crate::debug!("Sending {}", request_info);
let mut storage = Default::default();
let bufs = compute_length_field(self, bufs, &mut storage)?;
// Note: `inner` must be kept blocked until the request has been completely written
// or buffered to avoid sending the data of different requests interleaved. For this
// reason, `read_packet_and_enqueue` must always be called with `BlockingMode::NonBlocking`
// during a write, otherwise `inner` would be temporarily released.
let mut inner = self.inner.lock().unwrap();
loop {
let send_result = inner.inner.send_request(kind);
match send_result {
Some(seqno) => {
// Now actually send the buffers
let _inner = self.write_all_vectored(inner, bufs, fds)?;
return Ok(seqno);
}
None => {
crate::trace!("Syncing with the X11 server since there are too many outstanding void requests");
inner = self.send_sync(inner)?;
}
}
}
}
/// Send a synchronisation packet to the X11 server.
///
/// This function sends a `GetInputFocus` request to the X11 server and arranges for its reply
/// to be ignored. This ensures that a reply is expected (`ConnectionInner.next_reply_expected`
/// increases).
fn send_sync<'a>(
&'a self,
mut inner: MutexGuardInner<'a>,
) -> Result<MutexGuardInner<'a>, std::io::Error> {
let length = 1u16.to_ne_bytes();
let request = [
GET_INPUT_FOCUS_REQUEST,
0, /* pad */
length[0],
length[1],
];
let seqno = inner
.inner
.send_request(ReplyFdKind::ReplyWithoutFDs)
.expect("Sending a HasResponse request should not be blocked by syncs");
inner
.inner
.discard_reply(seqno, DiscardMode::DiscardReplyAndError);
let inner = self.write_all_vectored(inner, &[IoSlice::new(&request)], Vec::new())?;
Ok(inner)
}
/// Write a set of buffers on a `writer`. May also read packets
/// from the server.
fn write_all_vectored<'a>(
&'a self,
mut inner: MutexGuardInner<'a>,
mut bufs: &[IoSlice<'_>],
mut fds: Vec<RawFdContainer>,
) -> std::io::Result<MutexGuardInner<'a>> {
let mut partial_buf: &[u8] = &[];
while !partial_buf.is_empty() || !bufs.is_empty() {
self.stream.poll(PollMode::ReadAndWritable)?;
let write_result = if !partial_buf.is_empty() {
// "inner" is held, passed into this function, so this should never be held
inner
.write_buffer
.write(&self.stream, partial_buf, &mut fds)
} else {
// same as above
inner
.write_buffer
.write_vectored(&self.stream, bufs, &mut fds)
};
match write_result {
Ok(0) => {
return Err(std::io::Error::new(
std::io::ErrorKind::WriteZero,
"failed to write anything",
));
}
Ok(mut count) => {
// Successful write
if count >= partial_buf.len() {
count -= partial_buf.len();
partial_buf = &[];
} else {
partial_buf = &partial_buf[count..];
count = 0;
}
while count > 0 {
if count >= bufs[0].len() {
count -= bufs[0].len();
} else {
partial_buf = &bufs[0][count..];
count = 0;
}
bufs = &bufs[1..];
// Skip empty slices
while bufs.first().map(|s| s.len()) == Some(0) {
bufs = &bufs[1..];
}
}
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
crate::trace!("Writing more data would block for now");
// Writing would block, try to read instead because the
// server might not accept new requests after its
// buffered replies have been read.
inner = self.read_packet_and_enqueue(inner, BlockingMode::NonBlocking)?;
}
Err(e) => return Err(e),
}
}
if !fds.is_empty() {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Left over FDs after sending the request",
));
}
Ok(inner)
}
fn flush_impl<'a>(
&'a self,
mut inner: MutexGuardInner<'a>,
) -> std::io::Result<MutexGuardInner<'a>> {
// n.b. notgull: inner guard is held
while inner.write_buffer.needs_flush() {
self.stream.poll(PollMode::ReadAndWritable)?;
let flush_result = inner.write_buffer.flush(&self.stream);
match flush_result {
// Flush completed
Ok(()) => break,
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
crate::trace!("Flushing more data would block for now");
// Writing would block, try to read instead because the
// server might not accept new requests after its
// buffered replies have been read.
inner = self.read_packet_and_enqueue(inner, BlockingMode::NonBlocking)?;
}
Err(e) => return Err(e),
}
}
Ok(inner)
}
/// Read a packet from the connection.
///
/// This function waits for an X11 packet to be received. It drops the mutex protecting the
/// inner data while waiting for a packet so that other threads can make progress. For this
/// reason, you need to pass in a `MutexGuard` to be dropped. This function locks the mutex
/// again and returns a new `MutexGuard`.
///
/// Note: If `mode` is `BlockingMode::Blocking`, the lock on `inner` will be temporarily
/// released. While sending a request, `inner` must be kept locked to avoid sending the data
/// of different requests interleaved. So, when `read_packet_and_enqueue` is called as part
/// of a write, it must always be done with `mode` set to `BlockingMode::NonBlocking`.
fn read_packet_and_enqueue<'a>(
&'a self,
mut inner: MutexGuardInner<'a>,
mode: BlockingMode,
) -> Result<MutexGuardInner<'a>, std::io::Error> {
// 0.1. Try to lock the `packet_reader` mutex.
match self.packet_reader.try_lock() {
Err(TryLockError::WouldBlock) => {
// In non-blocking mode, we just return immediately
match mode {
BlockingMode::NonBlocking => {
crate::trace!("read_packet_and_enqueue in NonBlocking mode doing nothing since reader is already locked");
return Ok(inner);
}
BlockingMode::Blocking => {
crate::trace!("read_packet_and_enqueue in Blocking mode waiting for pre-existing reader");
}
}
// 1.1. Someone else is reading (other thread is at 2.2);
// wait for it. `Condvar::wait` will unlock `inner`, so
// the other thread can relock `inner` at 2.1.3 (and to allow
// other threads to arrive 0.1).
//
// When `wait` finishes, other thread has enqueued a packet,
// so the purpose of this function has been fulfilled. `wait`
// will relock `inner` when it returns.
Ok(self.reader_condition.wait(inner).unwrap())
}
Err(TryLockError::Poisoned(e)) => panic!("{}", e),
Ok(mut packet_reader) => {
// Make sure sleeping readers are woken up when we return
// (Even in case of errors)
let notify_on_drop = NotifyOnDrop(&self.reader_condition);
// 2.1. Poll for read if mode is blocking.
if mode == BlockingMode::Blocking {
// 2.1.1. Unlock `inner`, so other threads can use it while
// during the poll.
drop(inner);
// 2.1.2. Do the actual poll
self.stream.poll(PollMode::Readable)?;
// 2.1.3. Relock inner
inner = self.inner.lock().unwrap();
}
// 2.2. Try to read as many packets as possible without blocking.
let mut fds = Vec::new();
let mut packets = Vec::new();
packet_reader.try_read_packets(&self.stream, &mut packets, &mut fds)?;
// 2.3. Once `inner` has been relocked, drop the
// lock on `packet_reader`. While inner is locked, other
// threads cannot arrive at 0.1 anyways.
//
// `packet_reader` must be unlocked with `inner` is locked,
// otherwise it could let another thread wait on 2.1
// for a reply that has been read but not enqueued yet.
drop(packet_reader);
// 2.4. Actually enqueue the read packets.
inner.inner.enqueue_fds(fds);
packets
.into_iter()
.for_each(|packet| inner.inner.enqueue_packet(packet));
// 2.5. Notify the condvar by dropping the `notify_on_drop` object.
// The object would have been dropped when the function returns, so
// the explicit drop is not really needed. The purpose of having a
// explicit drop is to... make it explicit.
drop(notify_on_drop);
// 2.6. Return the locked `inner` back to the caller.
Ok(inner)
}
}
}
fn prefetch_maximum_request_bytes_impl(&self, max_bytes: &mut MutexGuard<'_, MaxRequestBytes>) {
if let MaxRequestBytes::Unknown = **max_bytes {
crate::info!("Prefetching maximum request length");
let request = self
.bigreq_enable()
.map(|cookie| cookie.into_sequence_number())
.ok();
**max_bytes = MaxRequestBytes::Requested(request);
}
}
/// Returns a reference to the contained stream.
pub fn stream(&self) -> &S {
&self.stream
}
}
impl<S: Stream> RequestConnection for RustConnection<S> {
type Buf = Vec<u8>;
fn send_request_with_reply<Reply>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, Reply>, ConnectionError>
where
Reply: TryParse,
{
Ok(Cookie::new(
self,
self.send_request(bufs, fds, ReplyFdKind::ReplyWithoutFDs)?,
))
}
fn send_request_with_reply_with_fds<Reply>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, Reply>, ConnectionError>
where
Reply: TryParseFd,
{
Ok(CookieWithFds::new(
self,
self.send_request(bufs, fds, ReplyFdKind::ReplyWithFDs)?,
))
}
fn send_request_without_reply(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
Ok(VoidCookie::new(
self,
self.send_request(bufs, fds, ReplyFdKind::NoReply)?,
))
}
fn discard_reply(&self, sequence: SequenceNumber, _kind: RequestKind, mode: DiscardMode) {
crate::debug!(
"Discarding reply to request {} in mode {:?}",
sequence,
mode
);
self.inner
.lock()
.unwrap()
.inner
.discard_reply(sequence, mode);
}
fn prefetch_extension_information(
&self,
extension_name: &'static str,
) -> Result<(), ConnectionError> {
self.extension_manager
.lock()
.unwrap()
.prefetch_extension_information(self, extension_name)
}
fn extension_information(
&self,
extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
self.extension_manager
.lock()
.unwrap()
.extension_information(self, extension_name)
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<Vec<u8>>, ConnectionError> {
match self.wait_for_reply_with_fds_raw(sequence)? {
ReplyOrError::Reply((reply, _fds)) => Ok(ReplyOrError::Reply(reply)),
ReplyOrError::Error(e) => Ok(ReplyOrError::Error(e)),
}
}
fn wait_for_reply(&self, sequence: SequenceNumber) -> Result<Option<Vec<u8>>, ConnectionError> {
let _guard = crate::debug_span!("wait_for_reply", sequence).entered();
let mut inner = self.inner.lock().unwrap();
inner = self.flush_impl(inner)?;
loop {
crate::trace!({ sequence }, "Polling for reply");
let poll_result = inner.inner.poll_for_reply(sequence);
match poll_result {
PollReply::TryAgain => {}
PollReply::NoReply => return Ok(None),
PollReply::Reply(buffer) => return Ok(Some(buffer)),
}
inner = self.read_packet_and_enqueue(inner, BlockingMode::Blocking)?;
}
}
fn check_for_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<Option<Buffer>, ConnectionError> {
let _guard = crate::debug_span!("check_for_raw_error", sequence).entered();
let mut inner = self.inner.lock().unwrap();
if inner.inner.prepare_check_for_reply_or_error(sequence) {
crate::trace!("Inserting sync with the X11 server");
inner = self.send_sync(inner)?;
assert!(!inner.inner.prepare_check_for_reply_or_error(sequence));
}
// Ensure the request is sent
inner = self.flush_impl(inner)?;
loop {
crate::trace!({ sequence }, "Polling for reply or error");
let poll_result = inner.inner.poll_check_for_reply_or_error(sequence);
match poll_result {
PollReply::TryAgain => {}
PollReply::NoReply => return Ok(None),
PollReply::Reply(buffer) => return Ok(Some(buffer)),
}
inner = self.read_packet_and_enqueue(inner, BlockingMode::Blocking)?;
}
}
fn wait_for_reply_with_fds_raw(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds, Buffer>, ConnectionError> {
let _guard = crate::debug_span!("wait_for_reply_with_fds_raw", sequence).entered();
let mut inner = self.inner.lock().unwrap();
// Ensure the request is sent
inner = self.flush_impl(inner)?;
loop {
crate::trace!({ sequence }, "Polling for reply or error");
if let Some(reply) = inner.inner.poll_for_reply_or_error(sequence) {
if reply.0[0] == 0 {
crate::trace!("Got error");
return Ok(ReplyOrError::Error(reply.0));
} else {
crate::trace!("Got reply");
return Ok(ReplyOrError::Reply(reply));
}
}
inner = self.read_packet_and_enqueue(inner, BlockingMode::Blocking)?;
}
}
fn maximum_request_bytes(&self) -> usize {
let mut max_bytes = self.maximum_request_bytes.lock().unwrap();
self.prefetch_maximum_request_bytes_impl(&mut max_bytes);
use MaxRequestBytes::*;
let max_bytes = &mut *max_bytes;
match max_bytes {
Unknown => unreachable!("We just prefetched this"),
Requested(seqno) => {
let _guard = crate::info_span!("maximum_request_bytes").entered();
let length = seqno
// If prefetching the request succeeded, get a cookie
.and_then(|seqno| {
Cookie::<_, EnableReply>::new(self, seqno)
// and then get the reply to the request
.reply()
.map(|reply| reply.maximum_request_length)
.ok()
})
// If anything failed (sending the request, getting the reply), use Setup
.unwrap_or_else(|| self.setup.maximum_request_length.into())
// Turn the u32 into usize, using the max value in case of overflow
.try_into()
.unwrap_or(usize::MAX);
let length = length * 4;
*max_bytes = Known(length);
crate::info!("Maximum request length is {} bytes", length);
length
}
Known(length) => *length,
}
}
fn prefetch_maximum_request_bytes(&self) {
let mut max_bytes = self.maximum_request_bytes.lock().unwrap();
self.prefetch_maximum_request_bytes_impl(&mut max_bytes);
}
fn parse_error(&self, error: &[u8]) -> Result<crate::x11_utils::X11Error, ParseError> {
let ext_mgr = self.extension_manager.lock().unwrap();
crate::x11_utils::X11Error::try_parse(error, &*ext_mgr)
}
fn parse_event(&self, event: &[u8]) -> Result<crate::protocol::Event, ParseError> {
let ext_mgr = self.extension_manager.lock().unwrap();
crate::protocol::Event::parse(event, &*ext_mgr)
}
}
impl<S: Stream> Connection for RustConnection<S> {
fn wait_for_raw_event_with_sequence(
&self,
) -> Result<RawEventAndSeqNumber<Vec<u8>>, ConnectionError> {
let _guard = crate::trace_span!("wait_for_raw_event_with_sequence").entered();
let mut inner = self.inner.lock().unwrap();
loop {
if let Some(event) = inner.inner.poll_for_event_with_sequence() {
return Ok(event);
}
inner = self.read_packet_and_enqueue(inner, BlockingMode::Blocking)?;
}
}
fn poll_for_raw_event_with_sequence(
&self,
) -> Result<Option<RawEventAndSeqNumber<Vec<u8>>>, ConnectionError> {
let _guard = crate::trace_span!("poll_for_raw_event_with_sequence").entered();
let mut inner = self.inner.lock().unwrap();
if let Some(event) = inner.inner.poll_for_event_with_sequence() {
Ok(Some(event))
} else {
inner = self.read_packet_and_enqueue(inner, BlockingMode::NonBlocking)?;
Ok(inner.inner.poll_for_event_with_sequence())
}
}
fn flush(&self) -> Result<(), ConnectionError> {
let inner = self.inner.lock().unwrap();
let _inner = self.flush_impl(inner)?;
Ok(())
}
fn setup(&self) -> &Setup {
&self.setup
}
fn generate_id(&self) -> Result<u32, ReplyOrIdError> {
let mut id_allocator = self.id_allocator.lock().unwrap();
if let Some(id) = id_allocator.generate_id() {
Ok(id)
} else {
use crate::protocol::xc_misc::{self, ConnectionExt as _};
if self
.extension_information(xc_misc::X11_EXTENSION_NAME)?
.is_none()
{
crate::error!("XIDs are exhausted and XC-MISC extension is not available");
Err(ReplyOrIdError::IdsExhausted)
} else {
crate::info!("XIDs are exhausted; fetching free range via XC-MISC");
id_allocator.update_xid_range(&self.xc_misc_get_xid_range()?.reply()?)?;
id_allocator
.generate_id()
.ok_or(ReplyOrIdError::IdsExhausted)
}
}
}
}
/// Call `notify_all` on a condition variable when dropped.
#[derive(Debug)]
struct NotifyOnDrop<'a>(&'a Condvar);
impl Drop for NotifyOnDrop<'_> {
fn drop(&mut self) {
self.0.notify_all();
}
}
/// Format information about a request in a Display impl
struct RequestInfo<'a> {
extension_manager: &'a Mutex<ExtensionManager>,
major_opcode: u8,
minor_opcode: u8,
}
impl std::fmt::Display for RequestInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// QueryExtension is used by the extension manager. We would deadlock if we
// tried to lock it again. Hence, this case is hardcoded here.
if self.major_opcode == QUERY_EXTENSION_REQUEST {
write!(f, "QueryExtension request")
} else {
let guard = self.extension_manager.lock().unwrap();
write!(
f,
"{} request",
x11rb_protocol::protocol::get_request_name(
&*guard,
self.major_opcode,
self.minor_opcode
)
)
}
}
}

View File

@@ -0,0 +1,208 @@
//! Read X11 packets from a reader
use std::io::{Error, ErrorKind, Result};
use std::{cmp, fmt};
use super::Stream;
use crate::utils::RawFdContainer;
use x11rb_protocol::packet_reader::PacketReader as ProtoPacketReader;
/// A wrapper around a reader that reads X11 packet.
pub(crate) struct PacketReader {
/// The read buffer to store incoming bytes in.
read_buffer: Box<[u8]>,
/// The inner reader that breaks these bytes into packets.
inner: ProtoPacketReader,
}
impl fmt::Debug for PacketReader {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PacketReader")
.field(
"read_buffer",
&format_args!("[buffer of size {}]", self.read_buffer.len()),
)
.field("inner", &self.inner)
.finish()
}
}
impl PacketReader {
/// Create a new `PacketReader` that reads from the given stream.
pub(crate) fn new() -> Self {
Self {
// Buffer size chosen by checking what libxcb does
read_buffer: vec![0; 4096].into_boxed_slice(),
inner: ProtoPacketReader::new(),
}
}
/// Reads as many packets as possible from stream reader without blocking.
pub(crate) fn try_read_packets(
&mut self,
stream: &impl Stream,
out_packets: &mut Vec<Vec<u8>>,
fd_storage: &mut Vec<RawFdContainer>,
) -> Result<()> {
let original_length = out_packets.len();
loop {
// if the necessary packet size is larger than our buffer, just fill straight
// into the buffer
if self.inner.remaining_capacity() >= self.read_buffer.len() {
crate::trace!(
"Trying to read large packet with {} bytes remaining",
self.inner.remaining_capacity()
);
match stream.read(self.inner.buffer(), fd_storage) {
Ok(0) => {
crate::error!("Large read returned zero");
return Err(Error::new(
ErrorKind::UnexpectedEof,
"The X11 server closed the connection",
));
}
Ok(n) => {
crate::trace!("Read {} bytes directly into large packet", n);
if let Some(packet) = self.inner.advance(n) {
out_packets.push(packet);
}
}
Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
Err(e) => return Err(e),
}
} else {
// read into our buffer
let nread = match stream.read(&mut self.read_buffer, fd_storage) {
Ok(0) => {
crate::error!("Buffered read returned zero");
return Err(Error::new(
ErrorKind::UnexpectedEof,
"The X11 server closed the connection",
));
}
Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
Err(e) => return Err(e),
};
crate::trace!("Read {} bytes into read buffer", nread);
// begin reading that data into packets
let mut src = &self.read_buffer[..nread];
while !src.is_empty() {
let dest = self.inner.buffer();
let amt_to_read = cmp::min(src.len(), dest.len());
// copy slices over
dest[..amt_to_read].copy_from_slice(&src[..amt_to_read]);
// reborrow src
src = &src[amt_to_read..];
// advance by the given amount
if let Some(packet) = self.inner.advance(amt_to_read) {
out_packets.push(packet);
}
}
}
}
crate::trace!(
"Read {} complete packet(s)",
out_packets.len() - original_length
);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::PacketReader;
use crate::rust_connection::{PollMode, Stream};
use crate::utils::RawFdContainer;
use std::cell::RefCell;
use std::cmp;
use std::io::{Error, ErrorKind, Result};
// make a Stream that just reads from a Vec<u8>
struct TestStream {
data: RefCell<Vec<u8>>,
}
impl TestStream {
fn new(data: Vec<u8>) -> Self {
Self {
data: RefCell::new(data),
}
}
}
impl Stream for TestStream {
fn read(&self, buf: &mut [u8], _: &mut Vec<RawFdContainer>) -> Result<usize> {
let mut data = self.data.borrow_mut();
if data.is_empty() {
return Err(Error::from(ErrorKind::WouldBlock));
}
let nread = cmp::min(data.len(), buf.len());
buf[..nread].copy_from_slice(&data[..nread]);
let _ = data.drain(..nread);
Ok(nread)
}
fn poll(&self, _: PollMode) -> Result<()> {
Ok(())
}
fn write(&self, _: &[u8], _: &mut Vec<RawFdContainer>) -> Result<usize> {
unreachable!()
}
}
fn test_packet(packet: Vec<u8>) {
let mut reader = PacketReader::new();
let original_packet = packet.clone();
let stream = TestStream::new(packet);
let mut packets = Vec::new();
let mut fd_storage = Vec::new();
reader
.try_read_packets(&stream, &mut packets, &mut fd_storage)
.unwrap();
assert_eq!(packets.len(), 1);
assert_eq!(packets[0], original_packet);
}
#[test]
fn fixed_size_packet() {
let packet = vec![0; 32];
test_packet(packet);
}
#[test]
fn variable_size_packet() {
let mut len = 120;
let mut packet = vec![0; len];
len = (len - 32) / 4;
// copy len to 4..8
packet[4..8].copy_from_slice(&(len as u32).to_ne_bytes());
packet[0] = 1;
test_packet(packet);
}
#[test]
fn very_large_packet() {
let mut len = 4800;
let mut packet = vec![0; len];
len = (len - 32) / 4;
// copy len to 4..8
packet[4..8].copy_from_slice(&(len as u32).to_ne_bytes());
packet[0] = 1;
test_packet(packet);
}
}

View File

@@ -0,0 +1,587 @@
use rustix::fd::{AsFd, BorrowedFd};
use std::io::{IoSlice, Result};
use std::net::TcpStream;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, IntoRawFd, OwnedFd, RawFd};
#[cfg(unix)]
use std::os::unix::net::UnixStream;
#[cfg(windows)]
use std::os::windows::io::{
AsRawSocket, AsSocket, BorrowedSocket, IntoRawSocket, OwnedSocket, RawSocket,
};
use crate::utils::RawFdContainer;
use x11rb_protocol::parse_display::ConnectAddress;
use x11rb_protocol::xauth::Family;
/// The kind of operation that one want to poll for.
#[derive(Debug, Clone, Copy)]
pub enum PollMode {
/// Check if the stream is readable, i.e. there is pending data to be read.
Readable,
/// Check if the stream is writable, i.e. some data could be successfully written to it.
Writable,
/// Check for both readability and writability.
ReadAndWritable,
}
impl PollMode {
/// Does this poll mode include readability?
pub fn readable(self) -> bool {
match self {
PollMode::Readable | PollMode::ReadAndWritable => true,
PollMode::Writable => false,
}
}
/// Does this poll mode include writability?
pub fn writable(self) -> bool {
match self {
PollMode::Writable | PollMode::ReadAndWritable => true,
PollMode::Readable => false,
}
}
}
/// A trait used to implement the raw communication with the X11 server.
///
/// None of the functions of this trait shall return [`std::io::ErrorKind::Interrupted`].
/// If a system call fails with this error, the implementation should try again.
pub trait Stream {
/// Waits for level-triggered read and/or write events on the stream.
///
/// This function does not return what caused it to complete the poll.
/// Instead, callers should try to read or write and check for
/// [`std::io::ErrorKind::WouldBlock`].
///
/// This function is allowed to spuriously return even if the stream
/// is neither readable nor writable. However, it shall not do it
/// continuously, which would cause a 100% CPU usage.
///
/// # Multithreading
///
/// If `Self` is `Send + Sync` and `poll` is used concurrently from more than
/// one thread, all threads should wake when the stream becomes readable (when
/// `read` is `true`) or writable (when `write` is `true`).
fn poll(&self, mode: PollMode) -> Result<()>;
/// Read some bytes and FDs from this reader without blocking, returning how many bytes
/// were read.
///
/// This function works like [`std::io::Read::read`], but also supports the reception of file
/// descriptors. Any received file descriptors are appended to the given `fd_storage`.
/// Whereas implementation of [`std::io::Read::read`] are allowed to block or not to block,
/// this method shall never block and return `ErrorKind::WouldBlock` if needed.
///
/// This function does not guarantee that all file descriptors were sent together with the data
/// with which they are received. However, file descriptors may not be received later than the
/// data that was sent at the same time. Instead, file descriptors may only be received
/// earlier.
///
/// # Multithreading
///
/// If `Self` is `Send + Sync` and `read` is used concurrently from more than one thread:
///
/// * Both the data and the file descriptors shall be read in order, but possibly
/// interleaved across threads.
/// * Neither the data nor the file descriptors shall be duplicated.
/// * The returned value shall always be the actual number of bytes read into `buf`.
fn read(&self, buf: &mut [u8], fd_storage: &mut Vec<RawFdContainer>) -> Result<usize>;
/// Write a buffer and some FDs into this writer without blocking, returning how many
/// bytes were written.
///
/// This function works like [`std::io::Write::write`], but also supports sending file
/// descriptors. The `fds` argument contains the file descriptors to send. The order of file
/// descriptors is maintained. Whereas implementation of [`std::io::Write::write`] are
/// allowed to block or not to block, this function must never block and return
/// `ErrorKind::WouldBlock` if needed.
///
/// This function does not guarantee that all file descriptors are sent together with the data.
/// Any file descriptors that were sent are removed from the beginning of the given `Vec`.
///
/// There is no guarantee that the given file descriptors are received together with the given
/// data. File descriptors might be received earlier than their corresponding data. It is not
/// allowed for file descriptors to be received later than the bytes that were sent at the same
/// time.
///
/// # Multithreading
///
/// If `Self` is `Send + Sync` and `write` is used concurrently from more than one thread:
///
/// * Both the data and the file descriptors shall be written in order, but possibly
/// interleaved across threads.
/// * Neither the data nor the file descriptors shall be duplicated.
/// * The returned value shall always be the actual number of bytes written from `buf`.
fn write(&self, buf: &[u8], fds: &mut Vec<RawFdContainer>) -> Result<usize>;
/// Like `write`, except that it writes from a slice of buffers. Like `write`, this
/// method must never block.
///
/// This method must behave as a call to `write` with the buffers concatenated would.
///
/// The default implementation calls `write` with the first nonempty buffer provided.
///
/// # Multithreading
///
/// Same as `write`.
fn write_vectored(&self, bufs: &[IoSlice<'_>], fds: &mut Vec<RawFdContainer>) -> Result<usize> {
for buf in bufs {
if !buf.is_empty() {
return self.write(buf, fds);
}
}
Ok(0)
}
}
/// A wrapper around a `TcpStream` or `UnixStream`.
///
/// Use by default in `RustConnection` as stream.
#[derive(Debug)]
pub struct DefaultStream {
inner: DefaultStreamInner,
}
#[cfg(unix)]
type DefaultStreamInner = RawFdContainer;
#[cfg(not(unix))]
type DefaultStreamInner = TcpStream;
/// The address of a peer in a format suitable for xauth.
///
/// These values can be directly given to [`x11rb_protocol::xauth::get_auth`].
type PeerAddr = (Family, Vec<u8>);
impl DefaultStream {
/// Try to connect to the X11 server described by the given arguments.
pub fn connect(addr: &ConnectAddress<'_>) -> Result<(Self, PeerAddr)> {
match addr {
ConnectAddress::Hostname(host, port) => {
// connect over TCP
let stream = TcpStream::connect((*host, *port))?;
Self::from_tcp_stream(stream)
}
#[cfg(unix)]
ConnectAddress::Socket(path) => {
// Try abstract unix socket first. If that fails, fall back to normal unix socket
#[cfg(any(target_os = "linux", target_os = "android"))]
if let Ok(stream) = connect_abstract_unix_stream(path.as_bytes()) {
// TODO: Does it make sense to add a constructor similar to from_unix_stream()?
// If this is done: Move the set_nonblocking() from
// connect_abstract_unix_stream() to that new function.
let stream = DefaultStream { inner: stream };
return Ok((stream, peer_addr::local()));
}
// connect over Unix domain socket
let stream = UnixStream::connect(path)?;
Self::from_unix_stream(stream)
}
#[cfg(not(unix))]
ConnectAddress::Socket(_) => {
// Unix domain sockets are not supported on Windows
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Unix domain sockets are not supported on Windows",
))
}
_ => Err(std::io::Error::new(
std::io::ErrorKind::Other,
"The given address family is not implemented",
)),
}
}
/// Creates a new `Stream` from an already connected `TcpStream`.
///
/// The stream will be set in non-blocking mode.
///
/// This returns the peer address in a format suitable for [`x11rb_protocol::xauth::get_auth`].
pub fn from_tcp_stream(stream: TcpStream) -> Result<(Self, PeerAddr)> {
let peer_addr = peer_addr::tcp(&stream.peer_addr()?);
stream.set_nonblocking(true)?;
let result = Self {
inner: stream.into(),
};
Ok((result, peer_addr))
}
/// Creates a new `Stream` from an already connected `UnixStream`.
///
/// The stream will be set in non-blocking mode.
///
/// This returns the peer address in a format suitable for [`x11rb_protocol::xauth::get_auth`].
#[cfg(unix)]
pub fn from_unix_stream(stream: UnixStream) -> Result<(Self, PeerAddr)> {
stream.set_nonblocking(true)?;
let result = Self {
inner: stream.into(),
};
Ok((result, peer_addr::local()))
}
fn as_fd(&self) -> BorrowedFd<'_> {
self.inner.as_fd()
}
}
#[cfg(unix)]
impl AsRawFd for DefaultStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(unix)]
impl AsFd for DefaultStream {
fn as_fd(&self) -> BorrowedFd<'_> {
self.inner.as_fd()
}
}
#[cfg(unix)]
impl IntoRawFd for DefaultStream {
fn into_raw_fd(self) -> RawFd {
self.inner.into_raw_fd()
}
}
#[cfg(unix)]
impl From<DefaultStream> for OwnedFd {
fn from(stream: DefaultStream) -> Self {
stream.inner
}
}
#[cfg(windows)]
impl AsRawSocket for DefaultStream {
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}
#[cfg(windows)]
impl AsSocket for DefaultStream {
fn as_socket(&self) -> BorrowedSocket<'_> {
self.inner.as_socket()
}
}
#[cfg(windows)]
impl IntoRawSocket for DefaultStream {
fn into_raw_socket(self) -> RawSocket {
self.inner.into_raw_socket()
}
}
#[cfg(windows)]
impl From<DefaultStream> for OwnedSocket {
fn from(stream: DefaultStream) -> Self {
stream.inner.into()
}
}
#[cfg(unix)]
fn do_write(
stream: &DefaultStream,
bufs: &[IoSlice<'_>],
fds: &mut Vec<RawFdContainer>,
) -> Result<usize> {
use rustix::io::Errno;
use rustix::net::{sendmsg, SendAncillaryBuffer, SendAncillaryMessage, SendFlags};
use std::mem::MaybeUninit;
fn sendmsg_wrapper(
fd: BorrowedFd<'_>,
iov: &[IoSlice<'_>],
cmsgs: &mut SendAncillaryBuffer<'_, '_, '_>,
flags: SendFlags,
) -> Result<usize> {
loop {
match sendmsg(fd, iov, cmsgs, flags) {
Ok(n) => return Ok(n),
// try again
Err(Errno::INTR) => {}
Err(e) => return Err(e.into()),
}
}
}
let fd = stream.as_fd();
let res = if !fds.is_empty() {
let fds = fds.iter().map(|fd| fd.as_fd()).collect::<Vec<_>>();
let rights = SendAncillaryMessage::ScmRights(&fds);
let mut cmsg_space = vec![MaybeUninit::uninit(); rights.size()];
let mut cmsg_buffer = SendAncillaryBuffer::new(&mut cmsg_space);
assert!(cmsg_buffer.push(rights));
sendmsg_wrapper(fd, bufs, &mut cmsg_buffer, SendFlags::empty())?
} else {
sendmsg_wrapper(fd, bufs, &mut Default::default(), SendFlags::empty())?
};
// We successfully sent all FDs
fds.clear();
Ok(res)
}
impl Stream for DefaultStream {
fn poll(&self, mode: PollMode) -> Result<()> {
use rustix::event::{poll, PollFd, PollFlags};
use rustix::io::Errno;
let mut poll_flags = PollFlags::empty();
if mode.readable() {
poll_flags |= PollFlags::IN;
}
if mode.writable() {
poll_flags |= PollFlags::OUT;
}
let fd = self.as_fd();
let mut poll_fds = [PollFd::from_borrowed_fd(fd, poll_flags)];
loop {
match poll(&mut poll_fds, None) {
Ok(_) => break,
Err(Errno::INTR) => {}
Err(e) => return Err(e.into()),
}
}
// Let the errors (POLLERR) be handled when trying to read or write.
Ok(())
}
fn read(&self, buf: &mut [u8], fd_storage: &mut Vec<RawFdContainer>) -> Result<usize> {
#[cfg(unix)]
{
use rustix::io::Errno;
use rustix::net::{recvmsg, RecvAncillaryBuffer, RecvAncillaryMessage};
use std::io::IoSliceMut;
use std::mem::MaybeUninit;
// 1024 bytes on the stack should be enough for more file descriptors than the X server will ever
// send, as well as the header for the ancillary data. If you can find a case where this can
// overflow with an actual production X11 server, I'll buy you a steak dinner.
let mut cmsg = [MaybeUninit::uninit(); 1024];
let mut iov = [IoSliceMut::new(buf)];
let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut cmsg);
let fd = self.as_fd();
let msg = loop {
match recvmsg(fd, &mut iov, &mut cmsg_buffer, recvmsg::flags()) {
Ok(msg) => break msg,
// try again
Err(Errno::INTR) => {}
Err(e) => return Err(e.into()),
}
};
let fds_received = cmsg_buffer
.drain()
.filter_map(|cmsg| match cmsg {
RecvAncillaryMessage::ScmRights(r) => Some(r),
_ => None,
})
.flatten();
let mut cloexec_error = Ok(());
fd_storage.extend(recvmsg::after_recvmsg(fds_received, &mut cloexec_error));
cloexec_error?;
Ok(msg.bytes)
}
#[cfg(not(unix))]
{
use std::io::Read;
// No FDs are read, so nothing needs to be done with fd_storage
let _ = fd_storage;
loop {
// Use `impl Read for &TcpStream` to avoid needing a mutable `TcpStream`.
match (&mut &self.inner).read(buf) {
Ok(n) => return Ok(n),
// try again
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
}
}
fn write(&self, buf: &[u8], fds: &mut Vec<RawFdContainer>) -> Result<usize> {
#[cfg(unix)]
{
do_write(self, &[IoSlice::new(buf)], fds)
}
#[cfg(not(unix))]
{
use std::io::{Error, ErrorKind, Write};
if !fds.is_empty() {
return Err(Error::new(ErrorKind::Other, "FD passing is unsupported"));
}
loop {
// Use `impl Write for &TcpStream` to avoid needing a mutable `TcpStream`.
match (&mut &self.inner).write(buf) {
Ok(n) => return Ok(n),
// try again
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
}
}
fn write_vectored(&self, bufs: &[IoSlice<'_>], fds: &mut Vec<RawFdContainer>) -> Result<usize> {
#[cfg(unix)]
{
do_write(self, bufs, fds)
}
#[cfg(not(unix))]
{
use std::io::{Error, ErrorKind, Write};
if !fds.is_empty() {
return Err(Error::new(ErrorKind::Other, "FD passing is unsupported"));
}
loop {
// Use `impl Write for &TcpStream` to avoid needing a mutable `TcpStream`.
match (&mut &self.inner).write_vectored(bufs) {
Ok(n) => return Ok(n),
// try again
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
}
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
fn connect_abstract_unix_stream(
path: &[u8],
) -> std::result::Result<RawFdContainer, rustix::io::Errno> {
use rustix::fs::{fcntl_getfl, fcntl_setfl, OFlags};
use rustix::net::{
connect, socket_with, AddressFamily, SocketAddrUnix, SocketFlags, SocketType,
};
let socket = socket_with(
AddressFamily::UNIX,
SocketType::STREAM,
SocketFlags::CLOEXEC,
None,
)?;
connect(&socket, &SocketAddrUnix::new_abstract_name(path)?)?;
// Make the FD non-blocking
fcntl_setfl(&socket, fcntl_getfl(&socket)? | OFlags::NONBLOCK)?;
Ok(socket)
}
/// Helper code to make sure that received FDs are marked as CLOEXEC
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"
))]
mod recvmsg {
use super::RawFdContainer;
use rustix::net::RecvFlags;
pub(crate) fn flags() -> RecvFlags {
RecvFlags::CMSG_CLOEXEC
}
pub(crate) fn after_recvmsg<'a>(
fds: impl Iterator<Item = RawFdContainer> + 'a,
_cloexec_error: &'a mut Result<(), rustix::io::Errno>,
) -> impl Iterator<Item = RawFdContainer> + 'a {
fds
}
}
/// Helper code to make sure that received FDs are marked as CLOEXEC
#[cfg(all(
unix,
not(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"
))
))]
mod recvmsg {
use super::RawFdContainer;
use rustix::io::{fcntl_getfd, fcntl_setfd, FdFlags};
use rustix::net::RecvFlags;
pub(crate) fn flags() -> RecvFlags {
RecvFlags::empty()
}
pub(crate) fn after_recvmsg<'a>(
fds: impl Iterator<Item = RawFdContainer> + 'a,
cloexec_error: &'a mut rustix::io::Result<()>,
) -> impl Iterator<Item = RawFdContainer> + 'a {
fds.map(move |fd| {
if let Err(e) =
fcntl_getfd(&fd).and_then(|flags| fcntl_setfd(&fd, flags | FdFlags::CLOEXEC))
{
*cloexec_error = Err(e);
}
fd
})
}
}
mod peer_addr {
use super::{Family, PeerAddr};
use std::net::{Ipv4Addr, SocketAddr};
// Get xauth information representing a local connection
pub(super) fn local() -> PeerAddr {
let hostname = gethostname::gethostname()
.to_str()
.map_or_else(Vec::new, |s| s.as_bytes().to_vec());
(Family::LOCAL, hostname)
}
// Get xauth information representing a TCP connection to the given address
pub(super) fn tcp(addr: &SocketAddr) -> PeerAddr {
let ip = match addr {
SocketAddr::V4(addr) => *addr.ip(),
SocketAddr::V6(addr) => {
let ip = addr.ip();
if ip.is_loopback() {
// This is a local connection.
// Use LOCALHOST to cause a fall-through in the code below.
Ipv4Addr::LOCALHOST
} else if let Some(ip) = ip.to_ipv4() {
// Let the ipv4 code below handle this
ip
} else {
// Okay, this is really a v6 address
return (Family::INTERNET6, ip.octets().to_vec());
}
}
};
// Handle the v4 address
if ip.is_loopback() {
local()
} else {
(Family::INTERNET, ip.octets().to_vec())
}
}
}

View File

@@ -0,0 +1,224 @@
use std::collections::VecDeque;
use std::io::IoSlice;
use super::Stream;
use crate::utils::RawFdContainer;
#[derive(Debug)]
pub(super) struct WriteBuffer {
data_buf: VecDeque<u8>,
fd_buf: Vec<RawFdContainer>,
}
impl WriteBuffer {
pub(super) fn new() -> Self {
// Buffer size chosen by checking what libxcb does
Self::with_capacity(16384)
}
fn with_capacity(capacity: usize) -> Self {
Self {
data_buf: VecDeque::with_capacity(capacity),
fd_buf: Vec::new(),
}
}
fn flush_buffer(&mut self, stream: &impl Stream) -> std::io::Result<()> {
while self.needs_flush() {
crate::trace!(
"Trying to flush {} bytes of data and {} FDs",
self.data_buf.len(),
self.fd_buf.len()
);
let (data_buf_1, data_buf_2) = self.data_buf.as_slices();
let data_bufs = [IoSlice::new(data_buf_1), IoSlice::new(data_buf_2)];
match stream.write_vectored(&data_bufs, &mut self.fd_buf) {
Ok(0) => {
if self.data_buf.is_empty() {
assert!(!self.fd_buf.is_empty());
return Err(std::io::Error::new(
std::io::ErrorKind::WriteZero,
"failed to write the buffered FDs",
));
} else {
return Err(std::io::Error::new(
std::io::ErrorKind::WriteZero,
"failed to write the buffered data",
));
}
}
Ok(n) => {
crate::trace!("Flushing wrote {} bytes of data", n);
let _ = self.data_buf.drain(..n);
}
Err(e) => return Err(e),
}
}
Ok(())
}
fn write_helper<W: Stream, F, G>(
&mut self,
stream: &W,
fds: &mut Vec<RawFdContainer>,
write_buffer: F,
write_inner: G,
first_buffer: &[u8],
to_write_length: usize,
) -> std::io::Result<usize>
where
F: FnOnce(&mut VecDeque<u8>),
G: FnOnce(&W, &mut Vec<RawFdContainer>) -> std::io::Result<usize>,
{
crate::trace!(
"Writing {} FDs and {} bytes of data",
fds.len(),
to_write_length
);
self.fd_buf.append(fds);
// Is there enough buffer space left for this write?
if (self.data_buf.capacity() - self.data_buf.len()) < to_write_length {
// Not enough space, try to flush
match self.flush_buffer(stream) {
Ok(_) => {}
Err(e) => {
if e.kind() == std::io::ErrorKind::WouldBlock {
let available_buf = self.data_buf.capacity() - self.data_buf.len();
if available_buf == 0 {
// Buffer filled and cannot flush anything without
// blocking, so return `WouldBlock`.
crate::trace!("Writing failed due to full buffer: {:?}", e);
return Err(e);
} else {
let n_to_write = first_buffer.len().min(available_buf);
self.data_buf.extend(&first_buffer[..n_to_write]);
// Return `Ok` because some or all data has been buffered,
// so from the outside it is seen as a successful write.
crate::trace!("Writing appended {} bytes to the buffer", n_to_write);
return Ok(n_to_write);
}
} else {
return Err(e);
}
}
}
}
if to_write_length >= self.data_buf.capacity() {
// Write is larger than the buffer capacity, thus we just flushed the buffer. This
// means that at this point the buffer is empty. Write directly to self.inner. No data
// is copied into the buffer, since that would just mean that the large write gets
// split into multiple smaller ones.
assert!(self.data_buf.is_empty());
crate::trace!("Large write is written directly to the stream");
write_inner(stream, &mut self.fd_buf)
} else {
// At this point there is enough space available in the buffer.
crate::trace!("Data to write is appended to the buffer");
write_buffer(&mut self.data_buf);
Ok(to_write_length)
}
}
pub(super) fn write(
&mut self,
stream: &impl Stream,
buf: &[u8],
fds: &mut Vec<RawFdContainer>,
) -> std::io::Result<usize> {
self.write_helper(
stream,
fds,
|w| w.extend(buf),
|w, fd| w.write(buf, fd),
buf,
buf.len(),
)
}
pub(super) fn write_vectored(
&mut self,
stream: &impl Stream,
bufs: &[IoSlice<'_>],
fds: &mut Vec<RawFdContainer>,
) -> std::io::Result<usize> {
let first_nonempty = bufs
.iter()
.find(|b| !b.is_empty())
.map_or(&[][..], |b| &**b);
let total_len = bufs.iter().map(|b| b.len()).sum();
self.write_helper(
stream,
fds,
|w| {
for buf in bufs.iter() {
w.extend(&**buf);
}
},
|w, fd| w.write_vectored(bufs, fd),
first_nonempty,
total_len,
)
}
/// Returns `true` if there is buffered data or FDs.
pub(super) fn needs_flush(&self) -> bool {
!self.data_buf.is_empty() || !self.fd_buf.is_empty()
}
pub(super) fn flush(&mut self, stream: &impl Stream) -> std::io::Result<()> {
self.flush_buffer(stream)
}
}
#[cfg(test)]
mod test {
use std::io::{Error, ErrorKind, IoSlice, Result};
use super::super::{PollMode, Stream};
use super::WriteBuffer;
use crate::utils::RawFdContainer;
struct WouldBlockWriter;
impl Stream for WouldBlockWriter {
fn poll(&self, _mode: PollMode) -> Result<()> {
unimplemented!();
}
fn read(&self, _buf: &mut [u8], _fd_storage: &mut Vec<RawFdContainer>) -> Result<usize> {
unimplemented!();
}
fn write(&self, _buf: &[u8], _fds: &mut Vec<RawFdContainer>) -> Result<usize> {
Err(Error::new(ErrorKind::WouldBlock, "would block"))
}
}
// Once upon a time, this paniced because it did bufs[0]
#[test]
fn empty_write() {
let stream = WouldBlockWriter;
let mut write_buffer = WriteBuffer::new();
let bufs = &[];
let _ = write_buffer
.write_vectored(&stream, bufs, &mut Vec::new())
.unwrap();
}
// Once upon a time, BufWriteFD fell back to only writing the first buffer. This could be
// mistaken as EOF.
#[test]
fn incorrect_eof() {
let stream = WouldBlockWriter;
let mut write_buffer = WriteBuffer::with_capacity(1);
let bufs = &[IoSlice::new(&[]), IoSlice::new(b"fooo")];
match write_buffer.write_vectored(&stream, bufs, &mut Vec::new()) {
Ok(0) => panic!("This looks like EOF!?"),
Ok(_) => {}
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
Err(e) => panic!("Unexpected error: {e:?}"),
}
}
}

54
vendor/x11rb/src/test.rs vendored Normal file
View File

@@ -0,0 +1,54 @@
use std::rc::Rc;
use std::sync::Arc;
use crate::connection::Connection;
use crate::errors::ReplyOrIdError;
use crate::protocol::xproto::{
ColormapAlloc, ColormapWrapper, FontWrapper, ModMask, SendEventDest, VisualClass, Visualid,
Window,
};
#[test]
fn test_enum_debug() {
assert_eq!("TRUE_COLOR", format!("{:?}", VisualClass::TRUE_COLOR));
assert_eq!("TrueColor", format!("{:#?}", VisualClass::TRUE_COLOR));
assert_eq!(
"POINTER_WINDOW",
format!("{:?}", SendEventDest::POINTER_WINDOW)
);
assert_eq!(
"PointerWindow",
format!("{:#?}", SendEventDest::POINTER_WINDOW)
);
assert_eq!("ITEM_FOCUS", format!("{:?}", SendEventDest::ITEM_FOCUS));
assert_eq!("ItemFocus", format!("{:#?}", SendEventDest::ITEM_FOCUS));
}
#[test]
fn test_bitmask_debug() {
assert_eq!("SHIFT", format!("{:?}", ModMask::SHIFT));
assert_eq!("Shift", format!("{:#?}", ModMask::SHIFT));
assert_eq!(
"SHIFT | LOCK",
format!("{:?}", ModMask::SHIFT | ModMask::LOCK)
);
assert_eq!(
"Shift | Lock",
format!("{:#?}", ModMask::SHIFT | ModMask::LOCK)
);
assert_eq!("0", format!("{:?}", ModMask::from(0u8)));
}
fn _compile_test_arc_in_wrapper<C: Connection>(
conn: &Arc<C>,
) -> Result<FontWrapper<Arc<C>>, ReplyOrIdError> {
FontWrapper::open_font(Arc::clone(conn), b"font")
}
fn _compile_test_rc_in_wrapper<C: Connection>(
conn: &Rc<C>,
window: Window,
visual: Visualid,
) -> Result<ColormapWrapper<Rc<C>>, ReplyOrIdError> {
ColormapWrapper::create_colormap(Rc::clone(conn), ColormapAlloc::NONE, window, visual)
}

126
vendor/x11rb/src/tracing.rs vendored Normal file
View File

@@ -0,0 +1,126 @@
//! Wrapper around tracing so that tracing can be an optional dependency.
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
pub(crate) enum Level {
Error,
Warn,
Info,
Debug,
Trace,
}
#[cfg(feature = "tracing")]
pub(crate) mod implementation {
impl super::Level {
pub(crate) const fn to_tracing(self) -> tracing::Level {
match self {
Self::Error => tracing::Level::ERROR,
Self::Warn => tracing::Level::WARN,
Self::Info => tracing::Level::INFO,
Self::Debug => tracing::Level::DEBUG,
Self::Trace => tracing::Level::TRACE,
}
}
}
macro_rules! event {
( $lvl:expr, $($arg:tt)+ ) => {
tracing::event!($crate::tracing::Level::to_tracing($lvl), $($arg)+)
}
}
macro_rules! span {
( $lvl:expr, $name:expr, $($fields:tt)* ) => {
tracing::span!($crate::tracing::Level::to_tracing($lvl), $name, $($fields)*)
}
}
pub(crate) use event;
pub(crate) use span;
}
#[cfg(not(feature = "tracing"))]
pub(crate) mod implementation {
macro_rules! event {
( $lvl:expr, { $($fields:tt)+ }, $($arg:tt)+ ) => {
let _ = format_args!($($arg)+);
};
( $lvl:expr, $($arg:tt)+ ) => {
let _ = format_args!($($arg)+);
};
}
pub(crate) struct Span;
pub(crate) struct EnteredSpan;
impl Span {
pub(crate) fn entered(&self) -> EnteredSpan {
EnteredSpan
}
}
macro_rules! span {
( $lvl:expr, $name:expr, $($fields:tt)* ) => {
$crate::tracing::implementation::Span
};
}
pub(crate) use event;
pub(crate) use span;
}
macro_rules! error {
( $($arg:tt)+ ) => { $crate::tracing::implementation::event!($crate::tracing::Level::Error, $($arg)+) };
}
macro_rules! warning {
( $($arg:tt)+ ) => { $crate::tracing::implementation::event!($crate::tracing::Level::Warn, $($arg)+) };
}
macro_rules! info {
( $($arg:tt)+ ) => { $crate::tracing::implementation::event!($crate::tracing::Level::Info, $($arg)+) };
}
macro_rules! debug {
( $($arg:tt)+ ) => { $crate::tracing::implementation::event!($crate::tracing::Level::Debug, $($arg)+) };
}
macro_rules! trace {
( $($arg:tt)+ ) => { $crate::tracing::implementation::event!($crate::tracing::Level::Trace, $($arg)+) };
}
pub(crate) use debug;
pub(crate) use error;
pub(crate) use info;
pub(crate) use trace;
pub(crate) use warning;
#[allow(unused_macros)]
macro_rules! error_span {
( $name:expr ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Error, $name, ) };
( $name:expr, $($fields:tt)* ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Error, $name, $($fields)*) };
}
#[allow(unused_macros)]
macro_rules! warning_span {
( $name:expr ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Warn, $name, ) };
( $name:expr, $($fields:tt)* ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Warn, $name, $($fields)*) };
}
#[allow(unused_macro_rules)]
macro_rules! info_span {
( $name:expr ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Info, $name, ) };
( $name:expr, $($fields:tt)* ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Info, $name, $($fields)*) };
}
macro_rules! debug_span {
( $name:expr ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Debug, $name, ) };
( $name:expr, $($fields:tt)* ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Debug, $name, $($fields)*) };
}
#[allow(unused_macro_rules)]
macro_rules! trace_span {
( $name:expr ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Trace, $name, ) };
( $name:expr, $($fields:tt)* ) => { $crate::tracing::implementation::span!($crate::tracing::Level::Trace, $name, $($fields)*) };
}
pub(crate) use debug_span;
#[allow(unused_imports)]
pub(crate) use error_span;
pub(crate) use info_span;
pub(crate) use trace_span;
#[allow(unused_imports)]
pub(crate) use warning_span;

99
vendor/x11rb/src/utils.rs vendored Normal file
View File

@@ -0,0 +1,99 @@
//! Utility functions that are not specific to X11.
//!
//! # CSlice
//!
//! [`CSlice`] is a wrapper around some bytes in memory. It is unsafe to construct, but takes
//! ownership of the bytes and allows accessing them as a `[u8]`. When dropped, the underlying
//! memory is freed via [`libc::free`].
//!
//! `CSlice` is only available when the `allow-unsafe-code` feature is enabled.
pub use x11rb_protocol::RawFdContainer;
#[cfg(feature = "allow-unsafe-code")]
mod unsafe_code {
use std::mem::forget;
use std::ops::{Deref, Index};
use std::ptr::NonNull;
use std::slice::{from_raw_parts, SliceIndex};
use libc::free;
/// Wrapper around a slice that was allocated in C code.
///
/// `CSlice` is only available when the `allow-unsafe-code` feature is enabled.
pub struct CSlice {
ptr: NonNull<[u8]>,
}
// `CSlice` is `Send` and `Sync` because, once created, it is
// completely immutable (it does not have interior mutability),
// so it can be safely accessed from different threads simultaneously.
unsafe impl Send for CSlice {}
unsafe impl Sync for CSlice {}
impl CSlice {
/// Constructs a new `CSlice` from the given parts. `libc::free` will be called on the given
/// pointer when the slice is dropped.
///
/// # Safety
///
/// The same rules as for `std::slice::from_raw_parts` apply. Additionally, the given pointer
/// must be safe to free with `libc::free`.
pub unsafe fn new(ptr: *const u8, len: usize) -> CSlice {
CSlice {
ptr: NonNull::from(from_raw_parts(ptr, len)),
}
}
/// Convert `self` into a raw part.
///
/// Ownership of the returned pointer is given to the caller. Specifically, `libc::free` will
/// not be called on it by `CSlice`.
pub fn into_ptr(self) -> *const u8 {
let ptr = self.ptr.as_ptr() as *const u8;
forget(self);
ptr
}
}
impl Drop for CSlice {
fn drop(&mut self) {
unsafe { free(self.ptr.as_ptr() as _) }
}
}
impl Deref for CSlice {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { self.ptr.as_ref() }
}
}
impl AsRef<[u8]> for CSlice {
fn as_ref(&self) -> &[u8] {
self
}
}
impl<I> Index<I> for CSlice
where
I: SliceIndex<[u8]>,
{
type Output = I::Output;
fn index(&self, index: I) -> &I::Output {
(**self).index(index)
}
}
impl std::fmt::Debug for CSlice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)
}
}
}
#[cfg(feature = "allow-unsafe-code")]
pub use unsafe_code::CSlice;

131
vendor/x11rb/src/wrapper.rs vendored Normal file
View File

@@ -0,0 +1,131 @@
//! Some wrappers around the generated code to simplify use.
use super::cookie::VoidCookie;
use super::errors::{ConnectionError, ReplyError};
use super::protocol::xproto::{Atom, ConnectionExt as XProtoConnectionExt, PropMode, Window};
/// Extension trait that simplifies API use
pub trait ConnectionExt: XProtoConnectionExt {
/// Change a property on a window with format 8.
fn change_property8<A, B>(
&self,
mode: PropMode,
window: Window,
property: A,
type_: B,
data: &[u8],
) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Atom>,
B: Into<Atom>,
{
self.change_property(
mode,
window,
property,
type_,
8,
data.len().try_into().expect("`data` has too many elements"),
data,
)
}
/// Change a property on a window with format 16.
fn change_property16<A, B>(
&self,
mode: PropMode,
window: Window,
property: A,
type_: B,
data: &[u16],
) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Atom>,
B: Into<Atom>,
{
let mut data_u8 = Vec::with_capacity(data.len() * 2);
for item in data {
data_u8.extend(item.to_ne_bytes());
}
self.change_property(
mode,
window,
property,
type_,
16,
data.len().try_into().expect("`data` has too many elements"),
&data_u8,
)
}
/// Change a property on a window with format 32.
fn change_property32<A, B>(
&self,
mode: PropMode,
window: Window,
property: A,
type_: B,
data: &[u32],
) -> Result<VoidCookie<'_, Self>, ConnectionError>
where
A: Into<Atom>,
B: Into<Atom>,
{
let mut data_u8 = Vec::with_capacity(data.len() * 4);
for item in data {
data_u8.extend(item.to_ne_bytes());
}
self.change_property(
mode,
window,
property,
type_,
32,
data.len().try_into().expect("`data` has too many elements"),
&data_u8,
)
}
/// Synchronise with the X11 server.
///
/// This function synchronises with the X11 server. This means that all requests that are still
/// in the output buffer are sent to the server. Then, we wait until the X11 server processed
/// all requests.
fn sync(&self) -> Result<(), ReplyError> {
// When a new request is generated, it is appended to the output buffer. Thus, this causes
// all previous requests to be sent.
// The X11 server is single-threaded and processes requests in-order. Thus, it will only
// reply to our GetInputFocus after everything before was processed.
self.get_input_focus()?.reply().and(Ok(()))
}
}
impl<C: XProtoConnectionExt + ?Sized> ConnectionExt for C {}
/// A RAII-like wrapper around [super::protocol::xproto::grab_server] and
/// [super::protocol::xproto::ungrab_server].
///
/// Instances of this struct represent that we sent a [super::protocol::xproto::grab_server]
/// request. When this struct is dropped, an [super::protocol::xproto::ungrab_server] request is
/// sent.
///
/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
/// X11 connection is broken and later requests will also fail.
#[derive(Debug)]
pub struct GrabServer<'c, C: XProtoConnectionExt>(&'c C);
impl<'c, C: XProtoConnectionExt> GrabServer<'c, C> {
/// Grab the server by sending a [super::protocol::xproto::grab_server] request.
///
/// The returned type will call [super::protocol::xproto::ungrab_server] when it is dropped.
pub fn grab(conn: &'c C) -> Result<Self, ConnectionError> {
// Grab the server, return any errors, ignore the resulting VoidCookie
drop(conn.grab_server()?);
Ok(Self(conn))
}
}
impl<C: XProtoConnectionExt> Drop for GrabServer<'_, C> {
fn drop(&mut self) {
let _ = (self.0).ungrab_server();
}
}

152
vendor/x11rb/src/x11_utils.rs vendored Normal file
View File

@@ -0,0 +1,152 @@
//! Some utilities for working with X11.
pub use x11rb_protocol::x11_utils::{
parse_request_header, BigRequests, ExtInfoProvider, ExtensionInformation, ReplyParsingFunction,
Request, RequestHeader, Serialize, TryParse, TryParseFd, X11Error,
};
/// A helper macro for managing atoms
///
/// In X11, one often has to work with many different atoms that are already known at compile time.
/// This macro can simplify managing such a list of atoms.
///
/// The following macro invocation:
/// ```
/// # use x11rb::atom_manager;
/// atom_manager! {
/// /// A collection of Atoms.
/// pub AtomCollection:
/// /// A handle to a response from the X11 server.
/// AtomCollectionCookie {
/// _NET_WM_NAME,
/// _NET_WM_ICON,
/// ATOM_WITH_SPACES: b"ATOM WITH SPACES",
/// WHATEVER,
/// }
/// }
/// ```
/// ...expands to this:
/// ```
/// # use x11rb::protocol::xproto::{Atom, ConnectionExt, InternAtomReply};
/// # use x11rb::errors::{ConnectionError, ReplyError};
/// # use x11rb::cookie::Cookie;
/// #[allow(non_snake_case)]
/// #[derive(Debug, Clone, Copy)]
/// /// A collection of Atoms.
/// pub struct AtomCollection {
/// pub _NET_WM_NAME: Atom,
/// pub _NET_WM_ICON: Atom,
/// pub ATOM_WITH_SPACES: Atom,
/// pub WHATEVER: Atom,
/// }
///
/// #[allow(non_snake_case)]
/// #[derive(Debug)]
/// /// A handle to a response from the X11 server.
/// struct AtomCollectionCookie<'c, C: ConnectionExt> {
/// // please treat the actual members as private
/// # phantom: std::marker::PhantomData<&'c C>,
/// # _NET_WM_NAME: Cookie<'c, C, InternAtomReply>,
/// # _NET_WM_ICON: Cookie<'c, C, InternAtomReply>,
/// # ATOM_WITH_SPACES: Cookie<'c, C, InternAtomReply>,
/// # WHATEVER: Cookie<'c, C, InternAtomReply>,
/// }
///
/// impl AtomCollection {
/// pub fn new<C: ConnectionExt>(
/// conn: &C,
/// ) -> Result<AtomCollectionCookie<'_, C>, ConnectionError> {
/// // This is just an example for readability; the actual code is more efficient.
/// Ok(AtomCollectionCookie {
/// phantom: std::marker::PhantomData,
/// _NET_WM_NAME: conn.intern_atom(false, b"_NET_WM_NAME")?,
/// _NET_WM_ICON: conn.intern_atom(false, b"_NET_WM_ICON")?,
/// ATOM_WITH_SPACES: conn.intern_atom(false, b"ATOM WITH SPACES")?,
/// WHATEVER: conn.intern_atom(false, b"WHATEVER")?,
/// })
/// }
/// }
///
/// impl<'c, C> AtomCollectionCookie<'c, C>
/// where
/// C: ConnectionExt,
/// {
/// pub fn reply(self) -> Result<AtomCollection, ReplyError> {
/// // This is just an example for readability; the actual code is different.
/// Ok(AtomCollection {
/// _NET_WM_NAME: self._NET_WM_NAME.reply()?.atom,
/// _NET_WM_ICON: self._NET_WM_ICON.reply()?.atom,
/// ATOM_WITH_SPACES: self.ATOM_WITH_SPACES.reply()?.atom,
/// WHATEVER: self.WHATEVER.reply()?.atom,
/// })
/// }
/// }
/// ```
#[macro_export]
macro_rules! atom_manager {
{
$(#[$struct_meta:meta])*
$vis:vis $struct_name:ident:
$(#[$cookie_meta:meta])*
$cookie_name:ident {
$($field_name:ident$(: $atom_value:expr)?,)*
}
} => {
// Cookie version
#[allow(non_snake_case)]
#[derive(Debug)]
$(#[$cookie_meta])*
$vis struct $cookie_name<'a, C: $crate::protocol::xproto::ConnectionExt> {
__private_phantom: ::std::marker::PhantomData<&'a C>,
__private_cookies: ::std::vec::Vec<$crate::cookie::Cookie<'a, C, $crate::protocol::xproto::InternAtomReply>>,
}
// Replies
#[allow(non_snake_case)]
#[derive(Debug, Clone, Copy)]
$(#[$struct_meta])*
$vis struct $struct_name {
$(
$vis $field_name: $crate::protocol::xproto::Atom,
)*
}
impl $struct_name {
$vis fn new<C: $crate::protocol::xproto::ConnectionExt>(
_conn: &C,
) -> ::std::result::Result<$cookie_name<'_, C>, $crate::errors::ConnectionError> {
let names = [
$($crate::__atom_manager_atom_value!($field_name$(: $atom_value)?),)*
];
let cookies: ::std::result::Result<::std::vec::Vec<_>, _>
= names.into_iter().map(|name| _conn.intern_atom(false, name)).collect();
Ok($cookie_name {
__private_phantom: ::std::marker::PhantomData,
__private_cookies: cookies?,
})
}
}
impl<'a, C: $crate::protocol::xproto::ConnectionExt> $cookie_name<'a, C> {
$vis fn reply(self) -> ::std::result::Result<$struct_name, $crate::errors::ReplyError> {
let mut replies = self.__private_cookies.into_iter();
Ok($struct_name {
$(
$field_name: replies.next().expect("new() should have constructed a Vec of the correct size").reply()?.atom,
)*
})
}
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __atom_manager_atom_value {
($field_name:ident) => {
stringify!($field_name).as_bytes()
};
($field_name:ident: $atom_value:expr) => {
$atom_value
};
}

35
vendor/x11rb/src/xcb_ffi/atomic_u64.rs vendored Normal file
View File

@@ -0,0 +1,35 @@
//! Either `AtomicU64` or emulating `AtomicU64` through a `Mutex`.
// Use the `AtomicU64` from the standard library if we're on a platform that supports atomic
// 64-bit operations.
#[cfg(target_has_atomic = "64")]
pub(crate) use std::sync::atomic::AtomicU64;
#[cfg(not(target_has_atomic = "64"))]
mod impl_ {
use std::sync::atomic::Ordering;
use std::sync::Mutex;
#[derive(Debug)]
pub(crate) struct AtomicU64(Mutex<u64>);
impl AtomicU64 {
pub(crate) fn new(val: u64) -> Self {
Self(Mutex::new(val))
}
pub(crate) fn load(&self, _: Ordering) -> u64 {
*self.0.lock().unwrap()
}
pub(crate) fn fetch_max(&self, val: u64, _: Ordering) -> u64 {
let mut lock = self.0.lock().unwrap();
let old = *lock;
*lock = old.max(val);
old
}
}
}
#[cfg(not(target_has_atomic = "64"))]
pub(crate) use self::impl_::AtomicU64;

747
vendor/x11rb/src/xcb_ffi/mod.rs vendored Normal file
View File

@@ -0,0 +1,747 @@
//! A FFI-based connection to an X11 server, using libxcb.
//!
//! This module is only available when the `allow-unsafe-code` feature is enabled.
use std::ffi::CStr;
use std::io::{Error as IOError, ErrorKind, IoSlice};
use std::os::raw::c_int;
#[cfg(unix)]
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use std::ptr::{null, null_mut};
use std::sync::{atomic::Ordering, Mutex};
use libc::c_void;
use crate::connection::{
compute_length_field, Connection, ReplyOrError, RequestConnection, RequestKind,
};
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::DisplayParsingError;
pub use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyError, ReplyOrIdError};
use crate::extension_manager::ExtensionManager;
use crate::protocol::xproto::Setup;
use crate::utils::{CSlice, RawFdContainer};
use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd};
use x11rb_protocol::{DiscardMode, SequenceNumber};
mod atomic_u64;
mod pending_errors;
mod raw_ffi;
use atomic_u64::AtomicU64;
#[cfg(all(not(test), feature = "dl-libxcb"))]
pub use raw_ffi::libxcb_library::load_libxcb;
type Buffer = <XCBConnection as RequestConnection>::Buf;
/// The raw bytes of an event received by [`XCBConnection`] and its sequence number.
pub type RawEventAndSeqNumber = x11rb_protocol::RawEventAndSeqNumber<Buffer>;
/// A combination of a buffer and a list of file descriptors for use by [`XCBConnection`].
pub type BufWithFds = crate::connection::BufWithFds<Buffer>;
/// A connection to an X11 server.
///
/// This type wraps `*mut xcb_connection_t` that is provided by libxcb. It provides a rust
/// interface to this C library.
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug)]
pub struct XCBConnection<Conn = raw_ffi::XcbConnectionWrapper> {
conn: Conn,
setup: Setup,
ext_mgr: Mutex<ExtensionManager>,
errors: pending_errors::PendingErrors,
maximum_sequence_received: AtomicU64,
}
impl XCBConnection {
/// Establish a new connection to an X11 server.
///
/// If a `dpy_name` is provided, it describes the display that should be connected to, for
/// example `127.0.0.1:1`. If no value is provided, the `$DISPLAY` environment variable is
/// used.
pub fn connect(dpy_name: Option<&CStr>) -> Result<(XCBConnection, usize), ConnectError> {
use libc::c_int;
unsafe {
let mut screen: c_int = 0;
let dpy_ptr = dpy_name.map_or(null(), |s| s.as_ptr());
let connection = raw_ffi::XcbConnectionWrapper::new(
raw_ffi::xcb_connect(dpy_ptr, &mut screen),
true,
);
let error = raw_ffi::xcb_connection_has_error(connection.as_ptr());
if error != 0 {
Err(Self::connect_error_from_c_error(error))
} else {
let setup = raw_ffi::xcb_get_setup(connection.as_ptr());
let conn = XCBConnection {
// `xcb_connect` will never return null.
conn: connection,
setup: Self::parse_setup(setup)?,
ext_mgr: Default::default(),
errors: Default::default(),
maximum_sequence_received: AtomicU64::new(0),
};
Ok((conn, screen as usize))
}
}
}
/// Create a connection wrapper for a raw libxcb `xcb_connection_t`.
///
/// `xcb_disconnect` is called on drop only if `should_drop` is `true`.
/// If this function returns an `Err()` and `should_drop` was true, then
/// `xcb_disconnect` was already called.
///
/// # Safety
///
/// If `should_drop` is `false`, the connection must live longer than the returned
/// `XCBConnection`. If `should_drop` is `true`, the returned `XCBConnection` will
/// take the ownership of the connection.
pub unsafe fn from_raw_xcb_connection(
ptr: *mut c_void,
should_drop: bool,
) -> Result<XCBConnection, ConnectError> {
Self::from_raw_xcb_connection_inner(raw_ffi::XcbConnectionWrapper::new(
ptr.cast(),
should_drop,
))
}
}
impl<Conn: as_raw_xcb_connection::AsRawXcbConnection> XCBConnection<Conn> {
unsafe fn from_raw_xcb_connection_inner(
conn: Conn,
) -> Result<XCBConnection<Conn>, ConnectError> {
let setup = raw_ffi::xcb_get_setup(conn.as_raw_xcb_connection().cast());
Ok(XCBConnection {
conn,
setup: Self::parse_setup(setup)?,
ext_mgr: Default::default(),
errors: Default::default(),
maximum_sequence_received: AtomicU64::new(0),
})
}
unsafe fn connection_error_from_connection(
c: *mut raw_ffi::xcb_connection_t,
) -> ConnectionError {
Self::connection_error_from_c_error(raw_ffi::xcb_connection_has_error(c))
}
fn connection_error_from_c_error(error: c_int) -> ConnectionError {
use crate::xcb_ffi::raw_ffi::connection_errors::*;
assert_ne!(error, 0);
match error {
ERROR => IOError::new(ErrorKind::Other, ConnectionError::UnknownError).into(),
EXT_NOTSUPPORTED => ConnectionError::UnsupportedExtension,
MEM_INSUFFICIENT => ConnectionError::InsufficientMemory,
REQ_LEN_EXCEED => ConnectionError::MaximumRequestLengthExceeded,
FDPASSING_FAILED => ConnectionError::FdPassingFailed,
_ => ConnectionError::UnknownError,
// Not possible here: PARSE_ERR, INVALID_SCREEN
}
}
fn connect_error_from_c_error(error: c_int) -> ConnectError {
use crate::xcb_ffi::raw_ffi::connection_errors::*;
assert_ne!(error, 0);
match error {
ERROR => IOError::new(ErrorKind::Other, ConnectionError::UnknownError).into(),
MEM_INSUFFICIENT => ConnectError::InsufficientMemory,
PARSE_ERR => DisplayParsingError::Unknown.into(),
INVALID_SCREEN => ConnectError::InvalidScreen,
_ => ConnectError::UnknownError,
// Not possible here: EXT_NOTSUPPORTED, REQ_LEN_EXCEED, FDPASSING_FAILED
}
}
/// Create an `XCBConnection` from an object that implements `AsRawXcbConnection`.
pub fn from_existing_connection(conn: Conn) -> Result<Self, ConnectError> {
let setup = unsafe { raw_ffi::xcb_get_setup(conn.as_raw_xcb_connection().cast()) };
Ok(XCBConnection {
conn,
setup: unsafe { Self::parse_setup(setup) }?,
ext_mgr: Default::default(),
errors: Default::default(),
maximum_sequence_received: AtomicU64::new(0),
})
}
/// Get a reference to the inner managed connection.
///
/// It is discouraged to use this inner connection for fetching events.
pub fn inner_connection(&self) -> &Conn {
&self.conn
}
fn as_ptr(&self) -> *mut raw_ffi::xcb_connection_t {
self.conn.as_raw_xcb_connection().cast()
}
unsafe fn parse_setup(setup: *const raw_ffi::xcb_setup_t) -> Result<Setup, ParseError> {
use std::slice::from_raw_parts;
// We know that the setup information has at least eight bytes.
// Use a slice instead of Buffer::CSlice since we must not free() the xcb_setup_t that libxcb owns.
let wrapper = from_raw_parts(setup as *const u8, 8);
// The length field is in the last two bytes
let length = u16::from_ne_bytes([wrapper[6], wrapper[7]]);
// The length is in four-byte-units after the known header
let length = usize::from(length) * 4 + 8;
let slice = from_raw_parts(wrapper.as_ptr(), length);
let result = Setup::try_parse(slice)?.0;
Ok(result)
}
// Slince the warning about ioslice.len().try_into().unwrap(). The target type is sometimes
// usize (where this warning is correct) and sometimes c_int (where we need the conversion). We
// need this here due to https://github.com/rust-lang/rust/issues/60681.
#[allow(clippy::useless_conversion)]
fn send_request(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
has_reply: bool,
reply_has_fds: bool,
) -> Result<SequenceNumber, ConnectionError> {
let mut storage = Default::default();
let new_bufs = compute_length_field(self, bufs, &mut storage)?;
// Now wrap the buffers with IoSlice
let mut new_bufs_ffi = Vec::with_capacity(2 + new_bufs.len());
// XCB wants to access bufs[-1] and bufs[-2], so we need to add two empty items in front.
new_bufs_ffi.push(raw_ffi::iovec {
iov_base: null_mut(),
iov_len: 0,
});
new_bufs_ffi.push(raw_ffi::iovec {
iov_base: null_mut(),
iov_len: 0,
});
new_bufs_ffi.extend(new_bufs.iter().map(|ioslice| raw_ffi::iovec {
iov_base: ioslice.as_ptr() as _,
iov_len: ioslice.len().try_into().unwrap(),
}));
// Set up the information that libxcb needs
let protocol_request = raw_ffi::xcb_protocol_request_t {
count: new_bufs.len(),
ext: null_mut(), // Not needed since we always use raw
opcode: 0,
isvoid: u8::from(!has_reply),
};
let mut flags = raw_ffi::send_request_flags::RAW;
assert!(has_reply || !reply_has_fds);
flags |= raw_ffi::send_request_flags::CHECKED;
if reply_has_fds {
flags |= raw_ffi::send_request_flags::REPLY_FDS;
}
let seqno = if fds.is_empty() {
unsafe {
raw_ffi::xcb_send_request64(
self.as_ptr(),
flags,
&mut new_bufs_ffi[2],
&protocol_request,
)
}
} else {
#[cfg(unix)]
{
// Convert the FDs into an array of ints. libxcb will close the FDs.
let mut fds: Vec<_> = fds.into_iter().map(RawFdContainer::into_raw_fd).collect();
let num_fds = fds.len().try_into().unwrap();
let fds_ptr = fds.as_mut_ptr();
unsafe {
raw_ffi::xcb_send_request_with_fds64(
self.as_ptr(),
flags,
&mut new_bufs_ffi[2],
&protocol_request,
num_fds,
fds_ptr,
)
}
}
#[cfg(not(unix))]
{
unreachable!("it is not possible to create a `RawFdContainer` on non-unix");
}
};
if seqno == 0 {
unsafe { Err(Self::connection_error_from_connection(self.as_ptr())) }
} else {
Ok(seqno)
}
}
/// Check if the underlying XCB connection is in an error state.
pub fn has_error(&self) -> Option<ConnectionError> {
unsafe {
let error = raw_ffi::xcb_connection_has_error(self.as_ptr());
if error == 0 {
None
} else {
Some(Self::connection_error_from_c_error(error))
}
}
}
/// Get access to the raw libxcb `xcb_connection_t`.
///
/// The returned pointer is valid for as long as the original object was not dropped. No
/// ownerhsip is transferred.
pub fn get_raw_xcb_connection(&self) -> *mut c_void {
self.as_ptr().cast()
}
/// Check if a reply to the given request already received.
///
/// Return Err(()) when the reply was not yet received. Returns Ok(None) when there can be no
/// reply. Returns Ok(buffer) with the reply if there is one (this buffer can be an error or a
/// reply).
fn poll_for_reply(&self, sequence: SequenceNumber) -> Result<Option<CSlice>, ()> {
unsafe {
let mut reply = null_mut();
let mut error = null_mut();
let found =
raw_ffi::xcb_poll_for_reply64(self.as_ptr(), sequence, &mut reply, &mut error);
if found == 0 {
return Err(());
}
assert_eq!(found, 1);
match (reply.is_null(), error.is_null()) {
(true, true) => Ok(None),
(true, false) => Ok(Some(self.wrap_error(error as _, sequence))),
(false, true) => Ok(Some(self.wrap_reply(reply as _, sequence))),
(false, false) => unreachable!(),
}
}
}
unsafe fn wrap_reply(&self, reply: *const u8, sequence: SequenceNumber) -> CSlice {
// Update our "max sequence number received" field
let _ = self
.maximum_sequence_received
.fetch_max(sequence, Ordering::Relaxed);
let header = CSlice::new(reply, 32);
let length_field = u32::from_ne_bytes(header[4..8].try_into().unwrap());
let length_field: usize = length_field
.try_into()
.expect("usize should have at least 32 bits");
let length = 32 + length_field * 4;
CSlice::new(header.into_ptr(), length)
}
unsafe fn wrap_error(&self, error: *const u8, sequence: SequenceNumber) -> CSlice {
// Update our "max sequence number received" field
let _ = self
.maximum_sequence_received
.fetch_max(sequence, Ordering::Relaxed);
CSlice::new(error, 32)
}
unsafe fn wrap_event(&self, event: *mut u8) -> Result<RawEventAndSeqNumber, ParseError> {
let header = CSlice::new(event, 36);
let mut length = 32;
// XCB inserts a uint32_t with the sequence number after the first 32 bytes.
let seqno = u32::from_ne_bytes([header[32], header[33], header[34], header[35]]);
let seqno = self.reconstruct_full_sequence(seqno);
// The first byte contains the event type, check for XGE events
if (*event & 0x7f) == super::protocol::xproto::GE_GENERIC_EVENT {
// Read the length field of the event to get its length
let length_field = u32::from_ne_bytes([header[4], header[5], header[6], header[7]]);
let length_field: usize = length_field
.try_into()
.or(Err(ParseError::ConversionFailed))?;
length += length_field * 4;
// Discard the `full_sequence` field inserted by xcb at
// the 32-byte boundary.
std::ptr::copy(event.add(36), event.add(32), length_field * 4);
}
Ok((CSlice::new(header.into_ptr(), length), seqno))
}
/// Reconstruct a full sequence number based on a partial value.
///
/// The assumption for the algorithm here is that the given sequence number was received
/// recently. Thus, the maximum sequence number that was received so far is used to fill in the
/// missing bytes for the result.
fn reconstruct_full_sequence(&self, seqno: u32) -> SequenceNumber {
reconstruct_full_sequence_impl(
self.maximum_sequence_received.load(Ordering::Relaxed),
seqno,
)
}
}
impl<Conn: as_raw_xcb_connection::AsRawXcbConnection> RequestConnection for XCBConnection<Conn> {
type Buf = CSlice;
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
Ok(Cookie::new(
self,
self.send_request(bufs, fds, true, false)?,
))
}
fn send_request_with_reply_with_fds<R>(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
Ok(CookieWithFds::new(
self,
self.send_request(bufs, fds, true, true)?,
))
}
fn send_request_without_reply(
&self,
bufs: &[IoSlice<'_>],
fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
Ok(VoidCookie::new(
self,
self.send_request(bufs, fds, false, false)?,
))
}
fn discard_reply(&self, sequence: SequenceNumber, _kind: RequestKind, mode: DiscardMode) {
match mode {
DiscardMode::DiscardReplyAndError => unsafe {
// libxcb can throw away everything for us
raw_ffi::xcb_discard_reply64(self.as_ptr(), sequence);
},
// We have to check for errors ourselves
DiscardMode::DiscardReply => self.errors.discard_reply(sequence),
}
}
fn prefetch_extension_information(
&self,
extension_name: &'static str,
) -> Result<(), ConnectionError> {
self.ext_mgr
.lock()
.unwrap()
.prefetch_extension_information(self, extension_name)
}
fn extension_information(
&self,
extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
self.ext_mgr
.lock()
.unwrap()
.extension_information(self, extension_name)
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<CSlice>, ConnectionError> {
unsafe {
let mut error = null_mut();
let reply = raw_ffi::xcb_wait_for_reply64(self.as_ptr(), sequence, &mut error);
match (reply.is_null(), error.is_null()) {
(true, true) => Err(Self::connection_error_from_connection(self.as_ptr())),
(false, true) => Ok(ReplyOrError::Reply(self.wrap_reply(reply as _, sequence))),
(true, false) => Ok(ReplyOrError::Error(self.wrap_error(error as _, sequence))),
// At least one of these pointers must be NULL.
(false, false) => unreachable!(),
}
}
}
fn wait_for_reply(&self, sequence: SequenceNumber) -> Result<Option<CSlice>, ConnectionError> {
match self.wait_for_reply_or_raw_error(sequence)? {
ReplyOrError::Reply(reply) => Ok(Some(reply)),
ReplyOrError::Error(error) => {
self.errors.append_error((sequence, error));
Ok(None)
}
}
}
#[cfg(unix)]
fn wait_for_reply_with_fds_raw(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds, Buffer>, ConnectionError> {
let buffer = match self.wait_for_reply_or_raw_error(sequence)? {
ReplyOrError::Reply(reply) => reply,
ReplyOrError::Error(error) => return Ok(ReplyOrError::Error(error)),
};
// Get a pointer to the array of integers where libxcb saved the FD numbers.
// libxcb saves the list of FDs after the data of the reply. Since the reply's
// length is encoded in "number of 4 bytes block", the following pointer is aligned
// correctly (if malloc() returned an aligned chunk, which it does).
#[allow(clippy::cast_ptr_alignment)]
let fd_ptr = (unsafe { buffer.as_ptr().add(buffer.len()) }) as *const RawFd;
// The number of FDs is in the second byte (= buffer[1]) in all replies.
let fd_slice = unsafe { std::slice::from_raw_parts(fd_ptr, usize::from(buffer[1])) };
let fd_vec = fd_slice
.iter()
.map(|&fd| unsafe { OwnedFd::from_raw_fd(fd) })
.collect();
Ok(ReplyOrError::Reply((buffer, fd_vec)))
}
#[cfg(not(unix))]
fn wait_for_reply_with_fds_raw(
&self,
_sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds, Buffer>, ConnectionError> {
unimplemented!("FD passing is currently only implemented on Unix-like systems")
}
fn check_for_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<Option<Buffer>, ConnectionError> {
let cookie = raw_ffi::xcb_void_cookie_t {
sequence: sequence as _,
};
let error = unsafe { raw_ffi::xcb_request_check(self.as_ptr(), cookie) };
if error.is_null() {
Ok(None)
} else {
unsafe { Ok(Some(self.wrap_error(error as _, sequence))) }
}
}
fn maximum_request_bytes(&self) -> usize {
4 * unsafe { raw_ffi::xcb_get_maximum_request_length(self.as_ptr()) as usize }
}
fn prefetch_maximum_request_bytes(&self) {
unsafe { raw_ffi::xcb_prefetch_maximum_request_length(self.as_ptr()) };
}
fn parse_error(&self, error: &[u8]) -> Result<crate::x11_utils::X11Error, ParseError> {
let ext_mgr = self.ext_mgr.lock().unwrap();
crate::x11_utils::X11Error::try_parse(error, &*ext_mgr)
}
fn parse_event(&self, event: &[u8]) -> Result<crate::protocol::Event, ParseError> {
let ext_mgr = self.ext_mgr.lock().unwrap();
crate::protocol::Event::parse(event, &*ext_mgr)
}
}
impl Connection for XCBConnection {
fn wait_for_raw_event_with_sequence(&self) -> Result<RawEventAndSeqNumber, ConnectionError> {
if let Some(error) = self.errors.get(self) {
return Ok((error.1, error.0));
}
unsafe {
let event = raw_ffi::xcb_wait_for_event(self.conn.as_ptr());
if event.is_null() {
return Err(Self::connection_error_from_connection(self.conn.as_ptr()));
}
Ok(self.wrap_event(event as _)?)
}
}
fn poll_for_raw_event_with_sequence(
&self,
) -> Result<Option<RawEventAndSeqNumber>, ConnectionError> {
if let Some(error) = self.errors.get(self) {
return Ok(Some((error.1, error.0)));
}
unsafe {
let event = raw_ffi::xcb_poll_for_event(self.conn.as_ptr());
if event.is_null() {
let err = raw_ffi::xcb_connection_has_error(self.conn.as_ptr());
if err == 0 {
return Ok(None);
} else {
return Err(Self::connection_error_from_c_error(err));
}
}
Ok(Some(self.wrap_event(event as _)?))
}
}
fn flush(&self) -> Result<(), ConnectionError> {
// xcb_flush() returns 0 if the connection is in (or just entered) an error state, else 1.
let res = unsafe { raw_ffi::xcb_flush(self.conn.as_ptr()) };
if res != 0 {
Ok(())
} else {
unsafe { Err(Self::connection_error_from_connection(self.conn.as_ptr())) }
}
}
fn generate_id(&self) -> Result<u32, ReplyOrIdError> {
unsafe {
let id = raw_ffi::xcb_generate_id(self.conn.as_ptr());
// XCB does not document the behaviour of `xcb_generate_id` when
// there is an error. Looking at its source code it seems that it
// returns `-1` (presumably `u32::MAX`).
if id == u32::MAX {
Err(Self::connection_error_from_connection(self.conn.as_ptr()).into())
} else {
Ok(id)
}
}
}
fn setup(&self) -> &Setup {
&self.setup
}
}
#[cfg(unix)]
impl AsRawFd for XCBConnection {
fn as_raw_fd(&self) -> RawFd {
unsafe { raw_ffi::xcb_get_file_descriptor(self.conn.as_ptr()) }
}
}
#[cfg(unix)]
impl AsFd for XCBConnection {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}
#[cfg(feature = "raw-window-handle")]
unsafe impl raw_window_handle::HasRawDisplayHandle for XCBConnection {
#[inline]
fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
let mut handle = raw_window_handle::XcbDisplayHandle::empty();
handle.connection = self.get_raw_xcb_connection();
raw_window_handle::RawDisplayHandle::Xcb(handle)
}
}
#[cfg(feature = "raw-window-handle")]
unsafe impl raw_window_handle::HasRawWindowHandle
for crate::protocol::xproto::WindowWrapper<XCBConnection>
{
#[inline]
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
let mut handle = raw_window_handle::XcbWindowHandle::empty();
handle.window = self.window();
raw_window_handle::RawWindowHandle::Xcb(handle)
}
}
// SAFETY: We provide a valid xcb_connection_t that is valid for as long as required by the trait.
unsafe impl as_raw_xcb_connection::AsRawXcbConnection for XCBConnection {
fn as_raw_xcb_connection(&self) -> *mut as_raw_xcb_connection::xcb_connection_t {
self.get_raw_xcb_connection().cast()
}
}
/// Reconstruct a partial sequence number based on a recently received 'full' sequence number.
///
/// The new sequence number may be before or after the `recent` sequence number.
fn reconstruct_full_sequence_impl(recent: SequenceNumber, value: u32) -> SequenceNumber {
// Expand 'value' to a full sequence number. The high bits are copied from 'recent'.
let u32_max = SequenceNumber::from(u32::MAX);
let expanded_value = SequenceNumber::from(value) | (recent & !u32_max);
// The "step size" is the difference between two sequence numbers that cannot be told apart
// from their truncated value.
let step: SequenceNumber = SequenceNumber::from(1u8) << 32;
// There are three possible values for the returned sequence number:
// - The extended value
// - The extended value plus one step
// - The extended value minus one step
// Pick the value out of the possible values that is closest to `recent`.
let result = [
expanded_value,
expanded_value + step,
expanded_value.wrapping_sub(step),
]
.iter()
.copied()
.min_by_key(|&value| value.abs_diff(recent))
.unwrap();
// Just because: Check that the result matches the passed-in value in the low bits
assert_eq!(
result & SequenceNumber::from(u32::MAX),
SequenceNumber::from(value),
);
result
}
#[cfg(test)]
mod test {
use super::XCBConnection;
use std::ffi::CString;
#[test]
fn xcb_connect_smoke_test() {
// in cfg(test), raw_ffi does not call XCB, but instead uses a mock. This test calls into
// that mock and tests a bit of XCBConnection.
let str = CString::new("display name").unwrap();
let (_conn, screen) = XCBConnection::connect(Some(&str)).expect("Failed to 'connect'");
assert_eq!(screen, 0);
}
#[test]
fn reconstruct_full_sequence() {
use super::reconstruct_full_sequence_impl;
let max32 = u32::MAX;
let max32_: u64 = max32.into();
let max32_p1 = max32_ + 1;
let large_offset = max32_p1 * u64::from(u16::MAX);
for &(recent, value, expected) in &[
(0, 0, 0),
(0, 10, 10),
// This one is a special case: Technically, -1 is closer and should be reconstructed,
// but -1 does not fit into an unsigned integer.
(0, max32, max32_),
(max32_, 0, max32_p1),
(max32_, 10, max32_p1 + 10),
(max32_, max32, max32_),
(max32_p1, 0, max32_p1),
(max32_p1, 10, max32_p1 + 10),
(max32_p1, max32, max32_),
(large_offset | 0xdead_cafe, 0, large_offset + max32_p1),
(large_offset | 0xdead_cafe, max32, large_offset + max32_),
(0xabcd_1234_5678, 0xf000_0000, 0xabcc_f000_0000),
(0xabcd_8765_4321, 0xf000_0000, 0xabcd_f000_0000),
] {
let actual = reconstruct_full_sequence_impl(recent, value);
assert_eq!(
actual, expected,
"reconstruct({recent:x}, {value:x}) == {expected:x}, but was {actual:x}"
);
}
}
}

View File

@@ -0,0 +1,70 @@
//! Management of pending errors for the XCB connection.
//!
//! We add our own error tracking ontop of what XCB already provides. For this reason, this module
//! contains a struct for tracking requests that were send and also tracking errors that were
//! received, but not yet given to the user of this library.
use std::cmp::Reverse;
use std::collections::{BinaryHeap, VecDeque};
use std::sync::Mutex;
use super::{Buffer, XCBConnection};
use x11rb_protocol::SequenceNumber;
#[derive(Debug, Default)]
struct PendingErrorsInner {
in_flight: BinaryHeap<Reverse<SequenceNumber>>,
pending: VecDeque<(SequenceNumber, Buffer)>,
}
/// A management struct for pending X11 errors
#[derive(Debug, Default)]
pub(crate) struct PendingErrors {
inner: Mutex<PendingErrorsInner>,
}
impl PendingErrors {
pub(crate) fn append_error(&self, error: (SequenceNumber, Buffer)) {
self.inner.lock().unwrap().pending.push_back(error)
}
pub(crate) fn discard_reply(&self, sequence: SequenceNumber) {
self.inner.lock().unwrap().in_flight.push(Reverse(sequence));
}
pub(crate) fn get(&self, conn: &XCBConnection) -> Option<(SequenceNumber, Buffer)> {
let mut inner = self.inner.lock().unwrap();
// Check if we already have an element at hand
let err = inner.pending.pop_front();
if err.is_some() {
return err;
}
// Check if any of the still in-flight responses got a reply/error
while let Some(&Reverse(seqno)) = inner.in_flight.peek() {
let result = match conn.poll_for_reply(seqno) {
Err(()) => {
// This request was not answered/errored yet, so later request will not
// have answers as well.
return None;
}
Ok(reply) => reply,
};
let seqno2 = inner.in_flight.pop();
assert_eq!(Some(Reverse(seqno)), seqno2);
if let Some(result) = result {
// Is this an error?
if result[0] == 0 {
return Some((seqno, result));
} else {
// It's a reply, just ignore it
}
}
}
None
}
}

194
vendor/x11rb/src/xcb_ffi/raw_ffi/ffi.rs vendored Normal file
View File

@@ -0,0 +1,194 @@
//! The code in this module allows to call libxcb's C functions.
//!
//! At its heart, this module only contains an `extern "C"` block that defines the C functions so
//! that they can be called from Rust.
//!
//! However, this module also contains the implementation of the `dl-libxcb` features. When this
//! future is enabled, we do not link against libxcb, but instead use `libloading` to load
//! `libxcb.so` at runtime. Most of the code is actually responsible for this later feature.
use super::{
c_char, c_int, c_uint, c_void, iovec, xcb_connection_t, xcb_generic_error_t,
xcb_generic_event_t, xcb_protocol_request_t, xcb_setup_t, xcb_void_cookie_t,
};
#[cfg(feature = "dl-libxcb")]
pub(crate) mod libxcb_library {
use super::LibxcbFuncs;
use crate::errors::LibxcbLoadError;
pub(super) struct LibxcbLibrary {
// Needed to keep the library loaded
_library: libloading::Library,
pub(super) funcs: LibxcbFuncs,
}
impl LibxcbLibrary {
/// # Safety
///
/// The functions pointers in `funcs` do not have lifetime,
/// but they must not outlive the returned result.
#[cold]
#[inline(never)]
unsafe fn load() -> Result<Self, LibxcbLoadError> {
// TODO: Names for non-unix platforms
#[cfg(not(unix))]
compile_error!("dl-libxcb feature is not supported on non-unix");
#[cfg(all(unix, target_os = "linux"))]
const LIB_NAME: &str = "libxcb.so.1";
// libtool turns -version-info differently into SONAMES on NetBSD.
// Also, the library is apparently not in the default search path, hence use a full path.
#[cfg(all(unix, target_os = "netbsd"))]
const LIB_NAME: &str = "/usr/X11R7/lib/libxcb.so.2";
// If we do not know anything, just assume libxcb.so and hope for the best.
// This is actually the right thing to do on OpenBSD since the dynamic linker then does
// some magic to find the right SONAME.
#[cfg(all(unix, not(any(target_os = "linux", target_os = "netbsd"))))]
const LIB_NAME: &str = "libxcb.so";
let library = libloading::Library::new(LIB_NAME)
.map_err(|e| LibxcbLoadError::OpenLibError(LIB_NAME.into(), e.to_string()))?;
let funcs = LibxcbFuncs::new(&library).map_err(|(symbol, e)| {
LibxcbLoadError::GetSymbolError(symbol.into(), e.to_string())
})?;
Ok(Self {
_library: library,
funcs,
})
}
}
use once_cell::sync::Lazy;
static LIBXCB_LIBRARY: Lazy<Result<LibxcbLibrary, LibxcbLoadError>> =
Lazy::new(|| unsafe { LibxcbLibrary::load() });
pub(super) fn get_libxcb() -> &'static LibxcbLibrary {
#[cold]
#[inline(never)]
fn failed(e: &LibxcbLoadError) -> ! {
panic!("failed to load libxcb: {e}");
}
match *LIBXCB_LIBRARY {
Ok(ref library) => library,
Err(ref e) => failed(e),
}
}
/// Tries to dynamically load libxcb, returning an error on failure.
///
/// It is not required to call this function, as libxcb will be lazily loaded.
/// However, if a lazy load fails, a panic will be raised, missing the chance
/// to (nicely) handle the error.
///
/// It is safe to call this function more than once from the same or different
/// threads. Only the first call will try to load libxcb, subsequent calls will
/// always return the same result.
pub fn load_libxcb() -> Result<(), LibxcbLoadError> {
match Lazy::force(&LIBXCB_LIBRARY) {
Ok(_) => Ok(()),
Err(e) => Err(e.clone()),
}
}
}
macro_rules! make_ffi_fn_defs {
{
$(
$(#[$fn_attr:meta])*
fn $fn_name:ident($($fn_arg_name:ident: $fn_arg_type:ty),*) $(-> $fn_ret_ty:ty)?;
)*
} => {
#[cfg(not(feature = "dl-libxcb"))]
#[link(name = "xcb")]
extern "C" {
$(
$(#[$fn_attr])*
pub(crate) fn $fn_name($($fn_arg_name: $fn_arg_type),*) $(-> $fn_ret_ty)?;
)*
}
#[cfg(feature = "dl-libxcb")]
struct LibxcbFuncs {
$(
$(#[$fn_attr])*
$fn_name: unsafe extern "C" fn($($fn_arg_name: $fn_arg_type),*) $(-> $fn_ret_ty)?,
)*
}
#[cfg(feature = "dl-libxcb")]
impl LibxcbFuncs {
unsafe fn new(library: &libloading::Library) -> Result<Self, (&'static [u8], libloading::Error)> {
Ok(Self {
$($fn_name: {
let symbol_name = concat!(stringify!($fn_name), "\0").as_bytes();
*library.get(symbol_name).map_err(|e| (stringify!($fn_name).as_bytes(), e))?
},)*
})
}
}
$(
#[cfg(feature = "dl-libxcb")]
$(#[$fn_attr])*
pub(crate) unsafe fn $fn_name($($fn_arg_name: $fn_arg_type),*) $(-> $fn_ret_ty)? {
(libxcb_library::get_libxcb().funcs.$fn_name)($($fn_arg_name),*)
}
)*
};
}
make_ffi_fn_defs! {
// From xcb.h
fn xcb_flush(c: *mut xcb_connection_t) -> c_int;
fn xcb_get_maximum_request_length(c: *mut xcb_connection_t) -> u32;
fn xcb_prefetch_maximum_request_length(c: *mut xcb_connection_t);
fn xcb_wait_for_event(c: *mut xcb_connection_t) -> *mut xcb_generic_event_t;
fn xcb_poll_for_event(c: *mut xcb_connection_t) -> *mut xcb_generic_event_t;
fn xcb_request_check(
c: *mut xcb_connection_t,
void_cookie: xcb_void_cookie_t
) -> *mut xcb_generic_error_t;
fn xcb_discard_reply64(c: *mut xcb_connection_t, sequence: u64);
fn xcb_get_setup(c: *mut xcb_connection_t) -> *const xcb_setup_t;
#[cfg(unix)]
fn xcb_get_file_descriptor(c: *mut xcb_connection_t) -> c_int;
fn xcb_connection_has_error(c: *mut xcb_connection_t) -> c_int;
fn xcb_disconnect(c: *mut xcb_connection_t);
fn xcb_connect(
displayname: *const c_char,
screenp: *mut c_int
) -> *mut xcb_connection_t;
fn xcb_generate_id(c: *mut xcb_connection_t) -> u32;
// From xcbext.h
fn xcb_send_request64(
c: *mut xcb_connection_t,
flags: c_int,
vector: *mut iovec,
request: *const xcb_protocol_request_t
) -> u64;
#[cfg(unix)]
fn xcb_send_request_with_fds64(
c: *mut xcb_connection_t,
flags: c_int,
vector: *mut iovec,
request: *const xcb_protocol_request_t,
num_fds: c_uint,
fds: *mut c_int
) -> u64;
fn xcb_wait_for_reply64(
c: *mut xcb_connection_t,
request: u64,
e: *mut *mut xcb_generic_error_t
) -> *mut c_void;
fn xcb_poll_for_reply64(
c: *mut xcb_connection_t,
request: u64,
reply: *mut *mut c_void,
error: *mut *mut xcb_generic_error_t
) -> c_int;
}

155
vendor/x11rb/src/xcb_ffi/raw_ffi/mod.rs vendored Normal file
View File

@@ -0,0 +1,155 @@
//! The low-level foreign function interface to interact with libxcb.
//!
//! This module contains some `#[repr(C)]` type definitions that match libxcb's definitions. The
//! actual functions are defined in the `ffi` submodule. There is also a `test` submodule that
//! contains a mock of the interface that is used for unit tests.
use std::ptr::NonNull;
#[cfg(not(all(test, unix)))]
use libc::c_void;
#[cfg(unix)]
pub(crate) use libc::iovec;
use libc::{c_char, c_int, c_uint};
// As defined in xcb_windefs.h
#[cfg(not(unix))]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub(crate) struct iovec {
pub(crate) iov_base: *mut c_void,
pub(crate) iov_len: c_int,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_connection_t {
_unused: [u8; 0],
}
#[derive(Debug)]
#[doc(hidden)]
pub struct XcbConnectionWrapper {
ptr: NonNull<xcb_connection_t>,
should_drop: bool,
}
unsafe impl as_raw_xcb_connection::AsRawXcbConnection for XcbConnectionWrapper {
fn as_raw_xcb_connection(&self) -> *mut as_raw_xcb_connection::xcb_connection_t {
self.ptr.as_ptr().cast()
}
}
// libxcb is fully thread-safe (well, except for xcb_disconnect()), so the following is
// actually fine and safe:
unsafe impl Send for XcbConnectionWrapper {}
unsafe impl Sync for XcbConnectionWrapper {}
impl Drop for XcbConnectionWrapper {
fn drop(&mut self) {
if self.should_drop {
unsafe {
xcb_disconnect(self.ptr.as_ptr());
}
}
}
}
impl XcbConnectionWrapper {
pub(crate) unsafe fn new(ptr: *mut xcb_connection_t, should_drop: bool) -> Self {
Self {
ptr: NonNull::new_unchecked(ptr),
should_drop,
}
}
pub(crate) fn as_ptr(&self) -> *mut xcb_connection_t {
self.ptr.as_ptr()
}
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_generic_event_t {
pub(crate) response_type: u8,
pub(crate) pad0: u8,
pub(crate) sequence: u16,
pub(crate) pad: [u32; 7],
pub(crate) full_sequence: u32,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_generic_error_t {
pub(crate) response_type: u8,
pub(crate) error_code: u8,
pub(crate) sequence: u16,
pub(crate) resource_id: u32,
pub(crate) minor_code: u16,
pub(crate) major_code: u8,
pub(crate) pad0: u8,
pub(crate) pad: [u32; 5],
pub(crate) full_sequence: u32,
}
#[derive(Clone, Copy)]
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_void_cookie_t {
pub(crate) sequence: c_uint,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_extension_t {
pub(crate) name: *const c_char,
pub(crate) global_id: c_int,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_protocol_request_t {
pub(crate) count: usize,
pub(crate) ext: *mut xcb_extension_t,
pub(crate) opcode: u8,
pub(crate) isvoid: u8,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub(crate) struct xcb_setup_t {
_unused: [u8; 0],
}
pub(crate) mod connection_errors {
use std::os::raw::c_int;
pub(crate) const ERROR: c_int = 1;
pub(crate) const EXT_NOTSUPPORTED: c_int = 2;
pub(crate) const MEM_INSUFFICIENT: c_int = 3;
pub(crate) const REQ_LEN_EXCEED: c_int = 4;
pub(crate) const PARSE_ERR: c_int = 5;
pub(crate) const INVALID_SCREEN: c_int = 6;
pub(crate) const FDPASSING_FAILED: c_int = 7;
}
pub(crate) mod send_request_flags {
use libc::c_int;
pub(crate) const CHECKED: c_int = 1;
pub(crate) const RAW: c_int = 2;
//pub(crate) const DISCARD_REPLY: c_int = 4;
pub(crate) const REPLY_FDS: c_int = 8;
}
#[cfg(not(test))]
mod ffi;
#[cfg(not(test))]
pub(crate) use ffi::*;
#[cfg(test)]
mod test;
#[cfg(test)]
pub(crate) use test::*;

156
vendor/x11rb/src/xcb_ffi/raw_ffi/test.rs vendored Normal file
View File

@@ -0,0 +1,156 @@
//! A mock of libxcb that is used by the unit tests in [`x11rb::xcb_ffi`].
use std::ffi::CStr;
use libc::{c_char, c_int, c_uint, c_void};
use super::{
iovec, xcb_connection_t, xcb_generic_error_t, xcb_generic_event_t, xcb_protocol_request_t,
xcb_setup_t, xcb_void_cookie_t,
};
use crate::protocol::xproto::{ImageOrder, Setup};
use crate::x11_utils::Serialize;
#[repr(C)]
struct ConnectionMock {
error: c_int,
setup: Vec<u8>,
}
// From xcb.h
pub(crate) unsafe fn xcb_flush(_c: *mut xcb_connection_t) -> c_int {
unimplemented!();
}
pub(crate) unsafe fn xcb_get_maximum_request_length(_c: *mut xcb_connection_t) -> u32 {
unimplemented!();
}
pub(crate) unsafe fn xcb_prefetch_maximum_request_length(_c: *mut xcb_connection_t) {
unimplemented!();
}
pub(crate) unsafe fn xcb_wait_for_event(_c: *mut xcb_connection_t) -> *mut xcb_generic_event_t {
unimplemented!();
}
pub(crate) unsafe fn xcb_poll_for_event(_c: *mut xcb_connection_t) -> *mut xcb_generic_event_t {
unimplemented!();
}
pub(crate) unsafe fn xcb_request_check(
_c: *mut xcb_connection_t,
_void_cookie: xcb_void_cookie_t,
) -> *mut xcb_generic_error_t {
unimplemented!();
}
pub(crate) unsafe fn xcb_discard_reply64(_c: *mut xcb_connection_t, _sequence: u64) {
unimplemented!();
}
pub(crate) unsafe fn xcb_get_setup(c: *mut xcb_connection_t) -> *const xcb_setup_t {
// The pointer is suitable aligned since our xcb_connect() mock above created it
#[allow(clippy::cast_ptr_alignment)]
((*(c as *const ConnectionMock)).setup.as_ptr() as _)
}
#[cfg(unix)]
pub(crate) unsafe fn xcb_get_file_descriptor(_c: *mut xcb_connection_t) -> c_int {
unimplemented!();
}
pub(crate) unsafe fn xcb_connection_has_error(c: *mut xcb_connection_t) -> c_int {
// The pointer is suitable aligned since our xcb_connect() mock above created it
#[allow(clippy::cast_ptr_alignment)]
(*(c as *const ConnectionMock)).error
}
pub(crate) unsafe fn xcb_disconnect(c: *mut xcb_connection_t) {
// The pointer is suitable aligned since our xcb_connect() mock above created it
#[allow(clippy::cast_ptr_alignment)]
let _ = Box::from_raw(c as *mut ConnectionMock);
}
pub(crate) unsafe fn xcb_connect(
displayname: *const c_char,
screenp: *mut c_int,
) -> *mut xcb_connection_t {
// Test that the provided displayname is correct
assert_eq!(
CStr::from_ptr(displayname).to_str().unwrap(),
"display name",
"Did not get the expected displayname",
);
std::ptr::write(screenp, 0);
let length_field = 10;
let setup = Setup {
status: 0,
protocol_major_version: 0,
protocol_minor_version: 0,
length: length_field,
release_number: 0,
resource_id_base: 0,
resource_id_mask: 0,
motion_buffer_size: 0,
maximum_request_length: 0,
image_byte_order: ImageOrder::LSB_FIRST,
bitmap_format_bit_order: ImageOrder::LSB_FIRST,
bitmap_format_scanline_unit: 0,
bitmap_format_scanline_pad: 0,
min_keycode: 0,
max_keycode: 0,
vendor: Default::default(),
pixmap_formats: Default::default(),
roots: Default::default(),
};
let setup = setup.serialize();
assert_eq!(setup.len(), 4 * length_field as usize);
let mock = ConnectionMock { error: 0, setup };
Box::into_raw(Box::new(mock)) as _
}
pub(crate) unsafe fn xcb_generate_id(_c: *mut xcb_connection_t) -> u32 {
unimplemented!();
}
// From xcbext.h
pub(crate) unsafe fn xcb_send_request64(
_c: *mut xcb_connection_t,
_flags: c_int,
_vector: *mut iovec,
_request: *const xcb_protocol_request_t,
) -> u64 {
unimplemented!();
}
#[cfg(unix)]
pub(crate) unsafe fn xcb_send_request_with_fds64(
_c: *mut xcb_connection_t,
_flags: c_int,
_vector: *mut iovec,
_request: *const xcb_protocol_request_t,
_num_fds: c_uint,
_fds: *mut c_int,
) -> u64 {
unimplemented!();
}
pub(crate) unsafe fn xcb_wait_for_reply64(
_c: *mut xcb_connection_t,
_request: u64,
_e: *mut *mut xcb_generic_error_t,
) -> *mut c_void {
unimplemented!();
}
pub(crate) unsafe fn xcb_poll_for_reply64(
_c: *mut xcb_connection_t,
_request: u64,
_reply: *mut *mut c_void,
_error: *mut *mut xcb_generic_error_t,
) -> c_int {
unimplemented!();
}

237
vendor/x11rb/tests/multithread_test.rs vendored Normal file
View File

@@ -0,0 +1,237 @@
use std::sync::Arc;
use x11rb::connection::Connection as _;
use x11rb::protocol::xproto::{
ClientMessageEvent, ConnectionExt as _, EventMask, CLIENT_MESSAGE_EVENT,
};
// Regression test for https://github.com/psychon/x11rb/issues/231
#[test]
fn multithread_test() {
let conn = fake_stream::connect().unwrap();
let conn = Arc::new(conn);
// Auxiliary thread: send requests and wait for replies
let conn1 = conn.clone();
let join = std::thread::spawn(move || {
// Bug #231 sometimes caused `reply` to hang forever.
// Send a huge amount of requests and wait for the reply
// to check if it hangs at some point.
for i in 1..=1_000_000 {
let cookie = conn1.get_input_focus().unwrap();
cookie.reply().unwrap();
if (i % 50_000) == 0 {
eprintln!("{i}");
}
}
eprintln!("all replies received successfully");
// Just anything, we don't care
let event = ClientMessageEvent::new(32, 0, 1u32, [0, 0, 0, 0, 0]);
conn1
.send_event(false, 0u32, EventMask::NO_EVENT, event)
.unwrap();
conn1.flush().unwrap();
});
// Main thread: wait for events until finished
loop {
let event = conn.wait_for_raw_event().unwrap();
if event[0] == CLIENT_MESSAGE_EVENT {
break;
}
}
join.join().unwrap();
}
/// Implementations of `Read` and `Write` that do enough for the test to work.
mod fake_stream {
use std::io::{Error, ErrorKind};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Condvar, Mutex};
use x11rb::errors::ConnectError;
use x11rb::protocol::xproto::{
ImageOrder, Setup, CLIENT_MESSAGE_EVENT, GET_INPUT_FOCUS_REQUEST, SEND_EVENT_REQUEST,
};
use x11rb::rust_connection::{PollMode, RustConnection, Stream};
use x11rb::utils::RawFdContainer;
use x11rb_protocol::SequenceNumber;
/// Create a new `RustConnection` connected to a fake stream
pub(crate) fn connect() -> Result<RustConnection<FakeStream>, ConnectError> {
let setup = Setup {
status: 0,
protocol_major_version: 0,
protocol_minor_version: 0,
length: 0,
release_number: 0,
resource_id_base: 0,
resource_id_mask: 0xff,
motion_buffer_size: 0,
maximum_request_length: 0,
image_byte_order: ImageOrder::LSB_FIRST,
bitmap_format_bit_order: ImageOrder::LSB_FIRST,
bitmap_format_scanline_unit: 0,
bitmap_format_scanline_pad: 0,
min_keycode: 0,
max_keycode: 0,
vendor: Vec::new(),
pixmap_formats: Vec::new(),
roots: Vec::new(),
};
let stream = fake_stream();
RustConnection::for_connected_stream(stream, setup)
}
/// Get a pair of fake streams that are connected to each other
fn fake_stream() -> FakeStream {
let (send, recv) = channel();
let pending = Vec::new();
FakeStream {
inner: Mutex::new(FakeStreamInner {
read: FakeStreamRead { recv, pending },
write: FakeStreamWrite {
send,
seqno: 0,
skip: 0,
},
}),
condvar: Condvar::new(),
}
}
/// A packet that still needs to be read from FakeStreamRead
#[derive(Debug)]
enum Packet {
GetInputFocusReply(SequenceNumber),
Event,
}
impl Packet {
fn to_raw(&self) -> Vec<u8> {
match self {
Packet::GetInputFocusReply(seqno) => {
let seqno = (*seqno as u16).to_ne_bytes();
let mut reply = vec![0; 32];
reply[0] = 1; // This is a reply
reply[2..4].copy_from_slice(&seqno);
reply
}
Packet::Event => {
let mut reply = vec![0; 32];
reply[0] = CLIENT_MESSAGE_EVENT;
reply
}
}
}
}
#[derive(Debug)]
pub(crate) struct FakeStream {
inner: Mutex<FakeStreamInner>,
condvar: Condvar,
}
#[derive(Debug)]
struct FakeStreamInner {
read: FakeStreamRead,
write: FakeStreamWrite,
}
#[derive(Debug)]
struct FakeStreamRead {
recv: Receiver<Packet>,
pending: Vec<u8>,
}
#[derive(Debug)]
pub(crate) struct FakeStreamWrite {
send: Sender<Packet>,
seqno: SequenceNumber,
skip: usize,
}
impl Stream for FakeStream {
fn poll(&self, mode: PollMode) -> std::io::Result<()> {
if mode.writable() {
Ok(())
} else {
let mut inner = self.inner.lock().unwrap();
loop {
if inner.read.pending.is_empty() {
let recv_result = inner.read.recv.try_recv();
match recv_result {
Ok(packet) => {
inner.read.pending.extend(packet.to_raw());
return Ok(());
}
Err(std::sync::mpsc::TryRecvError::Empty) => {
inner = self.condvar.wait(inner).unwrap();
}
Err(std::sync::mpsc::TryRecvError::Disconnected) => unreachable!(),
}
} else {
return Ok(());
}
}
}
}
fn read(
&self,
buf: &mut [u8],
_fd_storage: &mut Vec<RawFdContainer>,
) -> std::io::Result<usize> {
let mut inner = self.inner.lock().unwrap();
if inner.read.pending.is_empty() {
let recv_result = inner.read.recv.try_recv();
match recv_result {
Ok(packet) => inner.read.pending.extend(packet.to_raw()),
Err(std::sync::mpsc::TryRecvError::Empty) => {
return Err(Error::new(ErrorKind::WouldBlock, "Would block"));
}
Err(std::sync::mpsc::TryRecvError::Disconnected) => unreachable!(),
}
}
let len = inner.read.pending.len().min(buf.len());
buf[..len].copy_from_slice(&inner.read.pending[..len]);
inner.read.pending.drain(..len);
Ok(len)
}
fn write(&self, buf: &[u8], fds: &mut Vec<RawFdContainer>) -> std::io::Result<usize> {
assert!(fds.is_empty());
let mut inner = self.inner.lock().unwrap();
if inner.write.skip > 0 {
assert_eq!(inner.write.skip, buf.len());
inner.write.skip = 0;
return Ok(buf.len());
}
inner.write.seqno += 1;
match buf[0] {
GET_INPUT_FOCUS_REQUEST => inner
.write
.send
.send(Packet::GetInputFocusReply(inner.write.seqno))
.unwrap(),
SEND_EVENT_REQUEST => inner.write.send.send(Packet::Event).unwrap(),
_ => unimplemented!(),
}
// Compute how much of the package was not yet received
inner.write.skip = usize::from(u16::from_ne_bytes([buf[2], buf[3]])) * 4 - buf.len();
self.condvar.notify_all();
Ok(buf.len())
}
}
}

342
vendor/x11rb/tests/regression_tests.rs vendored Normal file
View File

@@ -0,0 +1,342 @@
use std::cell::RefCell;
use std::io::IoSlice;
use std::ops::Deref;
use x11rb::connection::{
compute_length_field, BufWithFds, ReplyOrError, RequestConnection, RequestKind,
};
use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie};
use x11rb::errors::{ConnectionError, ParseError, ReplyError};
use x11rb::protocol::xproto::{
ClientMessageData, ConnectionExt, KeymapNotifyEvent, Segment, SetupAuthenticate,
};
use x11rb::utils::RawFdContainer;
use x11rb::x11_utils::{ExtensionInformation, Serialize, TryParse, TryParseFd};
use x11rb_protocol::{DiscardMode, SequenceNumber};
#[derive(Debug)]
struct SavedRequest {
has_reply: bool,
data: Vec<u8>,
}
impl SavedRequest {
fn new(has_reply: bool, data: &[IoSlice]) -> SavedRequest {
let data = data
.iter()
.flat_map(|slice| slice.deref())
.copied()
.collect::<Vec<_>>();
SavedRequest { has_reply, data }
}
}
#[derive(Debug, Default)]
struct FakeConnection(RefCell<Vec<SavedRequest>>);
impl FakeConnection {
fn check_requests(&self, expected: &[(bool, Vec<u8>)]) {
let vec = self.0.borrow();
for (expected, actual) in expected.iter().zip(vec.iter()) {
assert_eq!(expected.0, actual.has_reply);
assert_eq!(actual.data, expected.1);
}
assert_eq!(expected.len(), vec.len());
}
fn internal_send_request(
&self,
bufs: &[IoSlice],
fds: Vec<RawFdContainer>,
) -> Result<SequenceNumber, ConnectionError> {
assert_eq!(fds.len(), 0);
let mut storage = Default::default();
let bufs = compute_length_field(self, bufs, &mut storage)?;
self.0.borrow_mut().push(SavedRequest::new(false, bufs));
Ok(0)
}
}
impl RequestConnection for FakeConnection {
type Buf = Vec<u8>;
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice],
fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
Ok(Cookie::new(self, self.internal_send_request(bufs, fds)?))
}
fn send_request_with_reply_with_fds<R>(
&self,
_bufs: &[IoSlice],
_fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
bufs: &[IoSlice],
fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
Ok(VoidCookie::new(
self,
self.internal_send_request(bufs, fds)?,
))
}
fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) {
// Just ignore this
}
fn prefetch_extension_information(
&self,
_extension_name: &'static str,
) -> Result<(), ConnectionError> {
unimplemented!();
}
fn extension_information(
&self,
_extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
_sequence: SequenceNumber,
) -> Result<ReplyOrError<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply(
&self,
_sequence: SequenceNumber,
) -> Result<Option<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Vec<u8>>, Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_sequence: SequenceNumber,
) -> Result<Option<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
// Must be at least 4 * 2^16 so that we can test BIG-REQUESTS
2usize.pow(19)
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn parse_error(&self, _error: &[u8]) -> Result<x11rb::x11_utils::X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _event: &[u8]) -> Result<x11rb::protocol::Event, ParseError> {
unimplemented!()
}
}
#[test]
fn test_poly_segment() -> Result<(), ReplyError> {
let conn = FakeConnection::default();
let drawable = 42;
let gc = 0x1337;
let segments = [
Segment {
x1: 1,
y1: 2,
x2: 3,
y2: 4,
},
Segment {
x1: 5,
y1: 6,
x2: 7,
y2: 8,
},
];
let length: u16 = (12 + segments.len() * 8) as u16 / 4;
conn.poly_segment(drawable, gc, &segments)?;
let mut expected = vec![
x11rb::protocol::xproto::POLY_SEGMENT_REQUEST,
0, // padding
];
expected.extend(length.to_ne_bytes()); // length, not in the xml
expected.extend(drawable.to_ne_bytes());
expected.extend(gc.to_ne_bytes());
// Segments
for x in 1u16..9u16 {
expected.extend(x.to_ne_bytes());
}
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_big_requests() -> Result<(), ConnectionError> {
let conn = FakeConnection::default();
let big_buffer = [0; (1 << 18) + 1];
let drawable: u32 = 42;
let gc: u32 = 0x1337;
let x: i16 = 21;
let y: i16 = 7;
let padding = 3; // big_buffer's size rounded up to a multiple of 4
let big_request_length_field = 4;
let length: u32 = (16 + big_request_length_field + big_buffer.len() as u32 + padding) / 4;
conn.poly_text16(drawable, gc, x, y, &big_buffer)?;
let mut expected = vec![
x11rb::protocol::xproto::POLY_TEXT16_REQUEST,
// padding
0,
// Length of zero: we use big requests
0,
0,
];
// Actual length
expected.extend(length.to_ne_bytes());
expected.extend(drawable.to_ne_bytes());
expected.extend(gc.to_ne_bytes());
expected.extend(x.to_ne_bytes());
expected.extend(y.to_ne_bytes());
expected.extend(big_buffer.iter());
expected.extend((0..padding).map(|_| 0));
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_too_large_request() {
let conn = FakeConnection::default();
let big_buffer = [0; (1 << 19) + 1];
let drawable: u32 = 42;
let gc: u32 = 0x1337;
let x: i16 = 21;
let y: i16 = 7;
let res = conn.poly_text16(drawable, gc, x, y, &big_buffer);
match res.unwrap_err() {
ConnectionError::MaximumRequestLengthExceeded => {}
err => panic!("Wrong error: {err:?}"),
};
}
#[test]
fn test_send_event() -> Result<(), ConnectionError> {
// Prepare the event
let buffer: [u8; 32] = [
11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30,
];
let event = KeymapNotifyEvent::try_parse(&buffer[..])?.0;
// "Send" it
let conn = FakeConnection::default();
let propagate = true;
let destination: u32 = 0x1337;
let event_mask = x11rb_protocol::protocol::xproto::EventMask::BUTTON3_MOTION;
conn.send_event(propagate, destination, event_mask, event)?;
let mut expected = vec![x11rb::protocol::xproto::SEND_EVENT_REQUEST, propagate as _];
expected.extend(((12u16 + 32u16) / 4).to_ne_bytes());
expected.extend(destination.to_ne_bytes());
expected.extend(u32::from(event_mask).to_ne_bytes());
expected.extend(buffer.iter());
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_get_keyboard_mapping() -> Result<(), ConnectionError> {
let conn = FakeConnection::default();
let cookie = conn.get_keyboard_mapping(1, 2)?;
// Prevent call to discard_reply(), we only check request sending
std::mem::forget(cookie);
let mut expected = Vec::new();
let length: u16 = 2;
expected.push(101); // request major code
expected.push(0); // padding
expected.extend(length.to_ne_bytes()); // length, not in the xml
expected.push(1); // first keycode
expected.push(2); // length
expected.extend([0, 0]); // padding
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_client_message_data_parse() {
let short_array = [0, 0, 0];
let err = ClientMessageData::try_parse(&short_array);
assert!(err.is_err());
assert_eq!(err.unwrap_err(), ParseError::InsufficientData);
}
#[test]
fn test_set_modifier_mapping() -> Result<(), ConnectionError> {
let conn = FakeConnection::default();
let cookie = conn.set_modifier_mapping(&(1..17).collect::<Vec<_>>())?;
// Prevent call to discard_reply(), we only check request sending
std::mem::forget(cookie);
let mut expected = Vec::new();
let length: u16 = 5;
expected.push(118); // request major code
expected.push(2); // keycodes per modifier
expected.extend(length.to_ne_bytes()); // length, not in the xml
expected.extend(1u8..17u8);
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_serialize_setup_authenticate() {
let setup = SetupAuthenticate {
status: 2,
reason: b"12345678".to_vec(),
};
// At the time of writing, the code generator does not produce the correct code...
let length = 2u16.to_ne_bytes();
let setup_bytes = [
2, 0, 0, 0, 0, 0, length[0], length[1], b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8',
];
assert_eq!(&setup_bytes[..], &setup.serialize()[..]);
}
#[cfg(feature = "xinput")]
#[allow(dead_code)]
fn compile_test(conn: &impl RequestConnection) {
use x11rb::protocol::xinput::{xi_query_device, Device};
let _ = xi_query_device(conn, Device::ALL);
}

276
vendor/x11rb/tests/resource_manager.rs vendored Normal file
View File

@@ -0,0 +1,276 @@
#[cfg(feature = "resource_manager")]
mod test {
use std::fs;
use std::io::IoSlice;
use std::path::{Path, PathBuf};
use x11rb::connection::{
BufWithFds, Connection, DiscardMode, RawEventAndSeqNumber, ReplyOrError, RequestConnection,
RequestKind,
};
use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie};
use x11rb::errors::{ConnectionError, ParseError, ReplyOrIdError};
use x11rb::protocol::xproto::{Screen, Setup};
use x11rb::protocol::Event;
use x11rb::resource_manager::{new_from_default, Database};
use x11rb::utils::RawFdContainer;
use x11rb::x11_utils::{ExtensionInformation, Serialize, TryParse, TryParseFd, X11Error};
use x11rb_protocol::SequenceNumber;
// Most tests in here are based on [1], which is: Copyright © 2016 Ingo Bürk
// [1]: https://github.com/Airblader/xcb-util-xrm/blob/master/tests/tests_database.c
/// Get the path to the `target` directory for the current build.
///
/// This is inspired by cargo:
/// https://github.com/rust-lang/cargo/blob/7302186d7beb2b11bf7366c0aa66269313ebe18f/crates/cargo-test-support/src/paths.rs#L18-L31
fn get_temporary_dir(unique_name: &str) -> PathBuf {
let mut path = std::env::current_exe().unwrap();
while path.file_name().and_then(|n| n.to_str()) != Some("target") {
path.pop();
}
path.push("test_data");
path.push(unique_name);
fs::create_dir_all(&path).unwrap();
path
}
fn write_file(base: impl AsRef<Path>, path: impl AsRef<Path>, content: &[u8]) -> PathBuf {
let mut file_path = PathBuf::from(base.as_ref());
file_path.push(path.as_ref());
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent).unwrap();
}
fs::write(&file_path, content).unwrap();
file_path
}
fn database_from_file(file: impl AsRef<Path>) -> Database {
// I decided against adding something like this to the API...
let file = file.as_ref();
let mut include = Vec::new();
include.extend(b"#include \"");
include.extend(file.file_name().unwrap().to_str().unwrap().bytes());
include.extend(b"\"\n");
Database::new_from_data_with_base_directory(&include, file.parent().unwrap())
}
fn check_db(db: &Database, queries: &[(&str, &[u8])]) {
let mut errors = 0;
for (query, expected) in queries {
let result = db.get_bytes(query, "");
if result != Some(expected) {
eprintln!(
"Queried database for \"{query}\" and expected {expected:?}, but got {result:?}"
);
errors += 1;
}
}
assert_eq!(errors, 0, "Had {errors} errors");
}
#[test]
fn relative_include() {
let dir = get_temporary_dir("relative_include");
let file = write_file(
&dir,
"Xresources1",
b"First: 1\n\n#include \"xresources2\"\n",
);
write_file(
&dir,
"xresources2",
b"#include \"sub/xresources3\"\nSecond: 2\n",
);
write_file(&dir, "sub/xresources3", b"Third: 3\n");
let db = database_from_file(file);
check_db(&db, &[("First", b"1"), ("Second", b"2"), ("Third", b"3")]);
}
#[test]
fn include_loop() {
let dir = get_temporary_dir("include_loop");
let file = write_file(
dir,
"loop.xresources",
b"First: 1\n! Provoke an endless chain of self-inclusion\n#include \"loop.xresources\"\nSecond: 2\n",
);
let db = database_from_file(file);
check_db(&db, &[("First", b"1")]);
}
#[test]
fn home_resolution() {
let mut dir = get_temporary_dir("home_resolution");
write_file(&dir, ".Xresources", b"First: 1\n");
write_file(&dir, "xenvironment", b"Second: 2\n");
std::env::set_var("HOME", &dir);
dir.push("xenvironment");
std::env::set_var("XENVIRONMENT", dir);
let conn = mock_connection(None);
let db = new_from_default(&conn).unwrap();
check_db(&db, &[("First", b"1"), ("Second", b"2")]);
}
#[test]
fn from_resource_manager() {
let conn = mock_connection(Some(b"First: 1\n*Second: 2\n"));
let db = new_from_default(&conn).unwrap();
check_db(&db, &[("First", b"1"), ("Second", b"2")]);
}
/// Create a mock connection that produces the given answer for queries of the RESOURCE_MANAGER
/// property.
fn mock_connection(resource_manager: Option<&[u8]>) -> impl Connection {
// Ugly way to get a default screen: Parse enough zero bytes
let screen = Screen::try_parse(&[0; 100]).unwrap().0;
let mut setup = Setup::try_parse(&[0; 100]).unwrap().0;
setup.roots.push(screen);
MockConnection(setup, resource_manager.map(|v| v.to_vec()))
}
struct MockConnection(Setup, Option<Vec<u8>>);
impl RequestConnection for MockConnection {
type Buf = Vec<u8>;
fn send_request_with_reply<R>(
&self,
_: &[IoSlice<'_>],
_: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
Ok(Cookie::new(self, 42))
}
fn send_request_with_reply_with_fds<R>(
&self,
_: &[IoSlice<'_>],
_: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
_: &[IoSlice<'_>],
_: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
unimplemented!()
}
fn discard_reply(&self, _: SequenceNumber, _: RequestKind, _: DiscardMode) {
unimplemented!()
}
fn prefetch_extension_information(&self, _: &'static str) -> Result<(), ConnectionError> {
unimplemented!()
}
fn extension_information(
&self,
_: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<Self::Buf>, ConnectionError> {
let value = self.1.as_ref().map(|v| &v[..]).unwrap_or(&[]);
// response type
let mut reply = vec![1];
// format
if value.is_empty() {
reply.push(0);
} else {
reply.push(8);
}
// sequence
(sequence as u16).serialize_into(&mut reply);
// length
0u32.serialize_into(&mut reply);
// type (STRING)
31u32.serialize_into(&mut reply);
// bytes_after
0u32.serialize_into(&mut reply);
(value.len() as u32).serialize_into(&mut reply);
// padding
reply.extend([0; 12].iter().copied());
reply.extend(value);
Ok(ReplyOrError::Reply(reply))
}
fn wait_for_reply(&self, _: SequenceNumber) -> Result<Option<Self::Buf>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Self::Buf>, Self::Buf>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_: SequenceNumber,
) -> Result<Option<Self::Buf>, ConnectionError> {
unimplemented!()
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
unimplemented!()
}
fn parse_error(&self, _: &[u8]) -> Result<X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _: &[u8]) -> Result<Event, ParseError> {
unimplemented!()
}
}
impl Connection for MockConnection {
fn wait_for_raw_event_with_sequence(
&self,
) -> Result<RawEventAndSeqNumber<Self::Buf>, ConnectionError> {
unimplemented!()
}
fn poll_for_raw_event_with_sequence(
&self,
) -> Result<Option<RawEventAndSeqNumber<Self::Buf>>, ConnectionError> {
unimplemented!()
}
fn flush(&self) -> Result<(), ConnectionError> {
unimplemented!()
}
fn setup(&self) -> &Setup {
&self.0
}
fn generate_id(&self) -> Result<u32, ReplyOrIdError> {
unimplemented!()
}
}
}

221
vendor/x11rb/tests/x11_utils.rs vendored Normal file
View File

@@ -0,0 +1,221 @@
use ::std::{
collections::HashMap, io::IoSlice, option::Option as RealOption, result::Result as RealResult,
vec::Vec as RealVec,
};
use ::x11rb::{
atom_manager,
connection::{
BufWithFds, DiscardMode, ReplyOrError, RequestConnection, RequestKind, SequenceNumber,
},
cookie::{Cookie, CookieWithFds, VoidCookie},
errors::{ConnectionError, ParseError, ReplyError},
protocol::xproto::{InternAtomReply, INTERN_ATOM_REQUEST},
utils::RawFdContainer,
x11_utils::{ExtensionInformation, Serialize, TryParse, TryParseFd},
};
// Just to be annoying, overwrite some standard types.
// We want to make sure atom_manager! does not use these directly.
mod std {}
mod x11rb {}
#[allow(dead_code)]
type Vec = ();
#[allow(dead_code)]
type Result = ();
#[allow(dead_code)]
type PhantomData = ();
#[allow(dead_code)]
type Option = ();
atom_manager! {
Atoms: AtomsCookies {
FIRST,
SECOND,
THIRD: b"3rd",
LAST,
}
}
struct AtomFakeConnection {
// Mapping from byte string to the corresponding atom value and sequence number.
// If no entry is found, sending the InternAtom request fails.
// If the entry does not fit into u16, fetching the reply fails.
atoms_and_cookies: HashMap<RealVec<u8>, u32>,
}
impl RequestConnection for AtomFakeConnection {
type Buf = RealVec<u8>;
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice],
_fds: RealVec<RawFdContainer>,
) -> RealResult<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
let bytes: RealVec<u8> = bufs.iter().flat_map(|buf| buf.iter().copied()).collect();
// request type and only-if-exists flag
assert_eq!(bytes[..2], [INTERN_ATOM_REQUEST, 0]);
// We ignore the length field
let name_len = usize::from(u16::from_ne_bytes([bytes[4], bytes[5]]));
let name = &bytes[8..(8 + name_len)];
match self.atoms_and_cookies.get(name) {
// We recycle the atom as the sequence number
Some(&atom) => Ok(Cookie::new(self, atom.into())),
None => Err(ConnectionError::UnsupportedExtension),
}
}
fn send_request_with_reply_with_fds<R>(
&self,
_bufs: &[IoSlice],
_fds: RealVec<RawFdContainer>,
) -> RealResult<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
_bufs: &[IoSlice],
_fds: RealVec<RawFdContainer>,
) -> RealResult<VoidCookie<'_, Self>, ConnectionError> {
unimplemented!()
}
fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) {
// Just ignore this
}
fn prefetch_extension_information(
&self,
_extension_name: &'static str,
) -> RealResult<(), ConnectionError> {
unimplemented!();
}
fn extension_information(
&self,
_extension_name: &'static str,
) -> RealResult<RealOption<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> RealResult<ReplyOrError<RealVec<u8>>, ConnectionError> {
let sequence_u16 = match u16::try_from(sequence) {
Ok(value) => value,
Err(_) => return Err(ConnectionError::UnsupportedExtension),
};
let reply = InternAtomReply {
length: 0,
sequence: sequence_u16,
atom: sequence.try_into().unwrap(),
};
let mut data = reply.serialize().to_vec();
data.extend([0; 32]);
Ok(ReplyOrError::Reply(data))
}
fn wait_for_reply(
&self,
_sequence: SequenceNumber,
) -> RealResult<RealOption<RealVec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_sequence: SequenceNumber,
) -> RealResult<ReplyOrError<BufWithFds<RealVec<u8>>, RealVec<u8>>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_sequence: SequenceNumber,
) -> RealResult<RealOption<RealVec<u8>>, ConnectionError> {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
2usize.pow(16)
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn parse_error(&self, _error: &[u8]) -> RealResult<::x11rb::x11_utils::X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _event: &[u8]) -> RealResult<::x11rb::protocol::Event, ParseError> {
unimplemented!()
}
}
#[test]
fn test_atom_manager_success() {
let conn = AtomFakeConnection {
atoms_and_cookies: [
(b"FIRST".to_vec(), 42),
(b"SECOND".to_vec(), 50),
(b"3rd".to_vec(), 100),
(b"LAST".to_vec(), 200),
]
.into(),
};
let atoms = Atoms::new(&conn).unwrap();
let atoms = atoms.reply().unwrap();
assert_eq!(atoms.FIRST, 42);
assert_eq!(atoms.SECOND, 50);
assert_eq!(atoms.THIRD, 100);
assert_eq!(atoms.LAST, 200);
}
#[test]
fn test_atom_manager_sending_fails() {
let conn = AtomFakeConnection {
atoms_and_cookies: [
(b"FIRST".to_vec(), 42),
(b"3rd".to_vec(), 100),
(b"LAST".to_vec(), 200),
]
.into(),
};
match Atoms::new(&conn) {
// This error is produced in send_request_with_reply() above
Err(ConnectionError::UnsupportedExtension) => {}
Err(err) => panic!("Unexpected error: {err:?}"),
Ok(_) => unreachable!(),
};
}
#[test]
fn test_atom_manager_receiving_fails() {
// A value that does not fit into u16 indicates to AtomFakeConnection that receiving fails
let too_large = u32::from(u16::MAX) * 3;
let conn = AtomFakeConnection {
atoms_and_cookies: [
(b"FIRST".to_vec(), 42),
(b"SECOND".to_vec(), too_large),
(b"3rd".to_vec(), 100),
(b"LAST".to_vec(), 200),
]
.into(),
};
let atoms = Atoms::new(&conn).unwrap();
match atoms.reply() {
// This error is produced in wait_for_reply_or_raw_error() above
Err(ReplyError::ConnectionError(ConnectionError::UnsupportedExtension)) => {}
result => panic!("Unexpected result: {result:?}"),
}
}