x11rb-0.13.0/.cargo_vcs_info.json0000644000000001430000000000100120500ustar { "git": { "sha1": "4b602657881fd66b4e6bc847fd8fe36ab653f570" }, "path_in_vcs": "x11rb" }x11rb-0.13.0/Cargo.lock0000644000000261200000000000100100260ustar # 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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5f312b0a56c5cdf967c0aeb67f6289603354951683bc97ddc595ab974ba9aa" [[package]] name = "bitflags" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "concurrent-queue" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "errno" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "gethostname" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" dependencies = [ "libc", "windows-targets 0.48.5", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "linux-raw-sys" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[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.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[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.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "polling" version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", "rustix", "tracing", "windows-sys 0.52.0", ] [[package]] name = "rustix" version = "0.38.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfeae074e687625746172d639330f1de242a178bf3189b51e35a7a21573513ac" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] [[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.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "thread_local" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ "cfg-if", "once_cell", ] [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 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.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "nu-ansi-term", "sharded-slab", "smallvec", "thread_local", "tracing-core", "tracing-log", ] [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[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-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.0", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm 0.52.0", "windows_aarch64_msvc 0.52.0", "windows_i686_gnu 0.52.0", "windows_i686_msvc 0.52.0", "windows_x86_64_gnu 0.52.0", "windows_x86_64_gnullvm 0.52.0", "windows_x86_64_msvc 0.52.0", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "x11rb" version = "0.13.0" dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", "libloading", "once_cell", "polling", "rustix", "tracing", "tracing-subscriber", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" x11rb-0.13.0/Cargo.toml0000644000000100620000000000100100470ustar # 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.63" name = "x11rb" version = "0.13.0" authors = [ "Uli Schlachter ", "Eduardo Sánchez Muñoz ", "notgull ", ] 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 [[example]] name = "generic_events" required-features = ["present"] [[example]] name = "shared_memory" required-features = [ "libc", "shm", ] [[example]] name = "xeyes" required-features = ["shape"] [[example]] name = "simple_window" required-features = [ "cursor", "resource_manager", "tracing", "tracing-subscriber/env-filter", ] [[example]] name = "display_ppm" required-features = ["image"] [[example]] name = "record" required-features = ["record"] [dependencies.as-raw-xcb-connection] version = "1.0" optional = true [dependencies.libc] version = "0.2" optional = true [dependencies.libloading] version = "0.8.0" optional = true [dependencies.once_cell] version = "1.17" optional = true [dependencies.rustix] version = "0.38" 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.0" features = ["std"] default-features = false [dev-dependencies.gethostname] version = "0.4" [dev-dependencies.polling] version = "3.3.1" [dev-dependencies.tracing-subscriber] version = "0.3" [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", ] 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", ] [target."cfg(not(unix))".dependencies.gethostname] version = "0.4" x11rb-0.13.0/Cargo.toml.orig000064400000000000000000000076251046102023000135430ustar 00000000000000[package] name = "x11rb" version = "0.13.0" description = "Rust bindings to X11" authors = [ "Uli Schlachter ", "Eduardo Sánchez Muñoz ", "notgull ", ] repository = "https://github.com/psychon/x11rb" readme = "../README.md" edition = "2021" rust-version = "1.63" license = "MIT OR Apache-2.0" keywords = ["xcb", "X11"] [dependencies] x11rb-protocol = { version = "0.13.0", default-features = false, features = ["std"], path = "../x11rb-protocol" } libc = { version = "0.2", optional = true } libloading = { version = "0.8.0", optional = true } once_cell = { version = "1.17", optional = true } as-raw-xcb-connection = { version = "1.0", optional = true } tracing = { version = "0.1", optional = true, default-features = false } rustix = { version = "0.38", default-features = false, features = ["std", "event", "fs", "net", "system"] } [target.'cfg(not(unix))'.dependencies] gethostname = "0.4" [dev-dependencies] gethostname = "0.4" polling = "3.3.1" tracing-subscriber = "0.3" [features] # Without this feature, all uses of `unsafe` in the crate are forbidden via # #![deny(unsafe_code)]. This has the effect of disabling the XCB FFI bindings. allow-unsafe-code = ["libc", "as-raw-xcb-connection"] # Enable utility functions in `x11rb::cursor` for loading mouse cursors. cursor = ["render", "resource_manager"] # Enable utility functions in `x11rb::image` for working with image data. image = [] # Enable utility functions in `x11rb::resource_manager` for querying the # resource databases. resource_manager = ["x11rb-protocol/resource_manager"] dl-libxcb = ["allow-unsafe-code", "libloading", "once_cell"] # Enable extra traits on protocol types. extra-traits = ["x11rb-protocol/extra-traits"] # Add the ability to parse X11 requests (not normally needed). request-parsing = ["x11rb-protocol/request-parsing"] # Enable this feature to enable all the X11 extensions 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" ] # Features to enable individual X11 extensions composite = ["x11rb-protocol/composite", "xfixes"] damage = ["x11rb-protocol/damage", "xfixes"] dbe = ["x11rb-protocol/dbe"] dpms = ["x11rb-protocol/dpms"] dri2 = ["x11rb-protocol/dri2"] dri3 = ["x11rb-protocol/dri3"] glx = ["x11rb-protocol/glx"] present = ["x11rb-protocol/present", "randr", "xfixes", "sync"] randr = ["x11rb-protocol/randr", "render"] record = ["x11rb-protocol/record"] render = ["x11rb-protocol/render"] res = ["x11rb-protocol/res"] 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"] [package.metadata.docs.rs] all-features = true [[example]] name = "generic_events" required-features = ["present"] [[example]] name = "shared_memory" required-features = ["libc", "shm"] [[example]] name = "xeyes" required-features = ["shape"] [[example]] name = "simple_window" required-features = ["cursor", "resource_manager", "tracing", "tracing-subscriber/env-filter"] [[example]] name = "display_ppm" required-features = ["image"] [[example]] name = "record" required-features = ["record"] x11rb-0.13.0/LICENSE-APACHE000064400000000000000000000261361046102023000125760ustar 00000000000000 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. x11rb-0.13.0/LICENSE-MIT000064400000000000000000000020421046102023000122740ustar 00000000000000Copyright 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. x11rb-0.13.0/README.md000064400000000000000000000051001046102023000121150ustar 00000000000000# 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.63+-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.15.2-gb016df1 contains a vendored copy of the package of the same name. It is covered by the MIT license. See [xcb-proto-1.15.2-gb016df1/COPYING](xcb-proto-1.15.2/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. x11rb-0.13.0/examples/check_unchecked_requests.rs000064400000000000000000000061301046102023000200470ustar 00000000000000// 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> { 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!("{:?} unexpected", e), } // 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 {:?} instead of an X11 error", event), } assert_eq!(seq, seq2); } assert!(conn.poll_for_event()?.is_none()); println!("Done"); Ok(()) } include!("integration_test_util/connect.rs"); x11rb-0.13.0/examples/display_ppm.rs000064400000000000000000000206421046102023000153530ustar 00000000000000// 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 { 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> { // 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 { 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> { 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 {}, but I expected 255.", max, ); 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> { use std::io::Cursor; parse_ppm(&mut Cursor::new(bytes)) } pub fn parse_ppm_file(file_name: &OsStr) -> IOResult> { 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"); x11rb-0.13.0/examples/generic_events.rs000064400000000000000000000045331046102023000160330ustar 00000000000000// 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> { 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"); x11rb-0.13.0/examples/hypnomoire.rs000064400000000000000000000172061046102023000152250ustar 00000000000000// 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> { 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( conn: Arc, window_state: Arc>, 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( conn_arc: Arc, windows: Vec>>, 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>], window: Window, ) -> Option<&Arc>> { 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"); x11rb-0.13.0/examples/integration_test_util/connect.rs000064400000000000000000000017111046102023000210760ustar 00000000000000/// 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) } } x11rb-0.13.0/examples/integration_test_util/util.rs000064400000000000000000000034131046102023000204230ustar 00000000000000// 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(conn: Arc, 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(); }); } } x11rb-0.13.0/examples/list_fonts.rs000064400000000000000000000026171046102023000152200ustar 00000000000000// This program should produce output identical to `xlsfonts -lu`. extern crate x11rb; use x11rb::protocol::xproto::{ConnectionExt, FontDraw}; fn main() -> Result<(), Box> { let (conn, _) = connect(None)?; println!("DIR MIN MAX EXIST DFLT PROP ASC DESC NAME"); for reply in conn.list_fonts_with_info(u16::max_value(), 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"); x11rb-0.13.0/examples/record.rs000064400000000000000000000143671046102023000143170ustar 00000000000000// 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 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> { // 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"); x11rb-0.13.0/examples/shared_memory.rs000064400000000000000000000120161046102023000156640ustar 00000000000000extern 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(conn: &C) -> Result, 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( conn: &C, screen: &xproto::Screen, shmseg: shm::Seg, offset: u32, ) -> Result, 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( 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 { 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(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(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 {}.{} of the SHM extension, but version 1.2 \ is needed", major, minor, ); 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"); x11rb-0.13.0/examples/simple_window.rs000064400000000000000000000120121046102023000157020ustar 00000000000000extern 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> { 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"); x11rb-0.13.0/examples/simple_window_manager.rs000064400000000000000000000357401046102023000174110ustar 00000000000000// 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, pending_expose: HashSet, wm_protocols: Atom, wm_delete_window: Atom, sequences_to_ignore: BinaryHeap>, // 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, 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, std::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_value() / 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(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> { 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"); x11rb-0.13.0/examples/tutorial.rs000064400000000000000000003224061046102023000147000ustar 00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////// // // This file contains a tutorial of both this crate and the X11 protocol. It was created by porting // an existing libxcb tutorial that is available here: // // https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html // // References to libxcb in the text were retained. Only the code examples were adapted, where // possible. Some detailed explanations of libxcb required heavier editing. // // Since the libxcb tutorial is part of the libxcb source code, I assume that its MIT LICENSE // applies. The exact situation is a bit unclear (libxcb's COPYING file has "Copyright (C) // 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.", but the git history says that the // tutorial was only started in 2006 and was last touched in 2014). // // This tutorial is in a Rust file to ensure that the contained code actually compiles and // everything works as intended. Nothing is worse than bitrotted tutorial. Here are all the // imports: extern crate x11rb; use std::error::Error; use x11rb::connection::Connection; use x11rb::errors::{ConnectionError, ReplyError, ReplyOrIdError}; use x11rb::protocol::xproto::*; use x11rb::protocol::Event; use x11rb::wrapper::ConnectionExt as _; use x11rb::COPY_DEPTH_FROM_PARENT; use x11rb_protocol::SequenceNumber; /////////////////////////////////////////////////////////////////////////////////////////////////// // // Introduction // ============ // // This tutorial is based on the [Xlib Tutorial] written by Guy Keren. The author allowed me to // take some parts of his text, mainly the text which deals with the X Windows generality. // // [Xlib Tutorial](http://users.actcom.co.il/~choo/lupg/tutorials/xlib-programming/xlib-programming.html) // // This tutorial is intended for people who want to start to program with the [XCB] library. keep // in mind that XCB, like the [Xlib] library, isn't what most programmers wanting to write X // applications are looking for. They should use a much higher level GUI toolkit like Motif, // [LessTiff], [GTK], [QT], [EWL], [ETK], or use [Cairo]. However, we need to start somewhere. More // than this, knowing how things work down below is never a bad idea. // // [XCB](http://xcb.freedesktop.org) // [Xlib](http://tronche.com/gui/x/xlib/introduction) // [LessTiff](http://www.lesstif.org) // [GTK](http://www.gtk.org) // [QT](http://www.trolltech.com) // [EWL](http://www.enlightenment.org) // [ETK](http://www.enlightenment.org) // [Cairo](http://cairographics.org) // // After reading this tutorial, one should be able to write very simple graphical programs, but not // programs with decent user interfaces. For such programs, one of the previously mentioned // libraries should be used. // // But what is XCB? Xlib has been the standard C binding for the [X Window System] protocol for // many years now. It is an excellent piece of work, but there are applications for which it is not // ideal, for example: // // [X Window System](http://www.x.org) // // * **Small platforms**: Xlib is a large piece of code, and it's difficult to make it smaller // * **Latency hiding**: Xlib requests requiring a reply are effectively synchronous: they block // until the reply appears, whether the result is needed immediately or // not. // * **Direct access to the protocol**: Xlib does quite a bit of caching, layering, and similar // optimizations. While this is normally a feature, it makes it difficult // to simply emit specified X protocol requests and process specific // responses. // * **Threaded applications**: While Xlib does attempt to support multithreading, the API makes // this difficult and error-prone. // * **New extensions**: The Xlib infrastructure provides limited support for the new creation of // X extension client side code. // // For these reasons, among others, XCB, an X C binding, has been designed to solve the above // problems and thus provide a base for // // * Toolkit implementation. // * Direct protocol-level programming. // * Lightweight emulation of commonly used portions of the Xlib API. // // // The client and server model of the X window system // ================================================== // // The X Window System was developed with one major goal: flexibility. The idea was that the way // things look is one thing, but the way things work is another matter. Thus, the lower levels // provide the tools required to draw windows, handle user input, allow drawing graphics using // colors (or black and white screens), etc. To this point, a decision was made to separate the // system into two parts. A client that decides what to do, and a server that actually draws on the // screen and reads user input in order to send it to the client for processing. // // This model is the complete opposite of what is used to when dealing with clients and servers. In // our case, the user sits near the machine controlled by the server, while the client might be // running on a remote machine. The server controls the screens, mouse and keyboard. A client may // connect to the server, request that it draws a window (or several windows), and ask the server // to send it any input the user sends to these windows. Thus, several clients may connect to a // single X server (one might be running mail software, one running a WWW browser, etc). When input // is sent by the user to some window, the server sends a message to the client controlling this // window for processing. The client decides what to do with this input, and sends the server // requests for drawing in the window. // // The whole session is carried out using the X message protocol. This protocol was originally // carried over the TCP/IP protocol suite, allowing the client to run on any machine connected to // the same network that the server is. Later on, the X servers were extended to allow clients // running on the local machine with more optimized access to the server (note that an X protocol // message may be several hundreds of KB in size), such as using shared memory, or using Unix // domain sockets (a method for creating a logical channel on a Unix system between two processes). // // // GUI programming: the asynchronous model // ======================================= // // Unlike conventional computer programs, that carry some serial nature, a GUI program usually uses // an asynchronous programming model, also known as "event-driven programming". This means that // that program mostly sits idle, waiting for events sent by the X server, and then acts upon these // events. An event may say "The user pressed the 1st button mouse in spot (x,y)", or "The window // you control needs to be redrawn". In order for the program to be responsive to the user input, // as well as to refresh requests, it needs to handle each event in a rather short period of time // (e.g. less that 200 milliseconds, as a rule of thumb). // // This also implies that the program may not perform operations that might take a long time while // handling an event (such as opening a network connection to some remote server, or connecting to // a database server, or even performing a long file copy operation). Instead, it needs to perform // all these operations in an asynchronous manner. This may be done by using various asynchronous // models to perform the longish operations, or by performing them in a different process or // thread. // // So the way a GUI program looks is something like that: // 1. Perform initialization routines. // 2. Connect to the X server. // 3. Perform X-related initialization. // 4. While not finished: // 1. Receive the next event from the X server. // 2. Handle the event, possibly sending various drawing requests to the X server. // 3. If the event was a quit message, exit the loop. // 5. Close down the connection to the X server. // 6. Perform cleanup operations. // // // Basic XCB notions // ================= // // XCB has been created to eliminate the need for programs to actually implement the X protocol // layer. This library gives a program a very low-level access to any X server. Since the protocol // is standardized, a client using any implementation of XCB may talk with any X server (the same // occurs for Xlib, of course). We now give a brief description of the basic XCB notions. They will // be detailed later. // // // The X Connection // ---------------- // // The major notion of using XCB is the X Connection. This is a structure representing the // connection we have open with a given X server. It hides a queue of messages coming from the // server, and a queue of pending requests that our client intends to send to the server. In XCB, // this structure is named 'xcb_connection_t'. It is analogous to the Xlib Display. When we open a // connection to an X server, the library returns a pointer to such a structure. Later, we supply // this pointer to any XCB function that should send messages to the X server or receive messages // from this server. // // // Requests and replies: the Xlib killers // -------------------------------------- // // To ask for information from the X server, we have to make a request and ask for a reply. With // Xlib, these two tasks are automatically done: Xlib locks the system, sends a request, waits for // a reply from the X server and unlocks. This is annoying, especially if one makes a lot of // requests to the X server. Indeed, Xlib has to wait for the end of a reply before asking for the // next request (because of the locks that Xlib sends). For example, here is a time-line of N=4 // requests/replies with Xlib, with a round-trip latency **T_round_trip** that is 5 times long as // the time required to write or read a request/reply (**T_write/T_read**): // // W-----RW-----RW-----RW-----R // // * W: Writing request // * -: Stalled, waiting for data // * R: Reading reply // // The total time is N * (T_write + T_round_trip + T_read). // // With XCB, we can suppress most of the round-trips as the requests and the replies are not // locked. We usually send a request, then XCB returns to us a **cookie**, which is an identifier. // Then, later, we ask for a reply using this **cookie** and XCB returns a pointer to that reply. // Hence, with XCB, we can send a lot of requests, and later in the program, ask for all the // replies when we need them. Here is the time-line for 4 requests/replies when we use this // property of XCB: // // WWWW--RRRR // // The total time is N * T_write + max (0, T_round_trip - (N-1) * T_write) + N * T_read. // Which can be considerably faster than all those Xlib round-trips. // // Here is a program that computes the time to create 500 atoms with Xlib and XCB. It shows the Xlib way, the bad XCB way (which is similar to Xlib) and the good XCB way. On my computer, XCB is 25 times faster than Xlib. // #[allow(clippy::needless_collect)] fn example1() -> Result<(), Box> { use std::time::Instant; let (conn, _) = x11rb::connect(None)?; const COUNT: usize = 500; let mut atoms = [Into::::into(AtomEnum::NONE); COUNT]; // Init names let names = (0..COUNT).map(|i| format!("NAME{}", i)).collect::>(); // Bad use let start = Instant::now(); for i in 0..COUNT { atoms[i] = conn.intern_atom(false, names[i].as_bytes())?.reply()?.atom; } let diff = start.elapsed(); println!("bad use time: {:?}", diff); // Good use let start = Instant::now(); // The `collect` is needed to make sure that the closure passed to // `map` is called for every iteration before executing the for loop. let cookies = names .iter() .map(|name| conn.intern_atom(false, name.as_bytes())) .collect::>(); for (i, atom) in cookies.into_iter().enumerate() { atoms[i] = atom?.reply()?.atom; } let diff2 = start.elapsed(); println!("good use time: {:?}", diff2); println!( "ratio: {:?}", diff.as_nanos() as f64 / diff2.as_nanos() as f64 ); Ok(()) } // // The Graphic Context // ------------------- // // When we perform various drawing operations (graphics, text, etc), we may specify various options // for controlling how the data will be drawn (what foreground and background colors to use, how // line edges will be connected, what font to use when drawing some text, etc). In order to avoid // the need to supply hundreds of parameters to each drawing function, a graphical context // structure is used. We set the various drawing options in this structure, and then we pass a // pointer to this structure to any drawing routines. This is rather handy, as we often need to // perform several drawing requests with the same options. Thus, we would initialize a graphical // context, set the desired options, and pass this structure to all drawing functions. // // Note that graphic contexts have no client-side structure in XCB, they're just XIDs. Xlib has a // client-side structure because it caches the GC contents so it can avoid making redundant // requests, but of course XCB doesn't do that. // // // Events // ------ // // A structure is used to pass events received from the X server. XCB supports exactly the events // specified in the protocol (33 events). This structure contains the type of event received // (including a bit for whether it came from the server or another client), as well as the data // associated with the event (e.g. position on the screen where the event was generated, mouse // button associated with the event, region of the screen associated with a "redraw" event, etc). // The way to read the event's data depends on the event type. // // // Using XCB-based programs // ======================== // // [This part of the tutorial was not translated. Go read https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html#use if you want. // // // Opening and closing the connection to an X server // ================================================= // // An X program first needs to open the connection to the X server. There is a function that opens // a connection. It requires the display name, or None. In the latter case, the display name will // be the one in the environment variable DISPLAY. // // pub fn connect(dpy_name: Option<&str>) -> Result<([...], usize), [...]>; // // The second tuple value provides the screen number used for the connection. The returned // structure describes an X11 connection and is opaque. Here is how the connection can be opened: fn example2() -> Result<(), Box> { let (conn, _screen) = x11rb::connect(None)?; // To close a connection, it suffices to drop the connection object drop(conn); Ok(()) } // Checking basic information about a connection // --------------------------------------------- // // Once we have opened a connection to an X server, we should check some basic information about // it: what screens it has, what is the size (width and height) of the screen, how many colors it // supports (black and white ? grey scale ?, 256 colors ? more ?), and so on. We get such // information from the x11rb::xproto::Screen structure: #[allow(unused)] #[derive(Debug, Clone)] pub struct RenamedScreen { pub root: u32, pub default_colormap: u32, pub white_pixel: u32, pub black_pixel: u32, pub current_input_masks: u32, pub width_in_pixels: u16, pub height_in_pixels: u16, pub width_in_millimeters: u16, pub height_in_millimeters: u16, pub min_installed_maps: u16, pub max_installed_maps: u16, pub root_visual: u32, pub backing_stores: u8, pub save_unders: u8, pub root_depth: u8, pub allowed_depths: Vec, } // Here is a small program that shows how to use get this struct: fn example3() -> Result<(), Box> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; println!(); println!("Informations of screen {}:", screen.root); println!(" width.........: {}", screen.width_in_pixels); println!(" height........: {}", screen.height_in_pixels); println!(" white pixel...: {}", screen.white_pixel); println!(" black pixel...: {}", screen.black_pixel); println!(); Ok(()) } // Creating a basic window - the "hello world" program // =================================================== // // After we got some basic information about our screen, we can create our first window. In the X // Window System, a window is characterized by an Id. So, in XCB, a window is of type: // #[allow(unused)] pub type Window = u32; // We first ask for a new Id for our window, with this function: // // trait Connection { // fn generate_id(&self) -> u32; // } // // Then, XCB supplies the following function to create new windows: #[allow(unused, clippy::too_many_arguments)] fn own_create_window( c: &A, // The connection to use depth: u8, // Depth of the screen wid: u32, // Id of the window parent: u32, // Id of an existing window that should be the parent of the new window x: i16, // X position of the top-left corner of the window (in pixels) y: i16, // Y position of the top-left corner of the window (in pixels) width: u16, // Width of the window (in pixels) height: u16, // Height of the window (in pixels) border_width: u16, // Width of the window's border (in pixels) class: B, visual: u32, value_list: &CreateWindowAux, ) -> Result where B: Into, { unimplemented!(); } // The fact that we created the window does not mean that it will be drawn on screen. By default, // newly created windows are not mapped on the screen (they are invisible). In order to make our // window visible, we use the function `map_window()`, whose prototype is // // fn map_window(&self, window: u32) -> Result; // // Finally, here is a small program to create a window of size 150x150 pixels, positioned at the top-left corner of the screen: fn example4() -> Result<(), Box> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Ask for our window's Id let win = conn.generate_id()?; // Create the window conn.create_window( COPY_DEPTH_FROM_PARENT, // depth (same as root) win, // window Id screen.root, // parent window 0, // x 0, // y 150, // width 150, // height 10, // border width WindowClass::INPUT_OUTPUT, // class screen.root_visual, // visual &Default::default(), )?; // masks, not used yet // Map the window on the screen conn.map_window(win)?; // Make sure commands are sent before the sleep, so window is shown conn.flush()?; std::thread::sleep(std::time::Duration::from_secs(10)); Ok(()) } // In this code, you see one more function - flush(), not explained yet. It is used to flush // all the pending requests. More precisely, there are 2 functions that do such things. The first // one is flush(): // // trait Connection { // fn flush(&self) -> Result<(), ConnectionError>; // } // // This function flushes all pending requests to the X server (much like the fflush() function is // used to flush standard output). The second function is xcb_aux_sync() / sync(): // // trait ConnectionExt { // fn sync(&self) -> Result<(), ReplyError>; // } // // This functions also flushes all pending requests to the X server, and then waits until the X // server finishing processing these requests. In a normal program, this will not be necessary // (we'll see why when we get to write a normal X program), but for now, we put it there. // // The window that is created by the above code has a non defined background. This one can be set // to a specific color, thanks to the two last parameters of `xcb_create_window()`, which are not // described yet. See the subsections [Configuring a window] or [Registering for event types using // event masks] for examples on how to use these parameters. In addition, as no events are handled, // you have to make a Ctrl-C to interrupt the program. // // // Drawing in a window // =================== // // Drawing in a window can be done using various graphical functions (drawing pixels, lines, // rectangles, etc). In order to draw in a window, we first need to define various general drawing // parameters (what line width to use, which color to draw with, etc). This is done using a // graphical context. // // // Allocating a Graphics Context // ----------------------------- // // As we said, a graphical context defines several attributes to be used with the various drawing // functions. For this, we define a graphical context. We can use more than one graphical context // with a single window, in order to draw in multiple styles (different colors, different line // widths, etc). In XCB, a Graphics Context is, as a window, characterized by an Id: // // pub type Gcontext = u32; // // We first ask the X server to attribute an Id to our graphic context with this function: // // trait Connection { // fn generate_id(&self) -> u32; // } // // Then, we set the attributes of the graphic context with this function: // #[allow(unused)] fn my_create_gc( c: &A, cid: u32, drawable: u32, value_list: &CreateGCAux, ) -> Result { unimplemented!(); } // The CreateGCAux parameter of this function is specific to x11rb. It contains all the optional // arguments of the request. It is defined like this: #[allow(unused)] #[derive(Debug, Clone, Copy, Default)] pub struct RenamedCreateGcAux { pub function: Option, pub plane_mask: Option, pub foreground: Option, pub background: Option, pub line_width: Option, pub line_style: Option, pub cap_style: Option, pub join_style: Option, pub fill_style: Option, pub fill_rule: Option, pub tile: Option, pub stipple: Option, pub tile_stipple_x_origin: Option, pub tile_stipple_y_origin: Option, pub font: Option, pub subwindow_mode: Option, pub graphics_exposures: Option, pub clip_x_origin: Option, pub clip_y_origin: Option, pub clip_mask: Option, pub dash_offset: Option, pub dashes: Option, pub arc_mode: Option, } // We give now an example on how to allocate a graphic context that specifies that each drawing // function that uses it will draw in foreground with a black color. fn example5() -> Result<(), Box> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Create a black graphic context for drawing in the foreground. let win = screen.root; let black = conn.generate_id()?; let values = CreateGCAux::default().foreground(screen.black_pixel); conn.create_gc(black, win, &values)?; Ok(()) } // [The following is a bit XCB-specific, because CreateGCAux does not exist in libxcb.] // // Note should be taken regarding the role of "value_mask" and "value_list" in the prototype of // `xcb_create_gc()`. Since a graphic context has many attributes, and since we often just want to // define a few of them, we need to be able to tell the `xcb_create_gc()` which attributes we want // to set. This is what the "value_mask" parameter is for. We then use the "value_list" parameter // to specify actual values for the attribute we defined in "value_mask". Thus, for each constant // used in "value_list", we will use the matching constant in "value_mask". In this case, we define // a graphic context with one attribute: when drawing (a point, a line, etc), the foreground color // will be black. The rest of the attributes of this graphic context will be set to their default // values. // // See the next Subsection for more details. // // Changing the attributes of a Graphics Context // --------------------------------------------- // // Once we have allocated a Graphic Context, we may need to change its attributes (for example, // changing the foreground color we use to draw a line, or changing the attributes of the font we // use to display strings. See Subsections Drawing with a color and [Assigning a Font to a Graphic // Context]. This is done by using this function: // // fn change_gc(&self, gc: u32, value_list: &ChangeGCAux) -> Result; // // [Some more XCB-specific explanations skipped] // // Drawing primitives: point, line, box, circle,... // ------------------------------------------------ // // After we have created a Graphic Context, we can draw on a window using this Graphic Context, // with a set of XCB functions, collectively called "drawing primitives". Let see how they are // used. // // To draw a point, or several points, we use // // fn poly_point(&self, coordinate_mode: B, drawable: u32, gc: u32, // points: &[Point]) -> Result // where B: Into; // // The `coordinate_mode` parameter specifies the coordinate mode. Available values are // // pub enum CoordMode { // Origin, // Previous, // } // // If XCB_COORD_MODE_PREVIOUS is used, then all points but the first one are relative to the // immediately previous point. // // The `Point` type is just a structure with two fields (the coordinates of the point): // // #[derive(Debug, Clone, Copy)] // pub struct Point { // pub x: i16, // pub y: i16, // } // // You could see an example in xpoints.c. **TODO** Set the link. // // To draw a line, or a polygonal line, we use // // fn poly_line(&self, coordinate_mode: A, drawable: u32, gc: u32, points: &[Point]) // -> Result // where A: Into // // This function will draw the line between the first and the second points, then the line between // the second and the third points, and so on. // // To draw a segment, or several segments, we use // // fn poly_segment(&self, drawable: u32, gc: u32, segments: &[Segment]) -> Result; // // The `xcb_segment_t` type is just a structure with four fields (the coordinates of the two points that define the segment): // // pub struct Segment { // pub x1: i16, // pub y1: i16, // pub x2: i16, // pub y2: i16, // } // // To draw a rectangle, or several rectangles, we use // // fn poly_rectangle(&self, drawable: u32, gc: u32, rectangles: &[Rectangle]) -> Result; // // The `xcb_rectangle_t` type is just a structure with four fields (the coordinates of the top-left // corner of the rectangle, and its width and height): // // pub struct Rectangle { // pub x: i16, // pub y: i16, // pub width: u16, // pub height: u16, // } // // To draw an elliptical arc, or several elliptical arcs, we use // // fn poly_arc(&self, drawable: u32, gc: u32, arcs: &[Arc]) -> Result; // // The `xcb_arc_t` type is a structure with six fields: // // pub struct Arc { // pub x: i16, // pub y: i16, // pub width: u16, // pub height: u16, // pub angle1: i16, // pub angle2: i16, // } // // Note: the angles are expressed in units of 1/64 of a degree, so to have an angle of 90 degrees, // starting at 0,`angle1 = 0` and `angle2 = 90 << 6`. Positive angles indicate counterclockwise // motion, while negative angles indicate clockwise motion. // // The corresponding function which fill inside the geometrical object are listed below, without // further explanation, as they are used as the above functions. // // To Fill a polygon defined by the points given as arguments , we use // // fn fill_poly(&self, drawable: u32, gc: u32, shape: A, coordinate_mode: B, points: &[Point]) -> Result // where A: Into, B: Into // // The `shape` parameter specifies a shape that helps the server to improve performance. Available values are // // pub enum PolyShape { // Complex, // Nonconvex, // Convex, // } // // To fill one or several rectangles, we use // // fn poly_fill_rectangle(&self, drawable: u32, gc: u32, rectangles: &[Rectangle]) -> Result; // // To fill one or several arcs, we use // // fn poly_fill_arc(&self, drawable: u32, gc: u32, arcs: &[Arc]) -> Result; // // To illustrate these functions, here is an example that draws four points, a polygonal line, two // segments, two rectangles and two arcs. Remark that we use events for the first time, as an // introduction to the next section. fn example6() -> Result<(), Box> { // geometric objects let points = [ Point { x: 10, y: 10 }, Point { x: 10, y: 20 }, Point { x: 20, y: 10 }, Point { x: 20, y: 20 }, ]; let polyline = [ Point { x: 50, y: 10 }, Point { x: 5, y: 20 }, // Rest of points are relative Point { x: 25, y: -20 }, Point { x: 10, y: 10 }, ]; let segments = [ Segment { x1: 100, y1: 10, x2: 140, y2: 30, }, Segment { x1: 110, y1: 25, x2: 130, y2: 60, }, ]; let rectangles = [ Rectangle { x: 10, y: 50, width: 40, height: 20, }, Rectangle { x: 80, y: 50, width: 10, height: 40, }, ]; let arcs = [ Arc { x: 10, y: 100, width: 60, height: 40, angle1: 0, angle2: 90 << 6, }, Arc { x: 90, y: 100, width: 55, height: 40, angle1: 0, angle2: 270 << 6, }, ]; // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Create black (foreground) graphic context let win = screen.root; let foreground = conn.generate_id()?; let values = CreateGCAux::default() .foreground(screen.black_pixel) .graphics_exposures(0); conn.create_gc(foreground, win, &values)?; // Ask for our window's Id let win = conn.generate_id()?; // Create the window let values = CreateWindowAux::default() .background_pixel(screen.white_pixel) .event_mask(EventMask::EXPOSURE); conn.create_window( COPY_DEPTH_FROM_PARENT, // depth win, // window Id screen.root, // parent window 0, // x 0, // y 150, // width 150, // height 10, // border_width WindowClass::INPUT_OUTPUT, // class screen.root_visual, // visual &values, )?; // Map the window on the screen conn.map_window(win)?; // We flush the request conn.flush()?; loop { let event = conn.wait_for_event()?; if let Event::Expose(_) = event { // We draw the points conn.poly_point(CoordMode::ORIGIN, win, foreground, &points)?; // We draw the polygonal line conn.poly_line(CoordMode::PREVIOUS, win, foreground, &polyline)?; // We draw the segments conn.poly_segment(win, foreground, &segments)?; // We draw the rectangles conn.poly_rectangle(win, foreground, &rectangles)?; // We draw the arcs conn.poly_arc(win, foreground, &arcs)?; // We flush the request conn.flush()?; } else { // Unknown event type, ignore it } } } // X Events // ======== // // In an X program, everything is driven by events. Event painting on the screen is sometimes done // as a response to an event (an `Expose` event). If part of a program's window that was hidden, // gets exposed (e.g. the window was raised above other widows), the X server will send an "expose" // event to let the program know it should repaint that part of the window. User input (key // presses, mouse movement, etc) is also received as a set of events. // // // Registering for event types using event masks // --------------------------------------------- // // During the creation of a window, you should give it what kind of events it wishes to receive. // Thus, you may register for various mouse (also called pointer) events, keyboard events, expose // events, and so on. This is done for optimizing the server-to-client connection (i.e. why send a // program (that might even be running at the other side of the globe) an event it is not // interested in ?) // // In XCB, you use the "value_mask" and "value_list" data in the `xcb_create_window()` function to // register for events. Here is how we register for `Expose` event when creating a window: // #[allow(unused)] fn example_expose( conn: &C, depth: u8, screen: &Screen, ) -> Result<(), Box> { let values = CreateWindowAux::default().event_mask(EventMask::EXPOSURE); let win = conn.generate_id()?; conn.create_window( depth, win, screen.root, 0, 0, 150, 150, 10, WindowClass::INPUT_OUTPUT, screen.root_visual, &values, )?; Ok(()) } // `XCB_EVENT_MASK_EXPOSURE` is a constant defined in the xcb_event_mask_t enumeration in the // "xproto.h" header file. // // If we wanted to register for several event types, we can logically "or" them, as follows: #[allow(unused)] fn example_or(conn: &C, depth: u8, screen: &Screen) -> Result<(), Box> { let values = CreateWindowAux::default().event_mask(EventMask::EXPOSURE | EventMask::BUTTON_PRESS); let win = conn.generate_id()?; conn.create_window( depth, win, screen.root, 0, 0, 150, 150, 10, WindowClass::INPUT_OUTPUT, screen.root_visual, &values, )?; Ok(()) } // This registers for `Expose` events as well as for mouse button presses inside the created // window. You should note that a mask may represent several event sub-types. // // The values that a mask could take are given by the `xcb_cw_t` enumeration: // // pub enum CW { // BackPixmap, // BackPixel, // BorderPixmap, // BorderPixel, // BitGravity, // WinGravity, // BackingStore, // BackingPlanes, // BackingPixel, // OverrideRedirect, // SaveUnder, // EventMask, // DontPropagate, // Colormap, // Cursor, // } // // // [This note only applies to xcb, not x11rb] // // Note: we must be careful when setting the values of the valwin parameter, as they have to follow // the order the `xcb_cw_t` enumeration. Here is an example: // // [example removed since x11rb does not have this problem] // // If the window has already been created, we can use the `xcb_change_window_attributes()` function // to set the events that the window will receive. The subsection Configuring a window shows its // prototype. As an example, here is a piece of code that configures the window to receive the // `Expose` and `ButtonPress` events: #[allow(unused)] fn example_change_event_mask(conn: &C, win: Window) -> Result<(), Box> { let values = ChangeWindowAttributesAux::default() .event_mask(EventMask::EXPOSURE | EventMask::BUTTON_PRESS); conn.change_window_attributes(win, &values)?; Ok(()) } // Note: A common bug programmers have is adding code to handle new event types in their program, // while forgetting to add the masks for these events in the creation of the window. Such a // programmer would then sit there for hours debugging their program, wondering "Why doesn't my // program notice that I released the button?", only to find that they registered for button press // events but not for button release events. // // // Receiving events: writing the events loop // ----------------------------------------- // // After we have registered for the event types we are interested in, we need to enter a loop of // receiving events and handling them. There are two ways to receive events: a blocking way and a // non-blocking way: // // * `xcb_wait_for_event (xcb_connection_t *c)` is the blocking way. It waits (so blocks...) // until an event is queued in the X server. Then it retrieves it into a newly allocated // structure (it dequeues it from the queue) and returns it. This structure has to be freed. The // function returns `NULL` if an error occurs. // // * `xcb_poll_for_event (xcb_connection_t *c, int *error)` is the non-blocking way. It looks at // the event queue and returns (and dequeues too) an existing event into a newly allocated // structure. This structure has to be freed. It returns `NULL` if there is no event. If an // error occurs, the parameter `error` will be filled with the error status. // // There are various ways to write such a loop. We present two ways to write such a loop, with the // two functions above. The first one uses `xcb_wait_for_event_t`, which is similar to an event // Xlib loop using only `XNextEvent`: #[allow(unused)] fn example_wait_for_event(conn: &C) -> Result<(), Box> { loop { let event = conn.wait_for_event()?; match event { Event::Expose(_event) => { // .... } Event::ButtonPress(_event) => { // .... } _ => { // Unknown event type, ignore it } } } Ok(()) } // You will certainly want to use `xcb_poll_for_event(xcb_connection_t *c, int *error)` if, in // Xlib, you use `XPending` or `XCheckMaskEvent`: // // while (XPending (display)) { // XEvent ev; // // XNextEvent(d, &ev); // // /* Manage your event */ // } // // Such a loop in XCB looks like: // // xcb_generic_event_t *ev; // // while ((ev = xcb_poll_for_event (conn, 0))) { // /* Manage your event */ // } // // The events are managed in the same way as with `xcb_wait_for_event_t`. Obviously, we will need // to give the user some way of terminating the program. This is usually done by handling a special // "quit" event, as we will soon see. // // // Expose events // ------------- // // The `Expose` event is one of the most basic (and most used) events an application may receive. // It will be sent to us in one of several cases: // // * A window that covered part of our window has moved away, exposing part (or all) of our window. // * Our window was raised above other windows. // * Our window mapped for the first time. // * Our window was de-iconified. // // You should note the implicit assumption hidden here: the contents of our window is lost when it // is being obscured (covered) by either windows. One may wonder why the X server does not save // this contents. The answer is: to save memory. After all, the number of windows on a display at a // given time may be very large, and storing the contents of all of them might require a lot of // memory. Actually, there is a way to tell the X server to store the contents of a window in // special cases, as we will see later. // // When we get an `Expose` event, we should take the event's data from the members of the following // structure: #[allow(unused)] pub struct RenamedExposeEvent { /// The Id of the window that receives the event (in case our application /// registered for events in several windows) pub window: u32, /// The x coordinate of the top-left part of the window that needs to be redrawn pub x: u16, /// The y coordinate of the top-left part of the window that needs to be redrawn pub y: u16, /// The width of the part of the window that needs to be redrawn pub width: u16, /// The height of the part of the window that needs to be redrawn pub height: u16, pub count: u16, } // Getting user input // ================== // // User input traditionally comes from two sources: the mouse and the keyboard. Various event types // exist to notify us of user input (a key being presses on the keyboard, a key being released on // the keyboard, the mouse moving over our window, the mouse entering (or leaving) our window, and // so on. // // // Mouse button press and release events // ------------------------------------- // // The first event type we will deal with is a mouse button-press (or button-release) event in our // window. In order to register to such an event type, we should add one (or more) of the following // masks when we create our window: // // * `XCB_EVENT_MASK_BUTTON_PRESS`: notify us of any button that was pressed in one of our windows. // * `XCB_EVENT_MASK_BUTTON_RELEASE`: notify us of any button that was released in one of our windows. // // The structure to be checked for in our events loop is the same for these two events, and is the // following: #[allow(unused)] pub struct RenamedButtonPressEvent { pub detail: u8, /// Time, in milliseconds the event took place in pub time: u32, pub root: u32, pub event: u32, pub child: u32, pub root_x: i16, pub root_y: i16, /// The x coordinate where the mouse has been pressed in the window pub event_x: i16, /// The y coordinate where the mouse has been pressed in the window pub event_y: i16, /// A mask of the buttons (or keys) during the event pub state: u16, pub same_screen: u8, } // The `time` field may be used to calculate "double-click" situations by an application (e.g. if // the mouse button was clicked two times in a duration shorter than a given amount of time, assume // this was a double click). // // The `state` field is a mask of the buttons held down during the event. It is a bitwise OR of any // of the following (from the xcb_button_mask_t and xcb_mod_mask_t enumerations): // // * `XCB_BUTTON_MASK_1` // * `XCB_BUTTON_MASK_2` // * `XCB_BUTTON_MASK_3` // * `XCB_BUTTON_MASK_4` // * `XCB_BUTTON_MASK_5` // * `XCB_MOD_MASK_SHIFT` // * `XCB_MOD_MASK_LOCK` // * `XCB_MOD_MASK_CONTROL` // * `XCB_MOD_MASK_1` // * `XCB_MOD_MASK_2` // * `XCB_MOD_MASK_3` // * `XCB_MOD_MASK_4` // * `XCB_MOD_MASK_5` // // Their names are self explanatory, where the first 5 refer to the mouse buttons that are being // pressed, while the rest refer to various "special keys" that are being pressed (Mod1 is usually // the 'Alt' key or the 'Meta' key). // // **TODO:** Problem: it seems that the state does not change when clicking with various buttons. // // // Mouse movement events // --------------------- // // Similar to mouse button press and release events, we also can be notified of various mouse // movement events. These can be split into two families. One is of mouse pointer movement while no // buttons are pressed, and the second is a mouse pointer motion while one (or more) of the buttons // are pressed (this is sometimes called "a mouse drag operation", or just "dragging"). The // following event masks may be added during the creation of our window: // // * `XCB_EVENT_MASK_POINTER_MOTION`: events of the pointer moving in one of the windows controlled // by our application, while no mouse button is held pressed. // * `XCB_EVENT_MASK_BUTTON_MOTION`: Events of the pointer moving while one or more of the mouse // buttons is held pressed. // * `XCB_EVENT_MASK_BUTTON_1_MOTION`: same as `XCB_EVENT_MASK_BUTTON_MOTION`, but only when the // 1st mouse button is held pressed. // * `XCB_EVENT_MASK_BUTTON_2_MOTION`, `XCB_EVENT_MASK_BUTTON_3_MOTION`, // `XCB_EVENT_MASK_BUTTON_4_MOTION`, `XCB_EVENT_MASK_BUTTON_5_MOTION`: same as // `XCB_EVENT_MASK_BUTTON_1_MOTION`, but respectively for 2nd, 3rd, 4th and 5th mouse button. // // The structure to be checked for in our events loop is the same for these events, and is the // following: #[allow(unused)] pub struct RenamedMotionNotifyEvent { pub detail: u8, /// Time, in milliseconds the event took place in pub time: u32, pub root: u32, pub event: u32, pub child: u32, pub root_x: i16, pub root_y: i16, /// The x coordinate where the mouse has been pressed in the window pub event_x: i16, /// The y coordinate where the mouse has been pressed in the window pub event_y: i16, /// A mask of the buttons (or keys) during the event pub state: u16, pub same_screen: u8, } // Mouse pointer enter and leave events // ------------------------------------ // // Another type of event that applications might be interested in, is a mouse pointer entering a // window the program controls, or leaving such a window. Some programs use these events to show // the user that the application is now in focus. In order to register for such an event type, we // should add one (or more) of the following masks when we create our window: // // * `xcb_event_enter_window_t`: notify us when the mouse pointer enters any of our controlled // windows. // * `xcb_event_leave_window_t`: notify us when the mouse pointer leaves any of our controlled // windows. // // The structure to be checked for in our events loop is the same for these two events, and is the // following: #[allow(unused)] pub struct RenamedEnterNotifyEvent { pub detail: u8, pub time: u32, pub root: u32, pub event: u32, pub child: u32, pub root_x: i16, pub root_y: i16, pub event_x: i16, pub event_y: i16, pub state: u16, pub mode: u8, pub same_screen_focus: u8, } // The keyboard focus // ------------------ // // There may be many windows on a screen, but only a single keyboard attached to them. How does the // X server then know which window should be sent a given keyboard input ? This is done using the // keyboard focus. Only a single window on the screen may have the keyboard focus at a given time. // There is a XCB function that allows a program to set the keyboard focus to a given window. The // user can usually set the keyboard focus using the window manager (often by clicking on the title // bar of the desired window). Once our window has the keyboard focus, every key press or key // release will cause an event to be sent to our program (if it registered for these event // types...). // // Keyboard press and release events // --------------------------------- // // If a window controlled by our program currently holds the keyboard focus, it can receive key // press and key release events. So, we should add one (or more) of the following masks when we // create our window: // // * `XCB_EVENT_MASK_KEY_PRESS`: notify us when a key was pressed while any of our controlled // windows had the keyboard focus. // * `XCB_EVENT_MASK_KEY_RELEASE`: notify us when a key was released while any of our controlled // windows had the keyboard focus. // // The structure to be checked for in our events loop is the same for these two events, and is the // following: #[allow(unused)] pub struct RenamedKeyPressEvent { pub detail: u8, /// Time, in milliseconds the event took place in pub time: u32, pub root: u32, pub event: u32, pub child: u32, pub root_x: i16, pub root_y: i16, pub event_x: i16, pub event_y: i16, pub state: u16, pub same_screen: u8, } // The `detail` field refers to the physical key on the keyboard. // // **TODO:** Talk about getting the ASCII code from the key code. // // // X events: a complete example // ============================ // // As an example for handling events, we show a program that creates a window, enters an events // loop and checks for all the events described above, and writes on the terminal the relevant // characteristics of the event. With this code, it should be easy to add drawing operations, like // those which have been described above. fn print_modifiers(mask: x11rb::protocol::xproto::KeyButMask) { println!("Modifier mask: {:#?}", mask); } fn example7() -> Result<(), Box> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Ask for our window's Id let win = conn.generate_id()?; // Create the window let values = CreateWindowAux::default() .background_pixel(screen.white_pixel) .event_mask( EventMask::EXPOSURE | EventMask::BUTTON_PRESS | EventMask::BUTTON_RELEASE | EventMask::POINTER_MOTION | EventMask::ENTER_WINDOW | EventMask::LEAVE_WINDOW | EventMask::KEY_PRESS | EventMask::KEY_RELEASE, ); conn.create_window( COPY_DEPTH_FROM_PARENT, // depth win, // window Id screen.root, // parent window 0, // x 0, // y 150, // width 150, // height 10, // border_width WindowClass::INPUT_OUTPUT, // class screen.root_visual, // visual &values, )?; // Map the window on the screen conn.map_window(win)?; conn.flush()?; loop { let event = conn.wait_for_event()?; match event { Event::Expose(event) => { println!( "Window {} exposed. Region to be redrawn at location ({},{}) with dimensions \ ({},{})", event.window, event.x, event.y, event.width, event.height ); } Event::ButtonPress(event) => { print_modifiers(event.state); match event.detail { 4 => println!( "Wheel Button up in window {}, at coordinates ({},{})", event.event, event.event_x, event.event_y ), 5 => println!( "Wheel Button down in window {}, at coordinates ({},{})", event.event, event.event_x, event.event_y ), _ => println!( "Button {} pressed in window {}, at coordinates ({},{})", event.detail, event.event, event.event_x, event.event_y ), } } Event::ButtonRelease(event) => { print_modifiers(event.state); println!( "Button {} released in window {}, at coordinates ({},{})", event.detail, event.event, event.event_x, event.event_y ); } Event::MotionNotify(event) => { println!( "Mouse moved in window {} at coordinates ({},{})", event.event, event.event_x, event.event_y ); } Event::EnterNotify(event) => { println!( "Mouse entered window {} at coordinates ({},{})", event.event, event.event_x, event.event_y ); } Event::LeaveNotify(event) => { println!( "Mouse left window {} at coordinates ({},{})", event.event, event.event_x, event.event_y ); } Event::KeyPress(event) => { print_modifiers(event.state); println!("Key pressed in window {}", event.event); } Event::KeyRelease(event) => { print_modifiers(event.state); println!("Key released in window {}", event.event); } _ => { // Unknown event type, ignore it println!("Unknown event: {:?}", event); } } } } // Handling text and fonts // // ======================= // // Besides drawing graphics on a window, we often want to draw text. Text strings have two major // properties: the characters to be drawn and the font with which they are drawn. In order to draw // text, we need to first request the X server to load a font. We then assign a font to a Graphic // Context, and finally, we draw the text in a window, using the Graphic Context. // // // The Font structure // ------------------ // // In order to support flexible fonts, a font type is defined. You know what ? It's an Id: // // pub type Font = u32; // // It is used to contain information about a font, and is passed to several functions that handle // fonts selection and text drawing. We ask the X server to attribute an Id to our font with the // function: // // conn.generate_id(); // // // Opening a Font // -------------- // // To open a font, we use the following function: // // pub fn open_font(&self, fid: u32, name: &[u8]) -> Result; // // The `fid` parameter is the font Id defined by `xcb_generate_id()` (see above). The `name` // parameter is the name of the font you want to open. Use the command `xlsfonts` in a terminal to // know which are the fonts available on your computer. The parameter `name_len` is the length of // the name of the font (given by `strlen()`). // // // Assigning a Font to a Graphic Context // ------------------------------------- // // Once a font is opened, you have to create a Graphic Context that will contain the informations // about the color of the foreground and the background used when you draw a text in a Drawable. // Here is an example of a Graphic Context that will allow us to draw an opened font with a black // foreground and a white background: #[allow(unused)] fn example_assign_font( conn: &C, screen: &Screen, window: Window, font: Font, ) -> Result<(), Box> { let gc = conn.generate_id()?; let values = CreateGCAux::default() .foreground(screen.black_pixel) .background(screen.white_pixel) .font(font); conn.create_gc(gc, window, &values)?; // The font is not needed anymore, so we close it conn.close_font(font)?; Ok(()) } // Drawing text in a drawable // -------------------------- // // To draw a text in a drawable, we use the following function: // // pub fn image_text8(&self, drawable: u32, gc: u32, x: i16, y: i16, string: &[u8]) // -> Result; // // The `string` parameter is the text to draw. The location of the drawing is given by the // parameters `x` and `y`. The base line of the text is exactly the parameter `y`. // // // Complete example // ---------------- // // This example draw a text at 10 pixels (for the base line) of the bottom of a window. Pressing // the Esc key exits the program. // // (This whole example uses checked requests in the original, but that does not really seem useful // to me, so I changed it.) fn text_draw( conn: &C, screen: &Screen, window: Window, x1: i16, y1: i16, label: &str, ) -> Result<(), Box> { let gc = gc_font_get(conn, screen, window, "7x13")?; conn.image_text8(window, gc, x1, y1, label.as_bytes())?; conn.free_gc(gc)?; Ok(()) } fn gc_font_get( conn: &C, screen: &Screen, window: Window, font_name: &str, ) -> Result { let font = conn.generate_id()?; conn.open_font(font, font_name.as_bytes())?; let gc = conn.generate_id()?; let values = CreateGCAux::default() .foreground(screen.black_pixel) .background(screen.white_pixel) .font(font); conn.create_gc(gc, window, &values)?; conn.close_font(font)?; Ok(gc) } fn example8() -> Result<(), Box> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; const WIDTH: u16 = 300; const HEIGHT: u16 = 100; // Creating the window let window = conn.generate_id()?; let values = CreateWindowAux::default() .background_pixel(screen.white_pixel) .event_mask(EventMask::KEY_RELEASE | EventMask::EXPOSURE); conn.create_window( screen.root_depth, window, screen.root, 20, 200, WIDTH, HEIGHT, 0, WindowClass::INPUT_OUTPUT, screen.root_visual, &values, )?; conn.map_window(window)?; conn.flush()?; loop { let event = conn.wait_for_event()?; match event { Event::Expose(_) => { let text = "Press ESC key to exit..."; text_draw(&conn, screen, window, 10, HEIGHT as i16 - 10, text)?; conn.flush()?; } Event::KeyRelease(event) => { if event.detail == 9 { // ESC return Ok(()); } } _ => {} // Unknown event type, ignore it } } } // Interacting with the window manager // =================================== // // After we have seen how to create windows and draw on them, we take one step back, and look at // how our windows are interacting with their environment (the full screen and the other windows). // First of all, our application needs to interact with the window manager. The window manager is // responsible to decorating drawn windows (i.e. adding a frame, an iconify button, a system menu, // a title bar, etc), as well as handling icons shown when windows are being iconified. It also // handles ordering of windows on the screen, and other administrative tasks. We need to give it // various hints as to how we want it to treat our application's windows. // // // Window properties // ----------------- // // Many of the parameters communicated to the window manager are passed using data called // "properties". These properties are attached by the X server to different windows, and are stored // in a format that makes it possible to read them from different machines that may use different // architectures (remember that an X client program may run on a remote machine). // // The property and its type (a string, an integer, etc) are Id. Their type are `xcb_atom_t`: // // pub type ATOM = u32; // // To change the property of a window, we use one of the following functions: // // fn change_property8( // &self, // mode: A, // window: Window, // property: B, // type_: C, // data: &[u8], // ) -> Result, ConnectionError> // where // A: Into, // B: Into, // C: Into // // fn change_property16( // &self, // mode: A, // window: Window, // property: B, // type_: C, // data: &[u16], // ) -> Result, ConnectionError> // where // A: Into, // B: Into, // C: Into // // fn change_property32( // &self, // mode: A, // window: Window, // property: B, // type_: C, // data: &[u32], // ) -> Result, ConnectionError> // where // A: Into, // B: Into, // C: Into // // The `mode` parameter could be one of the following values (defined in enumeration // xcb_prop_mode_t in the xproto.h header file): // // pub enum PropMode { // Replace, // Prepend, // Append, // } // // // // Setting the window name and icon name // ------------------------------------- // // The first thing we want to do would be to set the name for our window. This is done using the // `xcb_change_property()` function. This name may be used by the window manager as the title of // the window (in the title bar), in a task list, etc. The property atom to use to set the name of // a window is `WM_NAME` (and `WM_ICON_NAME` for the iconified window) and its type is `STRING`. // Here is an example of utilization: fn example9() -> Result<(), Box> { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Ask for our window's Id let win = conn.generate_id()?; // Create the window conn.create_window( 0, win, screen.root, 0, 0, 250, 150, 10, WindowClass::INPUT_OUTPUT, screen.root_visual, &Default::default(), )?; // Set the title of the window let title = "Hello World !"; conn.change_property8( PropMode::REPLACE, win, AtomEnum::WM_NAME, AtomEnum::STRING, title.as_bytes(), )?; // Set the title of the window icon let title_icon = "Hello World ! (iconified)"; conn.change_property8( PropMode::REPLACE, win, AtomEnum::WM_ICON_NAME, AtomEnum::STRING, title_icon.as_bytes(), )?; // Map the window on the screen conn.map_window(win)?; conn.flush()?; loop { conn.wait_for_event()?; } } // Simple window operations // ======================== // // One more thing we can do to our window is manipulate them on the screen (resize them, move them, // raise or lower them, iconify them, and so on). Some window operations functions are supplied by // XCB for this purpose. // // // Mapping and un-mapping a window // ------------------------------- // // The first pair of operations we can apply on a window is mapping it, or un-mapping it. Mapping a // window causes the window to appear on the screen, as we have seen in our simple window program // example. Un-mapping it causes it to be removed from the screen (although the window as a logical // entity still exists). This gives the effect of making a window hidden (unmapped) and shown again // (mapped). For example, if we have a dialog box window in our program, instead of creating it // every time the user asks to open it, we can create the window once, in an un-mapped mode, and // when the user asks to open it, we simply map the window on the screen. When the user clicked the // 'OK' or 'Cancel' button, we simply un-map the window. This is much faster than creating and // destroying the window, however, the cost is wasted resources, both on the client side, and on // the X server side. // // To map a window, you use the following function: // // fn map_window(&self, window: u32) -> Result; // // To have a simple example, see the examples above. The mapping operation will cause an `Expose` // event to be sent to our application, unless the window is completely covered by other windows. // // Un-mapping a window is also simple. You use the function // // fn unmap_window(&self, window: u32) -> Result; // // The utilization of this function is the same as `xcb_map_window()`. // // // Configuring a window // -------------------- // // As we have seen when we have created our first window, in the X Events subsection, we can set // some attributes for the window (that is, the position, the size, the events the window will // receive, etc). If we want to modify them, but the window is already created, we can change them // by using the following function: // // fn configure_window(&self, window: u32, value_list: &ConfigureWindowAux) -> Result; // // We set the `value_mask` to one or several mask values that are in the xcb_config_window_t enumeration in the xproto.h header: // // * `XCB_CONFIG_WINDOW_X`: new x coordinate of the window's top left corner // * `XCB_CONFIG_WINDOW_Y`: new y coordinate of the window's top left corner // * `XCB_CONFIG_WINDOW_WIDTH`: new width of the window // * `XCB_CONFIG_WINDOW_HEIGHT`: new height of the window // * `XCB_CONFIG_WINDOW_BORDER_WIDTH`: new width of the border of the window // * `XCB_CONFIG_WINDOW_SIBLING` // * `XCB_CONFIG_WINDOW_STACK_MODE`: the new stacking order // // We then give to `value_mask` the new value. We now describe how to use `xcb_configure_window_t` // in some useful situations. // // // Moving a window around the screen // --------------------------------- // // An operation we might want to do with windows is to move them to a different location. This can // be done like this: #[allow(unused)] fn example_move(conn: &C, win: Window) -> Result<(), ReplyError> { // Move the window to coordinates x = 10 and y = 20 let values = ConfigureWindowAux::default().x(10).y(20); conn.configure_window(win, &values)?; Ok(()) } // Note that when the window is moved, it might get partially exposed or partially hidden by other // windows, and thus we might get `Expose` events due to this operation. // // // Resizing a window // ----------------- // // Yet another operation we can do is to change the size of a window. This is done using the // following code: #[allow(unused)] fn example_resize(conn: &C, win: Window) -> Result<(), ReplyError> { // Move the window to coordinates width = 10 and height = 20 let values = ConfigureWindowAux::default().width(10).height(20); conn.configure_window(win, &values)?; Ok(()) } // We can also combine the move and resize operations using one single call to // `xcb_configure_window_t`: #[allow(unused)] fn example_move_resize(conn: &C, win: Window) -> Result<(), ReplyError> { // Move the window to coordinates x = 10 and y = 20 // and resize the window to width = 200 and height = 300 let values = ConfigureWindowAux::default() .x(10) .y(20) .width(200) .height(300); conn.configure_window(win, &values)?; Ok(()) } // Changing windows stacking order: raise and lower // ------------------------------------------------ // // Until now, we changed properties of a single window. We'll see that there are properties that // relate to the window and other windows. One of them is the stacking order. That is, the order in // which the windows are layered on top of each other. The front-most window is said to be on the // top of the stack, while the back-most window is at the bottom of the stack. Here is how to // manipulate our windows stack order: #[allow(unused)] fn example_stack_above(conn: &C, win: Window) -> Result<(), ReplyError> { // Move the window on the top of the stack let values = ConfigureWindowAux::default().stack_mode(StackMode::ABOVE); conn.configure_window(win, &values)?; Ok(()) } #[allow(unused)] fn example_stack_below(conn: &C, win: Window) -> Result<(), ReplyError> { // Move the window to the bottom of the stack let values = ConfigureWindowAux::default().stack_mode(StackMode::BELOW); conn.configure_window(win, &values)?; Ok(()) } // Getting information about a window // ---------------------------------- // // Just like we can set various attributes of our windows, we can also ask the X server supply the // current values of these attributes. For example, we can check where a window is located on the // screen, what is its current size, whether it is mapped or not, etc. The structure that contains // some of this information is pub struct RenamedGetGeometryReply { pub depth: u8, // depth of the window pub root: u32, // Id of the root window pub x: i16, // x coordinate of the window's location pub y: i16, // Y coordinate of the window's location pub width: u16, // Width of the window pub height: u16, // Height of the window pub border_width: u16, // Width of the window's border } // x11rb fills this structure with two functions: // // fn get_geometry(&self, drawable: u32) -> Result, ConnectionError>; // // and the .reply() function on the returned cookie // // You use them as follows: #[allow(unused)] fn example_get_geometry(conn: &C, win: Window) -> Result<(), ReplyError> { let geom = conn.get_geometry(win)?.reply()?; // Do something with the fields of geom Ok(()) } // Remark that you have to free the structure, as `xcb_get_geometry_reply_t` allocates a newly one. // // [Also remark that with x11rb and rust, you do not have to free the structure yourself] // // One problem is that the returned location of the window is relative to its parent window. This // makes these coordinates rather useless for any window manipulation functions, like moving it on // the screen. In order to overcome this problem, we need to take a two-step operation. First, we // find out the Id of the parent window of our window. We then translate the above relative // coordinates to the screen coordinates. // // To get the Id of the parent window, we need this structure: // // pub struct QueryTreeReply { // pub root: u32, // pub parent: u32, // pub children: Vec, // } // // x11rb fills this structure with two functions: // // fn query_tree(&self, window: u32) -> Result, ConnectionError>; // // and the .reply() function on the returned cookie // // The translated coordinates will be found in this structure: // // pub struct TranslateCoordinatesReply { // pub same_screen: u8, // pub child: u32, // pub dst_x: i16, // pub dst_y: i16, // } // // As usual, we need two functions to fill this structure: // // fn translate_coordinates(&self, src_window: u32, dst_window: u32, src_x: i16, src_y: i16) // -> Result, ConnectionError> // // and the .reply() function on the returned cookie // // We use them as follows: #[allow(unused)] fn example_get_and_query(conn: &C, win: Window) -> Result<(), ReplyError> { let geom = conn.get_geometry(win)?; let tree = conn.query_tree(win)?; let geom = geom.reply()?; let tree = tree.reply()?; let trans = conn .translate_coordinates(win, tree.parent, geom.x, geom.y)? .reply()?; // the translated coordinates are in trans.dst_x and trans.dst_y Ok(()) } // Of course, as for `geom`, `tree` and `trans` have to be freed. // [But not in rust / x11rb] // // The work is a bit hard, but XCB is a very low-level library. // // **TODO:** the utilization of these functions should be a prog, which displays the coordinates of the window. // // There is another structure that gives informations about our window: // // pub struct GetWindowAttributesReply { // pub backing_store: u8, // pub visual: u32, // pub class: u16, // pub bit_gravity: u8, // pub win_gravity: u8, // pub backing_planes: u32, // pub backing_pixel: u32, // pub save_under: u8, // pub map_is_installed: u8, // pub map_state: u8, // pub override_redirect: u8, // pub colormap: u32, // pub all_event_masks: u32, // pub your_event_mask: u32, // pub do_not_propagate_mask: u16, // } // // XCB supplies these two functions to fill it: // // fn get_window_attributes(&self, window: u32) -> Result, ConnectionError>; // // and the .reply() function on the returned cookie // // You use them as follows: #[allow(unused)] fn example_get_attributes(conn: &C, win: Window) -> Result<(), ReplyError> { let geom = conn.get_window_attributes(win)?.reply()?; // Do something with the fields of attr Ok(()) } // Using colors to paint the rainbow // ================================= // // Up until now, all our painting operation were done using black and white. We will (finally) see // now how to draw using colors. // // // Color maps // ---------- // // In the beginning, there were not enough colors. Screen controllers could only support a limited // number of colors simultaneously (initially 2, then 4, 16 and 256). Because of this, an // application could not just ask to draw in a "light purple-red" color, and expect that color to // be available. Each application allocated the colors it needed, and when all the color entries // (4, 16, 256 colors) were in use, the next color allocation would fail. // // Thus, the notion of "a color map" was introduced. A color map is a table whose size is the same // as the number of simultaneous colors a given screen controller. Each entry contained the RGB // (Red, Green and Blue) values of a different color (all colors can be drawn using some // combination of red, green and blue). When an application wants to draw on the screen, it does // not specify which color to use. Rather, it specifies which color entry of some color map to be // used during this drawing. Change the value in this color map entry and the drawing will use a // different color. // // In order to be able to draw using colors that got something to do with what the programmer // intended, color map allocation functions are supplied. You could ask to allocate entry for a // color with a set of RGB values. If one already existed, you would get its index in the table. If // none existed, and the table was not full, a new cell would be allocated to contain the given RGB // values, and its index returned. If the table was full, the procedure would fail. You could then // ask to get a color map entry with a color that is closest to the one you were asking for. This // would mean that the actual drawing on the screen would be done using colors similar to what you // wanted, but not the same. // // On today's more modern screens where one runs an X server with support for 16 million colors, // this limitation looks a little silly, but remember that there are still older computers with // older graphics cards out there. Using color map, support for these screen becomes transparent to // you. On a display supporting 16 million colors, any color entry allocation request would // succeed. On a display supporting a limited number of colors, some color allocation requests // would return similar colors. It won't look as good, but your application would still work. // // // Allocating and freeing Color Maps // --------------------------------- // // When you draw using XCB, you can choose to use the standard color map of the screen your window // is displayed on, or you can allocate a new color map and apply it to a window. In the latter // case, each time the mouse moves onto your window, the screen color map will be replaced by your // window's color map, and you'll see all the other windows on screen change their colors into // something quite bizarre. In fact, this is the effect you get with X applications that use the // "-install" command line option. // // In XCB, a color map is (as often in X) an Id: // // type COLORMAP = u32; // // In order to access the screen's default color map, you just have to retrieve the // `default_colormap` field of the `xcb_screen_t` structure (see Section [Checking basic // information about a connection](#screen)): #[allow(unused)] fn example_get_colormap(conn: &C) { let screen = &conn.setup().roots[0]; let _colormap = screen.default_colormap; } // This will return the color map used by default on the first screen (again, remember that an X // server may support several different screens, each of which might have its own resources). // // The other option, that of allocating a new colormap, works as follows. We first ask the X server // to give an Id to our color map, with this function: // // conn.generate_id(); // // Then, we create the color map with // // fn create_colormap(&self, alloc: A, mid: u32, window: u32, visual: u32) // -> Result // where A: Into // // Here is an example of creation of a new color map: #[allow(unused)] fn example_create_colormap( conn: &C, win: Window, screen: &Screen, ) -> Result<(), ReplyOrIdError> { let cmap = conn.generate_id()?; conn.create_colormap(ColormapAlloc::NONE, cmap, win, screen.root_visual)?; Ok(()) } // Note that the window parameter is only used to allow the X server to create the color map for // the given screen. We can then use this color map for any window drawn on the same screen. // // To free a color map, it suffices to use this function: // // fn free_colormap(&self, cmap: u32) -> Result; // // // Allocating and freeing a color entry // ------------------------------------ // // Once we got access to some color map, we can start allocating colors. The informations related // to a color are stored in the following structure: // // pub struct AllocColorReply { // pub red: u16, // pub green: u16, // pub blue: u16, // pub pixel: u32, // } // // XCB supplies these two functions to fill it: // // fn alloc_color(&self, cmap: u32, red: u16, green: u16, blue: u16) -> Result, ConnectionError>; // // and the .reply() function on the returned cookie // // The fuction `xcb_alloc_color()` takes the 3 RGB components as parameters (red, green and blue). // Here is an example of using these functions: #[allow(unused)] fn example_fill_colormap( conn: &C, win: Window, screen: &Screen, ) -> Result<(), ReplyOrIdError> { let cmap = conn.generate_id()?; conn.create_colormap(ColormapAlloc::NONE, cmap, win, screen.root_visual)?; let _rep = conn.alloc_color(cmap, 65535, 0, 0)?.reply()?; // Do something with r.pixel or the components Ok(()) } // As `xcb_alloc_color_reply()` allocates memory, you have to free `rep`. // [But not in rust / x11rb] // // **TODO**: Talk about freeing colors. // // // X Bitmaps and Pixmaps // ===================== // // One thing many so-called "Multi-Media" applications need to do, is display images. In the X // world, this is done using bitmaps and pixmaps. We have already seen some usage of them when // setting an icon for our application. Lets study them further, and see how to draw these images // inside a window, along side the simple graphics and text we have seen so far. // // One thing to note before delving further, is that XCB (nor Xlib) supplies no means of // manipulating popular image formats, such as gif, png, jpeg or tiff. It is up to the programmer // (or to higher level graphics libraries) to translate these image formats into formats that the X // server is familiar with (x bitmaps and x pixmaps). // // // What is a X Bitmap? An X Pixmap? // -------------------------------- // // An X bitmap is a two-color image stored in a format specific to the X window system. When stored // in a file, the bitmap data looks like a C source file. It contains variables defining the width // and the height of the bitmap, an array containing the bit values of the bitmap (the size of the // array is (width+7)/8*height and the bit and byte order are LSB), and an optional hot-spot // location (that will be explained later, when discussing mouse cursors). // // An X pixmap is a format used to stored images in the memory of an X server. This format can // store both black and white images (such as x bitmaps) as well as color images. It is the only // image format supported by the X protocol, and any image to be drawn on screen, should be first // translated into this format. // // In actuality, an X pixmap can be thought of as a window that does not appear on the screen. Many // graphics operations that work on windows, will also work on pixmaps. Indeed, the type of X // pixmap in XCB is an Id like a window: // // type PIXMAP = u32; // // Like Xlib, there is no difference between a Drawable, a Window or a Pixmap: // // type DRAWABLE = u32; // // in order to avoid confusion between a window and a pixmap. The operations that will work the // same on a window or a pixmap will require a `xcb_drawable_t` // // Remark: In Xlib, there is no specific difference between a `Drawable`, a `Pixmap` or a `Window`: // all are 32 bit long integer. XCB wraps all these different IDs in structures to provide some // measure of type-safety. // // // Creating a pixmap // ----------------- // // Sometimes we want to create an un-initialized pixmap, so we can later draw into it. This is // useful for image drawing programs (creating a new empty canvas will cause the creation of a new // pixmap on which the drawing can be stored). It is also useful when reading various image // formats: we load the image data into memory, create a pixmap on the server, and then draw the // decoded image data onto that pixmap. // // To create a new pixmap, we first ask the X server to give an Id to our pixmap, with this // function: // // conn.generate_id(); // // Then, XCB supplies the following function to create new pixmaps: // // fn create_pixmap(&self, depth: u8, pid: u32, drawable: u32, width: u16, height: u16) -> Result // // **TODO**: Explain the drawable parameter, and give an example (like xpoints.c) // // // Drawing a pixmap in a window // ---------------------------- // // Once we got a handle to a pixmap, we can draw it on some window, using the following function: // // fn copy_area(&self, src_drawable: u32, dst_drawable: u32, gc: u32, src_x: i16, // src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) // -> Result; // // As you can see, we could copy the whole pixmap, as well as only a given rectangle of the pixmap. // This is useful to optimize the drawing speed: we could copy only what we have modified in the // pixmap. // // **One important note should be made**: it is possible to create pixmaps with different depths on // the same screen. When we perform copy operations (a pixmap onto a window, etc), we should make // sure that both source and target have the same depth. If they have a different depth, the // operation would fail. The exception to this is if we copy a specific bit plane of the source // pixmap using the `xcb_copy_plane_t` function. In such an event, we can copy a specific plane to // the target window (in actuality, setting a specific bit in the color of each pixel copied). This // can be used to generate strange graphic effects in a window, but that is beyond the scope of // this tutorial. // // // Freeing a pixmap // ---------------- // // Finally, when we are done using a given pixmap, we should free it, in order to free resources of // the X server. This is done using this function: // // fn free_pixmap(&self, pixmap: u32) -> Result; // // Of course, after having freed it, we must not try accessing the pixmap again. // // **TODO**: Give an example, or a link to xpoints.c // // // Messing with the mouse cursor // ============================= // // It it possible to modify the shape of the mouse pointer (also called the X pointer) when in // certain states, as we often see in programs. For example, a busy application would often display // the hourglass cursor over its main window, to give the user a visual hint that they should wait. // Let's see how we can change the mouse cursor of our windows. // // // Creating and destroying a mouse cursor // -------------------------------------- // // There are two methods for creating cursors. One of them is by using a set of predefined cursors, // that are supplied by the X server, the other is by using a user-supplied bitmap. // // In the first method, we use a special font named "cursor", and the function // `xcb_create_glyph_cursor`: // // fn create_glyph_cursor(&self, cid: u32, source_font: u32, mask_font: u32, // source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, // fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) // -> Result; // // **TODO**: Describe `source_char` and `mask_char`, for example by giving an example on how to get // the values. There is a list there: [X Font Cursors](http://tronche.com/gui/x/xlib/appendix/b/) // // So we first open that font (see 'Loading a Font') and create the new cursor. As for // every X resource, we have to ask for an X id with `xcb_generate_id` first: #[allow(unused)] fn example_create_glyph_cursor( conn: &C, win: Window, screen: &Screen, ) -> Result<(), ReplyOrIdError> { let font = conn.generate_id()?; conn.open_font(font, b"cursor")?; let cursor = conn.generate_id()?; conn.create_glyph_cursor(cursor, font, font, 58, 58 + 1, 0, 0, 0, 0, 0, 0)?; Ok(()) } // We have created the cursor "right hand" by specifying 58 to the `source_fon`t argument and 58 + // 1 to the `mask_font`. // // The cursor is destroyed by using the function // // fn free_cursor(&self, cursor: u32) -> Result; // // In the second method, we create a new cursor by using a pair of pixmaps, with depth of one (that // is, two colors pixmaps). One pixmap defines the shape of the cursor, while the other works as a // mask, specifying which pixels of the cursor will be actually drawn. The rest of the pixels will // be transparent. // // **TODO**: give an example. // // // Setting a window's mouse cursor // ------------------------------- // // Once the cursor is created, we can modify the cursor of our window by using // `xcb_change_window_attributes` and using the `XCB_CWCURSOR` attribute: #[allow(unused)] fn example_change_window_cursor( conn: &C, win: Window, cursor: Cursor, ) -> Result<(), ReplyError> { let values = ChangeWindowAttributesAux::default().cursor(cursor); conn.change_window_attributes(win, &values)?; Ok(()) } // Of course, the cursor and the font must be freed. // // // Complete example // ---------------- // // The following example displays a window with a button. When entering the window, the window // cursor is changed to an arrow. When clicking once on the button, the cursor is changed to a // hand. When clicking again on the button, the cursor window gets back to the arrow. The Esc key // exits the application. fn button_draw( conn: &C, screen: &Screen, window: Window, x1: i16, y1: i16, label: &str, ) -> Result<(), ReplyOrIdError> { let inset = 2; let gc = gc_font_get(conn, screen, window, "7x13")?; let width = 7 * label.len() + 2 * (inset + 1); let height = 13 + 2 * (inset + 1); let (width, height) = (width as i16, height as i16); let inset = inset as i16; let points = [ Point { x: x1, y: y1 }, Point { x: x1 + width, y: y1, }, Point { x: x1 + width, y: y1 - height, }, Point { x: x1, y: y1 - height, }, Point { x: x1, y: y1 }, ]; conn.poly_line(CoordMode::ORIGIN, window, gc, &points)?; conn.image_text8(window, gc, x1 + inset + 1, y1 - inset - 1, label.as_bytes())?; conn.free_gc(gc)?; Ok(()) } // text_draw and gc_font_get were already defined above fn cursor_set( conn: &C, screen: &Screen, window: Window, cursor_id: u16, ) -> Result<(), ReplyOrIdError> { let font = conn.generate_id()?; conn.open_font(font, b"cursor")?; let cursor = conn.generate_id()?; conn.create_glyph_cursor( cursor, font, font, cursor_id, cursor_id + 1, 0, 0, 0, 0, 0, 0, )?; let gc = conn.generate_id()?; let values = CreateGCAux::default() .foreground(screen.black_pixel) .background(screen.black_pixel) .font(font); conn.create_gc(gc, window, &values)?; let values = ChangeWindowAttributesAux::default().cursor(cursor); conn.change_window_attributes(window, &values)?; conn.free_cursor(cursor)?; conn.close_font(font)?; Ok(()) } fn example10() -> Result<(), Box> { const WIDTH: i16 = 300; const HEIGHT: i16 = 300; // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None)?; // Get the screen #screen_num let screen = &conn.setup().roots[screen_num]; // Creating the window let window = conn.generate_id()?; let values = CreateWindowAux::default() .background_pixel(screen.white_pixel) .event_mask(EventMask::KEY_RELEASE | EventMask::BUTTON_PRESS | EventMask::EXPOSURE); conn.create_window( screen.root_depth, window, screen.root, 20, 200, WIDTH as u16, HEIGHT as u16, 0, WindowClass::INPUT_OUTPUT, screen.root_visual, &values, )?; conn.map_window(window)?; cursor_set(&conn, screen, window, 68)?; conn.flush()?; let mut is_hand = false; loop { let event = conn.wait_for_event()?; match event { Event::Expose(_) => { let text = "click here to change cursor"; button_draw( &conn, screen, window, (WIDTH - 7 * text.len() as i16) / 2, (HEIGHT - 16) / 2, text, )?; let text = "Press ESC key to exit..."; text_draw(&conn, screen, window, 10, HEIGHT - 10, text)?; conn.flush()?; } Event::ButtonPress(event) => { let length = "click here to change cursor".len() as i16; if (event.event_x >= (WIDTH - 7 * length) / 2) && (event.event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) && (event.event_y >= (HEIGHT - 16) / 2 - 19) && (event.event_y <= ((HEIGHT - 16) / 2)) { is_hand = !is_hand; } if is_hand { cursor_set(&conn, screen, window, 58)?; } else { cursor_set(&conn, screen, window, 68)?; } conn.flush()?; } Event::KeyRelease(event) => { if event.detail == 9 { // ESC return Ok(()); } } _ => {} // Unknown event type, ignore it } } } // Translation of basic Xlib functions and macros // // The problem when you want to port an Xlib program to XCB is that you don't know if the Xlib // function that you want to "translate" is a X Window one or an Xlib macro. In that section, we // describe a way to translate the usual functions or macros that Xlib provides. It's usually just // a member of a structure. // // // Members of the Display structure // -------------------------------- // // In this section, we look at how to translate the macros that return some members of the // `Display` structure. They are obtained by using a function that requires a `xcb_connection_t *` // or a member of the `xcb_setup_t` structure (via the function `xcb_get_setup`), or a function // that requires that structure. // // // ConnectionNumber // // This number is the file descriptor that connects the client to the server. You just have to use // the trait `std::os::unix::io::AsRawFd`. // // // DefaultScreen // // That number is not stored by XCB. It is returned in the second parameter of the function // `connect`. Hence, you have to store it yourself if you want to use it. Then, to get the // `xcb_screen_t` structure, you have to iterate on the screens. The equivalent function of the // Xlib's `ScreenOfDisplay` function can be found below at ScreenOfDisplay. This is also provided // in the xcb_aux_t library as `xcb_aux_get_screen()`. OK, here is the small piece of code to get // that number: #[allow(unused)] fn example_get_screen_number() { let (conn, screen_num) = x11rb::connect(None).unwrap(); // screen_num now contains the number of the default screen } // QLength // // Not documented yet. // // However, this points out a basic difference in philosophy between Xlib and XCB. Xlib has several // functions for filtering and manipulating the incoming and outgoing X message queues. XCB wishes // to hide this as much as possible from the user, which allows for more freedom in implementation // strategies. // // // ScreenCount // // You get the count of screens with the functions `xcb_get_setup` and `xcb_setup_roots_iterator` // (if you need to iterate): #[allow(unused)] fn example_get_screen_count() { let (conn, screen_num) = x11rb::connect(None).unwrap(); let _screen_count = conn.setup().roots.len(); // screen_num now contains the number of the default screen } // ServerVendor // // You get the name of the vendor of the server hardware with the functions `xcb_get_setup` and // `xcb_setup_vendor`. See the next example. // // // ProtocolVersion // // You get the major version of the protocol in the `xcb_setup_t` structure, with the function // `xcb_get_setup`. See the next example. // // // ProtocolRevision // // You get the minor version of the protocol in the `xcb_setup_t` structure, with the function // `xcb_get_setup`. See the next example. // // // VendorRelease // // You get the number of the release of the server hardware in the `xcb_setup_t` structure, with // the function `xcb_get_setup`. See the next example // // // DisplayString // // The name of the display is not stored in XCB. You have to store it by yourself. // // // BitmapUnit // // You get the bitmap scanline unit in the `xcb_setup_t` structure, with the function // `xcb_get_setup`. See the next example. // // // BitmapBitOrder // // You get the bitmap bit order in the `xcb_setup_t` structure, with the function `xcb_get_setup`. // See the next example. // // // BitmapPad // // You get the bitmap scanline pad in the `xcb_setup_t` structure, with the function // `xcb_get_setup`. See the next example. // // // ImageByteOrder // // You get the image byte order in the `xcb_setup_t` structure, with the function `xcb_get_setup`. // See the next example. fn example11() -> Result<(), Box> { let (conn, _) = x11rb::connect(None)?; let setup = conn.setup(); println!( "Name of server vendor is {}", String::from_utf8_lossy(&setup.vendor) ); println!("Release number is {}", setup.release_number); println!( "Protocol version is {}.{}", setup.protocol_major_version, setup.protocol_minor_version ); println!( "Bitmap format scanline unit is {}", setup.bitmap_format_scanline_unit ); println!( "Bitmap format bit order is {:?}", setup.bitmap_format_bit_order ); println!( "Bitmap format scanline pad is {}", setup.bitmap_format_scanline_pad ); println!("Image byte order is {:?}", setup.image_byte_order); Ok(()) } // ScreenOfDisplay related functions // --------------------------------- // // In Xlib, `ScreenOfDisplay` returns a `Screen` structure that contains several characteristics of // your screen. XCB has a similar structure (`xcb_screen_t`), but the way to obtain it is a bit // different. With Xlib, you just provide the number of the screen and you grab it from an array. // With XCB, you iterate over all the screens to obtain the one you want. The complexity of this // operation is O(n). So the best is to store this structure if you use it often. See // ScreenOfDisplay just below. // // Xlib provides generally two functions to obtain the characteristics related to the screen. One // with the display and the number of the screen, which calls `ScreenOfDisplay`, and the other that // uses the `Screen` structure. This might be a bit confusing. As mentioned above, with XCB, it is // better to store the `xcb_screen_t` structure. Then, you have to read the members of this // structure. That's why the Xlib functions are put by pairs (or more) as, with XCB, you will use // the same code. // // // ScreenOfDisplay // // This function returns the Xlib `Screen` structure. With XCB, you iterate over all the screens // and once you get the one you want, you return it: #[allow(unused)] fn example_get_screen(conn: &C, index: usize) -> &Screen { &conn.setup().roots[index] } // As mentioned above, you might want to store the value returned by this function. // // All the functions below will use the result of that function, as they just grab a specific // member of the `xcb_screen_t` structure. // // // DefaultScreenOfDisplay // // It is the default screen that you obtain when you connect to the X server. It suffices to call // the example_get_screen() function above with the connection and the number of the default // screen. #[allow(unused)] fn example_get_screen2(conn: &C, index: usize) { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None).unwrap(); let _default_screen = &conn.setup().roots[screen_num]; } // RootWindow / RootWindowOfScreen // // Just use the .root member of `Screen`. #[allow(unused)] fn example_get_root(conn: &C, index: usize) -> Window { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None).unwrap(); let default_screen = &conn.setup().roots[screen_num]; default_screen.root } // DefaultRootWindow // // It is the root window of the default screen. So, you call `ScreenOfDisplay` with the default // screen number and you get the root window as above in example_get_root(). // // // DefaultVisual / DefaultVisualOfScreen // // While a Visual is, in Xlib, a structure, in XCB, there are two types: `xcb_visualid_t`, which is // the Id of the visual, and `xcb_visualtype_t`, which corresponds to the Xlib Visual. To get the // Id of the visual of a screen, just get the `root_visual` member of a `xcb_screen_t`: #[allow(unused)] fn example_get_visual() { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None).unwrap(); let screen = &conn.setup().roots[screen_num]; let _root_visual = screen.root_visual; } // To get the `xcb_visualtype_t` structure, it's a bit less easy. You have to get the // `xcb_screen_t` structure that you want, get its `root_visual` member, then iterate over the // `xcb_depth_t`s and the `xcb_visualtype_t`s, and compare the `xcb_visualid_t` of these // `xcb_visualtype_t`s: with `root_visual`: #[allow(unused)] fn example_get_visual2(conn: &C, screen_num: usize) { // Open the connection to the X server. Use the DISPLAY environment variable. let (conn, screen_num) = x11rb::connect(None).unwrap(); let screen = &conn.setup().roots[screen_num]; for depth in &screen.allowed_depths { for visualtype in &depth.visuals { if visualtype.visual_id == screen.root_visual { println!("Found: {:?}", visualtype); } } } } // DefaultGC / DefaultGCOfScreen // // This default Graphic Context is just a newly created Graphic Context, associated to the root // window of a `xcb_screen_t`, using the black white pixels of that screen: #[allow(unused)] fn example_create_default_gc( conn: &C, screen_num: usize, ) -> Result { let screen = &conn.setup().roots[screen_num]; let values = CreateGCAux::default() .foreground(screen.black_pixel) .background(screen.white_pixel); let gc = conn.generate_id()?; conn.create_gc(gc, screen.root, &values)?; Ok(gc) } // BlackPixel / BlackPixelOfScreen // // It is the Id of the black pixel, which is in the structure of an `xcb_screen_t`. #[allow(unused)] fn example_black_pixel(conn: &C, screen_num: usize) { let _black_pixel = conn.setup().roots[screen_num].black_pixel; } // WhitePixel / WhitePixelOfScreen // // It is the Id of the white pixel, which is in the structure of an `xcb_screen_t`. #[allow(unused)] fn example_white_pixel(conn: &C, screen_num: usize) { let _white_pixel = conn.setup().roots[screen_num].white_pixel; } // DisplayWidth / WidthOfScreen // // It is the width in pixels of the screen that you want, and which is in the structure of the // corresponding `xcb_screen_t`. #[allow(unused)] fn example_display_width(conn: &C, screen_num: usize) { let _width = conn.setup().roots[screen_num].width_in_pixels; } // DisplayHeight / HeightOfScreen // // It is the height in pixels of the screen that you want, and which is in the structure of the // corresponding `xcb_screen_t`. #[allow(unused)] fn example_display_height(conn: &C, screen_num: usize) { let _height = conn.setup().roots[screen_num].height_in_pixels; } // DisplayWidthMM / WidthMMOfScreen // // It is the width in millimeters of the screen that you want, and which is in the structure of the // corresponding `xcb_screen_t`. #[allow(unused)] fn example_display_width_mm(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _width = screen.width_in_millimeters; } // DisplayHeightMM / HeightMMOfScreen // // It is the height in millimeters of the screen that you want, and which is in the structure of // the corresponding `xcb_screen_t`. #[allow(unused)] fn example_display_height_mm(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _height = screen.height_in_millimeters; } // DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen // // It is the depth (in bits) of the root window of the screen. You get it from the `xcb_screen_t` // structure. #[allow(unused)] fn example_display_depth(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _depth = screen.root_depth; } // DefaultColormap / DefaultColormapOfScreen // // This is the default colormap of the screen (and not the (default) colormap of the default screen // !). As usual, you get it from the `xcb_screen_t` structure: #[allow(unused)] fn example_display_colormap(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _map = screen.default_colormap; } // MinCmapsOfScreen // // You get the minimum installed colormaps in the `xcb_screen_t` structure: #[allow(unused)] fn example_display_min_installed_maps(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _min_installed = screen.min_installed_maps; } // MaxCmapsOfScreen // // You get the maximum installed colormaps in the `xcb_screen_t` structure: #[allow(unused)] fn example_display_max_installed_maps(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _max_installed = screen.max_installed_maps; } // DoesSaveUnders // // You know if `save_unders` is set, by looking in the `xcb_screen_t` structure: #[allow(unused)] fn example_save_unders(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _save_unders = screen.save_unders; } // DoesBackingStore // // You know the value of `backing_stores`, by looking in the `xcb_screen_t` structure: #[allow(unused)] fn example_backing_store(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _backing_stores = screen.backing_stores; } // EventMaskOfScreen // // To get the current input masks, you look in the `xcb_screen_t` structure: #[allow(unused)] fn example_input_masks(conn: &C, screen_num: usize) { let screen = &conn.setup().roots[screen_num]; let _input_masks = screen.current_input_masks; } // Miscellaneous macros // -------------------- // // // DisplayOfScreen // // in Xlib, the `Screen` structure stores its associated `Display` structure. This is not the case in the X Window protocol, hence, it's also not the case in XCB. So you have to store it by yourself. // // // DisplayCells / CellsOfScreen // // To get the colormap entries, you look in the `xcb_visualtype_t` structure, that you grab as // shown above: #[allow(unused)] fn example_visual_colormap_entries(visual: &Visualtype) -> u16 { visual.colormap_entries } fn main() { example1().unwrap(); example2().unwrap(); example3().unwrap(); example4().unwrap(); example5().unwrap(); example6().unwrap(); example7().unwrap(); example8().unwrap(); example9().unwrap(); example10().unwrap(); example11().unwrap(); } x11rb-0.13.0/examples/xclock_utc.rs000064400000000000000000000201361046102023000151660ustar 00000000000000use 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 { 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::>(); // ... 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> { // 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> { 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); impl Drop for CallOnDrop { fn drop(&mut self) { (self.0)(); } } x11rb-0.13.0/examples/xeyes.rs000064400000000000000000000254761046102023000142010ustar 00000000000000// 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( 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( 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( 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( conn: &C, screen: &Screen, window_size: (u16, u16), wm_protocols: Atom, wm_delete_window: Atom, ) -> Result { 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( conn: C, win_id: Window, foreground: u32, ) -> Result, ReplyOrIdError> { GcontextWrapper::create_gc( conn, win_id, &CreateGCAux::new() .graphics_exposures(0) .foreground(foreground), ) } fn main() -> Result<(), Box> { 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"); x11rb-0.13.0/src/connection/impls.rs000064400000000000000000000174741046102023000152770ustar 00000000000000//! Implement RequestConnection for wrappers around other connection types, e.g. //! `Box`. 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( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, ConnectionError> where R: TryParse, { (**self) .send_request_with_reply(bufs, fds) .map(|cookie| cookie.replace_connection(self)) } fn send_trait_request_with_reply( &self, request: R, ) -> Result::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( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, 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( &self, request: R, ) -> Result, 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, ) -> Result, ConnectionError> { (**self) .send_request_without_reply(bufs, fds) .map(|cookie| cookie.replace_connection(self)) } fn send_trait_request_without_reply( &self, request: R, ) -> Result, 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, ConnectionError> { (**self).extension_information(extension_name) } fn wait_for_reply_or_error( &self, sequence: SequenceNumber, ) -> Result { (**self).wait_for_reply_or_error(sequence) } fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, ) -> Result, ConnectionError> { (**self).wait_for_reply_or_raw_error(sequence) } fn wait_for_reply( &self, sequence: SequenceNumber, ) -> Result, ConnectionError> { (**self).wait_for_reply(sequence) } fn wait_for_reply_with_fds( &self, sequence: SequenceNumber, ) -> Result, ReplyError> { (**self).wait_for_reply_with_fds(sequence) } fn wait_for_reply_with_fds_raw( &self, sequence: SequenceNumber, ) -> Result, 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, 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 { (**self).parse_error(error) } fn parse_event(&self, event: &[u8]) -> Result { (**self).parse_event(event) } }; } macro_rules! impl_deref_connection_inner { () => { fn wait_for_event(&self) -> Result { (**self).wait_for_event() } fn wait_for_raw_event(&self) -> Result { (**self).wait_for_raw_event() } fn wait_for_event_with_sequence(&self) -> Result { (**self).wait_for_event_with_sequence() } fn wait_for_raw_event_with_sequence( &self, ) -> Result, ConnectionError> { (**self).wait_for_raw_event_with_sequence() } fn poll_for_event(&self) -> Result, ConnectionError> { (**self).poll_for_event() } fn poll_for_raw_event(&self) -> Result, ConnectionError> { (**self).poll_for_raw_event() } fn poll_for_event_with_sequence( &self, ) -> Result, ConnectionError> { (**self).poll_for_event_with_sequence() } fn poll_for_raw_event_with_sequence( &self, ) -> Result>, 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 { (**self).generate_id() } }; } macro_rules! impl_deref_connection { ($type:ty) => { impl RequestConnection for $type { impl_deref_request_connection_inner!(); } impl Connection for $type { impl_deref_connection_inner!(); } }; } impl_deref_connection!(&C); impl_deref_connection!(&mut C); impl_deref_connection!(Box); impl_deref_connection!(std::sync::Arc); impl_deref_connection!(std::rc::Rc); impl RequestConnection for std::borrow::Cow<'_, C> { impl_deref_request_connection_inner!(); } impl Connection for std::borrow::Cow<'_, C> { impl_deref_connection_inner!(); } x11rb-0.13.0/src/connection/mod.rs000064400000000000000000000605741046102023000147310ustar 00000000000000//! 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::convert::{TryFrom, TryInto}; 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, Vec); /// 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 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( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, 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( &self, request: R, ) -> Result::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( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, 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( &self, request: R, ) -> Result, 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, ) -> Result, 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( &self, request: R, ) -> Result, 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, 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 { 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, 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, 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, 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, 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, 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; /// Parse a generic event. fn parse_event(&self, event: &[u8]) -> Result; } /// 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 { 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 { 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 { 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, ConnectionError>; /// Poll for a new event from the X11 server. fn poll_for_event(&self) -> Result, 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, 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, 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>, 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; } /// 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; /// /// // [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, ConnectionError> { /// # unimplemented!() /// # } /// # fn wait_for_reply_or_raw_error(&self, sequence: SequenceNumber) /// # -> Result>, ConnectionError> { /// # unimplemented!() /// # } /// # fn wait_for_reply(&self, sequence: SequenceNumber) /// # -> Result>, x11rb::errors::ConnectionError> { /// # unimplemented!() /// # } /// # fn wait_for_reply_with_fds_raw(&self, sequence: SequenceNumber) /// # -> Result>, Vec>, ConnectionError> { /// # unimplemented!() /// # } /// # fn check_for_raw_error(&self, sequence: SequenceNumber) /// # ->Result>, ConnectionError> { /// # unimplemented!() /// # } /// # fn maximum_request_bytes(&self) -> usize { /// # unimplemented!() /// # } /// # fn prefetch_maximum_request_bytes(&self) { /// # unimplemented!() /// # } /// # fn parse_error(&self, _error: &[u8]) -> Result { /// # unimplemented!() /// # } /// # fn parse_event(&self, _event: &[u8]) -> Result { /// # unimplemented!() /// # } /// /// fn send_request_with_reply(&self, bufs: &[IoSlice], fds: Vec) /// -> Result, ConnectionError> /// where R: TryParse { /// Ok(Cookie::new(self, self.send_request(bufs, fds, true, false)?)) /// } /// /// fn send_request_with_reply_with_fds(&self, bufs: &[IoSlice], fds: Vec) /// -> Result, 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) /// -> Result, ConnectionError> { /// Ok(VoidCookie::new(self, self.send_request(bufs, fds, false, false)?)) /// } /// } /// /// impl MyConnection { /// fn send_request(&self, bufs: &[IoSlice], fds: Vec, /// has_reply: bool, reply_has_fds: bool) /// -> Result /// { /// 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>, [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[..]) } x11rb-0.13.0/src/cookie.rs000064400000000000000000000371251046102023000132600ustar 00000000000000//! 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` since that still refers to the same /// underlying connection. pub(crate) fn replace_connection( self, connection: &C2, ) -> VoidCookie<'_, C2> { let (_, sequence_number) = self.consume(); VoidCookie { connection, sequence_number, } } } impl 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 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` since that still refers to the same /// underlying connection. fn replace_connection( self, connection: &C2, ) -> RawCookie<'_, C2> { RawCookie { connection, sequence_number: self.into_sequence_number(), } } } impl 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, } impl 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 { 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, 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 { 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, 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` since that still refers to the same /// underlying connection. pub(crate) fn replace_connection( 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, } impl 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, 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 { 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` since that still refers to the same /// underlying connection. pub(crate) fn replace_connection( 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>); 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 { self.0.as_ref().map(|x| x.sequence_number) } } impl Iterator for $name<'_, C> where C: RequestConnection + ?Sized, { type Item = Result<$reply, ReplyError>; fn next(&mut self) -> Option { 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 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 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 } } x11rb-0.13.0/src/cursor/find_cursor.rs000064400000000000000000000267721046102023000156470ustar 00000000000000//! 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::env::{var, var_os}; use std::ffi::OsStr; use std::fs::File; use std::io::{BufRead, BufReader, Error as IOError}; use std::path::{Path, PathBuf}; 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 { CORE_CURSORS .iter() .filter(|&(name2, _)| name == *name2) .map(|&(_, id)| id) .next() } /// An error that occurred while searching #[derive(Debug)] pub(crate) enum Error { /// `$HOME` is not set NoHomeDir, /// No cursor file could be found NothingFound, } /// 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(F), } // Get the 'Inherits' entry from an index.theme file fn parse_inherits(filename: &Path) -> Result, IOError> { let file = File::open(filename)?; parse_inherits_impl(&mut BufReader::new(file)) } // Get the 'Inherits' entry from an index.theme file fn parse_inherits_impl(input: &mut impl BufRead) -> Result, IOError> { let mut buffer = Vec::new(); loop { buffer.clear(); // Read a line if 0 == input.read_until(b'\n', &mut buffer)? { // End of file, return an empty result return Ok(Default::default()); } // Remove end of line marker if buffer.last() == Some(&b'\n') { let _ = buffer.pop(); } let begin = b"Inherits"; if buffer.starts_with(begin) { let mut result = Vec::new(); let mut to_parse = &buffer[begin.len()..]; fn skip_while(mut slice: &[u8], f: impl Fn(u8) -> bool) -> &[u8] { while !slice.is_empty() && f(slice[0]) { slice = &slice[1..] } slice } // Skip all spaces to_parse = skip_while(to_parse, |c| c == b' '); // Now we need an equal sign if to_parse.first() == Some(&b'=') { to_parse = &to_parse[1..]; fn should_skip(c: u8) -> bool { matches!(c, b' ' | b'\t' | b'\n' | b';' | b',') } // Iterate over the pieces for mut part in to_parse.split(|&x| x == b':') { // Skip all leading whitespace part = skip_while(part, should_skip); // Skip all trailing whitespace while let Some((&last, rest)) = part.split_last() { if !should_skip(last) { break; } part = rest; } if !part.is_empty() { if let Ok(part) = std::str::from_utf8(part) { result.push(part.to_string()); } } } } return Ok(result); } } } #[cfg(test)] mod test_parse_inherits { use super::parse_inherits_impl; use std::io::Cursor; #[test] fn parse_inherits_successful() { let input = b"Hi\nInherits = \t ; whatever ;,::; stuff : i s ,: \tthis \t \nInherits=ignored\n"; let mut input = Cursor::new(&input[..]); let result = parse_inherits_impl(&mut input).unwrap(); assert_eq!(result, vec!["whatever", "stuff", "i s", "this"]); } } /// 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) -> Result, Error> { let home = match var_os("HOME") { Some(home) => home, None => return Err(Error::NoHomeDir), }; let cursor_path = var("XCURSOR_PATH").unwrap_or_else(|_| { "~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons".into() }); let open_cursor = |file: &Path| File::open(file); find_cursor_impl( &home, &cursor_path, theme, name, open_cursor, parse_inherits, ) } fn find_cursor_impl( home: &OsStr, cursor_path: &str, theme: &str, name: &str, mut open_cursor: G, mut parse_inherits: H, ) -> Result, Error> where G: FnMut(&Path) -> Result, H: FnMut(&Path) -> Result, IOError>, { if theme == "core" { if let Some(id) = cursor_shape_to_id(name) { return Ok(Cursor::CoreChar(id)); } } let cursor_path = cursor_path.split(':').collect::>(); let mut next_inherits = Vec::new(); let mut last_inherits = vec![theme.into()]; while !last_inherits.is_empty() { for theme in last_inherits { for path in &cursor_path { // Calculate the path to the theme's directory let mut theme_dir = PathBuf::new(); // Does the path begin with '~'? if let Some(mut path) = path.strip_prefix('~') { theme_dir.push(home); // Skip a path separator if there is one if path.chars().next().map(std::path::is_separator) == Some(true) { path = &path[1..]; } theme_dir.push(path); } else { theme_dir.push(path); } theme_dir.push(&theme); // Find the cursor in the theme let mut cursor_file = theme_dir.clone(); cursor_file.push("cursors"); cursor_file.push(name); if let Ok(file) = open_cursor(&cursor_file) { return Ok(Cursor::File(file)); } // Get the theme's index.theme file and parse its 'Inherits' line let mut index = theme_dir; index.push("index.theme"); if let Ok(res) = parse_inherits(&index) { next_inherits.extend(res); } } } last_inherits = next_inherits; next_inherits = Vec::new(); } Err(Error::NothingFound) } // FIXME: Make these tests pass on Windows; problem is "/" vs "\\" in paths #[cfg(all(test, unix))] mod test_find_cursor { use super::{find_cursor_impl, Cursor, Error}; use crate::errors::ConnectionError; use std::io::{Error as IOError, ErrorKind}; use std::path::Path; #[test] fn core_cursor() { let cb1 = |_: &Path| -> Result<(), _> { unimplemented!() }; let cb2 = |_: &Path| unimplemented!(); match find_cursor_impl("unused".as_ref(), "unused", "core", "heart", cb1, cb2).unwrap() { Cursor::CoreChar(31) => {} e => panic!("Unexpected result {:?}", e), } } #[test] fn nothing_found() { let mut opened = Vec::new(); let mut inherit_parsed = Vec::new(); let cb1 = |path: &Path| -> Result<(), _> { opened.push(path.to_str().unwrap().to_owned()); Err(IOError::new( ErrorKind::Other, ConnectionError::UnknownError, )) }; let cb2 = |path: &Path| { inherit_parsed.push(path.to_str().unwrap().to_owned()); Ok(Vec::new()) }; match find_cursor_impl( "home".as_ref(), "path:~/some/:/entries", "theme", "theCursor", cb1, cb2, ) { Err(Error::NothingFound) => {} e => panic!("Unexpected result {:?}", e), } assert_eq!( opened, &[ "path/theme/cursors/theCursor", "home/some/theme/cursors/theCursor", "/entries/theme/cursors/theCursor", ] ); assert_eq!( inherit_parsed, &[ "path/theme/index.theme", "home/some/theme/index.theme", "/entries/theme/index.theme", ] ); } #[test] fn inherit() { let mut opened = Vec::new(); let cb1 = |path: &Path| -> Result<(), _> { opened.push(path.to_str().unwrap().to_owned()); Err(IOError::new( ErrorKind::Other, ConnectionError::UnknownError, )) }; let cb2 = |path: &Path| { if path.starts_with("base/theTheme") { Ok(vec!["inherited".into()]) } else if path.starts_with("path/inherited") { Ok(vec!["theEnd".into()]) } else { Ok(vec![]) } }; match find_cursor_impl( "home".as_ref(), "path:base:tail", "theTheme", "theCursor", cb1, cb2, ) { Err(Error::NothingFound) => {} e => panic!("Unexpected result {:?}", e), } assert_eq!( opened, &[ "path/theTheme/cursors/theCursor", "base/theTheme/cursors/theCursor", "tail/theTheme/cursors/theCursor", "path/inherited/cursors/theCursor", "base/inherited/cursors/theCursor", "tail/inherited/cursors/theCursor", "path/theEnd/cursors/theCursor", "base/theEnd/cursors/theCursor", "tail/theEnd/cursors/theCursor", ] ); } } x11rb-0.13.0/src/cursor/mod.rs000064400000000000000000000262431046102023000141020ustar 00000000000000//! 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, Font, Window}; use crate::resource_manager::Database; use crate::NONE; use std::fs::File; 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> { conn: &'a C, screen: &'a xproto::Screen, resource_database: &'b Database, render_info: Option<( X11Cookie<'a, C, render::QueryVersionReply>, X11Cookie<'a, C, render::QueryPictFormatsReply>, )>, } impl Cookie<'_, '_, C> { /// Get the handle from the replies from the X11 server pub fn reply(self) -> Result { 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.conn, 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, 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.conn, self.screen, self.resource_database, render_version, picture_format, )?)) } fn from_replies( conn: &C, screen: &xproto::Screen, resource_database: &Database, render_version: (u32, u32), picture_format: Pictformat, ) -> Result { 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 = 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); let cursor_font = conn.generate_id()?; let _ = xproto::open_font(conn, cursor_font, b"cursor")?; Ok(Handle { root: screen.root, cursor_font, picture_format, render_support, theme, cursor_size, }) } } /// A handle necessary for loading cursors #[derive(Debug)] pub struct Handle { root: Window, cursor_font: Font, picture_format: Pictformat, render_support: RenderSupport, theme: Option, 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, 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 { conn, 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(&self, conn: &C, name: &str) -> Result where C: Connection, { load_cursor(conn, self, name) } } fn open_cursor(theme: &Option, name: &str) -> Option> { if let Some(theme) = theme { if let Ok(cursor) = find_cursor::find_cursor(theme, name) { return Some(cursor); } } if let Ok(cursor) = find_cursor::find_cursor("default", name) { Some(cursor) } else { None } } fn create_core_cursor( conn: &C, cursor_font: Font, cursor: u16, ) -> Result { let result = conn.generate_id()?; let _ = xproto::create_glyph_cursor( conn, result, cursor_font, cursor_font, cursor, cursor + 1, // foreground color 0, 0, 0, // background color u16::max_value(), u16::max_value(), u16::max_value(), )?; Ok(result) } fn create_render_cursor( conn: &C, handle: &Handle, image: &parse_cursor::Image, storage: &mut Option<(xproto::Pixmap, xproto::Gcontext, u16, u16)>, ) -> Result { let (cursor, picture) = (conn.generate_id()?, conn.generate_id()?); // Get a pixmap of the right size and a gc for it let (pixmap, gc) = if storage.map(|(_, _, w, h)| (w, h)) == Some((image.width, image.height)) { storage.map(|(pixmap, gc, _, _)| (pixmap, gc)).unwrap() } else { 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, image.width, image.height)?; let _ = xproto::create_gc(conn, gc, pixmap, &Default::default())?; *storage = Some((pixmap, gc, image.width, image.height)); (pixmap, gc) }; // Sigh. We need the pixel data as a bunch of bytes. let pixels = crate::x11_utils::Serialize::serialize(&image.pixels[..]); let _ = xproto::put_image( conn, xproto::ImageFormat::Z_PIXMAP, pixmap, gc, image.width, image.height, 0, 0, 0, 32, &pixels, )?; let _ = render::create_picture( conn, picture, pixmap, handle.picture_format, &Default::default(), )?; let _ = render::create_cursor(conn, cursor, picture, image.x_hot, image.y_hot)?; let _ = render::free_picture(conn, picture)?; Ok(render::Animcursorelt { cursor, delay: image.delay, }) } fn load_cursor( conn: &C, handle: &Handle, name: &str, ) -> Result { // 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, handle.cursor_font, 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::, _>>()?; 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) } x11rb-0.13.0/src/cursor/parse_cursor.rs000064400000000000000000000423641046102023000160340ustar 00000000000000//! 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::convert::TryInto; use std::io::{Read, Seek, SeekFrom}; const FILE_MAGIC: u32 = 0x7275_6358; const IMAGE_TYPE: u32 = 0xfffd_0002; const IMAGE_MAX_SIZE: u16 = 0x7fff; /// An error that occurred while parsing #[derive(Debug)] pub(crate) enum Error { /// An I/O error occurred Io(std::io::Error), /// The file did not begin with the expected magic InvalidMagic, /// The file contained unrealistically many images TooManyEntries, /// The file contains no images NoImages, /// Some image's entry is corrupt and not self-consistent CorruptImage, /// An entry is larger than the maximum size ImageTooLarge, } impl From for Error { fn from(value: std::io::Error) -> Self { Error::Io(value) } } /// Read a single `u32` from a cursor file /// /// The file stores these entries in little endian. fn read_u32(read: &mut R) -> Result { let mut buffer = [0; 4]; read.read_exact(&mut buffer)?; Ok(u32::from_le_bytes(buffer)) } /// A single cursor image #[derive(Debug)] pub(crate) struct Image { pub(crate) width: u16, pub(crate) height: u16, pub(crate) x_hot: u16, pub(crate) y_hot: u16, pub(crate) delay: u32, pub(crate) pixels: Vec, } impl Image { /// Read an `Image` from a reader fn read(read: &mut R, expected_kind: u32, expected_size: u32) -> Result { let (_header, kind, size, _version) = ( read_u32(read)?, read_u32(read)?, read_u32(read)?, read_u32(read)?, ); if (kind, size) != (expected_kind, expected_size) { return Err(Error::CorruptImage); } fn convert_size(size: u32) -> Result { size.try_into() .ok() .filter(|&size| size <= IMAGE_MAX_SIZE) .ok_or(Error::ImageTooLarge) } let (width, height) = ( convert_size(read_u32(read)?)?, convert_size(read_u32(read)?)?, ); let (x_hot, y_hot) = (read_u32(read)?, read_u32(read)?); let delay = read_u32(read)?; let x_hot = x_hot.try_into().or(Err(Error::ImageTooLarge))?; let y_hot = y_hot.try_into().or(Err(Error::ImageTooLarge))?; let num_pixels = u32::from(width) * u32::from(height); let pixels = (0..num_pixels) .map(|_| read_u32(read)) .collect::, _>>()?; Ok(Image { width, height, x_hot, y_hot, delay, pixels, }) } } /// A TOC entry in a cursor file #[derive(Debug)] struct TocEntry { kind: u32, size: u32, position: u32, } impl TocEntry { /// Read a `TocEntry` from a reader fn read(read: &mut R) -> Result { Ok(TocEntry { kind: read_u32(read)?, size: read_u32(read)?, position: read_u32(read)?, }) } } /// Find the size of the image in the toc with a size as close as possible to the desired size. fn find_best_size(toc: &[TocEntry], desired_size: u32) -> Result { fn distance(a: u32, b: u32) -> u32 { a.max(b) - a.min(b) } fn is_better(desired_size: u32, entry: &TocEntry, result: &Result) -> 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 toc { // If this is better than the best so far, replace best if entry.kind == IMAGE_TYPE && is_better(desired_size, entry, &result) { result = Ok(entry.size) } } result } /// Parse a complete cursor file pub(crate) fn parse_cursor( input: &mut R, desired_size: u32, ) -> Result, Error> { let (magic, header, _version, ntoc) = ( read_u32(input)?, read_u32(input)?, read_u32(input)?, read_u32(input)?, ); if magic != FILE_MAGIC { return Err(Error::InvalidMagic); } if ntoc > 0x1_0000 { return Err(Error::TooManyEntries); } // Read the table of contents let _ = input.seek(SeekFrom::Start(header.into()))?; let toc = (0..ntoc) .map(|_| TocEntry::read(input)) .collect::, _>>()?; // Find the cursor size that we should load let size = find_best_size(&toc, desired_size)?; // Now load all cursors that have the right size let mut result = Vec::new(); for entry in toc { if entry.kind != IMAGE_TYPE || entry.size != size { continue; } let _ = input.seek(SeekFrom::Start(entry.position.into()))?; result.push(Image::read(input, entry.kind, entry.size)?); } Ok(result) } #[cfg(test)] mod test { use super::{find_best_size, parse_cursor, Error, Image, TocEntry, IMAGE_TYPE}; use std::io::{Cursor, ErrorKind}; #[test] fn read_3x5_image() { let data = [ 0x00, 0x00, 0x00, 0x00, // header(?) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x03, 0x00, 0x00, 0x00, // width 3 0x05, 0x00, 0x00, 0x00, // height 5 0x07, 0x00, 0x00, 0x00, // x_hot 7 0x08, 0x00, 0x00, 0x00, // y_hot 8 0x2a, 0x00, 0x00, 0x00, // delay 42 // pixels 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, ]; let image = Image::read(&mut Cursor::new(&data[..]), IMAGE_TYPE, 4).unwrap(); assert_eq!(image.width, 3); assert_eq!(image.height, 5); assert_eq!(image.x_hot, 7); assert_eq!(image.y_hot, 8); assert_eq!(image.delay, 42); assert_eq!( image.pixels, &[ 0x0403_0201, 0x0807_0605, 0x0c0b_0a09, 0x100f_0e0d, 0x1413_1211, 0x1817_1615, 0x1c1b_1a19, 0x201f_1e1d, 0x2423_2221, 0x2827_2625, 0x2c2b_2a29, 0x302f_2e2d, 0x3433_3231, 0x3837_3635, 0x3c3b_3a39, ] ); } #[test] fn read_corrupt_image_wrong_kind() { let data = [ 0x00, 0x00, 0x00, 0x00, // header(?) 0x01, 0x00, 0xfd, 0xff, // IMAGE_TYPE - 1 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // width 0 0x00, 0x00, 0x00, 0x00, // height 0 0x00, 0x00, 0x00, 0x00, // x_hot 0 0x00, 0x00, 0x00, 0x00, // y_hot 0 0x00, 0x00, 0x00, 0x00, // delay 0 ]; match Image::read(&mut Cursor::new(&data[..]), IMAGE_TYPE, 4) { Err(Error::CorruptImage) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn read_corrupt_image_wrong_size() { let data = [ 0x00, 0x00, 0x00, 0x00, // header(?) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // width 0 0x00, 0x00, 0x00, 0x00, // height 0 0x00, 0x00, 0x00, 0x00, // x_hot 0 0x00, 0x00, 0x00, 0x00, // y_hot 0 0x00, 0x00, 0x00, 0x00, // delay 0 ]; match Image::read(&mut Cursor::new(&data[..]), IMAGE_TYPE, 42) { Err(Error::CorruptImage) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn read_image_too_large_width() { let data = [ 0x00, 0x00, 0x00, 0x00, // header(?) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x80, 0x00, 0x00, // width IMAGE_MAX_SIZE + 1 0x00, 0x00, 0x00, 0x00, // height 0 0x00, 0x00, 0x00, 0x00, // x_hot 0 0x00, 0x00, 0x00, 0x00, // y_hot 0 0x00, 0x00, 0x00, 0x00, // delay 0 ]; match Image::read(&mut Cursor::new(&data[..]), IMAGE_TYPE, 4) { Err(Error::ImageTooLarge) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn read_image_too_large_height() { let data = [ 0x00, 0x00, 0x00, 0x00, // header(?) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // width 0 0x00, 0x80, 0x00, 0x00, // height IMAGE_MAX_SIZE + 1 0x00, 0x00, 0x00, 0x00, // x_hot 0 0x00, 0x00, 0x00, 0x00, // y_hot 0 0x00, 0x00, 0x00, 0x00, // delay 0 ]; match Image::read(&mut Cursor::new(&data[..]), IMAGE_TYPE, 4) { Err(Error::ImageTooLarge) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn read_image_too_short() { let data = []; match Image::read(&mut Cursor::new(&data[..]), IMAGE_TYPE, 4) { Err(Error::Io(ref e)) if e.kind() == ErrorKind::UnexpectedEof => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn find_best_size_empty_input() { let res = find_best_size(&[], 42); match res { Err(Error::NoImages) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn find_best_size_one_input() { let input = [TocEntry { kind: IMAGE_TYPE, size: 42, position: 42, }]; assert_eq!(42, find_best_size(&input, 10).unwrap()); } #[test] fn find_best_size_selects_better() { let input = [ TocEntry { kind: IMAGE_TYPE, size: 42, position: 42, }, TocEntry { kind: IMAGE_TYPE, size: 32, position: 42, }, TocEntry { kind: IMAGE_TYPE, size: 3, position: 42, }, TocEntry { kind: IMAGE_TYPE, size: 22, position: 42, }, TocEntry { kind: 0, size: 10, position: 42, }, ]; assert_eq!(3, find_best_size(&input, 10).unwrap()); } #[test] fn parse_cursor_too_short() { let data = []; match parse_cursor(&mut Cursor::new(&data[..]), 10) { Err(Error::Io(ref e)) if e.kind() == ErrorKind::UnexpectedEof => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn parse_cursor_incorrect_magic() { let data = [ 0x00, 0x00, 0x00, 0x00, // magic 0x00, 0x00, 0x00, 0x00, // header file offset 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // num TOC entries ]; match parse_cursor(&mut Cursor::new(&data[..]), 10) { Err(Error::InvalidMagic) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn parse_cursor_too_many_entries() { let data = [ b'X', b'c', b'u', b'r', // magic 0x00, 0x00, 0x00, 0x00, // header file offset 0x00, 0x00, 0x00, 0x00, // version(?) 0x01, 0x00, 0x01, 0x00, // num TOC entries, limit + 1 ]; match parse_cursor(&mut Cursor::new(&data[..]), 10) { Err(Error::TooManyEntries) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn parse_cursor_empty_toc() { let data = [ b'X', b'c', b'u', b'r', // magic 0x10, 0x00, 0x00, 0x00, // header file offset (16) 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // num TOC entries, 0 ]; match parse_cursor(&mut Cursor::new(&data[..]), 10) { Err(Error::NoImages) => {} r => panic!("Unexpected result {:?}", r), } } #[test] fn parse_cursor_one_image() { let data = [ b'X', b'c', b'u', b'r', // magic 0x10, 0x00, 0x00, 0x00, // header file offset (16) 0x00, 0x00, 0x00, 0x00, // version(?) 0x01, 0x00, 0x00, 0x00, // num TOC entries, 1 // TOC 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x1c, 0x00, 0x00, 0x00, // image offset (28) // image 0x00, 0x00, 0x00, 0x00, // header(?) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // width 0 0x00, 0x00, 0x00, 0x00, // height 0 0x00, 0x00, 0x00, 0x00, // x_hot 0 0x00, 0x00, 0x00, 0x00, // y_hot 0 0x00, 0x00, 0x00, 0x00, // delay 0 ]; let expected = [Image { width: 0, height: 0, x_hot: 0, y_hot: 0, delay: 0, pixels: vec![], }]; let actual = parse_cursor(&mut Cursor::new(&data[..]), 10).unwrap(); assert_same_images(&expected, &actual); } #[test] fn parse_cursor_two_images_plus_one_ignored() { let data = [ b'X', b'c', b'u', b'r', // magic 0x10, 0x00, 0x00, 0x00, // header file offset (16) 0x00, 0x00, 0x00, 0x00, // version(?) 0x03, 0x00, 0x00, 0x00, // num TOC entries, 3 // TOC 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x34, 0x00, 0x00, 0x00, // image offset (52) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x03, 0x00, 0x00, 0x00, // size 3 0x34, 0x00, 0x00, 0x00, // image offset (52) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x34, 0x00, 0x00, 0x00, // image offset (52) // image 0x00, 0x00, 0x00, 0x00, // header(?) 0x02, 0x00, 0xfd, 0xff, // IMAGE_TYPE 0x04, 0x00, 0x00, 0x00, // size 4 0x00, 0x00, 0x00, 0x00, // version(?) 0x00, 0x00, 0x00, 0x00, // width 0 0x00, 0x00, 0x00, 0x00, // height 0 0x00, 0x00, 0x00, 0x00, // x_hot 0 0x00, 0x00, 0x00, 0x00, // y_hot 0 0x00, 0x00, 0x00, 0x00, // delay 0 ]; let expected = [ Image { width: 0, height: 0, x_hot: 0, y_hot: 0, delay: 0, pixels: vec![], }, Image { width: 0, height: 0, x_hot: 0, y_hot: 0, delay: 0, pixels: vec![], }, ]; let actual = parse_cursor(&mut Cursor::new(&data[..]), 10).unwrap(); assert_same_images(&expected, &actual); } fn assert_same_images(a: &[Image], b: &[Image]) { assert_eq!(a.len(), b.len(), "{:?} == {:?}", a, b); for (i, (im1, im2)) in a.iter().zip(b.iter()).enumerate() { assert_eq!( im1.width, im2.width, "Width image {}: {} == {}", i + 1, im1.width, im2.width ); assert_eq!( im1.height, im2.height, "Height image {}: {} == {}", i + 1, im1.height, im2.height ); assert_eq!( im1.x_hot, im2.x_hot, "X-hot image {}: {} == {}", i + 1, im1.x_hot, im2.x_hot ); assert_eq!( im1.y_hot, im2.y_hot, "Y-hot image {}: {} == {}", i + 1, im1.y_hot, im2.y_hot ); assert_eq!( im1.delay, im2.delay, "Delay image {}: {} == {}", i + 1, im1.delay, im2.delay ); assert_eq!( im1.pixels, im2.pixels, "Pixels image {}: {:?} == {:?}", i + 1, im1.pixels, im2.pixels ); } } } x11rb-0.13.0/src/errors.rs000064400000000000000000000141441046102023000133170ustar 00000000000000//! 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, 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 for ConnectionError { fn from(err: ParseError) -> Self { ConnectionError::ParseError(err) } } impl From 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 for ReplyError { fn from(err: ParseError) -> Self { Self::from(ConnectionError::from(err)) } } impl From for ReplyError { fn from(err: std::io::Error) -> Self { ConnectionError::from(err).into() } } impl From for ReplyError { fn from(err: ConnectionError) -> Self { Self::ConnectionError(err) } } impl From 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 for ReplyOrIdError { fn from(err: ParseError) -> Self { ConnectionError::from(err).into() } } impl From for ReplyOrIdError { fn from(err: ConnectionError) -> Self { ReplyOrIdError::ConnectionError(err) } } impl From for ReplyOrIdError { fn from(err: X11Error) -> Self { ReplyOrIdError::X11Error(err) } } impl From for ReplyOrIdError { fn from(err: ReplyError) -> Self { match err { ReplyError::ConnectionError(err) => ReplyOrIdError::ConnectionError(err), ReplyError::X11Error(err) => ReplyOrIdError::X11Error(err), } } } impl From for ReplyOrIdError { fn from(_: IdsExhausted) -> Self { ReplyOrIdError::IdsExhausted } } x11rb-0.13.0/src/event_loop_integration.rs000064400000000000000000000075751046102023000165720ustar 00000000000000//! # 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(event: T) {} //! # fn poll_for_readable(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. x11rb-0.13.0/src/extension_manager.rs000064400000000000000000000301761046102023000155140ustar 00000000000000//! 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( &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( &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, ) { 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( &mut self, conn: &C, extension_name: &'static str, ) -> Result, 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::::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); impl RequestConnection for FakeConnection { type Buf = Vec; fn send_request_with_reply( &self, _bufs: &[IoSlice<'_>], _fds: Vec, ) -> Result, ConnectionError> where R: TryParse, { Ok(Cookie::new(self, 1)) } fn send_request_with_reply_with_fds( &self, _bufs: &[IoSlice<'_>], _fds: Vec, ) -> Result, ConnectionError> where R: TryParseFd, { unimplemented!() } fn send_request_without_reply( &self, _bufs: &[IoSlice<'_>], _fds: Vec, ) -> Result, 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, ConnectionError> { unimplemented!() } fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, ) -> Result>, 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>, ConnectionError> { unimplemented!() } fn wait_for_reply_with_fds_raw( &self, _sequence: SequenceNumber, ) -> Result>, Vec>, ConnectionError> { unimplemented!() } fn check_for_raw_error( &self, _sequence: SequenceNumber, ) -> Result>, ConnectionError> { unimplemented!() } fn maximum_request_bytes(&self) -> usize { 0 } fn prefetch_maximum_request_bytes(&self) { unimplemented!() } fn parse_error(&self, _error: &[u8]) -> Result { unimplemented!() } fn parse_event(&self, _event: &[u8]) -> Result { 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))); } } x11rb-0.13.0/src/image.rs000064400000000000000000001252441046102023000130710ustar 00000000000000//! Utility code for working with images. //! //! This module contains the [`Image`] struct which represents an arbitrary image in //! `ImageFormat::ZPixmap`. If you do not know what `ZPixmap` means, then rest assured that you do //! not want to know the details. It suffices to know that the values of the individual pixels are //! saved one after another in memory. //! //! An [`Image`] can be converted to a different internal representation. [`Image::native`] //! converts it to the native format of the X11 server. These conversions do not change the actual //! content of the image, but only the way that it is laid out in memory (e.g. byte order and //! padding). Specifically, there is no support for converting an image to another `depth`. //! //! The code in this module is only available when the `image` feature of the library is //! enabled. // For future readers: // // - Z-Pixmap means that the pixels are right next to each other. I.e. first you have the value of // the pixel at (0, 0), then (1, 0), .... At the end of the row, there might be some padding // before the next row begins. // - XY-Bitmap consists of individual bits. The bits are assigned colors via a GC's foreground and // background color when uploading to the X11 server. // - XY-Pixmap consists of bit planes. This means you first get the first bit of each pixel, // stuffed together into bytes. After all of the first pixels are represented, the second plane // begins with the second bit of each pixel etc. use std::borrow::Cow; use std::convert::{TryFrom, TryInto}; use crate::connection::Connection; use crate::cookie::VoidCookie; use crate::errors::{ConnectionError, ParseError, ReplyError}; use crate::protocol::xproto::{ get_image, put_image, Drawable, Format, Gcontext, GetImageReply, ImageFormat, ImageOrder as XprotoImageOrder, Setup, VisualClass, Visualid, Visualtype, }; /// The description of a single color component. /// /// For example, in an RGB image, pixels are often saved as `0xRRGGBB`, where each letter /// represents the respective color component. In the example, green has a `width` of 8 (it takes /// up 8 bits) and a `shift` of `16` (there are 16 less significant bits beyond it). This info is /// represented as a `ColorComponent`. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ColorComponent { /// Number of bits for the component width: u8, /// Offset in an u32 of the component shift: u8, } impl ColorComponent { /// Create a new color component with the given information. /// /// The following conditions must be satisfied: /// - `width <= 16`: color components have at most 16 bits. /// - `shift < 32`: pixel values have at most 32 bits. /// - `shift + width <= 32`: pixel values have at most 32 bits. pub fn new(width: u8, shift: u8) -> Result { if width > 16 || shift >= 32 || shift + width > 32 { Err(ParseError::InvalidValue) } else { Ok(Self { width, shift }) } } /// Get the bit width of the color component. pub fn width(self) -> u8 { self.width } /// Get the bit shift of the color component. pub fn shift(self) -> u8 { self.shift } /// Get the pixel mask representing this color component. /// /// The mask can be used to mask off other colors in a pixel value. Only the bits that /// correspond to this color component are set. /// ``` /// # use x11rb::image::ColorComponent; /// let red = ColorComponent::new(8, 16)?; /// assert_eq!(red.mask(), 0xff0000); /// # Ok::<(), x11rb::errors::ParseError>(()) /// ``` pub fn mask(self) -> u32 { // Get a mask with 'width' set bits. let mask = (1u32 << self.width) - 1; // Shift the mask into the right position mask << self.shift } /// Create a new color component from a color mask. /// /// This turns a color mask into its individual components. /// ``` /// # use x11rb::image::ColorComponent; /// let red1 = ColorComponent::new(8, 16); /// let red2 = ColorComponent::from_mask(0xff0000); /// ``` /// /// # Errors /// /// This function fails if the given value is not a well-formed mask. This means that at least /// one bit must be set and the set bits must be consecutive. pub fn from_mask(mask: u32) -> Result { let width = mask.count_ones(); let shift = mask.trailing_zeros(); // Both width and shift can be at most 32, which should fit into u8. let result = Self::new(width.try_into().unwrap(), shift.try_into().unwrap())?; if mask != result.mask() { Err(ParseError::InvalidValue) } else { Ok(result) } } /// Get this color component out of a pixel value. /// /// This function gets a single pixel value and returns this color component's value in that /// pixel value, expanded to width 16. /// ``` /// # use x11rb::image::ColorComponent; /// let red = ColorComponent::new(8, 16)?; /// assert_eq!(0xABAB, red.decode(0x78AB_4321)); /// # Ok::<(), x11rb::errors::ParseError>(()) /// ``` pub fn decode(self, pixel: u32) -> u16 { // Get the color component out let value = (pixel & self.mask()) >> self.shift; // Now expand from with `self.width` to width 16. let mut width = self.width; let mut value = value << (16 - width); // Add some low bits by using the high bits while width < 16 { value |= value >> width; width <<= 1; } value.try_into().unwrap() } /// Encode a color value according to this pixel format. /// /// ``` /// # use x11rb::image::ColorComponent; /// let red = ColorComponent::new(8, 16)?; /// assert_eq!(0xAB0000, red.encode(0xABCD)); /// # Ok::<(), x11rb::errors::ParseError>(()) /// ``` pub fn encode(self, intensity: u16) -> u32 { // First truncate to width `self.width`, then place at the correct offset. (u32::from(intensity) >> (16 - self.width)) << self.shift } } /// A collection of color components describing the red, green, and blue components of a pixel. /// /// A [`ColorComponent`] describes a single color component in an image. This structure describes /// the `red`, `green`, and `blue` color components by containing a [`ColorComponent`] for each of /// them. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct PixelLayout { red: ColorComponent, green: ColorComponent, blue: ColorComponent, } impl PixelLayout { /// Create a new pixel layout from the description of each component pub fn new(red: ColorComponent, green: ColorComponent, blue: ColorComponent) -> Self { Self { red, green, blue } } /// Create a new pixel layout /// /// This function errors if the visual has a different class than `TrueColor` or `DirectColor`, /// because color pallets and grayscales are not supported. This function also errors if the /// mask components of the visual are malformed. pub fn from_visual_type(visual: Visualtype) -> Result { if visual.class != VisualClass::TRUE_COLOR && visual.class != VisualClass::DIRECT_COLOR { Err(ParseError::InvalidValue) } else { Ok(Self::new( ColorComponent::from_mask(visual.red_mask)?, ColorComponent::from_mask(visual.green_mask)?, ColorComponent::from_mask(visual.blue_mask)?, )) } } /// Get the depth of this pixel layout. /// /// The depth is the number of significant bits of each pixel value. pub fn depth(self) -> u8 { // TODO: I am not quite sure this implementation is correct. The protocol seems to allow // unused bits in the middle..? self.red.width + self.green.width + self.blue.width } /// Decode a pixel value into its red, green, and blue components. /// /// This function returns each component expanded to width 16. /// ``` /// # use x11rb::image::{ColorComponent, PixelLayout}; /// let layout = PixelLayout::new( /// ColorComponent::new(8, 16)?, /// ColorComponent::new(8, 8)?, /// ColorComponent::new(8, 0)?, /// ); /// assert_eq!((0xABAB, 0x4343, 0x2121), layout.decode(0x78AB_4321)); /// # Ok::<(), x11rb::errors::ParseError>(()) /// ``` pub fn decode(self, pixel: u32) -> (u16, u16, u16) { let red = self.red.decode(pixel); let green = self.green.decode(pixel); let blue = self.blue.decode(pixel); (red, green, blue) } /// Encode a color value according to this layout. /// /// ``` /// # use x11rb::image::{ColorComponent, PixelLayout}; /// let layout = PixelLayout::new( /// ColorComponent::new(8, 16)?, /// ColorComponent::new(8, 8)?, /// ColorComponent::new(8, 0)?, /// ); /// assert_eq!(0x00AB_4321, layout.encode((0xABAB, 0x4343, 0x2121))); /// # Ok::<(), x11rb::errors::ParseError>(()) /// ``` pub fn encode(self, (red, green, blue): (u16, u16, u16)) -> u32 { let red = self.red.encode(red); let green = self.green.encode(green); let blue = self.blue.encode(blue); red | green | blue } } // Compute the stride based on some information of the image fn compute_stride(width: u16, bits_per_pixel: BitsPerPixel, scanline_pad: ScanlinePad) -> usize { let value = usize::from(width) * usize::from(bits_per_pixel); scanline_pad.round_to_multiple(value) / 8 } #[cfg(test)] mod test_stride { use super::compute_stride; use std::convert::TryInto; #[test] fn test_stride() { for &(width, bpp, pad, stride) in &[ // bpp=pad=8 (0, 8, 8, 0), (1, 8, 8, 1), (2, 8, 8, 2), (3, 8, 8, 3), (41, 8, 8, 41), // bpp=8, pad=16 (0, 8, 16, 0), (1, 8, 16, 2), (2, 8, 16, 2), (3, 8, 16, 4), (41, 8, 16, 42), // bpp=16, pad=16 (0, 16, 16, 0), (1, 16, 16, 2), (2, 16, 16, 4), (3, 16, 16, 6), (41, 16, 16, 82), // bpp=16, pad=32 (0, 16, 32, 0), (1, 16, 32, 4), (2, 16, 32, 4), (3, 16, 32, 8), (41, 16, 32, 84), // bpp=32, pad=32 (0, 32, 32, 0), (1, 32, 32, 4), (2, 32, 32, 8), (3, 32, 32, 12), (41, 32, 32, 164), ] { let actual = compute_stride(width, bpp.try_into().unwrap(), pad.try_into().unwrap()); assert_eq!(stride, actual, "width={}, bpp={}, pad={}", width, bpp, pad); } } } // Find the format with the given depth in `setup.pixmap_formats`. fn find_format(setup: &Setup, depth: u8) -> Result<&Format, ParseError> { setup .pixmap_formats .iter() .find(|f| f.depth == depth) .ok_or(ParseError::InvalidValue) } macro_rules! number_enum { { $(#[$meta:meta])* $vis:vis enum $enum_name:ident { $( $(#[$variant_meta:meta])* $variant_name:ident = $value:literal, )* } } => { $(#[$meta])* #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] $vis enum $enum_name { $( $(#[$variant_meta])* $variant_name = $value, )* } impl TryFrom for $enum_name { type Error = ParseError; fn try_from(value: u8) -> Result { match value { $($value => Ok(Self::$variant_name),)* _ => Err(ParseError::InvalidValue), } } } impl From<$enum_name> for u8 { fn from(value: $enum_name) -> u8 { match value { $($enum_name::$variant_name => $value,)* } } } impl From<$enum_name> for usize { fn from(value: $enum_name) -> usize { u8::from(value).into() } } } } number_enum! { /// The padding of scanlines. /// /// Each line of an image is padded to a multiple of some value. This value is the scanline /// padding, which this enum represents. #[non_exhaustive] pub enum ScanlinePad { /// Padding to multiples of 8 bits, i.e. no padding. Pad8 = 8, /// Padding to multiples of 16 bits, i.e. the next even number of bytes. Pad16 = 16, /// Padding to multiples of 32 bits, i.e. the next multiple of 4. Pad32 = 32, } } impl ScanlinePad { fn round_to_multiple(self, value: usize) -> usize { let value = value + usize::from(self) - 1; value - value % usize::from(self) } } #[cfg(test)] mod test_scanline_pad { use super::ScanlinePad; use std::convert::TryInto; #[test] fn number_conversions() { assert_eq!(8_u8, ScanlinePad::Pad8.into()); assert_eq!(16_u8, ScanlinePad::Pad16.into()); assert_eq!(32_u8, ScanlinePad::Pad32.into()); assert_eq!(8.try_into(), Ok(ScanlinePad::Pad8)); assert_eq!(16.try_into(), Ok(ScanlinePad::Pad16)); assert_eq!(32.try_into(), Ok(ScanlinePad::Pad32)); } #[test] fn test_round_to_multiple() { for &(value, pad8, pad16, pad32) in [ (0, 0, 0, 0), (1, 8, 16, 32), (2, 8, 16, 32), (3, 8, 16, 32), (4, 8, 16, 32), (5, 8, 16, 32), (6, 8, 16, 32), (7, 8, 16, 32), (8, 8, 16, 32), (9, 16, 16, 32), (10, 16, 16, 32), (11, 16, 16, 32), (12, 16, 16, 32), (13, 16, 16, 32), (14, 16, 16, 32), (15, 16, 16, 32), (16, 16, 16, 32), (17, 24, 32, 32), (33, 40, 48, 64), (47, 48, 48, 64), (48, 48, 48, 64), (49, 56, 64, 64), ] .iter() { assert_eq!( pad8, ScanlinePad::Pad8.round_to_multiple(value), "value={} for pad8", value, ); assert_eq!( pad16, ScanlinePad::Pad16.round_to_multiple(value), "value={} for pad16", value, ); assert_eq!( pad32, ScanlinePad::Pad32.round_to_multiple(value), "value={} for pad32", value, ); } } } number_enum! { /// The number of bits required to store one pixel. /// /// This value is only about the size of one pixel in memory. Other names for it include /// `bits_per_pixel` or `bpp`. It may be larger than the number of meaningful bits for a pixel /// value, which is its `depth`. #[non_exhaustive] pub enum BitsPerPixel { /// Each pixel takes one bit of memory. B1 = 1, /// Each pixel takes four bits of memory. B4 = 4, /// Each pixel takes one byte of memory. B8 = 8, /// Each pixel takes two bytes of memory. B16 = 16, /// Each pixel takes three bytes of memory. /// /// This is most likely not what you want to use, even if you have RGB data with 8 bits per /// channel. This corresponds to `depth=24`, but is almost always stored as four bytes /// per pixel, which is `BitsPerPixel::B32`. B24 = 24, /// Each pixel takes four bytes of memory. B32 = 32, } } /// Order in which bytes are stored in memory. /// /// If the numberof bits per pixel is less than 8, then this is the /// order in which bits are packed into bytes. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum ImageOrder { /// Least significant byte first LsbFirst, /// Most significant byte first MsbFirst, } impl TryFrom for ImageOrder { type Error = ParseError; fn try_from(value: XprotoImageOrder) -> Result { match value { XprotoImageOrder::LSB_FIRST => Ok(Self::LsbFirst), XprotoImageOrder::MSB_FIRST => Ok(Self::MsbFirst), _ => Err(ParseError::InvalidValue), } } } /// The description of an image. #[derive(Debug, PartialEq, Eq, Clone)] pub struct Image<'a> { /// Width in pixels. width: u16, /// Height in pixels. height: u16, /// Right padding on each scanline. scanline_pad: ScanlinePad, /// Color depth in bits. depth: u8, /// Storage per pixel in bits. Must be >= depth. bits_per_pixel: BitsPerPixel, /// Byte order of components. /// /// This is the nibble order when bits_per_pixel is 4. byte_order: ImageOrder, /// The image data. data: Cow<'a, [u8]>, } impl<'a> Image<'a> { /// The width in pixels. pub fn width(&self) -> u16 { self.width } /// The height in pixels. pub fn height(&self) -> u16 { self.height } /// The padding on the right side of each scanline. /// /// Each scanline is rounded up to some multiple of the `scanline_pad`. pub fn scanline_pad(&self) -> ScanlinePad { self.scanline_pad } /// Color depth in bits. pub fn depth(&self) -> u8 { self.depth } /// Number of bits required to store one pixel. /// /// This is always `>= depth`. pub fn bits_per_pixel(&self) -> BitsPerPixel { self.bits_per_pixel } /// Order in which bytes are stored in memory. /// /// If `bits_per_pixel()` is smaller than 8, then this is the order in which bits are packed /// into bytes. pub fn byte_order(&self) -> ImageOrder { self.byte_order } /// Raw pixel data. pub fn data(&self) -> &[u8] { &self.data } /// Mutable access to the raw pixel data. /// /// If the `Image` was constructed with `Cow::Borrowed`-access to its pixel data, then a copy /// is made when this method is called. pub fn data_mut(&mut self) -> &mut [u8] { self.data.to_mut() } /// Construct a new image from existing data. /// /// This constructs a new `Image` from given `data` without copying this data around. The other /// parameters describe the format that the image data is in. /// /// See [`Image::allocate`] for a variant that allocates memory for you and /// [`Image::allocate_native`] for allocating an image that is in an X11 server's native /// format. /// /// # Errors /// /// The only possible error is that `data.len()` is too short for an image as described by the /// other parameters. pub fn new( width: u16, height: u16, scanline_pad: ScanlinePad, depth: u8, bits_per_pixel: BitsPerPixel, byte_order: ImageOrder, data: Cow<'a, [u8]>, ) -> Result { let stride = compute_stride(width, bits_per_pixel, scanline_pad); let expected_size = usize::from(height) * stride; if data.len() < expected_size { Err(ParseError::InsufficientData) } else { Ok(Self { width, height, scanline_pad, depth, bits_per_pixel, byte_order, data, }) } } /// Construct a new, empty image. /// /// This function allocates memory for a new image in the format that is described by the /// parameters. /// /// See [`Image::new`] for a variant that wraps an existing in-memory image in an `Image` and /// [`Image::allocate_native`] for allocating an image that is in an X11 server's native /// format. pub fn allocate( width: u16, height: u16, scanline_pad: ScanlinePad, depth: u8, bits_per_pixel: BitsPerPixel, byte_order: ImageOrder, ) -> Self { let stride = compute_stride(width, bits_per_pixel, scanline_pad); let data = Cow::Owned(vec![0; usize::from(height) * stride]); Self { width, height, scanline_pad, depth, bits_per_pixel, byte_order, data, } } /// Construct a new, empty image. /// /// This function allocates memory for a new image in the format that the X11 server expects. /// The image will have size `width`x`height` and a depth of `depth`. /// /// See [`Image::new`] for a variant that wraps an existing in-memory image in an `Image` and /// [`Image::allocate`] for allocating an image that is in a more general format, not /// necessarily what the X11 server wants. pub fn allocate_native( width: u16, height: u16, depth: u8, setup: &Setup, ) -> Result { let format = find_format(setup, depth)?; Ok(Self::allocate( width, height, format.scanline_pad.try_into()?, depth, format.bits_per_pixel.try_into()?, setup.image_byte_order.try_into()?, )) } /// The stride is the number of bytes that each row of pixel data occupies in memory. fn stride(&self) -> usize { compute_stride(self.width, self.bits_per_pixel, self.scanline_pad) } /// Get an image from the X11 server. /// /// This function sends a [`GetImage`](crate::protocol::xproto::GetImageRequest) request, waits /// for its response and wraps it in a new `Image`. The image and the corresponding visual id /// are returned. /// /// The returned image contains the rectangle with top left corner `(x, y)` and size `(width, /// height)` of the given `drawable`. pub fn get( conn: &impl Connection, drawable: Drawable, x: i16, y: i16, width: u16, height: u16, ) -> Result<(Self, Visualid), ReplyError> { let reply = get_image( conn, ImageFormat::Z_PIXMAP, drawable, x, y, width, height, !0, )? .reply()?; let visual = reply.visual; let image = Self::get_from_reply(conn.setup(), width, height, reply)?; Ok((image, visual)) } /// Construct an `Image` from a `GetImageReply`. /// /// This function takes a `GetImageReply` and wraps it in an `Image`. The given `width` and /// `height` describe the corresponding values of the `GetImage` request that was used to get /// the `GetImageReply`. pub fn get_from_reply( setup: &Setup, width: u16, height: u16, reply: GetImageReply, ) -> Result { let format = find_format(setup, reply.depth)?; Self::new( width, height, format.scanline_pad.try_into()?, reply.depth, format.bits_per_pixel.try_into()?, setup.image_byte_order.try_into()?, Cow::Owned(reply.data), ) } /// Put an image to the X11 server. /// /// This function sends a [`PutImage`](crate::protocol::xproto::PutImageRequest) request. This /// will upload this image to the given `drawable` to position `(dst_x, dst_y)`. /// /// The server's maximum request size is honored. This means that a too large `PutImage` /// request is automatically split up into smaller pieces. Thus, if this function returns an /// error, the image could already be partially sent. /// /// Before uploading, the image is translated into the server's native format via /// [`Image::native`]. This may convert the image to another format, which can be slow. If you /// intend to upload the same image multiple times, it is likely more efficient to call /// [`Image::native`] once initially so that the conversion is not repeated on each upload. pub fn put<'c, Conn: Connection>( &self, conn: &'c Conn, drawable: Drawable, gc: Gcontext, dst_x: i16, dst_y: i16, ) -> Result>, ConnectionError> { self.native(conn.setup())? .put_impl(conn, drawable, gc, dst_x, dst_y) } fn put_impl<'c, Conn: Connection>( &self, conn: &'c Conn, drawable: Drawable, gc: Gcontext, dst_x: i16, dst_y: i16, ) -> Result>, ConnectionError> { // Upload the image without exceeding the server's maximum request size let max_bytes = conn.maximum_request_bytes(); let put_image_header = 24; let stride = self.stride(); let lines_per_request = (max_bytes - put_image_header) / stride; let mut result = Vec::with_capacity( (usize::from(self.height()) + lines_per_request - 1) / lines_per_request, ); let lines_per_request = lines_per_request.try_into().unwrap_or(u16::max_value()); assert!(lines_per_request > 0); let (mut y_offset, mut byte_offset) = (0, 0); while y_offset < self.height { let next_lines = lines_per_request.min(self.height - y_offset); let next_byte_offset = byte_offset + usize::from(next_lines) * stride; let data = &self.data[byte_offset..next_byte_offset]; result.push(put_image( conn, ImageFormat::Z_PIXMAP, drawable, gc, self.width, next_lines, dst_x, dst_y + i16::try_from(y_offset).unwrap(), 0, // left_pad must always be 0 for ZPixmap self.depth, data, )?); y_offset += next_lines; byte_offset = next_byte_offset; } Ok(result) } /// Convert this image into the format specified by the other parameters. /// /// This function may need to copy the image, hence returns a `Cow`. pub fn convert( &self, scanline_pad: ScanlinePad, bits_per_pixel: BitsPerPixel, byte_order: ImageOrder, ) -> Cow<'_, Self> { let already_converted = scanline_pad == self.scanline_pad && bits_per_pixel == self.bits_per_pixel && byte_order == self.byte_order; if already_converted { Cow::Borrowed(self) } else { let mut copy = Image::allocate( self.width, self.height, scanline_pad, self.depth, bits_per_pixel, byte_order, ); // This is the slowest possible way to do this. But also the easiest one to implement. for y in 0..self.height { for x in 0..self.width { copy.put_pixel(x, y, self.get_pixel(x, y)) } } Cow::Owned(copy) } } /// Convert this image into the native format of the X11 server. /// /// This function may need to copy the image, hence returns a `Cow`. pub fn native(&self, setup: &Setup) -> Result, ParseError> { let format = find_format(setup, self.depth)?; Ok(self.convert( format.scanline_pad.try_into()?, format.bits_per_pixel.try_into()?, setup.image_byte_order.try_into()?, )) } /// Reencode this image to a different pixel layout / depth. /// /// Each pixel of this image is interpreted according to `own` and written to the resulting /// image in the format described by `output`. /// /// The resulting image is always in the native format as described by `setup`. pub fn reencode<'b>( &'b self, own: PixelLayout, output: PixelLayout, setup: &Setup, ) -> Result, ParseError> { if own == output { self.native(setup) } else { // Yay, we get to convert the image :-( let (width, height) = (self.width(), self.height()); let mut result = Image::allocate_native(width, height, output.depth(), setup)?; for y in 0..height { for x in 0..width { let pixel = self.get_pixel(x, y); let pixel = output.encode(own.decode(pixel)); result.put_pixel(x, y, pixel); } } Ok(Cow::Owned(result)) } } /// Set a single pixel in this image. /// /// The pixel at position `(x, y)` will be set to the value `pixel`. `pixel` is truncated to /// this image's [`Self::bits_per_pixel`]. /// /// If the image was constructed from a `Cow::Borrowed` access to its pixel data, this causes /// the whole pixel data to be copied. See [`Image::new`] and [`Image::data_mut`]. pub fn put_pixel(&mut self, x: u16, y: u16, pixel: u32) { assert!(x < self.width); assert!(y < self.height); let row_start = usize::from(y) * self.stride(); let x = usize::from(x); let data = self.data.to_mut(); match self.bits_per_pixel { BitsPerPixel::B1 => { let (byte, bit) = compute_depth_1_address(x, self.byte_order); let pixel = ((pixel & 0x01) << bit) as u8; let old = data[row_start + byte]; let bit_cleared = old & !(1 << bit); data[row_start + byte] = bit_cleared | pixel; } BitsPerPixel::B4 => { let mut pixel = pixel & 0x0f; let odd_x = x % 2 == 1; let mask = if odd_x == (self.byte_order == ImageOrder::MsbFirst) { pixel <<= 4; 0xf0 } else { 0x0f }; data[row_start + x / 2] = (data[row_start + x / 2] & !mask) | (pixel as u8); } BitsPerPixel::B8 => data[row_start + x] = pixel as u8, BitsPerPixel::B16 => { let (p0, p1) = match self.byte_order { ImageOrder::LsbFirst => (pixel, pixel >> 8), ImageOrder::MsbFirst => (pixel >> 8, pixel), }; data[row_start + 2 * x + 1] = p1 as u8; data[row_start + 2 * x] = p0 as u8; } BitsPerPixel::B24 => { let (p0, p1, p2) = match self.byte_order { ImageOrder::LsbFirst => (pixel, pixel >> 8, pixel >> 16), ImageOrder::MsbFirst => (pixel >> 16, pixel >> 8, pixel), }; data[row_start + 3 * x + 2] = p2 as u8; data[row_start + 3 * x + 1] = p1 as u8; data[row_start + 3 * x] = p0 as u8; } BitsPerPixel::B32 => { let (p0, p1, p2, p3) = match self.byte_order { ImageOrder::LsbFirst => (pixel, pixel >> 8, pixel >> 16, pixel >> 24), ImageOrder::MsbFirst => (pixel >> 24, pixel >> 16, pixel >> 8, pixel), }; data[row_start + 4 * x + 3] = p3 as u8; data[row_start + 4 * x + 2] = p2 as u8; data[row_start + 4 * x + 1] = p1 as u8; data[row_start + 4 * x] = p0 as u8; } } } /// Get the value of a single pixel. /// /// This function gets the value of the pixel at `(x, y)`. pub fn get_pixel(&self, x: u16, y: u16) -> u32 { assert!(x < self.width); assert!(y < self.height); let row_start = usize::from(y) * self.stride(); let x = usize::from(x); // TODO Can this code (and the one in put_pixel) be simplified? E.g. handle B4 as a special // case and copy bits_per_pixel.into() / 8 bytes in other cases? match self.bits_per_pixel { BitsPerPixel::B1 => { let (byte, bit) = compute_depth_1_address(x, self.byte_order); ((self.data[row_start + byte] >> bit) & 1).into() } BitsPerPixel::B4 => { let byte = u32::from(self.data[row_start + x / 2]); let odd_x = x % 2 == 1; if odd_x == (self.byte_order == ImageOrder::MsbFirst) { byte >> 4 } else { byte & 0x0f } } BitsPerPixel::B8 => self.data[row_start + x].into(), BitsPerPixel::B16 => { let p1 = u32::from(self.data[row_start + 2 * x + 1]); let p0 = u32::from(self.data[row_start + 2 * x]); match self.byte_order { ImageOrder::LsbFirst => p0 | (p1 << 8), ImageOrder::MsbFirst => p1 | (p0 << 8), } } BitsPerPixel::B24 => { let p2 = u32::from(self.data[row_start + 3 * x + 2]); let p1 = u32::from(self.data[row_start + 3 * x + 1]); let p0 = u32::from(self.data[row_start + 3 * x]); match self.byte_order { ImageOrder::LsbFirst => p0 | (p1 << 8) | (p2 << 16), ImageOrder::MsbFirst => p2 | (p1 << 8) | (p0 << 16), } } BitsPerPixel::B32 => { let p3 = u32::from(self.data[row_start + 4 * x + 3]); let p2 = u32::from(self.data[row_start + 4 * x + 2]); let p1 = u32::from(self.data[row_start + 4 * x + 1]); let p0 = u32::from(self.data[row_start + 4 * x]); match self.byte_order { ImageOrder::LsbFirst => p0 | (p1 << 8) | (p2 << 16) | (p3 << 24), ImageOrder::MsbFirst => p3 | (p2 << 8) | (p1 << 16) | (p0 << 24), } } } } /// Get a version of this image with `'static` lifetime. /// /// If the image was constructed from a `Cow::Borrowed`, this clones the contained data. /// Otherwise, this simply returns `self`. pub fn into_owned(self) -> Image<'static> { // It would be great if we could just implement ToOwned, but that requires implementing // Borrow, which we cannot do. Thus, this function exists as a work-around. Image { data: self.data.into_owned().into(), ..self } } } fn compute_depth_1_address(x: usize, order: ImageOrder) -> (usize, usize) { let bit = match order { ImageOrder::MsbFirst => 7 - x % 8, ImageOrder::LsbFirst => x % 8, }; (x / 8, bit) } #[cfg(test)] mod test_image { use super::{BitsPerPixel, Image, ImageOrder, ParseError, ScanlinePad}; use std::borrow::Cow; #[test] fn test_new_too_short() { let depth = 16; // Due to Pad16, this image needs two bytes let result = Image::new( 1, 1, ScanlinePad::Pad16, depth, BitsPerPixel::B8, ImageOrder::MsbFirst, Cow::Owned(vec![0]), ); assert_eq!(result.unwrap_err(), ParseError::InsufficientData); } #[test] fn test_new() { let depth = 16; let image = Image::new( 2, 1, ScanlinePad::Pad16, depth, BitsPerPixel::B8, ImageOrder::MsbFirst, Cow::Owned(vec![42, 125]), ) .unwrap(); assert_eq!(image.width(), 2); assert_eq!(image.height(), 1); assert_eq!(image.scanline_pad(), ScanlinePad::Pad16); assert_eq!(image.depth(), depth); assert_eq!(image.bits_per_pixel(), BitsPerPixel::B8); assert_eq!(image.byte_order(), ImageOrder::MsbFirst); assert_eq!(image.data(), [42, 125]); } #[test] fn test_into_owned_keeps_owned_data() { fn with_data(data: Cow<'_, [u8]>) -> *const u8 { let orig_ptr = data.as_ptr(); let image = Image::new( 1, 1, ScanlinePad::Pad8, 1, BitsPerPixel::B1, ImageOrder::MsbFirst, data, ) .unwrap(); assert_eq!(image.data().as_ptr(), orig_ptr); image.into_owned().data().as_ptr() } // Cow::Borrowed is copied let data = vec![0]; let orig_ptr = data.as_ptr(); assert_ne!(with_data(Cow::Borrowed(&data)), orig_ptr); // Cow::Owned is kept assert_eq!(with_data(Cow::Owned(data)), orig_ptr); } #[test] fn put_pixel_depth1() { let mut image = Image::allocate( 16, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B1, ImageOrder::MsbFirst, ); for x in 0..8 { image.put_pixel(x, 0, 1); } assert_eq!(0b_1111_1111, image.data()[0]); image.put_pixel(0, 0, 0); assert_eq!(0b_0111_1111, image.data()[0]); image.put_pixel(2, 0, 0); assert_eq!(0b_0101_1111, image.data()[0]); image.put_pixel(4, 0, 0); assert_eq!(0b_0101_0111, image.data()[0]); image.put_pixel(6, 0, 0); assert_eq!(0b_0101_0101, image.data()[0]); image.data_mut()[1] = 0; image.put_pixel(8, 0, 1); assert_eq!(0b_1000_0000, image.data()[1]); image.put_pixel(15, 0, 1); assert_eq!(0b_1000_0001, image.data()[1]); assert_eq!(0b_0000_0000, image.data()[5]); image.put_pixel(15, 1, 1); assert_eq!(0b_0000_0001, image.data()[5]); } #[test] fn put_pixel_depth4() { let mut image = Image::allocate( 8, 2, ScanlinePad::Pad16, 1, BitsPerPixel::B4, ImageOrder::MsbFirst, ); for pos in 0..=0xf { image.put_pixel(pos % 8, pos / 8, pos.into()); } assert_eq!( image.data(), [0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE] ); } #[test] fn put_pixel_depth8() { let mut image = Image::allocate( 256, 2, ScanlinePad::Pad8, 1, BitsPerPixel::B8, ImageOrder::MsbFirst, ); for x in 0..=0xff { image.put_pixel(x, 0, x.into()); } image.put_pixel(255, 1, 0x1245_89AB); let expected = (0..=0xff) .chain((0..0xff).map(|_| 0)) .chain(std::iter::once(0xAB)) .collect::>(); assert_eq!(image.data(), &expected[..]); } #[test] fn put_pixel_depth16() { let mut image = Image::allocate( 5, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B16, ImageOrder::MsbFirst, ); image.put_pixel(0, 0, 0xAB_36_18_F8); image.put_pixel(4, 0, 0x12_34_56_78); image.put_pixel(4, 1, 0xFE_DC_BA_98); #[rustfmt::skip] let expected = [ // First row 0x18, 0xF8, 0, 0, 0, 0, 0, 0, 0x56, 0x78, // Padding Pad32 0, 0, // Second row 0, 0, 0, 0, 0, 0, 0, 0, 0xBA, 0x98, // Padding Pad32 0, 0, ]; assert_eq!(image.data(), expected); } #[test] fn put_pixel_depth32() { let mut image = Image::allocate( 2, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B32, ImageOrder::MsbFirst, ); image.put_pixel(0, 0, 0xAB_36_18_F8); image.put_pixel(1, 0, 0x12_34_56_78); image.put_pixel(1, 1, 0xFE_DC_BA_98); #[rustfmt::skip] let expected = [ // First row 0xAB, 0x36, 0x18, 0xF8, 0x12, 0x34, 0x56, 0x78, // Second row 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, 0xBA, 0x98, ]; assert_eq!(image.data(), expected); } #[test] fn get_pixel_depth1() { let image = Image::new( 16, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B1, ImageOrder::MsbFirst, Cow::Borrowed(&DATA), ) .unwrap(); assert_eq!(1, image.get_pixel(0, 0)); assert_eq!(1, image.get_pixel(10, 0)); assert_eq!(0, image.get_pixel(15, 0)); assert_eq!(0, image.get_pixel(0, 1)); assert_eq!(1, image.get_pixel(10, 1)); assert_eq!(0, image.get_pixel(15, 1)); } #[test] fn get_pixel_depth4() { let image = Image::new( 16, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B4, ImageOrder::MsbFirst, Cow::Borrowed(&DATA), ) .unwrap(); assert_eq!(0xB, image.get_pixel(0, 0)); assert_eq!(0x4, image.get_pixel(10, 0)); assert_eq!(0x7, image.get_pixel(15, 0)); assert_eq!(0x0, image.get_pixel(0, 1)); assert_eq!(0xC, image.get_pixel(10, 1)); assert_eq!(0x9, image.get_pixel(15, 1)); } #[test] fn get_pixel_depth8() { let image = Image::new( 3, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B8, ImageOrder::MsbFirst, Cow::Borrowed(&DATA), ) .unwrap(); assert_eq!(0xAB, image.get_pixel(0, 0)); assert_eq!(0x36, image.get_pixel(1, 0)); assert_eq!(0x18, image.get_pixel(2, 0)); assert_eq!(0x12, image.get_pixel(0, 1)); assert_eq!(0x34, image.get_pixel(1, 1)); assert_eq!(0x56, image.get_pixel(2, 1)); } #[test] fn get_pixel_depth16() { let image = Image::new( 3, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B16, ImageOrder::MsbFirst, Cow::Borrowed(&DATA), ) .unwrap(); assert_eq!(0xAB36, image.get_pixel(0, 0)); assert_eq!(0x18F8, image.get_pixel(1, 0)); assert_eq!(0x1234, image.get_pixel(2, 0)); assert_eq!(0x0000, image.get_pixel(0, 1)); assert_eq!(0x0000, image.get_pixel(1, 1)); assert_eq!(0xFEDC, image.get_pixel(2, 1)); } #[test] fn get_pixel_depth32() { let image = Image::new( 2, 2, ScanlinePad::Pad32, 1, BitsPerPixel::B32, ImageOrder::MsbFirst, Cow::Borrowed(&DATA), ) .unwrap(); assert_eq!(0xAB36_18F8, image.get_pixel(0, 0)); assert_eq!(0x1234_5678, image.get_pixel(1, 0)); assert_eq!(0x0000_0000, image.get_pixel(0, 1)); assert_eq!(0xFEDC_BA98, image.get_pixel(1, 1)); } static DATA: [u8; 16] = [ 0xAB, 0x36, 0x18, 0xF8, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, 0xBA, 0x98, ]; } x11rb-0.13.0/src/lib.rs000064400000000000000000000207211046102023000125470ustar 00000000000000//! 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> { //! 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. #![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_import_braces, unused_results, clippy::cast_lossless, clippy::needless_pass_by_value, )] // 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( // #[derive] generates an #[allow] for this unused_qualifications, // Not everything in x11rb::protocol has doc comments missing_docs, )] #![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}; use std::ffi::OsString; /// 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; #[cfg(not(unix))] fn hostname() -> OsString { gethostname::gethostname() } #[cfg(unix)] fn hostname() -> OsString { use std::os::unix::ffi::OsStringExt; OsString::from_vec(rustix::system::uname().nodename().to_bytes().to_vec()) } x11rb-0.13.0/src/properties.rs000064400000000000000000000667221046102023000142100ustar 00000000000000//! Utility functions for working with X11 properties use std::convert::TryInto; 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, 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, 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 { 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 { /// 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( conn: &C, window: Window, ) -> Result, 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, 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, ) -> Result { 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) { (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, } 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( conn: &C, window: Window, property: impl Into, ) -> Result, 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( conn: &C, window: Window, ) -> Result, 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, 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, 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, ) -> Result, 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::(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; 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) { 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 { 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, /// The state that the window should be when it leaves the Withdrawn state. pub initial_state: Option, /// A pixmap that represents the icon of this window. pub icon_pixmap: Option, /// A window that should be used as icon. pub icon_window: Option, /// 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, /// 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, /// 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( conn: &C, window: Window, ) -> Result, 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, 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, ConnectionError> { let data = self.serialize(); xproto::change_property( conn, xproto::PropMode::REPLACE, window, xproto::AtomEnum::WM_HINTS, xproto::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::(remaining, flags, HINT_INPUT)?; let (initial_state, remaining) = parse_with_flag::(remaining, flags, HINT_STATE)?; let (icon_pixmap, remaining) = parse_with_flag::(remaining, flags, HINT_ICON_PIXMAP)?; let (icon_window, remaining) = parse_with_flag::(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::(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::(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; 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) { 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( remaining: &[u8], flags: u32, bit: u32, ) -> Result<(Option, &[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 std::convert::TryInto; 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) -> 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::>(); 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::>(); 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()); } } x11rb-0.13.0/src/protocol/bigreq.rs000064400000000000000000000046021046102023000151130ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, ConnectionError> { enable(self) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/composite.rs000064400000000000000000000313621046102023000156470ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u32, client_minor_version: u32) -> Result, 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 heirarchy 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 heirarchy 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, window: xproto::Window, update: Redirect) -> Result, 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 heirarchy 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, window: xproto::Window, update: Redirect) -> Result, 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, window: xproto::Window, update: Redirect) -> Result, 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 window’s 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, window: xproto::Window, update: Redirect) -> Result, 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, region: xfixes::Region, window: xproto::Window) -> Result, 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, window: xproto::Window, pixmap: xproto::Pixmap) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window) -> Result, 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, ConnectionError> { query_version(self, client_major_version, client_minor_version) } /// Redirect the heirarchy 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 heirarchy 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, 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 heirarchy 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, 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, ConnectionError> { unredirect_window(self, window, update) } /// Terminate redirection of the specified window’s 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, ConnectionError> { unredirect_subwindows(self, window, update) } fn composite_create_region_from_border_clip(&self, region: xfixes::Region, window: xproto::Window) -> Result, ConnectionError> { create_region_from_border_clip(self, region, window) } fn composite_name_window_pixmap(&self, window: xproto::Window, pixmap: xproto::Pixmap) -> Result, ConnectionError> { name_window_pixmap(self, window, pixmap) } fn composite_get_overlay_window(&self, window: xproto::Window) -> Result, ConnectionError> { get_overlay_window(self, window) } fn composite_release_overlay_window(&self, window: xproto::Window) -> Result, ConnectionError> { release_overlay_window(self, window) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/damage.rs000064400000000000000000000327731046102023000150720ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u32, client_minor_version: u32) -> Result, 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, damage: Damage, drawable: xproto::Drawable, level: ReportLevel) -> Result, 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, damage: Damage) -> Result, 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 /// for details. /// /// # Fields /// /// * `damage` - The ID you provided to `xcb_create_damage`. pub fn subtract(conn: &Conn, damage: Damage, repair: A, parts: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { 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 /// for details. /// /// # Fields /// /// * `damage` - The ID you provided to `xcb_create_damage`. pub fn add(conn: &Conn, drawable: xproto::Drawable, region: xfixes::Region) -> Result, 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, 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, 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, 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 /// for details. /// /// # Fields /// /// * `damage` - The ID you provided to `xcb_create_damage`. fn damage_subtract(&self, damage: Damage, repair: A, parts: B) -> Result, ConnectionError> where A: Into, B: Into, { 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 /// for details. /// /// # Fields /// /// * `damage` - The ID you provided to `xcb_create_damage`. fn damage_add(&self, drawable: xproto::Drawable, region: xfixes::Region) -> Result, ConnectionError> { add(self, drawable, region) } } impl 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, Damage); impl DamageWrapper { /// 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 DamageWrapper { /// 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 { let damage = conn.generate_id()?; let _ = create(&conn, damage, drawable, level)?; Ok(Self::for_damage(conn, damage)) } } impl From<&DamageWrapper> for Damage { fn from(from: &DamageWrapper) -> Self { from.1 } } impl Drop for DamageWrapper { fn drop(&mut self) { let _ = destroy(&self.0, self.1); } } x11rb-0.13.0/src/protocol/dbe.rs000064400000000000000000000276761046102023000144140ustar 00000000000000// 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: &Conn) -> Result { 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, major_version: u8, minor_version: u8) -> Result, 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, window: xproto::Window, buffer: BackBuffer, swap_action: u8) -> Result, 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, buffer: BackBuffer) -> Result, 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, 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) -> Result, 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) -> Result, 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, 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, buffer: BackBuffer) -> Result, 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, 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, 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, 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, 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, ConnectionError> { begin_idiom(self) } /// Ends a logical swap block. fn dbe_end_idiom(&self) -> Result, ConnectionError> { end_idiom(self) } /// Requests visuals that support double buffering. fn dbe_get_visual_info<'c, 'input>(&'c self, drawables: &'input [xproto::Drawable]) -> Result, 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, ConnectionError> { get_back_buffer_attributes(self, buffer) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/dpms.rs000064400000000000000000000144111046102023000146040ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u16, client_minor_version: u16) -> Result, 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) -> Result, 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) -> Result, 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, standby_timeout: u16, suspend_timeout: u16, off_timeout: u16) -> Result, 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) -> Result, 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) -> Result, 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, power_level: DPMSMode) -> Result, 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) -> Result, 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, event_mask: EventMask) -> Result, 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, ConnectionError> { get_version(self, client_major_version, client_minor_version) } fn dpms_capable(&self) -> Result, ConnectionError> { capable(self) } fn dpms_get_timeouts(&self) -> Result, ConnectionError> { get_timeouts(self) } fn dpms_set_timeouts(&self, standby_timeout: u16, suspend_timeout: u16, off_timeout: u16) -> Result, ConnectionError> { set_timeouts(self, standby_timeout, suspend_timeout, off_timeout) } fn dpms_enable(&self) -> Result, ConnectionError> { enable(self) } fn dpms_disable(&self) -> Result, ConnectionError> { disable(self) } fn dpms_force_level(&self, power_level: DPMSMode) -> Result, ConnectionError> { force_level(self, power_level) } fn dpms_info(&self) -> Result, ConnectionError> { info(self) } fn dpms_select_input(&self, event_mask: EventMask) -> Result, ConnectionError> { select_input(self, event_mask) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/dri2.rs000064400000000000000000000267451046102023000145160ustar 00000000000000// 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: &Conn) -> Result { 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, major_version: u32, minor_version: u32) -> Result, 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, window: xproto::Window, driver_type: DriverType) -> Result, 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, window: xproto::Window, magic: u32) -> Result, 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, drawable: xproto::Drawable) -> Result, 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, drawable: xproto::Drawable) -> Result, 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, 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, drawable: xproto::Drawable, region: u32, dest: u32, src: u32) -> Result, 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, 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, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result, 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, drawable: xproto::Drawable) -> Result, 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, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result, 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, drawable: xproto::Drawable, target_sbc_hi: u32, target_sbc_lo: u32) -> Result, 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, drawable: xproto::Drawable, interval: u32) -> Result, 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, drawable: xproto::Drawable, param: u32) -> Result, 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, ConnectionError> { query_version(self, major_version, minor_version) } fn dri2_connect(&self, window: xproto::Window, driver_type: DriverType) -> Result, ConnectionError> { connect(self, window, driver_type) } fn dri2_authenticate(&self, window: xproto::Window, magic: u32) -> Result, ConnectionError> { authenticate(self, window, magic) } fn dri2_create_drawable(&self, drawable: xproto::Drawable) -> Result, ConnectionError> { create_drawable(self, drawable) } fn dri2_destroy_drawable(&self, drawable: xproto::Drawable) -> Result, ConnectionError> { destroy_drawable(self, drawable) } fn dri2_get_buffers<'c, 'input>(&'c self, drawable: xproto::Drawable, count: u32, attachments: &'input [u32]) -> Result, ConnectionError> { get_buffers(self, drawable, count, attachments) } fn dri2_copy_region(&self, drawable: xproto::Drawable, region: u32, dest: u32, src: u32) -> Result, 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, 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, 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, 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, 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, ConnectionError> { wait_sbc(self, drawable, target_sbc_hi, target_sbc_lo) } fn dri2_swap_interval(&self, drawable: xproto::Drawable, interval: u32) -> Result, ConnectionError> { swap_interval(self, drawable, interval) } fn dri2_get_param(&self, drawable: xproto::Drawable, param: u32) -> Result, ConnectionError> { get_param(self, drawable, param) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/dri3.rs000064400000000000000000000226231046102023000145060ustar 00000000000000// 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: &Conn) -> Result { 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, major_version: u32, minor_version: u32) -> Result, 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, drawable: xproto::Drawable, provider: u32) -> Result, 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: &Conn, pixmap: xproto::Pixmap, drawable: xproto::Drawable, size: u32, width: u16, height: u16, stride: u16, depth: u8, bpp: u8, pixmap_fd: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, pixmap: xproto::Pixmap) -> Result, 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: &Conn, drawable: xproto::Drawable, fence: u32, initially_triggered: bool, fence_fd: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, drawable: xproto::Drawable, fence: u32) -> Result, 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, window: u32, depth: u8, bpp: u8) -> Result, 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, 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) -> Result, 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, pixmap: xproto::Pixmap) -> Result, 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, window: xproto::Window, drm_major: u32, drm_minor: u32) -> Result, 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) } /// Extension trait defining the requests of this extension. pub trait ConnectionExt: RequestConnection { fn dri3_query_version(&self, major_version: u32, minor_version: u32) -> Result, ConnectionError> { query_version(self, major_version, minor_version) } fn dri3_open(&self, drawable: xproto::Drawable, provider: u32) -> Result, ConnectionError> { open(self, drawable, provider) } fn dri3_pixmap_from_buffer(&self, pixmap: xproto::Pixmap, drawable: xproto::Drawable, size: u32, width: u16, height: u16, stride: u16, depth: u8, bpp: u8, pixmap_fd: A) -> Result, ConnectionError> where A: Into, { pixmap_from_buffer(self, pixmap, drawable, size, width, height, stride, depth, bpp, pixmap_fd) } fn dri3_buffer_from_pixmap(&self, pixmap: xproto::Pixmap) -> Result, ConnectionError> { buffer_from_pixmap(self, pixmap) } fn dri3_fence_from_fd(&self, drawable: xproto::Drawable, fence: u32, initially_triggered: bool, fence_fd: A) -> Result, ConnectionError> where A: Into, { fence_from_fd(self, drawable, fence, initially_triggered, fence_fd) } fn dri3_fd_from_fence(&self, drawable: xproto::Drawable, fence: u32) -> Result, ConnectionError> { fd_from_fence(self, drawable, fence) } fn dri3_get_supported_modifiers(&self, window: u32, depth: u8, bpp: u8) -> Result, 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) -> Result, 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, ConnectionError> { buffers_from_pixmap(self, pixmap) } fn dri3_set_drm_device_in_use(&self, window: xproto::Window, drm_major: u32, drm_minor: u32) -> Result, ConnectionError> { set_drm_device_in_use(self, window, drm_major, drm_minor) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/ge.rs000064400000000000000000000037501046102023000142400ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u16, client_minor_version: u16) -> Result, 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, ConnectionError> { query_version(self, client_major_version, client_minor_version) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/glx.rs000064400000000000000000002240461046102023000144420ustar 00000000000000// This file contains generated code. Do not edit directly. // To regenerate this, run 'make'. //! Bindings to the `Glx` 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::glx::*; /// Get the major opcode of this extension fn major_opcode(conn: &Conn) -> Result { let info = conn.extension_information(X11_EXTENSION_NAME)?; let info = info.ok_or(ConnectionError::UnsupportedExtension)?; Ok(info.major_opcode) } pub fn render<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = RenderRequest { context_tag, 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 render_large<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, request_num: u16, request_total: u16, data: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = RenderLargeRequest { context_tag, request_num, request_total, 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 create_context(conn: &Conn, context: Context, visual: xproto::Visualid, screen: u32, share_list: Context, is_direct: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateContextRequest { context, visual, screen, share_list, is_direct, }; 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_context(conn: &Conn, context: Context) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DestroyContextRequest { 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 make_current(conn: &Conn, drawable: Drawable, context: Context, old_context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = MakeCurrentRequest { drawable, context, old_context_tag, }; 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_direct(conn: &Conn, context: Context) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = IsDirectRequest { 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 query_version(conn: &Conn, major_version: u32, minor_version: u32) -> Result, 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 wait_gl(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = WaitGLRequest { context_tag, }; 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 wait_x(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = WaitXRequest { context_tag, }; 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 copy_context(conn: &Conn, src: Context, dest: Context, mask: u32, src_context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CopyContextRequest { src, dest, mask, src_context_tag, }; 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 swap_buffers(conn: &Conn, context_tag: ContextTag, drawable: Drawable) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SwapBuffersRequest { context_tag, 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 use_x_font(conn: &Conn, context_tag: ContextTag, font: xproto::Font, first: u32, count: u32, list_base: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = UseXFontRequest { context_tag, font, first, count, list_base, }; 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_glx_pixmap(conn: &Conn, screen: u32, visual: xproto::Visualid, pixmap: xproto::Pixmap, glx_pixmap: Pixmap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateGLXPixmapRequest { screen, visual, pixmap, glx_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_visual_configs(conn: &Conn, screen: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetVisualConfigsRequest { 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 destroy_glx_pixmap(conn: &Conn, glx_pixmap: Pixmap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DestroyGLXPixmapRequest { glx_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 vendor_private<'c, 'input, Conn>(conn: &'c Conn, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = VendorPrivateRequest { vendor_code, context_tag, 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 vendor_private_with_reply<'c, 'input, Conn>(conn: &'c Conn, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = VendorPrivateWithReplyRequest { vendor_code, context_tag, 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_with_reply(&slices, fds) } pub fn query_extensions_string(conn: &Conn, screen: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryExtensionsStringRequest { 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 query_server_string(conn: &Conn, screen: u32, name: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryServerStringRequest { screen, name, }; 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 client_info<'c, 'input, Conn>(conn: &'c Conn, major_version: u32, minor_version: u32, string: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ClientInfoRequest { major_version, minor_version, string: Cow::Borrowed(string), }; 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_fb_configs(conn: &Conn, screen: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetFBConfigsRequest { 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_pixmap<'c, 'input, Conn>(conn: &'c Conn, screen: u32, fbconfig: Fbconfig, pixmap: xproto::Pixmap, glx_pixmap: Pixmap, attribs: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreatePixmapRequest { screen, fbconfig, pixmap, glx_pixmap, attribs: Cow::Borrowed(attribs), }; 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_pixmap(conn: &Conn, glx_pixmap: Pixmap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DestroyPixmapRequest { glx_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 create_new_context(conn: &Conn, context: Context, fbconfig: Fbconfig, screen: u32, render_type: u32, share_list: Context, is_direct: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateNewContextRequest { context, fbconfig, screen, render_type, share_list, is_direct, }; 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_context(conn: &Conn, context: Context) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryContextRequest { 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 make_context_current(conn: &Conn, old_context_tag: ContextTag, drawable: Drawable, read_drawable: Drawable, context: Context) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = MakeContextCurrentRequest { old_context_tag, drawable, read_drawable, 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 create_pbuffer<'c, 'input, Conn>(conn: &'c Conn, screen: u32, fbconfig: Fbconfig, pbuffer: Pbuffer, attribs: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreatePbufferRequest { screen, fbconfig, pbuffer, attribs: Cow::Borrowed(attribs), }; 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_pbuffer(conn: &Conn, pbuffer: Pbuffer) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DestroyPbufferRequest { pbuffer, }; 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_attributes(conn: &Conn, drawable: Drawable) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDrawableAttributesRequest { 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 change_drawable_attributes<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, attribs: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeDrawableAttributesRequest { drawable, attribs: Cow::Borrowed(attribs), }; 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_window<'c, 'input, Conn>(conn: &'c Conn, screen: u32, fbconfig: Fbconfig, window: xproto::Window, glx_window: Window, attribs: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateWindowRequest { screen, fbconfig, window, glx_window, attribs: Cow::Borrowed(attribs), }; 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_window(conn: &Conn, glxwindow: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeleteWindowRequest { glxwindow, }; 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_client_info_arb<'c, 'input, Conn>(conn: &'c Conn, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetClientInfoARBRequest { major_version, minor_version, gl_versions: Cow::Borrowed(gl_versions), gl_extension_string: Cow::Borrowed(gl_extension_string), glx_extension_string: Cow::Borrowed(glx_extension_string), }; 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])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn create_context_attribs_arb<'c, 'input, Conn>(conn: &'c Conn, context: Context, fbconfig: Fbconfig, screen: u32, share_list: Context, is_direct: bool, attribs: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateContextAttribsARBRequest { context, fbconfig, screen, share_list, is_direct, attribs: Cow::Borrowed(attribs), }; 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_client_info2_arb<'c, 'input, Conn>(conn: &'c Conn, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetClientInfo2ARBRequest { major_version, minor_version, gl_versions: Cow::Borrowed(gl_versions), gl_extension_string: Cow::Borrowed(gl_extension_string), glx_extension_string: Cow::Borrowed(glx_extension_string), }; 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])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn new_list(conn: &Conn, context_tag: ContextTag, list: u32, mode: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = NewListRequest { context_tag, list, 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 end_list(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = EndListRequest { context_tag, }; 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_lists(conn: &Conn, context_tag: ContextTag, list: u32, range: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeleteListsRequest { context_tag, list, range, }; 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 gen_lists(conn: &Conn, context_tag: ContextTag, range: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GenListsRequest { context_tag, range, }; 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 feedback_buffer(conn: &Conn, context_tag: ContextTag, size: i32, type_: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FeedbackBufferRequest { context_tag, size, type_, }; 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_buffer(conn: &Conn, context_tag: ContextTag, size: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SelectBufferRequest { context_tag, size, }; 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 render_mode(conn: &Conn, context_tag: ContextTag, mode: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = RenderModeRequest { context_tag, mode, }; 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 finish(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FinishRequest { context_tag, }; 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 pixel_storef(conn: &Conn, context_tag: ContextTag, pname: u32, datum: Float32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PixelStorefRequest { context_tag, pname, datum, }; 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 pixel_storei(conn: &Conn, context_tag: ContextTag, pname: u32, datum: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PixelStoreiRequest { context_tag, pname, datum, }; 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 read_pixels(conn: &Conn, context_tag: ContextTag, x: i32, y: i32, width: i32, height: i32, format: u32, type_: u32, swap_bytes: bool, lsb_first: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ReadPixelsRequest { context_tag, x, y, width, height, format, type_, swap_bytes, lsb_first, }; 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_booleanv(conn: &Conn, context_tag: ContextTag, pname: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetBooleanvRequest { context_tag, pname, }; 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_clip_plane(conn: &Conn, context_tag: ContextTag, plane: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetClipPlaneRequest { context_tag, plane, }; 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_doublev(conn: &Conn, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDoublevRequest { context_tag, pname, }; 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_error(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetErrorRequest { context_tag, }; 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_floatv(conn: &Conn, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetFloatvRequest { context_tag, pname, }; 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_integerv(conn: &Conn, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetIntegervRequest { context_tag, pname, }; 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_lightfv(conn: &Conn, context_tag: ContextTag, light: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetLightfvRequest { context_tag, light, pname, }; 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_lightiv(conn: &Conn, context_tag: ContextTag, light: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetLightivRequest { context_tag, light, pname, }; 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_mapdv(conn: &Conn, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMapdvRequest { context_tag, target, query, }; 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_mapfv(conn: &Conn, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMapfvRequest { context_tag, target, query, }; 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_mapiv(conn: &Conn, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMapivRequest { context_tag, target, query, }; 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_materialfv(conn: &Conn, context_tag: ContextTag, face: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMaterialfvRequest { context_tag, face, pname, }; 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_materialiv(conn: &Conn, context_tag: ContextTag, face: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMaterialivRequest { context_tag, face, pname, }; 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_pixel_mapfv(conn: &Conn, context_tag: ContextTag, map: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetPixelMapfvRequest { context_tag, map, }; 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_pixel_mapuiv(conn: &Conn, context_tag: ContextTag, map: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetPixelMapuivRequest { context_tag, map, }; 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_pixel_mapusv(conn: &Conn, context_tag: ContextTag, map: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetPixelMapusvRequest { context_tag, map, }; 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_polygon_stipple(conn: &Conn, context_tag: ContextTag, lsb_first: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetPolygonStippleRequest { context_tag, lsb_first, }; 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_string(conn: &Conn, context_tag: ContextTag, name: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetStringRequest { context_tag, name, }; 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_tex_envfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexEnvfvRequest { context_tag, target, pname, }; 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_tex_enviv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexEnvivRequest { context_tag, target, pname, }; 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_tex_gendv(conn: &Conn, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexGendvRequest { context_tag, coord, pname, }; 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_tex_genfv(conn: &Conn, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexGenfvRequest { context_tag, coord, pname, }; 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_tex_geniv(conn: &Conn, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexGenivRequest { context_tag, coord, pname, }; 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_tex_image(conn: &Conn, context_tag: ContextTag, target: u32, level: i32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexImageRequest { context_tag, target, level, format, type_, swap_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 get_tex_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexParameterfvRequest { context_tag, target, pname, }; 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_tex_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexParameterivRequest { context_tag, target, pname, }; 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_tex_level_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexLevelParameterfvRequest { context_tag, target, level, pname, }; 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_tex_level_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetTexLevelParameterivRequest { context_tag, target, level, pname, }; 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_enabled(conn: &Conn, context_tag: ContextTag, capability: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = IsEnabledRequest { context_tag, capability, }; 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_list(conn: &Conn, context_tag: ContextTag, list: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = IsListRequest { context_tag, list, }; 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 flush(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FlushRequest { context_tag, }; 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 are_textures_resident<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, textures: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = AreTexturesResidentRequest { context_tag, textures: Cow::Borrowed(textures), }; 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 delete_textures<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, textures: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeleteTexturesRequest { context_tag, textures: Cow::Borrowed(textures), }; 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 gen_textures(conn: &Conn, context_tag: ContextTag, n: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GenTexturesRequest { context_tag, n, }; 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_texture(conn: &Conn, context_tag: ContextTag, texture: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = IsTextureRequest { context_tag, texture, }; 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_color_table(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetColorTableRequest { context_tag, target, format, type_, swap_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 get_color_table_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetColorTableParameterfvRequest { context_tag, target, pname, }; 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_color_table_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetColorTableParameterivRequest { context_tag, target, pname, }; 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_convolution_filter(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetConvolutionFilterRequest { context_tag, target, format, type_, swap_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 get_convolution_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetConvolutionParameterfvRequest { context_tag, target, pname, }; 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_convolution_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetConvolutionParameterivRequest { context_tag, target, pname, }; 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_separable_filter(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetSeparableFilterRequest { context_tag, target, format, type_, swap_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 get_histogram(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetHistogramRequest { context_tag, target, format, type_, swap_bytes, reset, }; 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_histogram_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetHistogramParameterfvRequest { context_tag, target, pname, }; 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_histogram_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetHistogramParameterivRequest { context_tag, target, pname, }; 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_minmax(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMinmaxRequest { context_tag, target, format, type_, swap_bytes, reset, }; 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_minmax_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMinmaxParameterfvRequest { context_tag, target, pname, }; 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_minmax_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetMinmaxParameterivRequest { context_tag, target, pname, }; 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_compressed_tex_image_arb(conn: &Conn, context_tag: ContextTag, target: u32, level: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetCompressedTexImageARBRequest { context_tag, target, level, }; 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 delete_queries_arb<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, ids: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeleteQueriesARBRequest { context_tag, ids: Cow::Borrowed(ids), }; 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 gen_queries_arb(conn: &Conn, context_tag: ContextTag, n: i32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GenQueriesARBRequest { context_tag, n, }; 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_query_arb(conn: &Conn, context_tag: ContextTag, id: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = IsQueryARBRequest { context_tag, 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 get_queryiv_arb(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetQueryivARBRequest { context_tag, target, pname, }; 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_query_objectiv_arb(conn: &Conn, context_tag: ContextTag, id: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetQueryObjectivARBRequest { context_tag, id, pname, }; 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_query_objectuiv_arb(conn: &Conn, context_tag: ContextTag, id: u32, pname: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetQueryObjectuivARBRequest { context_tag, id, pname, }; 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 glx_render<'c, 'input>(&'c self, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> { render(self, context_tag, data) } fn glx_render_large<'c, 'input>(&'c self, context_tag: ContextTag, request_num: u16, request_total: u16, data: &'input [u8]) -> Result, ConnectionError> { render_large(self, context_tag, request_num, request_total, data) } fn glx_create_context(&self, context: Context, visual: xproto::Visualid, screen: u32, share_list: Context, is_direct: bool) -> Result, ConnectionError> { create_context(self, context, visual, screen, share_list, is_direct) } fn glx_destroy_context(&self, context: Context) -> Result, ConnectionError> { destroy_context(self, context) } fn glx_make_current(&self, drawable: Drawable, context: Context, old_context_tag: ContextTag) -> Result, ConnectionError> { make_current(self, drawable, context, old_context_tag) } fn glx_is_direct(&self, context: Context) -> Result, ConnectionError> { is_direct(self, context) } fn glx_query_version(&self, major_version: u32, minor_version: u32) -> Result, ConnectionError> { query_version(self, major_version, minor_version) } fn glx_wait_gl(&self, context_tag: ContextTag) -> Result, ConnectionError> { wait_gl(self, context_tag) } fn glx_wait_x(&self, context_tag: ContextTag) -> Result, ConnectionError> { wait_x(self, context_tag) } fn glx_copy_context(&self, src: Context, dest: Context, mask: u32, src_context_tag: ContextTag) -> Result, ConnectionError> { copy_context(self, src, dest, mask, src_context_tag) } fn glx_swap_buffers(&self, context_tag: ContextTag, drawable: Drawable) -> Result, ConnectionError> { swap_buffers(self, context_tag, drawable) } fn glx_use_x_font(&self, context_tag: ContextTag, font: xproto::Font, first: u32, count: u32, list_base: u32) -> Result, ConnectionError> { use_x_font(self, context_tag, font, first, count, list_base) } fn glx_create_glx_pixmap(&self, screen: u32, visual: xproto::Visualid, pixmap: xproto::Pixmap, glx_pixmap: Pixmap) -> Result, ConnectionError> { create_glx_pixmap(self, screen, visual, pixmap, glx_pixmap) } fn glx_get_visual_configs(&self, screen: u32) -> Result, ConnectionError> { get_visual_configs(self, screen) } fn glx_destroy_glx_pixmap(&self, glx_pixmap: Pixmap) -> Result, ConnectionError> { destroy_glx_pixmap(self, glx_pixmap) } fn glx_vendor_private<'c, 'input>(&'c self, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> { vendor_private(self, vendor_code, context_tag, data) } fn glx_vendor_private_with_reply<'c, 'input>(&'c self, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> { vendor_private_with_reply(self, vendor_code, context_tag, data) } fn glx_query_extensions_string(&self, screen: u32) -> Result, ConnectionError> { query_extensions_string(self, screen) } fn glx_query_server_string(&self, screen: u32, name: u32) -> Result, ConnectionError> { query_server_string(self, screen, name) } fn glx_client_info<'c, 'input>(&'c self, major_version: u32, minor_version: u32, string: &'input [u8]) -> Result, ConnectionError> { client_info(self, major_version, minor_version, string) } fn glx_get_fb_configs(&self, screen: u32) -> Result, ConnectionError> { get_fb_configs(self, screen) } fn glx_create_pixmap<'c, 'input>(&'c self, screen: u32, fbconfig: Fbconfig, pixmap: xproto::Pixmap, glx_pixmap: Pixmap, attribs: &'input [u32]) -> Result, ConnectionError> { create_pixmap(self, screen, fbconfig, pixmap, glx_pixmap, attribs) } fn glx_destroy_pixmap(&self, glx_pixmap: Pixmap) -> Result, ConnectionError> { destroy_pixmap(self, glx_pixmap) } fn glx_create_new_context(&self, context: Context, fbconfig: Fbconfig, screen: u32, render_type: u32, share_list: Context, is_direct: bool) -> Result, ConnectionError> { create_new_context(self, context, fbconfig, screen, render_type, share_list, is_direct) } fn glx_query_context(&self, context: Context) -> Result, ConnectionError> { query_context(self, context) } fn glx_make_context_current(&self, old_context_tag: ContextTag, drawable: Drawable, read_drawable: Drawable, context: Context) -> Result, ConnectionError> { make_context_current(self, old_context_tag, drawable, read_drawable, context) } fn glx_create_pbuffer<'c, 'input>(&'c self, screen: u32, fbconfig: Fbconfig, pbuffer: Pbuffer, attribs: &'input [u32]) -> Result, ConnectionError> { create_pbuffer(self, screen, fbconfig, pbuffer, attribs) } fn glx_destroy_pbuffer(&self, pbuffer: Pbuffer) -> Result, ConnectionError> { destroy_pbuffer(self, pbuffer) } fn glx_get_drawable_attributes(&self, drawable: Drawable) -> Result, ConnectionError> { get_drawable_attributes(self, drawable) } fn glx_change_drawable_attributes<'c, 'input>(&'c self, drawable: Drawable, attribs: &'input [u32]) -> Result, ConnectionError> { change_drawable_attributes(self, drawable, attribs) } fn glx_create_window<'c, 'input>(&'c self, screen: u32, fbconfig: Fbconfig, window: xproto::Window, glx_window: Window, attribs: &'input [u32]) -> Result, ConnectionError> { create_window(self, screen, fbconfig, window, glx_window, attribs) } fn glx_delete_window(&self, glxwindow: Window) -> Result, ConnectionError> { delete_window(self, glxwindow) } fn glx_set_client_info_arb<'c, 'input>(&'c self, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Result, ConnectionError> { set_client_info_arb(self, major_version, minor_version, gl_versions, gl_extension_string, glx_extension_string) } fn glx_create_context_attribs_arb<'c, 'input>(&'c self, context: Context, fbconfig: Fbconfig, screen: u32, share_list: Context, is_direct: bool, attribs: &'input [u32]) -> Result, ConnectionError> { create_context_attribs_arb(self, context, fbconfig, screen, share_list, is_direct, attribs) } fn glx_set_client_info2_arb<'c, 'input>(&'c self, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Result, ConnectionError> { set_client_info2_arb(self, major_version, minor_version, gl_versions, gl_extension_string, glx_extension_string) } fn glx_new_list(&self, context_tag: ContextTag, list: u32, mode: u32) -> Result, ConnectionError> { new_list(self, context_tag, list, mode) } fn glx_end_list(&self, context_tag: ContextTag) -> Result, ConnectionError> { end_list(self, context_tag) } fn glx_delete_lists(&self, context_tag: ContextTag, list: u32, range: i32) -> Result, ConnectionError> { delete_lists(self, context_tag, list, range) } fn glx_gen_lists(&self, context_tag: ContextTag, range: i32) -> Result, ConnectionError> { gen_lists(self, context_tag, range) } fn glx_feedback_buffer(&self, context_tag: ContextTag, size: i32, type_: i32) -> Result, ConnectionError> { feedback_buffer(self, context_tag, size, type_) } fn glx_select_buffer(&self, context_tag: ContextTag, size: i32) -> Result, ConnectionError> { select_buffer(self, context_tag, size) } fn glx_render_mode(&self, context_tag: ContextTag, mode: u32) -> Result, ConnectionError> { render_mode(self, context_tag, mode) } fn glx_finish(&self, context_tag: ContextTag) -> Result, ConnectionError> { finish(self, context_tag) } fn glx_pixel_storef(&self, context_tag: ContextTag, pname: u32, datum: Float32) -> Result, ConnectionError> { pixel_storef(self, context_tag, pname, datum) } fn glx_pixel_storei(&self, context_tag: ContextTag, pname: u32, datum: i32) -> Result, ConnectionError> { pixel_storei(self, context_tag, pname, datum) } fn glx_read_pixels(&self, context_tag: ContextTag, x: i32, y: i32, width: i32, height: i32, format: u32, type_: u32, swap_bytes: bool, lsb_first: bool) -> Result, ConnectionError> { read_pixels(self, context_tag, x, y, width, height, format, type_, swap_bytes, lsb_first) } fn glx_get_booleanv(&self, context_tag: ContextTag, pname: i32) -> Result, ConnectionError> { get_booleanv(self, context_tag, pname) } fn glx_get_clip_plane(&self, context_tag: ContextTag, plane: i32) -> Result, ConnectionError> { get_clip_plane(self, context_tag, plane) } fn glx_get_doublev(&self, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> { get_doublev(self, context_tag, pname) } fn glx_get_error(&self, context_tag: ContextTag) -> Result, ConnectionError> { get_error(self, context_tag) } fn glx_get_floatv(&self, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> { get_floatv(self, context_tag, pname) } fn glx_get_integerv(&self, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> { get_integerv(self, context_tag, pname) } fn glx_get_lightfv(&self, context_tag: ContextTag, light: u32, pname: u32) -> Result, ConnectionError> { get_lightfv(self, context_tag, light, pname) } fn glx_get_lightiv(&self, context_tag: ContextTag, light: u32, pname: u32) -> Result, ConnectionError> { get_lightiv(self, context_tag, light, pname) } fn glx_get_mapdv(&self, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> { get_mapdv(self, context_tag, target, query) } fn glx_get_mapfv(&self, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> { get_mapfv(self, context_tag, target, query) } fn glx_get_mapiv(&self, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> { get_mapiv(self, context_tag, target, query) } fn glx_get_materialfv(&self, context_tag: ContextTag, face: u32, pname: u32) -> Result, ConnectionError> { get_materialfv(self, context_tag, face, pname) } fn glx_get_materialiv(&self, context_tag: ContextTag, face: u32, pname: u32) -> Result, ConnectionError> { get_materialiv(self, context_tag, face, pname) } fn glx_get_pixel_mapfv(&self, context_tag: ContextTag, map: u32) -> Result, ConnectionError> { get_pixel_mapfv(self, context_tag, map) } fn glx_get_pixel_mapuiv(&self, context_tag: ContextTag, map: u32) -> Result, ConnectionError> { get_pixel_mapuiv(self, context_tag, map) } fn glx_get_pixel_mapusv(&self, context_tag: ContextTag, map: u32) -> Result, ConnectionError> { get_pixel_mapusv(self, context_tag, map) } fn glx_get_polygon_stipple(&self, context_tag: ContextTag, lsb_first: bool) -> Result, ConnectionError> { get_polygon_stipple(self, context_tag, lsb_first) } fn glx_get_string(&self, context_tag: ContextTag, name: u32) -> Result, ConnectionError> { get_string(self, context_tag, name) } fn glx_get_tex_envfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_tex_envfv(self, context_tag, target, pname) } fn glx_get_tex_enviv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_tex_enviv(self, context_tag, target, pname) } fn glx_get_tex_gendv(&self, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> { get_tex_gendv(self, context_tag, coord, pname) } fn glx_get_tex_genfv(&self, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> { get_tex_genfv(self, context_tag, coord, pname) } fn glx_get_tex_geniv(&self, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> { get_tex_geniv(self, context_tag, coord, pname) } fn glx_get_tex_image(&self, context_tag: ContextTag, target: u32, level: i32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> { get_tex_image(self, context_tag, target, level, format, type_, swap_bytes) } fn glx_get_tex_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_tex_parameterfv(self, context_tag, target, pname) } fn glx_get_tex_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_tex_parameteriv(self, context_tag, target, pname) } fn glx_get_tex_level_parameterfv(&self, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Result, ConnectionError> { get_tex_level_parameterfv(self, context_tag, target, level, pname) } fn glx_get_tex_level_parameteriv(&self, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Result, ConnectionError> { get_tex_level_parameteriv(self, context_tag, target, level, pname) } fn glx_is_enabled(&self, context_tag: ContextTag, capability: u32) -> Result, ConnectionError> { is_enabled(self, context_tag, capability) } fn glx_is_list(&self, context_tag: ContextTag, list: u32) -> Result, ConnectionError> { is_list(self, context_tag, list) } fn glx_flush(&self, context_tag: ContextTag) -> Result, ConnectionError> { flush(self, context_tag) } fn glx_are_textures_resident<'c, 'input>(&'c self, context_tag: ContextTag, textures: &'input [u32]) -> Result, ConnectionError> { are_textures_resident(self, context_tag, textures) } fn glx_delete_textures<'c, 'input>(&'c self, context_tag: ContextTag, textures: &'input [u32]) -> Result, ConnectionError> { delete_textures(self, context_tag, textures) } fn glx_gen_textures(&self, context_tag: ContextTag, n: i32) -> Result, ConnectionError> { gen_textures(self, context_tag, n) } fn glx_is_texture(&self, context_tag: ContextTag, texture: u32) -> Result, ConnectionError> { is_texture(self, context_tag, texture) } fn glx_get_color_table(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> { get_color_table(self, context_tag, target, format, type_, swap_bytes) } fn glx_get_color_table_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_color_table_parameterfv(self, context_tag, target, pname) } fn glx_get_color_table_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_color_table_parameteriv(self, context_tag, target, pname) } fn glx_get_convolution_filter(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> { get_convolution_filter(self, context_tag, target, format, type_, swap_bytes) } fn glx_get_convolution_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_convolution_parameterfv(self, context_tag, target, pname) } fn glx_get_convolution_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_convolution_parameteriv(self, context_tag, target, pname) } fn glx_get_separable_filter(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> { get_separable_filter(self, context_tag, target, format, type_, swap_bytes) } fn glx_get_histogram(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Result, ConnectionError> { get_histogram(self, context_tag, target, format, type_, swap_bytes, reset) } fn glx_get_histogram_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_histogram_parameterfv(self, context_tag, target, pname) } fn glx_get_histogram_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_histogram_parameteriv(self, context_tag, target, pname) } fn glx_get_minmax(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Result, ConnectionError> { get_minmax(self, context_tag, target, format, type_, swap_bytes, reset) } fn glx_get_minmax_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_minmax_parameterfv(self, context_tag, target, pname) } fn glx_get_minmax_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_minmax_parameteriv(self, context_tag, target, pname) } fn glx_get_compressed_tex_image_arb(&self, context_tag: ContextTag, target: u32, level: i32) -> Result, ConnectionError> { get_compressed_tex_image_arb(self, context_tag, target, level) } fn glx_delete_queries_arb<'c, 'input>(&'c self, context_tag: ContextTag, ids: &'input [u32]) -> Result, ConnectionError> { delete_queries_arb(self, context_tag, ids) } fn glx_gen_queries_arb(&self, context_tag: ContextTag, n: i32) -> Result, ConnectionError> { gen_queries_arb(self, context_tag, n) } fn glx_is_query_arb(&self, context_tag: ContextTag, id: u32) -> Result, ConnectionError> { is_query_arb(self, context_tag, id) } fn glx_get_queryiv_arb(&self, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> { get_queryiv_arb(self, context_tag, target, pname) } fn glx_get_query_objectiv_arb(&self, context_tag: ContextTag, id: u32, pname: u32) -> Result, ConnectionError> { get_query_objectiv_arb(self, context_tag, id, pname) } fn glx_get_query_objectuiv_arb(&self, context_tag: ContextTag, id: u32, pname: u32) -> Result, ConnectionError> { get_query_objectuiv_arb(self, context_tag, id, pname) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/mod.rs000064400000000000000000000036011046102023000144170ustar 00000000000000// 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; x11rb-0.13.0/src/protocol/present.rs000064400000000000000000000133451046102023000153260ustar 00000000000000// 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::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: &Conn) -> Result { 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, major_version: u32, minor_version: u32) -> Result, 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, 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, window: xproto::Window, serial: u32, target_msc: u64, divisor: u64, remainder: u64) -> Result, 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, eid: Event, window: xproto::Window, event_mask: EventMask) -> Result, 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, target: u32) -> Result, 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) } /// Extension trait defining the requests of this extension. pub trait ConnectionExt: RequestConnection { fn present_query_version(&self, major_version: u32, minor_version: u32) -> Result, 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, 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, ConnectionError> { notify_msc(self, window, serial, target_msc, divisor, remainder) } fn present_select_input(&self, eid: Event, window: xproto::Window, event_mask: EventMask) -> Result, ConnectionError> { select_input(self, eid, window, event_mask) } fn present_query_capabilities(&self, target: u32) -> Result, ConnectionError> { query_capabilities(self, target) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/randr.rs000064400000000000000000001070241046102023000147520ustar 00000000000000// 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: &Conn) -> Result { 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, major_version: u32, minor_version: u32) -> Result, 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, window: xproto::Window, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, size_id: u16, rotation: Rotation, rate: u16) -> Result, 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, window: xproto::Window, enable: NotifyMask) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window, width: u16, height: u16, mm_width: u32, mm_height: u32) -> Result, 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, window: xproto::Window) -> Result, 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, output: Output, config_timestamp: xproto::Timestamp) -> Result, 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, output: Output) -> Result, 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, output: Output, property: xproto::Atom) -> Result, 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, 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, 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, output: Output, property: xproto::Atom) -> Result, 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: &Conn, output: Output, property: xproto::Atom, type_: A, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, 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, mode: Mode) -> Result, 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, output: Output, mode: Mode) -> Result, 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, output: Output, mode: Mode) -> Result, 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, crtc: Crtc, config_timestamp: xproto::Timestamp) -> Result, 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, 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, crtc: Crtc) -> Result, 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, crtc: Crtc) -> Result, 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, 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, window: xproto::Window) -> Result, 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, 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, crtc: Crtc) -> Result, 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, crtc: Crtc) -> Result, 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, 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, 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, window: xproto::Window, output: Output) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window) -> Result, 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, provider: Provider, config_timestamp: xproto::Timestamp) -> Result, 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, provider: Provider, sink_provider: Provider, config_timestamp: xproto::Timestamp) -> Result, 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, provider: Provider, source_provider: Provider, config_timestamp: xproto::Timestamp) -> Result, 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, provider: Provider) -> Result, 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, provider: Provider, property: xproto::Atom) -> Result, 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, 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, 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, provider: Provider, property: xproto::Atom) -> Result, 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, provider: Provider, property: xproto::Atom, type_: xproto::Atom, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result, 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, window: xproto::Window, get_active: bool) -> Result, 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, window: xproto::Window, monitorinfo: MonitorInfo) -> Result, 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, window: xproto::Window, name: xproto::Atom) -> Result, 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, 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, lid: Lease, terminate: u8) -> Result, 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, 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, ConnectionError> { set_screen_config(self, window, timestamp, config_timestamp, size_id, rotation, rate) } fn randr_select_input(&self, window: xproto::Window, enable: NotifyMask) -> Result, ConnectionError> { select_input(self, window, enable) } fn randr_get_screen_info(&self, window: xproto::Window) -> Result, ConnectionError> { get_screen_info(self, window) } fn randr_get_screen_size_range(&self, window: xproto::Window) -> Result, 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, ConnectionError> { set_screen_size(self, window, width, height, mm_width, mm_height) } fn randr_get_screen_resources(&self, window: xproto::Window) -> Result, ConnectionError> { get_screen_resources(self, window) } fn randr_get_output_info(&self, output: Output, config_timestamp: xproto::Timestamp) -> Result, ConnectionError> { get_output_info(self, output, config_timestamp) } fn randr_list_output_properties(&self, output: Output) -> Result, ConnectionError> { list_output_properties(self, output) } fn randr_query_output_property(&self, output: Output, property: xproto::Atom) -> Result, 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, 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, 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, ConnectionError> { delete_output_property(self, output, property) } fn randr_get_output_property(&self, output: Output, property: xproto::Atom, type_: A, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result, ConnectionError> where A: Into, { 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, ConnectionError> { create_mode(self, window, mode_info, name) } fn randr_destroy_mode(&self, mode: Mode) -> Result, ConnectionError> { destroy_mode(self, mode) } fn randr_add_output_mode(&self, output: Output, mode: Mode) -> Result, ConnectionError> { add_output_mode(self, output, mode) } fn randr_delete_output_mode(&self, output: Output, mode: Mode) -> Result, ConnectionError> { delete_output_mode(self, output, mode) } fn randr_get_crtc_info(&self, crtc: Crtc, config_timestamp: xproto::Timestamp) -> Result, 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, ConnectionError> { set_crtc_config(self, crtc, timestamp, config_timestamp, x, y, mode, rotation, outputs) } fn randr_get_crtc_gamma_size(&self, crtc: Crtc) -> Result, ConnectionError> { get_crtc_gamma_size(self, crtc) } fn randr_get_crtc_gamma(&self, crtc: Crtc) -> Result, 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, ConnectionError> { set_crtc_gamma(self, crtc, red, green, blue) } fn randr_get_screen_resources_current(&self, window: xproto::Window) -> Result, 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, ConnectionError> { set_crtc_transform(self, crtc, transform, filter_name, filter_params) } fn randr_get_crtc_transform(&self, crtc: Crtc) -> Result, ConnectionError> { get_crtc_transform(self, crtc) } fn randr_get_panning(&self, crtc: Crtc) -> Result, 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, 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, ConnectionError> { set_output_primary(self, window, output) } fn randr_get_output_primary(&self, window: xproto::Window) -> Result, ConnectionError> { get_output_primary(self, window) } fn randr_get_providers(&self, window: xproto::Window) -> Result, ConnectionError> { get_providers(self, window) } fn randr_get_provider_info(&self, provider: Provider, config_timestamp: xproto::Timestamp) -> Result, 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, 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, ConnectionError> { set_provider_output_source(self, provider, source_provider, config_timestamp) } fn randr_list_provider_properties(&self, provider: Provider) -> Result, ConnectionError> { list_provider_properties(self, provider) } fn randr_query_provider_property(&self, provider: Provider, property: xproto::Atom) -> Result, 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, 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, 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, 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, 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, ConnectionError> { get_monitors(self, window, get_active) } fn randr_set_monitor(&self, window: xproto::Window, monitorinfo: MonitorInfo) -> Result, ConnectionError> { set_monitor(self, window, monitorinfo) } fn randr_delete_monitor(&self, window: xproto::Window, name: xproto::Atom) -> Result, 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, ConnectionError> { create_lease(self, window, lid, crtcs, outputs) } fn randr_free_lease(&self, lid: Lease, terminate: u8) -> Result, ConnectionError> { free_lease(self, lid, terminate) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/record.rs000064400000000000000000000236571046102023000151330ustar 00000000000000// 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: &Conn) -> Result { 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, major_version: u16, minor_version: u16) -> Result, 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, 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, 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, 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, context: Context) -> Result, 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, context: Context) -> Result, 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, context: Context) -> Result, 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, context: Context) -> Result, 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, 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, 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, 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, ConnectionError> { unregister_clients(self, context, client_specs) } fn record_get_context(&self, context: Context) -> Result, ConnectionError> { get_context(self, context) } fn record_enable_context(&self, context: Context) -> Result, ConnectionError> { enable_context(self, context) } fn record_disable_context(&self, context: Context) -> Result, ConnectionError> { disable_context(self, context) } fn record_free_context(&self, context: Context) -> Result, ConnectionError> { free_context(self, context) } } impl 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, Context); impl ContextWrapper { /// 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 ContextWrapper { /// 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 { let context = conn.generate_id()?; let _ = create_context(&conn, context, element_header, client_specs, ranges)?; Ok(Self::for_context(conn, context)) } } impl From<&ContextWrapper> for Context { fn from(from: &ContextWrapper) -> Self { from.1 } } impl Drop for ContextWrapper { fn drop(&mut self) { let _ = free_context(&self.0, self.1); } } x11rb-0.13.0/src/protocol/render.rs000064400000000000000000001163371046102023000151320ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u32, client_minor_version: u32) -> Result, 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) -> Result, 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, format: Pictformat) -> Result, 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, 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, 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, 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, picture: Picture) -> Result, 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: &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, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, 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, 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, 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, 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, gsid: Glyphset, format: Pictformat) -> Result, 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, gsid: Glyphset, existing: Glyphset) -> Result, 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, glyphset: Glyphset) -> Result, 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, 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, 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, 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, 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, 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, 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, cid: xproto::Cursor, source: Picture, x: u16, y: u16) -> Result, 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, picture: Picture, transform: Transform) -> Result, 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, drawable: xproto::Drawable) -> Result, 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, 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, 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, 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, picture: Picture, color: Color) -> Result, 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, 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, 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, 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, ConnectionError> { query_version(self, client_major_version, client_minor_version) } fn render_query_pict_formats(&self) -> Result, ConnectionError> { query_pict_formats(self) } fn render_query_pict_index_values(&self, format: Pictformat) -> Result, 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, ConnectionError> { create_picture(self, pid, drawable, format, value_list) } fn render_change_picture<'c, 'input>(&'c self, picture: Picture, value_list: &'input ChangePictureAux) -> Result, 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, ConnectionError> { set_picture_clip_rectangles(self, picture, clip_x_origin, clip_y_origin, rectangles) } fn render_free_picture(&self, picture: Picture) -> Result, ConnectionError> { free_picture(self, picture) } fn render_composite(&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, ConnectionError> where A: Into, { 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, 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, 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, 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, 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, ConnectionError> { create_glyph_set(self, gsid, format) } fn render_reference_glyph_set(&self, gsid: Glyphset, existing: Glyphset) -> Result, ConnectionError> { reference_glyph_set(self, gsid, existing) } fn render_free_glyph_set(&self, glyphset: Glyphset) -> Result, 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, ConnectionError> { add_glyphs(self, glyphset, glyphids, glyphs, data) } fn render_free_glyphs<'c, 'input>(&'c self, glyphset: Glyphset, glyphs: &'input [Glyph]) -> Result, 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, 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, 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, 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, ConnectionError> { fill_rectangles(self, op, dst, color, rects) } fn render_create_cursor(&self, cid: xproto::Cursor, source: Picture, x: u16, y: u16) -> Result, ConnectionError> { create_cursor(self, cid, source, x, y) } fn render_set_picture_transform(&self, picture: Picture, transform: Transform) -> Result, ConnectionError> { set_picture_transform(self, picture, transform) } fn render_query_filters(&self, drawable: xproto::Drawable) -> Result, ConnectionError> { query_filters(self, drawable) } fn render_set_picture_filter<'c, 'input>(&'c self, picture: Picture, filter: &'input [u8], values: &'input [Fixed]) -> Result, ConnectionError> { set_picture_filter(self, picture, filter, values) } fn render_create_anim_cursor<'c, 'input>(&'c self, cid: xproto::Cursor, cursors: &'input [Animcursorelt]) -> Result, 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, ConnectionError> { add_traps(self, picture, x_off, y_off, traps) } fn render_create_solid_fill(&self, picture: Picture, color: Color) -> Result, 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, 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, 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, ConnectionError> { create_conical_gradient(self, picture, center, angle, stops, colors) } } impl 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, Picture); impl PictureWrapper { /// 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 PictureWrapper { /// 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 { 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 PictureWrapper { /// 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 { 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 PictureWrapper { /// 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 { 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 PictureWrapper { /// 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 { 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 PictureWrapper { /// 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 { let picture = conn.generate_id()?; let _ = create_conical_gradient(&conn, picture, center, angle, stops, colors)?; Ok(Self::for_picture(conn, picture)) } } impl From<&PictureWrapper> for Picture { fn from(from: &PictureWrapper) -> Self { from.1 } } impl Drop for PictureWrapper { 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, Glyphset); impl GlyphsetWrapper { /// 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 GlyphsetWrapper { /// 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 { let gsid = conn.generate_id()?; let _ = create_glyph_set(&conn, gsid, format)?; Ok(Self::for_glyphset(conn, gsid)) } } impl From<&GlyphsetWrapper> for Glyphset { fn from(from: &GlyphsetWrapper) -> Self { from.1 } } impl Drop for GlyphsetWrapper { fn drop(&mut self) { let _ = free_glyph_set(&self.0, self.1); } } x11rb-0.13.0/src/protocol/res.rs000064400000000000000000000123251046102023000144340ustar 00000000000000// 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: &Conn) -> Result { 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, client_major: u8, client_minor: u8) -> Result, 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) -> Result, 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, xid: u32) -> Result, 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, xid: u32) -> Result, 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, 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, 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, ConnectionError> { query_version(self, client_major, client_minor) } fn res_query_clients(&self) -> Result, ConnectionError> { query_clients(self) } fn res_query_client_resources(&self, xid: u32) -> Result, ConnectionError> { query_client_resources(self, xid) } fn res_query_client_pixmap_bytes(&self, xid: u32) -> Result, ConnectionError> { query_client_pixmap_bytes(self, xid) } fn res_query_client_ids<'c, 'input>(&'c self, specs: &'input [ClientIdSpec]) -> Result, ConnectionError> { query_client_ids(self, specs) } fn res_query_resource_bytes<'c, 'input>(&'c self, client: u32, specs: &'input [ResourceIdSpec]) -> Result, ConnectionError> { query_resource_bytes(self, client, specs) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/screensaver.rs000064400000000000000000000132101046102023000161550ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u8, client_minor_version: u8) -> Result, 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, drawable: xproto::Drawable) -> Result, 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, drawable: xproto::Drawable, event_mask: Event) -> Result, 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, 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, drawable: xproto::Drawable) -> Result, 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, suspend: u32) -> Result, 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, ConnectionError> { query_version(self, client_major_version, client_minor_version) } fn screensaver_query_info(&self, drawable: xproto::Drawable) -> Result, ConnectionError> { query_info(self, drawable) } fn screensaver_select_input(&self, drawable: xproto::Drawable, event_mask: Event) -> Result, 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, 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, ConnectionError> { unset_attributes(self, drawable) } fn screensaver_suspend(&self, suspend: u32) -> Result, ConnectionError> { self::suspend(self, suspend) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/shape.rs000064400000000000000000000207111046102023000147410ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, 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: &Conn, operation: SO, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_bitmap: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, operation: SO, destination_kind: SK, source_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_window: xproto::Window) -> Result, 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, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16) -> Result, 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, destination_window: xproto::Window) -> Result, 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, destination_window: xproto::Window, enable: bool) -> Result, 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, destination_window: xproto::Window) -> Result, 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, window: xproto::Window, source_kind: SK) -> Result, 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, 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, ConnectionError> { self::rectangles(self, operation, destination_kind, ordering, destination_window, x_offset, y_offset, rectangles) } fn shape_mask(&self, operation: SO, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_bitmap: A) -> Result, ConnectionError> where A: Into, { 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, 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, ConnectionError> { offset(self, destination_kind, destination_window, x_offset, y_offset) } fn shape_query_extents(&self, destination_window: xproto::Window) -> Result, ConnectionError> { query_extents(self, destination_window) } fn shape_select_input(&self, destination_window: xproto::Window, enable: bool) -> Result, ConnectionError> { select_input(self, destination_window, enable) } fn shape_input_selected(&self, destination_window: xproto::Window) -> Result, ConnectionError> { input_selected(self, destination_window) } fn shape_get_rectangles(&self, window: xproto::Window, source_kind: SK) -> Result, ConnectionError> { get_rectangles(self, window, source_kind) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/shm.rs000064400000000000000000000560131046102023000144340ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, shmseg: Seg, shmid: u32, read_only: bool) -> Result, 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, shmseg: Seg) -> Result, 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, 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, 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, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Result, 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, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Result, 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: &Conn, shmseg: Seg, shm_fd: A, read_only: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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 server’s 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, shmseg: Seg, size: u32, read_only: bool) -> Result, 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, 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, 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, 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, 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, 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, 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(&self, shmseg: Seg, shm_fd: A, read_only: bool) -> Result, ConnectionError> where A: Into, { 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 server’s 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, ConnectionError> { create_segment(self, shmseg, size, read_only) } } impl 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, Seg); impl SegWrapper { /// 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 SegWrapper { /// 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 { 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(conn: &'c C, shm_fd: A, read_only: bool) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> where A: Into, { let shmseg = conn.generate_id()?; let cookie = attach_fd(conn, shmseg, shm_fd, read_only)?; Ok((Self::for_seg(conn, shmseg), cookie)) } } impl SegWrapper { /// 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(conn: C, shm_fd: A, read_only: bool) -> Result where A: Into, { let shmseg = conn.generate_id()?; let _ = attach_fd(&conn, shmseg, shm_fd, read_only)?; Ok(Self::for_seg(conn, shmseg)) } } impl From<&SegWrapper> for Seg { fn from(from: &SegWrapper) -> Self { from.1 } } impl Drop for SegWrapper { fn drop(&mut self) { let _ = detach(&self.0, self.1); } } x11rb-0.13.0/src/protocol/sync.rs000064400000000000000000000565651046102023000146350ustar 00000000000000// 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: &Conn) -> Result { let info = conn.extension_information(X11_EXTENSION_NAME)?; let info = info.ok_or(ConnectionError::UnsupportedExtension)?; Ok(info.major_opcode) } pub fn initialize(conn: &Conn, desired_major_version: u8, desired_minor_version: u8) -> Result, 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) -> Result, 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, id: Counter, initial_value: Int64) -> Result, 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, counter: Counter) -> Result, 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, counter: Counter) -> Result, 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, 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, counter: Counter, amount: Int64) -> Result, 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, counter: Counter, value: Int64) -> Result, 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, 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, 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, alarm: Alarm) -> Result, 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, alarm: Alarm) -> Result, 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, id: u32, priority: i32) -> Result, 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, id: u32) -> Result, 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, drawable: xproto::Drawable, fence: Fence, initially_triggered: bool) -> Result, 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, fence: Fence) -> Result, 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, fence: Fence) -> Result, 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, fence: Fence) -> Result, 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, fence: Fence) -> Result, 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, 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, ConnectionError> { initialize(self, desired_major_version, desired_minor_version) } fn sync_list_system_counters(&self) -> Result, ConnectionError> { list_system_counters(self) } fn sync_create_counter(&self, id: Counter, initial_value: Int64) -> Result, ConnectionError> { create_counter(self, id, initial_value) } fn sync_destroy_counter(&self, counter: Counter) -> Result, ConnectionError> { destroy_counter(self, counter) } fn sync_query_counter(&self, counter: Counter) -> Result, ConnectionError> { query_counter(self, counter) } fn sync_await_<'c, 'input>(&'c self, wait_list: &'input [Waitcondition]) -> Result, ConnectionError> { await_(self, wait_list) } fn sync_change_counter(&self, counter: Counter, amount: Int64) -> Result, ConnectionError> { change_counter(self, counter, amount) } fn sync_set_counter(&self, counter: Counter, value: Int64) -> Result, ConnectionError> { set_counter(self, counter, value) } fn sync_create_alarm<'c, 'input>(&'c self, id: Alarm, value_list: &'input CreateAlarmAux) -> Result, ConnectionError> { create_alarm(self, id, value_list) } fn sync_change_alarm<'c, 'input>(&'c self, id: Alarm, value_list: &'input ChangeAlarmAux) -> Result, ConnectionError> { change_alarm(self, id, value_list) } fn sync_destroy_alarm(&self, alarm: Alarm) -> Result, ConnectionError> { destroy_alarm(self, alarm) } fn sync_query_alarm(&self, alarm: Alarm) -> Result, ConnectionError> { query_alarm(self, alarm) } fn sync_set_priority(&self, id: u32, priority: i32) -> Result, ConnectionError> { set_priority(self, id, priority) } fn sync_get_priority(&self, id: u32) -> Result, ConnectionError> { get_priority(self, id) } fn sync_create_fence(&self, drawable: xproto::Drawable, fence: Fence, initially_triggered: bool) -> Result, ConnectionError> { create_fence(self, drawable, fence, initially_triggered) } fn sync_trigger_fence(&self, fence: Fence) -> Result, ConnectionError> { trigger_fence(self, fence) } fn sync_reset_fence(&self, fence: Fence) -> Result, ConnectionError> { reset_fence(self, fence) } fn sync_destroy_fence(&self, fence: Fence) -> Result, ConnectionError> { destroy_fence(self, fence) } fn sync_query_fence(&self, fence: Fence) -> Result, ConnectionError> { query_fence(self, fence) } fn sync_await_fence<'c, 'input>(&'c self, fence_list: &'input [Fence]) -> Result, ConnectionError> { await_fence(self, fence_list) } } impl 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, Counter); impl CounterWrapper { /// 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 CounterWrapper { /// 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 { let id = conn.generate_id()?; let _ = create_counter(&conn, id, initial_value)?; Ok(Self::for_counter(conn, id)) } } impl From<&CounterWrapper> for Counter { fn from(from: &CounterWrapper) -> Self { from.1 } } impl Drop for CounterWrapper { 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, Alarm); impl AlarmWrapper { /// 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 AlarmWrapper { /// 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 { let id = conn.generate_id()?; let _ = create_alarm(&conn, id, value_list)?; Ok(Self::for_alarm(conn, id)) } } impl From<&AlarmWrapper> for Alarm { fn from(from: &AlarmWrapper) -> Self { from.1 } } impl Drop for AlarmWrapper { 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, Fence); impl FenceWrapper { /// 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 FenceWrapper { /// 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 { 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(conn: &'c C, drawable: xproto::Drawable, initially_triggered: bool, fence_fd: A) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> where A: Into, { 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 FenceWrapper { /// 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(conn: C, drawable: xproto::Drawable, initially_triggered: bool, fence_fd: A) -> Result where A: Into, { 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 From<&FenceWrapper> for Fence { fn from(from: &FenceWrapper) -> Self { from.1 } } impl Drop for FenceWrapper { fn drop(&mut self) { let _ = destroy_fence(&self.0, self.1); } } x11rb-0.13.0/src/protocol/xc_misc.rs000064400000000000000000000060601046102023000152670ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u16, client_minor_version: u16) -> Result, 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) -> Result, 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, count: u32) -> Result, 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, ConnectionError> { get_version(self, client_major_version, client_minor_version) } fn xc_misc_get_xid_range(&self) -> Result, ConnectionError> { get_xid_range(self) } fn xc_misc_get_xid_list(&self, count: u32) -> Result, ConnectionError> { get_xid_list(self, count) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xevie.rs000064400000000000000000000102721046102023000147620ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u16, client_minor_version: u16) -> Result, 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, screen: u32) -> Result, 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, cmap: u32) -> Result, 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, event: Event, data_type: u32) -> Result, 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, event_mask: u32) -> Result, 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, ConnectionError> { query_version(self, client_major_version, client_minor_version) } fn xevie_start(&self, screen: u32) -> Result, ConnectionError> { start(self, screen) } fn xevie_end(&self, cmap: u32) -> Result, ConnectionError> { end(self, cmap) } fn xevie_send(&self, event: Event, data_type: u32) -> Result, ConnectionError> { send(self, event, data_type) } fn xevie_select_input(&self, event_mask: u32) -> Result, ConnectionError> { select_input(self, event_mask) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xf86dri.rs000064400000000000000000000212011046102023000151260ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, screen: u32) -> Result, 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, screen: u32) -> Result, 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, screen: u32) -> Result, 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, screen: u32) -> Result, 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, screen: u32, visual: u32, context: u32) -> Result, 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, screen: u32, context: u32) -> Result, 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, screen: u32, drawable: u32) -> Result, 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, screen: u32, drawable: u32) -> Result, 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, screen: u32, drawable: u32) -> Result, 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, screen: u32) -> Result, 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, screen: u32, magic: u32) -> Result, 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, ConnectionError> { query_version(self) } fn xf86dri_query_direct_rendering_capable(&self, screen: u32) -> Result, ConnectionError> { query_direct_rendering_capable(self, screen) } fn xf86dri_open_connection(&self, screen: u32) -> Result, ConnectionError> { open_connection(self, screen) } fn xf86dri_close_connection(&self, screen: u32) -> Result, ConnectionError> { close_connection(self, screen) } fn xf86dri_get_client_driver_name(&self, screen: u32) -> Result, ConnectionError> { get_client_driver_name(self, screen) } fn xf86dri_create_context(&self, screen: u32, visual: u32, context: u32) -> Result, ConnectionError> { create_context(self, screen, visual, context) } fn xf86dri_destroy_context(&self, screen: u32, context: u32) -> Result, ConnectionError> { destroy_context(self, screen, context) } fn xf86dri_create_drawable(&self, screen: u32, drawable: u32) -> Result, ConnectionError> { create_drawable(self, screen, drawable) } fn xf86dri_destroy_drawable(&self, screen: u32, drawable: u32) -> Result, ConnectionError> { destroy_drawable(self, screen, drawable) } fn xf86dri_get_drawable_info(&self, screen: u32, drawable: u32) -> Result, ConnectionError> { get_drawable_info(self, screen, drawable) } fn xf86dri_get_device_info(&self, screen: u32) -> Result, ConnectionError> { get_device_info(self, screen) } fn xf86dri_auth_connection(&self, screen: u32, magic: u32) -> Result, ConnectionError> { auth_connection(self, screen, magic) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xf86vidmode.rs000064400000000000000000000453071046102023000160140ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, screen: u16) -> Result, 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, 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, screen: u16, zoom: u16) -> Result, 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, screen: u16) -> Result, 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, screen: u16, lock: u16) -> Result, 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, screen: u16) -> Result, 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, 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, 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, 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, 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, screen: u16) -> Result, 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, screen: u16, x: u32, y: u32) -> Result, 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, screen: u16) -> Result, 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, major: u16, minor: u16) -> Result, 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, screen: u16, red: u32, green: u32, blue: u32) -> Result, 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, screen: u16) -> Result, 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, screen: u16, size: u16) -> Result, 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, 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, screen: u16) -> Result, 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, screen: u16) -> Result, 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, ConnectionError> { query_version(self) } fn xf86vidmode_get_mode_line(&self, screen: u16) -> Result, 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, 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, ConnectionError> { switch_mode(self, screen, zoom) } fn xf86vidmode_get_monitor(&self, screen: u16) -> Result, ConnectionError> { get_monitor(self, screen) } fn xf86vidmode_lock_mode_switch(&self, screen: u16, lock: u16) -> Result, ConnectionError> { lock_mode_switch(self, screen, lock) } fn xf86vidmode_get_all_mode_lines(&self, screen: u16) -> Result, 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, 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, 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, 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, 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, ConnectionError> { get_view_port(self, screen) } fn xf86vidmode_set_view_port(&self, screen: u16, x: u32, y: u32) -> Result, ConnectionError> { set_view_port(self, screen, x, y) } fn xf86vidmode_get_dot_clocks(&self, screen: u16) -> Result, ConnectionError> { get_dot_clocks(self, screen) } fn xf86vidmode_set_client_version(&self, major: u16, minor: u16) -> Result, ConnectionError> { set_client_version(self, major, minor) } fn xf86vidmode_set_gamma(&self, screen: u16, red: u32, green: u32, blue: u32) -> Result, ConnectionError> { set_gamma(self, screen, red, green, blue) } fn xf86vidmode_get_gamma(&self, screen: u16) -> Result, ConnectionError> { get_gamma(self, screen) } fn xf86vidmode_get_gamma_ramp(&self, screen: u16, size: u16) -> Result, 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, ConnectionError> { set_gamma_ramp(self, screen, size, red, green, blue) } fn xf86vidmode_get_gamma_ramp_size(&self, screen: u16) -> Result, ConnectionError> { get_gamma_ramp_size(self, screen) } fn xf86vidmode_get_permissions(&self, screen: u16) -> Result, ConnectionError> { get_permissions(self, screen) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xfixes.rs000064400000000000000000001113261046102023000151520ustar 00000000000000// 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: &Conn) -> Result { 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, client_major_version: u32, client_minor_version: u32) -> Result, 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, mode: SaveSetMode, target: SaveSetTarget, map: SaveSetMapping, window: xproto::Window) -> Result, 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, window: xproto::Window, selection: xproto::Atom, event_mask: SelectionEventMask) -> Result, 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, window: xproto::Window, event_mask: CursorNotifyMask) -> Result, 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) -> Result, 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, 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, region: Region, bitmap: xproto::Pixmap) -> Result, 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, region: Region, window: xproto::Window, kind: shape::SK) -> Result, 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, region: Region, gc: xproto::Gcontext) -> Result, 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, region: Region, picture: render::Picture) -> Result, 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, region: Region) -> Result, 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, 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, source: Region, destination: Region) -> Result, 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, source1: Region, source2: Region, destination: Region) -> Result, 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, source1: Region, source2: Region, destination: Region) -> Result, 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, source1: Region, source2: Region, destination: Region) -> Result, 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, source: Region, bounds: xproto::Rectangle, destination: Region) -> Result, 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, region: Region, dx: i16, dy: i16) -> Result, 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, source: Region, destination: Region) -> Result, 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, region: Region) -> Result, 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: &Conn, gc: xproto::Gcontext, region: A, x_origin: i16, y_origin: i16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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: &Conn, dest: xproto::Window, dest_kind: shape::SK, x_offset: i16, y_offset: i16, region: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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: &Conn, picture: render::Picture, region: A, x_origin: i16, y_origin: i16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, 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, cursor: xproto::Cursor) -> Result, 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) -> Result, 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, source: xproto::Cursor, destination: xproto::Cursor) -> Result, 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, 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, source: Region, destination: Region, left: u16, right: u16, top: u16, bottom: u16) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window) -> Result, 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, 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, barrier: Barrier) -> Result, 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, disconnect_mode: ClientDisconnectFlags) -> Result, 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) -> Result, 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, 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, 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, ConnectionError> { select_selection_input(self, window, selection, event_mask) } fn xfixes_select_cursor_input(&self, window: xproto::Window, event_mask: CursorNotifyMask) -> Result, ConnectionError> { select_cursor_input(self, window, event_mask) } fn xfixes_get_cursor_image(&self) -> Result, ConnectionError> { get_cursor_image(self) } fn xfixes_create_region<'c, 'input>(&'c self, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result, ConnectionError> { create_region(self, region, rectangles) } fn xfixes_create_region_from_bitmap(&self, region: Region, bitmap: xproto::Pixmap) -> Result, ConnectionError> { create_region_from_bitmap(self, region, bitmap) } fn xfixes_create_region_from_window(&self, region: Region, window: xproto::Window, kind: shape::SK) -> Result, ConnectionError> { create_region_from_window(self, region, window, kind) } fn xfixes_create_region_from_gc(&self, region: Region, gc: xproto::Gcontext) -> Result, ConnectionError> { create_region_from_gc(self, region, gc) } fn xfixes_create_region_from_picture(&self, region: Region, picture: render::Picture) -> Result, ConnectionError> { create_region_from_picture(self, region, picture) } fn xfixes_destroy_region(&self, region: Region) -> Result, ConnectionError> { destroy_region(self, region) } fn xfixes_set_region<'c, 'input>(&'c self, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result, ConnectionError> { set_region(self, region, rectangles) } fn xfixes_copy_region(&self, source: Region, destination: Region) -> Result, ConnectionError> { copy_region(self, source, destination) } fn xfixes_union_region(&self, source1: Region, source2: Region, destination: Region) -> Result, ConnectionError> { union_region(self, source1, source2, destination) } fn xfixes_intersect_region(&self, source1: Region, source2: Region, destination: Region) -> Result, ConnectionError> { intersect_region(self, source1, source2, destination) } fn xfixes_subtract_region(&self, source1: Region, source2: Region, destination: Region) -> Result, ConnectionError> { subtract_region(self, source1, source2, destination) } fn xfixes_invert_region(&self, source: Region, bounds: xproto::Rectangle, destination: Region) -> Result, ConnectionError> { invert_region(self, source, bounds, destination) } fn xfixes_translate_region(&self, region: Region, dx: i16, dy: i16) -> Result, ConnectionError> { translate_region(self, region, dx, dy) } fn xfixes_region_extents(&self, source: Region, destination: Region) -> Result, ConnectionError> { region_extents(self, source, destination) } fn xfixes_fetch_region(&self, region: Region) -> Result, ConnectionError> { fetch_region(self, region) } fn xfixes_set_gc_clip_region(&self, gc: xproto::Gcontext, region: A, x_origin: i16, y_origin: i16) -> Result, ConnectionError> where A: Into, { set_gc_clip_region(self, gc, region, x_origin, y_origin) } fn xfixes_set_window_shape_region(&self, dest: xproto::Window, dest_kind: shape::SK, x_offset: i16, y_offset: i16, region: A) -> Result, ConnectionError> where A: Into, { set_window_shape_region(self, dest, dest_kind, x_offset, y_offset, region) } fn xfixes_set_picture_clip_region(&self, picture: render::Picture, region: A, x_origin: i16, y_origin: i16) -> Result, ConnectionError> where A: Into, { 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, ConnectionError> { set_cursor_name(self, cursor, name) } fn xfixes_get_cursor_name(&self, cursor: xproto::Cursor) -> Result, ConnectionError> { get_cursor_name(self, cursor) } fn xfixes_get_cursor_image_and_name(&self) -> Result, ConnectionError> { get_cursor_image_and_name(self) } fn xfixes_change_cursor(&self, source: xproto::Cursor, destination: xproto::Cursor) -> Result, ConnectionError> { change_cursor(self, source, destination) } fn xfixes_change_cursor_by_name<'c, 'input>(&'c self, src: xproto::Cursor, name: &'input [u8]) -> Result, 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, ConnectionError> { expand_region(self, source, destination, left, right, top, bottom) } fn xfixes_hide_cursor(&self, window: xproto::Window) -> Result, ConnectionError> { hide_cursor(self, window) } fn xfixes_show_cursor(&self, window: xproto::Window) -> Result, 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, ConnectionError> { create_pointer_barrier(self, barrier, window, x1, y1, x2, y2, directions, devices) } fn xfixes_delete_pointer_barrier(&self, barrier: Barrier) -> Result, 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, ConnectionError> { set_client_disconnect_mode(self, disconnect_mode) } fn xfixes_get_client_disconnect_mode(&self) -> Result, ConnectionError> { get_client_disconnect_mode(self) } } impl 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, Region); impl RegionWrapper { /// 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 RegionWrapper { /// 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 { 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 RegionWrapper { /// 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 { 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 RegionWrapper { /// 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 { 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 RegionWrapper { /// 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 { 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 RegionWrapper { /// 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 { 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 RegionWrapper { /// 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 { 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 From<&RegionWrapper> for Region { fn from(from: &RegionWrapper) -> Self { from.1 } } impl Drop for RegionWrapper { fn drop(&mut self) { let _ = destroy_region(&self.0, self.1); } } x11rb-0.13.0/src/protocol/xinerama.rs000064400000000000000000000114161046102023000154470ustar 00000000000000// 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: &Conn) -> Result { 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, major: u8, minor: u8) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window) -> Result, 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, window: xproto::Window, screen: u32) -> Result, 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) -> Result, 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) -> Result, 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, ConnectionError> { query_version(self, major, minor) } fn xinerama_get_state(&self, window: xproto::Window) -> Result, ConnectionError> { get_state(self, window) } fn xinerama_get_screen_count(&self, window: xproto::Window) -> Result, ConnectionError> { get_screen_count(self, window) } fn xinerama_get_screen_size(&self, window: xproto::Window, screen: u32) -> Result, ConnectionError> { get_screen_size(self, window, screen) } fn xinerama_is_active(&self) -> Result, ConnectionError> { is_active(self) } fn xinerama_query_screens(&self) -> Result, ConnectionError> { query_screens(self) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xinput.rs000064400000000000000000001524661046102023000152050ustar 00000000000000// This file contains generated code. Do not edit directly. // To regenerate this, run 'make'. //! Bindings to the `Input` 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::xinput::*; /// Get the major opcode of this extension fn major_opcode(conn: &Conn) -> Result { let info = conn.extension_information(X11_EXTENSION_NAME)?; let info = info.ok_or(ConnectionError::UnsupportedExtension)?; Ok(info.major_opcode) } pub fn get_extension_version<'c, 'input, Conn>(conn: &'c Conn, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetExtensionVersionRequest { 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 list_input_devices(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListInputDevicesRequest; 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_device(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = OpenDeviceRequest { device_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 close_device(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CloseDeviceRequest { device_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 set_device_mode(conn: &Conn, device_id: u8, mode: ValuatorMode) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetDeviceModeRequest { device_id, mode, }; 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_extension_event<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, classes: &'input [EventClass]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SelectExtensionEventRequest { window, classes: Cow::Borrowed(classes), }; 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_selected_extension_events(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetSelectedExtensionEventsRequest { 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 change_device_dont_propagate_list<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, mode: PropagateMode, classes: &'input [EventClass]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeDeviceDontPropagateListRequest { window, mode, classes: Cow::Borrowed(classes), }; 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_dont_propagate_list(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDeviceDontPropagateListRequest { 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_device_motion_events(conn: &Conn, start: xproto::Timestamp, stop: A, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let stop: xproto::Timestamp = stop.into(); let request0 = GetDeviceMotionEventsRequest { start, stop, device_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 change_keyboard_device(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeKeyboardDeviceRequest { device_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 change_pointer_device(conn: &Conn, x_axis: u8, y_axis: u8, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangePointerDeviceRequest { x_axis, y_axis, device_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 grab_device<'c, 'input, Conn, A>(conn: &'c Conn, grab_window: xproto::Window, time: A, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, device_id: u8, classes: &'input [EventClass]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: xproto::Timestamp = time.into(); let request0 = GrabDeviceRequest { grab_window, time, this_device_mode, other_device_mode, owner_events, device_id, classes: Cow::Borrowed(classes), }; 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 ungrab_device(conn: &Conn, time: A, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: xproto::Timestamp = time.into(); let request0 = UngrabDeviceRequest { time, device_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 grab_device_key<'c, 'input, Conn, A, B>(conn: &'c Conn, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, grabbed_device: u8, key: B, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, classes: &'input [EventClass]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let modifier_device: u8 = modifier_device.into(); let key: u8 = key.into(); let request0 = GrabDeviceKeyRequest { grab_window, modifiers, modifier_device, grabbed_device, key, this_device_mode, other_device_mode, owner_events, classes: Cow::Borrowed(classes), }; 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 ungrab_device_key(conn: &Conn, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, key: B, grabbed_device: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let modifier_device: u8 = modifier_device.into(); let key: u8 = key.into(); let request0 = UngrabDeviceKeyRequest { grab_window, modifiers, modifier_device, key, grabbed_device, }; 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_device_button<'c, 'input, Conn, A, B>(conn: &'c Conn, grab_window: xproto::Window, grabbed_device: u8, modifier_device: A, modifiers: xproto::ModMask, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, button: B, owner_events: bool, classes: &'input [EventClass]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let modifier_device: u8 = modifier_device.into(); let button: u8 = button.into(); let request0 = GrabDeviceButtonRequest { grab_window, grabbed_device, modifier_device, modifiers, this_device_mode, other_device_mode, button, owner_events, classes: Cow::Borrowed(classes), }; 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 ungrab_device_button(conn: &Conn, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, button: B, grabbed_device: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let modifier_device: u8 = modifier_device.into(); let button: u8 = button.into(); let request0 = UngrabDeviceButtonRequest { grab_window, modifiers, modifier_device, button, grabbed_device, }; 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 allow_device_events(conn: &Conn, time: A, mode: DeviceInputMode, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: xproto::Timestamp = time.into(); let request0 = AllowDeviceEventsRequest { time, mode, device_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 get_device_focus(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDeviceFocusRequest { device_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_focus(conn: &Conn, focus: A, time: B, revert_to: xproto::InputFocus, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let focus: xproto::Window = focus.into(); let time: xproto::Timestamp = time.into(); let request0 = SetDeviceFocusRequest { focus, time, revert_to, device_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 get_feedback_control(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetFeedbackControlRequest { device_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 change_feedback_control(conn: &Conn, mask: ChangeFeedbackControlMask, device_id: u8, feedback_id: u8, feedback: FeedbackCtl) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeFeedbackControlRequest { mask, device_id, feedback_id, feedback, }; 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_key_mapping(conn: &Conn, device_id: u8, first_keycode: KeyCode, count: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDeviceKeyMappingRequest { device_id, first_keycode, 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) } pub fn change_device_key_mapping<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, first_keycode: KeyCode, keysyms_per_keycode: u8, keycode_count: u8, keysyms: &'input [xproto::Keysym]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeDeviceKeyMappingRequest { device_id, first_keycode, keysyms_per_keycode, keycode_count, keysyms: Cow::Borrowed(keysyms), }; 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_modifier_mapping(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDeviceModifierMappingRequest { device_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_modifier_mapping<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, keymaps: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetDeviceModifierMappingRequest { device_id, keymaps: Cow::Borrowed(keymaps), }; 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_device_button_mapping(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDeviceButtonMappingRequest { device_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_button_mapping<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, map: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetDeviceButtonMappingRequest { device_id, map: Cow::Borrowed(map), }; 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_device_state(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryDeviceStateRequest { device_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 device_bell(conn: &Conn, device_id: u8, feedback_id: u8, feedback_class: u8, percent: i8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeviceBellRequest { device_id, feedback_id, feedback_class, percent, }; 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_device_valuators<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, first_valuator: u8, valuators: &'input [i32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetDeviceValuatorsRequest { device_id, first_valuator, valuators: Cow::Borrowed(valuators), }; 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_device_control(conn: &Conn, control_id: DeviceControl, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDeviceControlRequest { control_id, device_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 change_device_control(conn: &Conn, control_id: DeviceControl, device_id: u8, control: DeviceCtl) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeDeviceControlRequest { control_id, device_id, control, }; 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 list_device_properties(conn: &Conn, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListDevicePropertiesRequest { device_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 change_device_property<'c, 'input, Conn>(conn: &'c Conn, property: xproto::Atom, type_: xproto::Atom, device_id: u8, mode: xproto::PropMode, num_items: u32, items: &'input ChangeDevicePropertyAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeDevicePropertyRequest { property, type_, device_id, mode, num_items, items: Cow::Borrowed(items), }; 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_device_property(conn: &Conn, property: xproto::Atom, device_id: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeleteDevicePropertyRequest { property, device_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 get_device_property(conn: &Conn, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32, device_id: u8, delete: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetDevicePropertyRequest { property, type_, offset, len, device_id, delete, }; 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 xi_query_pointer(conn: &Conn, window: xproto::Window, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIQueryPointerRequest { window, deviceid, }; 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 xi_warp_pointer(conn: &Conn, src_win: xproto::Window, dst_win: xproto::Window, src_x: Fp1616, src_y: Fp1616, src_width: u16, src_height: u16, dst_x: Fp1616, dst_y: Fp1616, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIWarpPointerRequest { src_win, dst_win, src_x, src_y, src_width, src_height, dst_x, dst_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 xi_change_cursor(conn: &Conn, window: xproto::Window, cursor: xproto::Cursor, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIChangeCursorRequest { window, cursor, 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 xi_change_hierarchy<'c, 'input, Conn>(conn: &'c Conn, changes: &'input [HierarchyChange]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = XIChangeHierarchyRequest { changes: Cow::Borrowed(changes), }; 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 xi_set_client_pointer(conn: &Conn, window: xproto::Window, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XISetClientPointerRequest { window, 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 xi_get_client_pointer(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = XIGetClientPointerRequest { 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 xi_select_events<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, masks: &'input [EventMask]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = XISelectEventsRequest { window, masks: Cow::Borrowed(masks), }; 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 xi_query_version(conn: &Conn, major_version: u16, minor_version: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = XIQueryVersionRequest { 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 xi_query_device(conn: &Conn, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIQueryDeviceRequest { deviceid, }; 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 xi_set_focus(conn: &Conn, window: xproto::Window, time: A, deviceid: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let time: xproto::Timestamp = time.into(); let deviceid: DeviceId = deviceid.into(); let request0 = XISetFocusRequest { window, time, 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 xi_get_focus(conn: &Conn, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIGetFocusRequest { deviceid, }; 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 xi_grab_device<'c, 'input, Conn, A, B>(conn: &'c Conn, window: xproto::Window, time: A, cursor: xproto::Cursor, deviceid: B, mode: xproto::GrabMode, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let time: xproto::Timestamp = time.into(); let deviceid: DeviceId = deviceid.into(); let request0 = XIGrabDeviceRequest { window, time, cursor, deviceid, mode, paired_device_mode, owner_events, mask: Cow::Borrowed(mask), }; 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 xi_ungrab_device(conn: &Conn, time: A, deviceid: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let time: xproto::Timestamp = time.into(); let deviceid: DeviceId = deviceid.into(); let request0 = XIUngrabDeviceRequest { time, 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 xi_allow_events(conn: &Conn, time: A, deviceid: B, event_mode: EventMode, touchid: u32, grab_window: xproto::Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let time: xproto::Timestamp = time.into(); let deviceid: DeviceId = deviceid.into(); let request0 = XIAllowEventsRequest { time, deviceid, event_mode, touchid, grab_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 xi_passive_grab_device<'c, 'input, Conn, A, B>(conn: &'c Conn, time: A, grab_window: xproto::Window, cursor: xproto::Cursor, detail: u32, deviceid: B, grab_type: GrabType, grab_mode: GrabMode22, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32], modifiers: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let time: xproto::Timestamp = time.into(); let deviceid: DeviceId = deviceid.into(); let request0 = XIPassiveGrabDeviceRequest { time, grab_window, cursor, detail, deviceid, grab_type, grab_mode, paired_device_mode, owner_events, mask: Cow::Borrowed(mask), modifiers: Cow::Borrowed(modifiers), }; 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(&slices, fds) } pub fn xi_passive_ungrab_device<'c, 'input, Conn, A>(conn: &'c Conn, grab_window: xproto::Window, detail: u32, deviceid: A, grab_type: GrabType, modifiers: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIPassiveUngrabDeviceRequest { grab_window, detail, deviceid, grab_type, modifiers: Cow::Borrowed(modifiers), }; 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 xi_list_properties(conn: &Conn, deviceid: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIListPropertiesRequest { deviceid, }; 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 xi_change_property<'c, 'input, Conn, A>(conn: &'c Conn, deviceid: A, mode: xproto::PropMode, property: xproto::Atom, type_: xproto::Atom, num_items: u32, items: &'input XIChangePropertyAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIChangePropertyRequest { deviceid, mode, property, type_, num_items, items: Cow::Borrowed(items), }; 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 xi_delete_property(conn: &Conn, deviceid: A, property: xproto::Atom) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIDeletePropertyRequest { deviceid, 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 xi_get_property(conn: &Conn, deviceid: A, delete: bool, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let deviceid: DeviceId = deviceid.into(); let request0 = XIGetPropertyRequest { deviceid, delete, property, type_, offset, len, }; 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 xi_get_selected_events(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = XIGetSelectedEventsRequest { 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 xi_barrier_release_pointer<'c, 'input, Conn>(conn: &'c Conn, barriers: &'input [BarrierReleasePointerInfo]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = XIBarrierReleasePointerRequest { barriers: Cow::Borrowed(barriers), }; 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 send_extension_event<'c, 'input, Conn>(conn: &'c Conn, destination: xproto::Window, device_id: u8, propagate: bool, events: &'input [EventForSend], classes: &'input [EventClass]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SendExtensionEventRequest { destination, device_id, propagate, events: Cow::Borrowed(events), classes: Cow::Borrowed(classes), }; 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 xinput_get_extension_version<'c, 'input>(&'c self, name: &'input [u8]) -> Result, ConnectionError> { get_extension_version(self, name) } fn xinput_list_input_devices(&self) -> Result, ConnectionError> { list_input_devices(self) } fn xinput_open_device(&self, device_id: u8) -> Result, ConnectionError> { open_device(self, device_id) } fn xinput_close_device(&self, device_id: u8) -> Result, ConnectionError> { close_device(self, device_id) } fn xinput_set_device_mode(&self, device_id: u8, mode: ValuatorMode) -> Result, ConnectionError> { set_device_mode(self, device_id, mode) } fn xinput_select_extension_event<'c, 'input>(&'c self, window: xproto::Window, classes: &'input [EventClass]) -> Result, ConnectionError> { select_extension_event(self, window, classes) } fn xinput_get_selected_extension_events(&self, window: xproto::Window) -> Result, ConnectionError> { get_selected_extension_events(self, window) } fn xinput_change_device_dont_propagate_list<'c, 'input>(&'c self, window: xproto::Window, mode: PropagateMode, classes: &'input [EventClass]) -> Result, ConnectionError> { change_device_dont_propagate_list(self, window, mode, classes) } fn xinput_get_device_dont_propagate_list(&self, window: xproto::Window) -> Result, ConnectionError> { get_device_dont_propagate_list(self, window) } fn xinput_get_device_motion_events(&self, start: xproto::Timestamp, stop: A, device_id: u8) -> Result, ConnectionError> where A: Into, { get_device_motion_events(self, start, stop, device_id) } fn xinput_change_keyboard_device(&self, device_id: u8) -> Result, ConnectionError> { change_keyboard_device(self, device_id) } fn xinput_change_pointer_device(&self, x_axis: u8, y_axis: u8, device_id: u8) -> Result, ConnectionError> { change_pointer_device(self, x_axis, y_axis, device_id) } fn xinput_grab_device<'c, 'input, A>(&'c self, grab_window: xproto::Window, time: A, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, device_id: u8, classes: &'input [EventClass]) -> Result, ConnectionError> where A: Into, { grab_device(self, grab_window, time, this_device_mode, other_device_mode, owner_events, device_id, classes) } fn xinput_ungrab_device(&self, time: A, device_id: u8) -> Result, ConnectionError> where A: Into, { ungrab_device(self, time, device_id) } fn xinput_grab_device_key<'c, 'input, A, B>(&'c self, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, grabbed_device: u8, key: B, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, classes: &'input [EventClass]) -> Result, ConnectionError> where A: Into, B: Into, { grab_device_key(self, grab_window, modifiers, modifier_device, grabbed_device, key, this_device_mode, other_device_mode, owner_events, classes) } fn xinput_ungrab_device_key(&self, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, key: B, grabbed_device: u8) -> Result, ConnectionError> where A: Into, B: Into, { ungrab_device_key(self, grab_window, modifiers, modifier_device, key, grabbed_device) } fn xinput_grab_device_button<'c, 'input, A, B>(&'c self, grab_window: xproto::Window, grabbed_device: u8, modifier_device: A, modifiers: xproto::ModMask, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, button: B, owner_events: bool, classes: &'input [EventClass]) -> Result, ConnectionError> where A: Into, B: Into, { grab_device_button(self, grab_window, grabbed_device, modifier_device, modifiers, this_device_mode, other_device_mode, button, owner_events, classes) } fn xinput_ungrab_device_button(&self, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, button: B, grabbed_device: u8) -> Result, ConnectionError> where A: Into, B: Into, { ungrab_device_button(self, grab_window, modifiers, modifier_device, button, grabbed_device) } fn xinput_allow_device_events(&self, time: A, mode: DeviceInputMode, device_id: u8) -> Result, ConnectionError> where A: Into, { allow_device_events(self, time, mode, device_id) } fn xinput_get_device_focus(&self, device_id: u8) -> Result, ConnectionError> { get_device_focus(self, device_id) } fn xinput_set_device_focus(&self, focus: A, time: B, revert_to: xproto::InputFocus, device_id: u8) -> Result, ConnectionError> where A: Into, B: Into, { set_device_focus(self, focus, time, revert_to, device_id) } fn xinput_get_feedback_control(&self, device_id: u8) -> Result, ConnectionError> { get_feedback_control(self, device_id) } fn xinput_change_feedback_control(&self, mask: ChangeFeedbackControlMask, device_id: u8, feedback_id: u8, feedback: FeedbackCtl) -> Result, ConnectionError> { change_feedback_control(self, mask, device_id, feedback_id, feedback) } fn xinput_get_device_key_mapping(&self, device_id: u8, first_keycode: KeyCode, count: u8) -> Result, ConnectionError> { get_device_key_mapping(self, device_id, first_keycode, count) } fn xinput_change_device_key_mapping<'c, 'input>(&'c self, device_id: u8, first_keycode: KeyCode, keysyms_per_keycode: u8, keycode_count: u8, keysyms: &'input [xproto::Keysym]) -> Result, ConnectionError> { change_device_key_mapping(self, device_id, first_keycode, keysyms_per_keycode, keycode_count, keysyms) } fn xinput_get_device_modifier_mapping(&self, device_id: u8) -> Result, ConnectionError> { get_device_modifier_mapping(self, device_id) } fn xinput_set_device_modifier_mapping<'c, 'input>(&'c self, device_id: u8, keymaps: &'input [u8]) -> Result, ConnectionError> { set_device_modifier_mapping(self, device_id, keymaps) } fn xinput_get_device_button_mapping(&self, device_id: u8) -> Result, ConnectionError> { get_device_button_mapping(self, device_id) } fn xinput_set_device_button_mapping<'c, 'input>(&'c self, device_id: u8, map: &'input [u8]) -> Result, ConnectionError> { set_device_button_mapping(self, device_id, map) } fn xinput_query_device_state(&self, device_id: u8) -> Result, ConnectionError> { query_device_state(self, device_id) } fn xinput_device_bell(&self, device_id: u8, feedback_id: u8, feedback_class: u8, percent: i8) -> Result, ConnectionError> { device_bell(self, device_id, feedback_id, feedback_class, percent) } fn xinput_set_device_valuators<'c, 'input>(&'c self, device_id: u8, first_valuator: u8, valuators: &'input [i32]) -> Result, ConnectionError> { set_device_valuators(self, device_id, first_valuator, valuators) } fn xinput_get_device_control(&self, control_id: DeviceControl, device_id: u8) -> Result, ConnectionError> { get_device_control(self, control_id, device_id) } fn xinput_change_device_control(&self, control_id: DeviceControl, device_id: u8, control: DeviceCtl) -> Result, ConnectionError> { change_device_control(self, control_id, device_id, control) } fn xinput_list_device_properties(&self, device_id: u8) -> Result, ConnectionError> { list_device_properties(self, device_id) } fn xinput_change_device_property<'c, 'input>(&'c self, property: xproto::Atom, type_: xproto::Atom, device_id: u8, mode: xproto::PropMode, num_items: u32, items: &'input ChangeDevicePropertyAux) -> Result, ConnectionError> { change_device_property(self, property, type_, device_id, mode, num_items, items) } fn xinput_delete_device_property(&self, property: xproto::Atom, device_id: u8) -> Result, ConnectionError> { delete_device_property(self, property, device_id) } fn xinput_get_device_property(&self, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32, device_id: u8, delete: bool) -> Result, ConnectionError> { get_device_property(self, property, type_, offset, len, device_id, delete) } fn xinput_xi_query_pointer(&self, window: xproto::Window, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_query_pointer(self, window, deviceid) } fn xinput_xi_warp_pointer(&self, src_win: xproto::Window, dst_win: xproto::Window, src_x: Fp1616, src_y: Fp1616, src_width: u16, src_height: u16, dst_x: Fp1616, dst_y: Fp1616, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_warp_pointer(self, src_win, dst_win, src_x, src_y, src_width, src_height, dst_x, dst_y, deviceid) } fn xinput_xi_change_cursor(&self, window: xproto::Window, cursor: xproto::Cursor, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_change_cursor(self, window, cursor, deviceid) } fn xinput_xi_change_hierarchy<'c, 'input>(&'c self, changes: &'input [HierarchyChange]) -> Result, ConnectionError> { xi_change_hierarchy(self, changes) } fn xinput_xi_set_client_pointer(&self, window: xproto::Window, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_set_client_pointer(self, window, deviceid) } fn xinput_xi_get_client_pointer(&self, window: xproto::Window) -> Result, ConnectionError> { xi_get_client_pointer(self, window) } fn xinput_xi_select_events<'c, 'input>(&'c self, window: xproto::Window, masks: &'input [EventMask]) -> Result, ConnectionError> { xi_select_events(self, window, masks) } fn xinput_xi_query_version(&self, major_version: u16, minor_version: u16) -> Result, ConnectionError> { xi_query_version(self, major_version, minor_version) } fn xinput_xi_query_device(&self, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_query_device(self, deviceid) } fn xinput_xi_set_focus(&self, window: xproto::Window, time: A, deviceid: B) -> Result, ConnectionError> where A: Into, B: Into, { xi_set_focus(self, window, time, deviceid) } fn xinput_xi_get_focus(&self, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_get_focus(self, deviceid) } fn xinput_xi_grab_device<'c, 'input, A, B>(&'c self, window: xproto::Window, time: A, cursor: xproto::Cursor, deviceid: B, mode: xproto::GrabMode, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32]) -> Result, ConnectionError> where A: Into, B: Into, { xi_grab_device(self, window, time, cursor, deviceid, mode, paired_device_mode, owner_events, mask) } fn xinput_xi_ungrab_device(&self, time: A, deviceid: B) -> Result, ConnectionError> where A: Into, B: Into, { xi_ungrab_device(self, time, deviceid) } fn xinput_xi_allow_events(&self, time: A, deviceid: B, event_mode: EventMode, touchid: u32, grab_window: xproto::Window) -> Result, ConnectionError> where A: Into, B: Into, { xi_allow_events(self, time, deviceid, event_mode, touchid, grab_window) } fn xinput_xi_passive_grab_device<'c, 'input, A, B>(&'c self, time: A, grab_window: xproto::Window, cursor: xproto::Cursor, detail: u32, deviceid: B, grab_type: GrabType, grab_mode: GrabMode22, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32], modifiers: &'input [u32]) -> Result, ConnectionError> where A: Into, B: Into, { xi_passive_grab_device(self, time, grab_window, cursor, detail, deviceid, grab_type, grab_mode, paired_device_mode, owner_events, mask, modifiers) } fn xinput_xi_passive_ungrab_device<'c, 'input, A>(&'c self, grab_window: xproto::Window, detail: u32, deviceid: A, grab_type: GrabType, modifiers: &'input [u32]) -> Result, ConnectionError> where A: Into, { xi_passive_ungrab_device(self, grab_window, detail, deviceid, grab_type, modifiers) } fn xinput_xi_list_properties(&self, deviceid: A) -> Result, ConnectionError> where A: Into, { xi_list_properties(self, deviceid) } fn xinput_xi_change_property<'c, 'input, A>(&'c self, deviceid: A, mode: xproto::PropMode, property: xproto::Atom, type_: xproto::Atom, num_items: u32, items: &'input XIChangePropertyAux) -> Result, ConnectionError> where A: Into, { xi_change_property(self, deviceid, mode, property, type_, num_items, items) } fn xinput_xi_delete_property(&self, deviceid: A, property: xproto::Atom) -> Result, ConnectionError> where A: Into, { xi_delete_property(self, deviceid, property) } fn xinput_xi_get_property(&self, deviceid: A, delete: bool, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32) -> Result, ConnectionError> where A: Into, { xi_get_property(self, deviceid, delete, property, type_, offset, len) } fn xinput_xi_get_selected_events(&self, window: xproto::Window) -> Result, ConnectionError> { xi_get_selected_events(self, window) } fn xinput_xi_barrier_release_pointer<'c, 'input>(&'c self, barriers: &'input [BarrierReleasePointerInfo]) -> Result, ConnectionError> { xi_barrier_release_pointer(self, barriers) } fn xinput_send_extension_event<'c, 'input>(&'c self, destination: xproto::Window, device_id: u8, propagate: bool, events: &'input [EventForSend], classes: &'input [EventClass]) -> Result, ConnectionError> { send_extension_event(self, destination, device_id, propagate, events, classes) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xkb.rs000064400000000000000000000733111046102023000144310ustar 00000000000000// 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: &Conn) -> Result { 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, wanted_major: u16, wanted_minor: u16) -> Result, 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, 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, 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, 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, device_spec: DeviceSpec) -> Result, 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, 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, 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, device_spec: DeviceSpec) -> Result, 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, 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, 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, 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, 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, device_spec: DeviceSpec, groups: SetOfGroup, get_all_si: bool, first_si: u16, n_si: u16) -> Result, 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, 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, device_spec: DeviceSpec) -> Result, 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, device_spec: DeviceSpec, which: u32) -> Result, 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, 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: &Conn, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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: &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, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, device_spec: DeviceSpec, which: NameDetail) -> Result, 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, 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, device_spec: DeviceSpec, change: PerClientFlag, value: PerClientFlag, ctrls_to_change: BoolCtrl, auto_ctrls: BoolCtrl, auto_ctrls_values: BoolCtrl) -> Result, 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, device_spec: DeviceSpec, max_names: u16) -> Result, 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, device_spec: DeviceSpec, need: GBNDetail, want: GBNDetail, load: bool) -> Result, 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: &Conn, device_spec: DeviceSpec, wanted: XIFeature, all_buttons: bool, first_button: u8, n_buttons: u8, led_class: LedClass, led_id: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, ConnectionError> { get_indicator_state(self, device_spec) } fn xkb_get_indicator_map(&self, device_spec: DeviceSpec, which: u32) -> Result, 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, ConnectionError> { set_indicator_map(self, device_spec, which, maps) } fn xkb_get_named_indicator(&self, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom) -> Result, ConnectionError> where A: Into, { get_named_indicator(self, device_spec, led_class, led_id, indicator) } fn xkb_set_named_indicator(&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, ConnectionError> where A: Into, { 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, 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, 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, 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, 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, ConnectionError> { get_kbd_by_name(self, device_spec, need, want, load) } fn xkb_get_device_info(&self, device_spec: DeviceSpec, wanted: XIFeature, all_buttons: bool, first_button: u8, n_buttons: u8, led_class: LedClass, led_id: A) -> Result, ConnectionError> where A: Into, { 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, 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, ConnectionError> { set_debugging_flags(self, affect_flags, flags, affect_ctrls, ctrls, message) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xprint.rs000064400000000000000000000437671046102023000152050ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, 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) -> Result, 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, 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, context: u32) -> Result, 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) -> Result, 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, context: u32) -> Result, 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) -> Result, 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, output_mode: u8) -> Result, 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, cancel: bool) -> Result, 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, driver_mode: u8) -> Result, 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, cancel: bool) -> Result, 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, 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, context: Pcontext, max_bytes: u32) -> Result, 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, window: xproto::Window) -> Result, 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, cancel: bool) -> Result, 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, context: Pcontext, event_mask: u32) -> Result, 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, context: Pcontext) -> Result, 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, context: Pcontext, pool: u8) -> Result, 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, 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, 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, context: Pcontext) -> Result, 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) -> Result, 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, context: Pcontext, image_resolution: u16) -> Result, 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, context: Pcontext) -> Result, 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, ConnectionError> { print_query_version(self) } fn xprint_print_get_printer_list<'c, 'input>(&'c self, printer_name: &'input [String8], locale: &'input [String8]) -> Result, ConnectionError> { print_get_printer_list(self, printer_name, locale) } fn xprint_print_rehash_printer_list(&self) -> Result, 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, ConnectionError> { create_context(self, context_id, printer_name, locale) } fn xprint_print_set_context(&self, context: u32) -> Result, ConnectionError> { print_set_context(self, context) } fn xprint_print_get_context(&self) -> Result, ConnectionError> { print_get_context(self) } fn xprint_print_destroy_context(&self, context: u32) -> Result, ConnectionError> { print_destroy_context(self, context) } fn xprint_print_get_screen_of_context(&self) -> Result, ConnectionError> { print_get_screen_of_context(self) } fn xprint_print_start_job(&self, output_mode: u8) -> Result, ConnectionError> { print_start_job(self, output_mode) } fn xprint_print_end_job(&self, cancel: bool) -> Result, ConnectionError> { print_end_job(self, cancel) } fn xprint_print_start_doc(&self, driver_mode: u8) -> Result, ConnectionError> { print_start_doc(self, driver_mode) } fn xprint_print_end_doc(&self, cancel: bool) -> Result, 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, ConnectionError> { print_put_document_data(self, drawable, data, doc_format, options) } fn xprint_print_get_document_data(&self, context: Pcontext, max_bytes: u32) -> Result, ConnectionError> { print_get_document_data(self, context, max_bytes) } fn xprint_print_start_page(&self, window: xproto::Window) -> Result, ConnectionError> { print_start_page(self, window) } fn xprint_print_end_page(&self, cancel: bool) -> Result, ConnectionError> { print_end_page(self, cancel) } fn xprint_print_select_input(&self, context: Pcontext, event_mask: u32) -> Result, ConnectionError> { print_select_input(self, context, event_mask) } fn xprint_print_input_selected(&self, context: Pcontext) -> Result, ConnectionError> { print_input_selected(self, context) } fn xprint_print_get_attributes(&self, context: Pcontext, pool: u8) -> Result, 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, 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, ConnectionError> { print_set_attributes(self, context, string_len, pool, rule, attributes) } fn xprint_print_get_page_dimensions(&self, context: Pcontext) -> Result, ConnectionError> { print_get_page_dimensions(self, context) } fn xprint_print_query_screens(&self) -> Result, ConnectionError> { print_query_screens(self) } fn xprint_print_set_image_resolution(&self, context: Pcontext, image_resolution: u16) -> Result, ConnectionError> { print_set_image_resolution(self, context, image_resolution) } fn xprint_print_get_image_resolution(&self, context: Pcontext) -> Result, ConnectionError> { print_get_image_resolution(self, context) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xproto.rs000064400000000000000000006716071046102023000152140ustar 00000000000000// This file contains generated code. Do not edit directly. // To regenerate this, run 'make'. //! Bindings to the core X11 protocol. //! //! For more documentation on the X11 protocol, see the //! [protocol reference manual](https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html). //! This is especially recommended for looking up the exact semantics of //! specific errors, events, or requests. #![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::ListFontsWithInfoCookie; use crate::errors::ConnectionError; #[allow(unused_imports)] use crate::errors::ReplyOrIdError; pub use x11rb_protocol::protocol::xproto::*; /// Creates a window. /// /// Creates an unmapped window as child of the specified `parent` window. A /// CreateNotify event will be generated. The new window is placed on top in the /// stacking order with respect to siblings. /// /// The coordinate system has the X axis horizontal and the Y axis vertical with /// the origin [0, 0] at the upper-left corner. Coordinates are integral, in terms /// of pixels, and coincide with pixel centers. Each window and pixmap has its own /// coordinate system. For a window, the origin is inside the border at the inside, /// upper-left corner. /// /// The created window is not yet displayed (mapped), call `xcb_map_window` to /// display it. /// /// The created window will initially use the same cursor as its parent. /// /// # Fields /// /// * `wid` - The ID with which you will refer to the new window, created by /// `xcb_generate_id`. /// * `depth` - Specifies the new window's depth (TODO: what unit?). /// /// The special value `XCB_COPY_FROM_PARENT` means the depth is taken from the /// `parent` window. /// * `visual` - Specifies the id for the new window's visual. /// /// The special value `XCB_COPY_FROM_PARENT` means the visual is taken from the /// `parent` window. /// * `class` - /// * `parent` - The parent window of the new window. /// * `border_width` - TODO: /// /// Must be zero if the `class` is `InputOnly` or a `xcb_match_error_t` occurs. /// * `x` - The X coordinate of the new window. /// * `y` - The Y coordinate of the new window. /// * `width` - The width of the new window. /// * `height` - The height of the new window. /// /// # Errors /// /// * `Colormap` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Cursor` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Window` - TODO: reasons? /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # See /// /// * `xcb_generate_id`: function /// * `MapWindow`: request /// * `CreateNotify`: event pub fn create_window<'c, 'input, Conn>(conn: &'c Conn, depth: u8, wid: Window, parent: Window, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: WindowClass, visual: Visualid, value_list: &'input CreateWindowAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateWindowRequest { depth, wid, parent, x, y, width, height, border_width, class, visual, value_list: Cow::Borrowed(value_list), }; let (bytes, fds) = request0.serialize(); 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) } /// change window attributes. /// /// Changes the attributes specified by `value_mask` for the specified `window`. /// /// # Fields /// /// * `window` - The window to change. /// * `value_mask` - /// * `value_list` - Values for each of the attributes specified in the bitmask `value_mask`. The /// order has to correspond to the order of possible `value_mask` bits. See the /// example. /// /// # Errors /// /// * `Access` - TODO: reasons? /// * `Colormap` - TODO: reasons? /// * `Cursor` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. pub fn change_window_attributes<'c, 'input, Conn>(conn: &'c Conn, window: Window, value_list: &'input ChangeWindowAttributesAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeWindowAttributesRequest { window, value_list: Cow::Borrowed(value_list), }; let (bytes, fds) = request0.serialize(); 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) } /// Gets window attributes. /// /// Gets the current attributes for the specified `window`. /// /// # Fields /// /// * `window` - The window to get the attributes from. /// /// # Errors /// /// * `Window` - The specified `window` does not exist. /// * `Drawable` - TODO: reasons? pub fn get_window_attributes(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetWindowAttributesRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// Destroys a window. /// /// Destroys the specified window and all of its subwindows. A DestroyNotify event /// is generated for each destroyed window (a DestroyNotify event is first generated /// for any given window's inferiors). If the window was mapped, it will be /// automatically unmapped before destroying. /// /// Calling DestroyWindow on the root window will do nothing. /// /// # Fields /// /// * `window` - The window to destroy. /// /// # Errors /// /// * `Window` - The specified window does not exist. /// /// # See /// /// * `DestroyNotify`: event /// * `MapWindow`: request /// * `UnmapWindow`: request pub fn destroy_window(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DestroyWindowRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn destroy_subwindows(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DestroySubwindowsRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Changes a client's save set. /// /// TODO: explain what the save set is for. /// /// This function either adds or removes the specified window to the client's (your /// application's) save set. /// /// # Fields /// /// * `mode` - Insert to add the specified window to the save set or Delete to delete it from the save set. /// * `window` - The window to add or delete to/from your save set. /// /// # Errors /// /// * `Match` - You created the specified window. This does not make sense, you can only add /// windows created by other clients to your save set. /// * `Value` - You specified an invalid mode. /// * `Window` - The specified window does not exist. /// /// # See /// /// * `ReparentWindow`: request pub fn change_save_set(conn: &Conn, mode: SetMode, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeSaveSetRequest { mode, window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Reparents a window. /// /// Makes the specified window a child of the specified parent window. If the /// window is mapped, it will automatically be unmapped before reparenting and /// re-mapped after reparenting. The window is placed in the stacking order on top /// with respect to sibling windows. /// /// After reparenting, a ReparentNotify event is generated. /// /// # Fields /// /// * `window` - The window to reparent. /// * `parent` - The new parent of the window. /// * `x` - The X position of the window within its new parent. /// * `y` - The Y position of the window within its new parent. /// /// # Errors /// /// * `Match` - The new parent window is not on the same screen as the old parent window. /// /// The new parent window is the specified window or an inferior of the specified window. /// /// The new parent is InputOnly and the window is not. /// /// The specified window has a ParentRelative background and the new parent window is not the same depth as the specified window. /// * `Window` - The specified window does not exist. /// /// # See /// /// * `ReparentNotify`: event /// * `MapWindow`: request /// * `UnmapWindow`: request pub fn reparent_window(conn: &Conn, window: Window, parent: Window, x: i16, y: i16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ReparentWindowRequest { window, parent, x, y, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Makes a window visible. /// /// Maps the specified window. This means making the window visible (as long as its /// parent is visible). /// /// This MapWindow request will be translated to a MapRequest request if a window /// manager is running. The window manager then decides to either map the window or /// not. Set the override-redirect window attribute to true if you want to bypass /// this mechanism. /// /// If the window manager decides to map the window (or if no window manager is /// running), a MapNotify event is generated. /// /// If the window becomes viewable and no earlier contents for it are remembered, /// the X server tiles the window with its background. If the window's background /// is undefined, the existing screen contents are not altered, and the X server /// generates zero or more Expose events. /// /// If the window type is InputOutput, an Expose event will be generated when the /// window becomes visible. The normal response to an Expose event should be to /// repaint the window. /// /// # Fields /// /// * `window` - The window to make visible. /// /// # Errors /// /// * `Match` - The specified window does not exist. /// /// # See /// /// * `MapNotify`: event /// * `Expose`: event /// * `UnmapWindow`: request pub fn map_window(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = MapWindowRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn map_subwindows(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = MapSubwindowsRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Makes a window invisible. /// /// Unmaps the specified window. This means making the window invisible (and all /// its child windows). /// /// Unmapping a window leads to the `UnmapNotify` event being generated. Also, /// `Expose` events are generated for formerly obscured windows. /// /// # Fields /// /// * `window` - The window to make invisible. /// /// # Errors /// /// * `Window` - The specified window does not exist. /// /// # See /// /// * `UnmapNotify`: event /// * `Expose`: event /// * `MapWindow`: request pub fn unmap_window(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = UnmapWindowRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn unmap_subwindows(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = UnmapSubwindowsRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Configures window attributes. /// /// Configures a window's size, position, border width and stacking order. /// /// # Fields /// /// * `window` - The window to configure. /// * `value_mask` - Bitmask of attributes to change. /// * `value_list` - New values, corresponding to the attributes in value_mask. The order has to /// correspond to the order of possible `value_mask` bits. See the example. /// /// # Errors /// /// * `Match` - You specified a Sibling without also specifying StackMode or the window is not /// actually a Sibling. /// * `Window` - The specified window does not exist. TODO: any other reason? /// * `Value` - TODO: reasons? /// /// # See /// /// * `MapNotify`: event /// * `Expose`: event /// /// # Example /// /// ```text /// /* /// * Configures the given window to the left upper corner /// * with a size of 1024x768 pixels. /// * /// */ /// void my_example(xcb_connection_t *c, xcb_window_t window) { /// uint16_t mask = 0; /// /// mask |= XCB_CONFIG_WINDOW_X; /// mask |= XCB_CONFIG_WINDOW_Y; /// mask |= XCB_CONFIG_WINDOW_WIDTH; /// mask |= XCB_CONFIG_WINDOW_HEIGHT; /// /// const uint32_t values[] = { /// 0, /* x */ /// 0, /* y */ /// 1024, /* width */ /// 768 /* height */ /// }; /// /// xcb_configure_window(c, window, mask, values); /// xcb_flush(c); /// } /// ``` pub fn configure_window<'c, 'input, Conn>(conn: &'c Conn, window: Window, value_list: &'input ConfigureWindowAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ConfigureWindowRequest { window, value_list: Cow::Borrowed(value_list), }; let (bytes, fds) = request0.serialize(); 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) } /// Change window stacking order. /// /// If `direction` is `XCB_CIRCULATE_RAISE_LOWEST`, the lowest mapped child (if /// any) will be raised to the top of the stack. /// /// If `direction` is `XCB_CIRCULATE_LOWER_HIGHEST`, the highest mapped child will /// be lowered to the bottom of the stack. /// /// # Fields /// /// * `direction` - /// * `window` - The window to raise/lower (depending on `direction`). /// /// # Errors /// /// * `Window` - The specified `window` does not exist. /// * `Value` - The specified `direction` is invalid. pub fn circulate_window(conn: &Conn, direction: Circulate, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CirculateWindowRequest { direction, window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Get current window geometry. /// /// Gets the current geometry of the specified drawable (either `Window` or `Pixmap`). /// /// # Fields /// /// * `drawable` - The drawable (`Window` or `Pixmap`) of which the geometry will be received. /// /// # Errors /// /// * `Drawable` - TODO: reasons? /// * `Window` - TODO: reasons? /// /// # See /// /// * `xwininfo`: program /// /// # Example /// /// ```text /// /* /// * Displays the x and y position of the given window. /// * /// */ /// void my_example(xcb_connection_t *c, xcb_window_t window) { /// xcb_get_geometry_cookie_t cookie; /// xcb_get_geometry_reply_t *reply; /// /// cookie = xcb_get_geometry(c, window); /// /* ... do other work here if possible ... */ /// if ((reply = xcb_get_geometry_reply(c, cookie, NULL))) { /// printf("This window is at %d, %d\\n", reply->x, reply->y); /// } /// free(reply); /// } /// ``` pub fn get_geometry(conn: &Conn, drawable: Drawable) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetGeometryRequest { drawable, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// query the window tree. /// /// Gets the root window ID, parent window ID and list of children windows for the /// specified `window`. The children are listed in bottom-to-top stacking order. /// /// # Fields /// /// * `window` - The `window` to query. /// /// # See /// /// * `xwininfo`: program /// /// # Example /// /// ```text /// /* /// * Displays the root, parent and children of the specified window. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_window_t window) { /// xcb_query_tree_cookie_t cookie; /// xcb_query_tree_reply_t *reply; /// /// cookie = xcb_query_tree(conn, window); /// if ((reply = xcb_query_tree_reply(conn, cookie, NULL))) { /// printf("root = 0x%08x\\n", reply->root); /// printf("parent = 0x%08x\\n", reply->parent); /// /// xcb_window_t *children = xcb_query_tree_children(reply); /// for (int i = 0; i < xcb_query_tree_children_length(reply); i++) /// printf("child window = 0x%08x\\n", children[i]); /// /// free(reply); /// } /// } /// ``` pub fn query_tree(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryTreeRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// Get atom identifier by name. /// /// Retrieves the identifier (xcb_atom_t TODO) for the atom with the specified /// name. Atoms are used in protocols like EWMH, for example to store window titles /// (`_NET_WM_NAME` atom) as property of a window. /// /// If `only_if_exists` is 0, the atom will be created if it does not already exist. /// If `only_if_exists` is 1, `XCB_ATOM_NONE` will be returned if the atom does /// not yet exist. /// /// # Fields /// /// * `name_len` - The length of the following `name`. /// * `name` - The name of the atom. /// * `only_if_exists` - Return a valid atom id only if the atom already exists. /// /// # Errors /// /// * `Alloc` - TODO: reasons? /// * `Value` - A value other than 0 or 1 was specified for `only_if_exists`. /// /// # See /// /// * `xlsatoms`: program /// * `GetAtomName`: request /// /// # Example /// /// ```text /// /* /// * Resolves the _NET_WM_NAME atom. /// * /// */ /// void my_example(xcb_connection_t *c) { /// xcb_intern_atom_cookie_t cookie; /// xcb_intern_atom_reply_t *reply; /// /// cookie = xcb_intern_atom(c, 0, strlen("_NET_WM_NAME"), "_NET_WM_NAME"); /// /* ... do other work here if possible ... */ /// if ((reply = xcb_intern_atom_reply(c, cookie, NULL))) { /// printf("The _NET_WM_NAME atom has ID %u\n", reply->atom); /// free(reply); /// } /// } /// ``` pub fn intern_atom<'c, 'input, Conn>(conn: &'c Conn, only_if_exists: bool, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = InternAtomRequest { only_if_exists, name: Cow::Borrowed(name), }; let (bytes, fds) = request0.serialize(); 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_atom_name(conn: &Conn, atom: Atom) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetAtomNameRequest { atom, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// Changes a window property. /// /// Sets or updates a property on the specified `window`. Properties are for /// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). /// Protocols such as EWMH also use properties - for example EWMH defines the /// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. /// /// # Fields /// /// * `window` - The window whose property you want to change. /// * `mode` - /// * `property` - The property you want to change (an atom). /// * `type` - The type of the property you want to change (an atom). /// * `format` - Specifies whether the data should be viewed as a list of 8-bit, 16-bit or /// 32-bit quantities. Possible values are 8, 16 and 32. This information allows /// the X server to correctly perform byte-swap operations as necessary. /// * `data_len` - Specifies the number of elements (see `format`). /// * `data` - The property data. /// /// # Errors /// /// * `Match` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. /// * `Atom` - `property` or `type` do not refer to a valid atom. /// * `Alloc` - The X server could not store the property (no memory?). /// /// # See /// /// * `InternAtom`: request /// * `xprop`: program /// /// # Example /// /// ```text /// /* /// * Sets the WM_NAME property of the window to "XCB Example". /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_window_t window) { /// xcb_change_property(conn, /// XCB_PROP_MODE_REPLACE, /// window, /// XCB_ATOM_WM_NAME, /// XCB_ATOM_STRING, /// 8, /// strlen("XCB Example"), /// "XCB Example"); /// xcb_flush(conn); /// } /// ``` pub fn change_property<'c, 'input, Conn, A, B>(conn: &'c Conn, mode: PropMode, window: Window, property: A, type_: B, format: u8, data_len: u32, data: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let property: Atom = property.into(); let type_: Atom = type_.into(); let request0 = ChangePropertyRequest { mode, window, property, type_, format, data_len, data: Cow::Borrowed(data), }; let (bytes, fds) = request0.serialize(); 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_property(conn: &Conn, window: Window, property: Atom) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = DeletePropertyRequest { window, property, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Gets a window property. /// /// Gets the specified `property` from the specified `window`. Properties are for /// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). /// Protocols such as EWMH also use properties - for example EWMH defines the /// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. /// /// TODO: talk about `type` /// /// TODO: talk about `delete` /// /// TODO: talk about the offset/length thing. what's a valid use case? /// /// # Fields /// /// * `window` - The window whose property you want to get. /// * `delete` - Whether the property should actually be deleted. For deleting a property, the /// specified `type` has to match the actual property type. /// * `property` - The property you want to get (an atom). /// * `type` - The type of the property you want to get (an atom). /// * `long_offset` - Specifies the offset (in 32-bit multiples) in the specified property where the /// data is to be retrieved. /// * `long_length` - Specifies how many 32-bit multiples of data should be retrieved (e.g. if you /// set `long_length` to 4, you will receive 16 bytes of data). /// /// # Errors /// /// * `Window` - The specified `window` does not exist. /// * `Atom` - `property` or `type` do not refer to a valid atom. /// * `Value` - The specified `long_offset` is beyond the actual property length (e.g. the /// property has a length of 3 bytes and you are setting `long_offset` to 1, /// resulting in a byte offset of 4). /// /// # See /// /// * `InternAtom`: request /// * `xprop`: program /// /// # Example /// /// ```text /// /* /// * Prints the WM_NAME property of the window. /// * /// */ /// void my_example(xcb_connection_t *c, xcb_window_t window) { /// xcb_get_property_cookie_t cookie; /// xcb_get_property_reply_t *reply; /// /// /* These atoms are predefined in the X11 protocol. */ /// xcb_atom_t property = XCB_ATOM_WM_NAME; /// xcb_atom_t type = XCB_ATOM_STRING; /// /// // TODO: a reasonable long_length for WM_NAME? /// cookie = xcb_get_property(c, 0, window, property, type, 0, 0); /// if ((reply = xcb_get_property_reply(c, cookie, NULL))) { /// int len = xcb_get_property_value_length(reply); /// if (len == 0) { /// printf("TODO\\n"); /// free(reply); /// return; /// } /// printf("WM_NAME is %.*s\\n", len, /// (char*)xcb_get_property_value(reply)); /// } /// free(reply); /// } /// ``` pub fn get_property(conn: &Conn, delete: bool, window: Window, property: A, type_: B, long_offset: u32, long_length: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let property: Atom = property.into(); let type_: Atom = type_.into(); let request0 = GetPropertyRequest { delete, window, property, type_, long_offset, long_length, }; let (bytes, fds) = request0.serialize(); 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, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListPropertiesRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// Sets the owner of a selection. /// /// Makes `window` the owner of the selection `selection` and updates the /// last-change time of the specified selection. /// /// TODO: briefly explain what a selection is. /// /// # Fields /// /// * `selection` - The selection. /// * `owner` - The new owner of the selection. /// /// The special value `XCB_NONE` means that the selection will have no owner. /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The selection will not be changed if `time` is earlier than the current /// last-change time of the `selection` or is later than the current X server time. /// Otherwise, the last-change time is set to the specified time. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// /// # Errors /// /// * `Atom` - `selection` does not refer to a valid atom. /// /// # See /// /// * `SetSelectionOwner`: request pub fn set_selection_owner(conn: &Conn, owner: A, selection: Atom, time: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let owner: Window = owner.into(); let time: Timestamp = time.into(); let request0 = SetSelectionOwnerRequest { owner, selection, time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Gets the owner of a selection. /// /// Gets the owner of the specified selection. /// /// TODO: briefly explain what a selection is. /// /// # Fields /// /// * `selection` - The selection. /// /// # Errors /// /// * `Atom` - `selection` does not refer to a valid atom. /// /// # See /// /// * `SetSelectionOwner`: request pub fn get_selection_owner(conn: &Conn, selection: Atom) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetSelectionOwnerRequest { selection, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn convert_selection(conn: &Conn, requestor: Window, selection: Atom, target: Atom, property: A, time: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let property: Atom = property.into(); let time: Timestamp = time.into(); let request0 = ConvertSelectionRequest { requestor, selection, target, property, time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// send an event. /// /// Identifies the `destination` window, determines which clients should receive /// the specified event and ignores any active grabs. /// /// The `event` must be one of the core events or an event defined by an extension, /// so that the X server can correctly byte-swap the contents as necessary. The /// contents of `event` are otherwise unaltered and unchecked except for the /// `send_event` field which is forced to 'true'. /// /// # Fields /// /// * `destination` - The window to send this event to. Every client which selects any event within /// `event_mask` on `destination` will get the event. /// /// The special value `XCB_SEND_EVENT_DEST_POINTER_WINDOW` refers to the window /// that contains the mouse pointer. /// /// The special value `XCB_SEND_EVENT_DEST_ITEM_FOCUS` refers to the window which /// has the keyboard focus. /// * `event_mask` - Event_mask for determining which clients should receive the specified event. /// See `destination` and `propagate`. /// * `propagate` - If `propagate` is true and no clients have selected any event on `destination`, /// the destination is replaced with the closest ancestor of `destination` for /// which some client has selected a type in `event_mask` and for which no /// intervening window has that type in its do-not-propagate-mask. If no such /// window exists or if the window is an ancestor of the focus window and /// `InputFocus` was originally specified as the destination, the event is not sent /// to any clients. Otherwise, the event is reported to every client selecting on /// the final destination any of the types specified in `event_mask`. /// * `event` - The event to send to the specified `destination`. /// /// # Errors /// /// * `Window` - The specified `destination` window does not exist. /// * `Value` - The given `event` is neither a core event nor an event defined by an extension. /// /// # See /// /// * `ConfigureNotify`: event /// /// # Example /// /// ```text /// /* /// * Tell the given window that it was configured to a size of 800x600 pixels. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_window_t window) { /// /* Every X11 event is 32 bytes long. Therefore, XCB will copy 32 bytes. /// * In order to properly initialize these bytes, we allocate 32 bytes even /// * though we only need less for an xcb_configure_notify_event_t */ /// xcb_configure_notify_event_t *event = calloc(32, 1); /// /// event->event = window; /// event->window = window; /// event->response_type = XCB_CONFIGURE_NOTIFY; /// /// event->x = 0; /// event->y = 0; /// event->width = 800; /// event->height = 600; /// /// event->border_width = 0; /// event->above_sibling = XCB_NONE; /// event->override_redirect = false; /// /// xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, /// (char*)event); /// xcb_flush(conn); /// free(event); /// } /// ``` pub fn send_event(conn: &Conn, propagate: bool, destination: A, event_mask: EventMask, event: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into<[u8; 32]>, { let destination: Window = destination.into(); let event = Cow::Owned(event.into()); let request0 = SendEventRequest { propagate, destination, event_mask, event, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Grab the pointer. /// /// Actively grabs control of the pointer. Further pointer events are reported only to the grabbing client. Overrides any active pointer grab by this client. /// /// # Fields /// /// * `event_mask` - Specifies which pointer events are reported to the client. /// /// TODO: which values? /// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to /// move the pointer out of that window). /// /// The special value `XCB_NONE` means don't confine the pointer. /// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the /// cursor. /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the pointer should be grabbed. /// * `time` - The time argument allows you to avoid certain circumstances that come up if /// applications take a long time to respond or if there are long network delays. /// Consider a situation where you have two applications, both of which normally /// grab the pointer when clicked on. If both applications specify the timestamp /// from the event, the second application may wake up faster and successfully grab /// the pointer before the first application. The first application then will get /// an indication that the other application grabbed the pointer before its request /// was processed. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// * `pointer_mode` - /// * `keyboard_mode` - /// /// # Errors /// /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. /// /// # See /// /// * `GrabKeyboard`: request /// /// # Example /// /// ```text /// /* /// * Grabs the pointer actively /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { /// xcb_grab_pointer_cookie_t cookie; /// xcb_grab_pointer_reply_t *reply; /// /// cookie = xcb_grab_pointer( /// conn, /// false, /* get all pointer events specified by the following mask */ /// screen->root, /* grab the root window */ /// XCB_NONE, /* which events to let through */ /// XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */ /// XCB_GRAB_MODE_ASYNC, /* keyboard mode */ /// XCB_NONE, /* confine_to = in which window should the cursor stay */ /// cursor, /* we change the cursor to whatever the user wanted */ /// XCB_CURRENT_TIME /// ); /// /// if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL))) { /// if (reply->status == XCB_GRAB_STATUS_SUCCESS) /// printf("successfully grabbed the pointer\\n"); /// free(reply); /// } /// } /// ``` pub fn grab_pointer(conn: &Conn, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, time: C) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, C: Into, { let confine_to: Window = confine_to.into(); let cursor: Cursor = cursor.into(); let time: Timestamp = time.into(); let request0 = GrabPointerRequest { owner_events, grab_window, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// release the pointer. /// /// Releases the pointer and any queued events if you actively grabbed the pointer /// before using `xcb_grab_pointer`, `xcb_grab_button` or within a normal button /// press. /// /// EnterNotify and LeaveNotify events are generated. /// /// # Fields /// /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The pointer will not be released if `time` is earlier than the /// last-pointer-grab time or later than the current X server time. /// * `name_len` - Length (in bytes) of `name`. /// * `name` - A pattern describing an X core font. /// /// # See /// /// * `GrabPointer`: request /// * `GrabButton`: request /// * `EnterNotify`: event /// * `LeaveNotify`: event pub fn ungrab_pointer(conn: &Conn, time: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: Timestamp = time.into(); let request0 = UngrabPointerRequest { time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Grab pointer button(s). /// /// This request establishes a passive grab. The pointer is actively grabbed as /// described in GrabPointer, the last-pointer-grab time is set to the time at /// which the button was pressed (as transmitted in the ButtonPress event), and the /// ButtonPress event is reported if all of the following conditions are true: /// /// The pointer is not grabbed and the specified button is logically pressed when /// the specified modifier keys are logically down, and no other buttons or /// modifier keys are logically down. /// /// The grab-window contains the pointer. /// /// The confine-to window (if any) is viewable. /// /// A passive grab on the same button/key combination does not exist on any /// ancestor of grab-window. /// /// The interpretation of the remaining arguments is the same as for GrabPointer. /// The active grab is terminated automatically when the logical state of the /// pointer has all buttons released, independent of the logical state of modifier /// keys. Note that the logical state of a device (as seen by means of the /// protocol) may lag the physical state if device event processing is frozen. This /// request overrides all previous passive grabs by the same client on the same /// button/key combinations on the same window. A modifier of AnyModifier is /// equivalent to issuing the request for all possible modifier combinations /// (including the combination of no modifiers). It is not required that all /// specified modifiers have currently assigned keycodes. A button of AnyButton is /// equivalent to issuing the request for all possible buttons. Otherwise, it is /// not required that the button specified currently be assigned to a physical /// button. /// /// An Access error is generated if some other client has already issued a /// GrabButton request with the same button/key combination on the same window. /// When using AnyModifier or AnyButton, the request fails completely (no grabs are /// established), and an Access error is generated if there is a conflicting grab /// for any combination. The request has no effect on an active grab. /// /// # Fields /// /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the pointer should be grabbed. /// * `event_mask` - Specifies which pointer events are reported to the client. /// /// TODO: which values? /// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to /// move the pointer out of that window). /// /// The special value `XCB_NONE` means don't confine the pointer. /// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the /// cursor. /// * `modifiers` - The modifiers to grab. /// /// Using the special value `XCB_MOD_MASK_ANY` means grab the pointer with all /// possible modifier combinations. /// * `pointer_mode` - /// * `keyboard_mode` - /// * `button` - /// /// # Errors /// /// * `Access` - Another client has already issued a GrabButton with the same button/key /// combination on the same window. /// * `Value` - TODO: reasons? /// * `Cursor` - The specified `cursor` does not exist. /// * `Window` - The specified `window` does not exist. pub fn grab_button(conn: &Conn, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, button: ButtonIndex, modifiers: ModMask) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let confine_to: Window = confine_to.into(); let cursor: Cursor = cursor.into(); let request0 = GrabButtonRequest { owner_events, grab_window, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, button, modifiers, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn ungrab_button(conn: &Conn, button: ButtonIndex, grab_window: Window, modifiers: ModMask) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = UngrabButtonRequest { button, grab_window, modifiers, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn change_active_pointer_grab(conn: &Conn, cursor: A, time: B, event_mask: EventMask) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let cursor: Cursor = cursor.into(); let time: Timestamp = time.into(); let request0 = ChangeActivePointerGrabRequest { cursor, time, event_mask, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Grab the keyboard. /// /// Actively grabs control of the keyboard and generates FocusIn and FocusOut /// events. Further key events are reported only to the grabbing client. /// /// Any active keyboard grab by this client is overridden. If the keyboard is /// actively grabbed by some other client, `AlreadyGrabbed` is returned. If /// `grab_window` is not viewable, `GrabNotViewable` is returned. If the keyboard /// is frozen by an active grab of another client, `GrabFrozen` is returned. If the /// specified `time` is earlier than the last-keyboard-grab time or later than the /// current X server time, `GrabInvalidTime` is returned. Otherwise, the /// last-keyboard-grab time is set to the specified time. /// /// # Fields /// /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the pointer should be grabbed. /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// * `pointer_mode` - /// * `keyboard_mode` - /// /// # Errors /// /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. /// /// # See /// /// * `GrabPointer`: request /// /// # Example /// /// ```text /// /* /// * Grabs the keyboard actively /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_screen_t *screen) { /// xcb_grab_keyboard_cookie_t cookie; /// xcb_grab_keyboard_reply_t *reply; /// /// cookie = xcb_grab_keyboard( /// conn, /// true, /* report events */ /// screen->root, /* grab the root window */ /// XCB_CURRENT_TIME, /// XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ /// XCB_GRAB_MODE_ASYNC /// ); /// /// if ((reply = xcb_grab_keyboard_reply(conn, cookie, NULL))) { /// if (reply->status == XCB_GRAB_STATUS_SUCCESS) /// printf("successfully grabbed the keyboard\\n"); /// /// free(reply); /// } /// } /// ``` pub fn grab_keyboard(conn: &Conn, owner_events: bool, grab_window: Window, time: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: Timestamp = time.into(); let request0 = GrabKeyboardRequest { owner_events, grab_window, time, pointer_mode, keyboard_mode, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn ungrab_keyboard(conn: &Conn, time: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: Timestamp = time.into(); let request0 = UngrabKeyboardRequest { time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Grab keyboard key(s). /// /// Establishes a passive grab on the keyboard. In the future, the keyboard is /// actively grabbed (as for `GrabKeyboard`), the last-keyboard-grab time is set to /// the time at which the key was pressed (as transmitted in the KeyPress event), /// and the KeyPress event is reported if all of the following conditions are true: /// /// The keyboard is not grabbed and the specified key (which can itself be a /// modifier key) is logically pressed when the specified modifier keys are /// logically down, and no other modifier keys are logically down. /// /// Either the grab_window is an ancestor of (or is) the focus window, or the /// grab_window is a descendant of the focus window and contains the pointer. /// /// A passive grab on the same key combination does not exist on any ancestor of /// grab_window. /// /// The interpretation of the remaining arguments is as for XGrabKeyboard. The active grab is terminated /// automatically when the logical state of the keyboard has the specified key released (independent of the /// logical state of the modifier keys), at which point a KeyRelease event is reported to the grabbing window. /// /// Note that the logical state of a device (as seen by client applications) may lag the physical state if /// device event processing is frozen. /// /// A modifiers argument of AnyModifier is equivalent to issuing the request for all possible modifier combinations (including the combination of no modifiers). It is not required that all modifiers specified /// have currently assigned KeyCodes. A keycode argument of AnyKey is equivalent to issuing the request for /// all possible KeyCodes. Otherwise, the specified keycode must be in the range specified by min_keycode /// and max_keycode in the connection setup, or a BadValue error results. /// /// If some other client has issued a XGrabKey with the same key combination on the same window, a BadAccess /// error results. When using AnyModifier or AnyKey, the request fails completely, and a BadAccess error /// results (no grabs are established) if there is a conflicting grab for any combination. /// /// # Fields /// /// * `owner_events` - If 1, the `grab_window` will still get the key events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the key should be grabbed. /// * `key` - The keycode of the key to grab. /// /// The special value `XCB_GRAB_ANY` means grab any key. /// * `modifiers` - The modifiers to grab. /// /// Using the special value `XCB_MOD_MASK_ANY` means grab the key with all /// possible modifier combinations. /// * `pointer_mode` - /// * `keyboard_mode` - /// /// # Errors /// /// * `Access` - Another client has already issued a GrabKey with the same button/key /// combination on the same window. /// * `Value` - The key is not `XCB_GRAB_ANY` and not in the range specified by `min_keycode` /// and `max_keycode` in the connection setup. /// * `Window` - The specified `window` does not exist. /// /// # See /// /// * `GrabKeyboard`: request pub fn grab_key(conn: &Conn, owner_events: bool, grab_window: Window, modifiers: ModMask, key: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let key: Keycode = key.into(); let request0 = GrabKeyRequest { owner_events, grab_window, modifiers, key, pointer_mode, keyboard_mode, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// release a key combination. /// /// Releases the key combination on `grab_window` if you grabbed it using /// `xcb_grab_key` before. /// /// # Fields /// /// * `key` - The keycode of the specified key combination. /// /// Using the special value `XCB_GRAB_ANY` means releasing all possible key codes. /// * `grab_window` - The window on which the grabbed key combination will be released. /// * `modifiers` - The modifiers of the specified key combination. /// /// Using the special value `XCB_MOD_MASK_ANY` means releasing the key combination /// with every possible modifier combination. /// /// # Errors /// /// * `Window` - The specified `grab_window` does not exist. /// * `Value` - TODO: reasons? /// /// # See /// /// * `GrabKey`: request /// * `xev`: program pub fn ungrab_key(conn: &Conn, key: A, grab_window: Window, modifiers: ModMask) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let key: Keycode = key.into(); let request0 = UngrabKeyRequest { key, grab_window, modifiers, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// release queued events. /// /// Releases queued events if the client has caused a device (pointer/keyboard) to /// freeze due to grabbing it actively. This request has no effect if `time` is /// earlier than the last-grab time of the most recent active grab for this client /// or if `time` is later than the current X server time. /// /// # Fields /// /// * `mode` - /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// /// # Errors /// /// * `Value` - You specified an invalid `mode`. pub fn allow_events(conn: &Conn, mode: Allow, time: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let time: Timestamp = time.into(); let request0 = AllowEventsRequest { mode, time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn grab_server(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GrabServerRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn ungrab_server(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = UngrabServerRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// get pointer coordinates. /// /// Gets the root window the pointer is logically on and the pointer coordinates /// relative to the root window's origin. /// /// # Fields /// /// * `window` - A window to check if the pointer is on the same screen as `window` (see the /// `same_screen` field in the reply). /// /// # Errors /// /// * `Window` - The specified `window` does not exist. pub fn query_pointer(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryPointerRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn get_motion_events(conn: &Conn, window: Window, start: A, stop: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let start: Timestamp = start.into(); let stop: Timestamp = stop.into(); let request0 = GetMotionEventsRequest { window, start, stop, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn translate_coordinates(conn: &Conn, src_window: Window, dst_window: Window, src_x: i16, src_y: i16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = TranslateCoordinatesRequest { src_window, dst_window, src_x, src_y, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// move mouse pointer. /// /// Moves the mouse pointer to the specified position. /// /// If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the /// pointer is inside `src_window` and within the rectangle specified by (`src_x`, /// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to /// `src_window`. /// /// If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the /// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is /// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) /// relative to the current position of the pointer. /// /// # Fields /// /// * `src_window` - If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the /// pointer is inside `src_window` and within the rectangle specified by (`src_x`, /// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to /// `src_window`. /// * `dst_window` - If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the /// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is /// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) /// relative to the current position of the pointer. /// /// # Errors /// /// * `Window` - TODO: reasons? /// /// # See /// /// * `SetInputFocus`: request pub fn warp_pointer(conn: &Conn, src_window: A, dst_window: B, src_x: i16, src_y: i16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let src_window: Window = src_window.into(); let dst_window: Window = dst_window.into(); let request0 = WarpPointerRequest { src_window, dst_window, src_x, src_y, src_width, src_height, dst_x, dst_y, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Sets input focus. /// /// Changes the input focus and the last-focus-change time. If the specified `time` /// is earlier than the current last-focus-change time, the request is ignored (to /// avoid race conditions when running X over the network). /// /// A FocusIn and FocusOut event is generated when focus is changed. /// /// # Fields /// /// * `focus` - The window to focus. All keyboard events will be reported to this window. The /// window must be viewable (TODO), or a `xcb_match_error_t` occurs (TODO). /// /// If `focus` is `XCB_NONE` (TODO), all keyboard events are /// discarded until a new focus window is set. /// /// If `focus` is `XCB_POINTER_ROOT` (TODO), focus is on the root window of the /// screen on which the pointer is on currently. /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// * `revert_to` - Specifies what happens when the `focus` window becomes unviewable (if `focus` /// is neither `XCB_NONE` nor `XCB_POINTER_ROOT`). /// /// # Errors /// /// * `Window` - The specified `focus` window does not exist. /// * `Match` - The specified `focus` window is not viewable. /// * `Value` - TODO: Reasons? /// /// # See /// /// * `FocusIn`: event /// * `FocusOut`: event pub fn set_input_focus(conn: &Conn, revert_to: InputFocus, focus: A, time: B) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, B: Into, { let focus: Window = focus.into(); let time: Timestamp = time.into(); let request0 = SetInputFocusRequest { revert_to, focus, time, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn get_input_focus(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetInputFocusRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn query_keymap(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryKeymapRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// opens a font. /// /// Opens any X core font matching the given `name` (for example "-misc-fixed-*"). /// /// Note that X core fonts are deprecated (but still supported) in favor of /// client-side rendering using Xft. /// /// # Fields /// /// * `fid` - The ID with which you will refer to the font, created by `xcb_generate_id`. /// * `name_len` - Length (in bytes) of `name`. /// * `name` - A pattern describing an X core font. /// /// # Errors /// /// * `Name` - No font matches the given `name`. /// /// # See /// /// * `xcb_generate_id`: function pub fn open_font<'c, 'input, Conn>(conn: &'c Conn, fid: Font, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = OpenFontRequest { fid, name: Cow::Borrowed(name), }; let (bytes, fds) = request0.serialize(); 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 close_font(conn: &Conn, font: Font) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CloseFontRequest { font, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// query font metrics. /// /// Queries information associated with the font. /// /// # Fields /// /// * `font` - The fontable (Font or Graphics Context) to query. pub fn query_font(conn: &Conn, font: Fontable) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryFontRequest { font, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// get text extents. /// /// Query text extents from the X11 server. This request returns the bounding box /// of the specified 16-bit character string in the specified `font` or the font /// contained in the specified graphics context. /// /// `font_ascent` is set to the maximum of the ascent metrics of all characters in /// the string. `font_descent` is set to the maximum of the descent metrics. /// `overall_width` is set to the sum of the character-width metrics of all /// characters in the string. For each character in the string, let W be the sum of /// the character-width metrics of all characters preceding it in the string. Let L /// be the left-side-bearing metric of the character plus W. Let R be the /// right-side-bearing metric of the character plus W. The lbearing member is set /// to the minimum L of all characters in the string. The rbearing member is set to /// the maximum R. /// /// For fonts defined with linear indexing rather than 2-byte matrix indexing, each /// `xcb_char2b_t` structure is interpreted as a 16-bit number with byte1 as the /// most significant byte. If the font has no defined default character, undefined /// characters in the string are taken to have all zero metrics. /// /// Characters with all zero metrics are ignored. If the font has no defined /// default_char, the undefined characters in the string are also ignored. /// /// # Fields /// /// * `font` - The `font` to calculate text extents in. You can also pass a graphics context. /// * `string_len` - The number of characters in `string`. /// * `string` - The text to get text extents for. /// /// # Errors /// /// * `GContext` - The specified graphics context does not exist. /// * `Font` - The specified `font` does not exist. pub fn query_text_extents<'c, 'input, Conn>(conn: &'c Conn, font: Fontable, string: &'input [Char2b]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryTextExtentsRequest { font, string: Cow::Borrowed(string), }; let (bytes, fds) = request0.serialize(); 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) } /// get matching font names. /// /// Gets a list of available font names which match the given `pattern`. /// /// # Fields /// /// * `pattern_len` - The length (in bytes) of `pattern`. /// * `pattern` - A font pattern, for example "-misc-fixed-*". /// /// The asterisk (*) is a wildcard for any number of characters. The question mark /// (?) is a wildcard for a single character. Use of uppercase or lowercase does /// not matter. /// * `max_names` - The maximum number of fonts to be returned. pub fn list_fonts<'c, 'input, Conn>(conn: &'c Conn, max_names: u16, pattern: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListFontsRequest { max_names, pattern: Cow::Borrowed(pattern), }; let (bytes, fds) = request0.serialize(); 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) } /// get matching font names and information. /// /// Gets a list of available font names which match the given `pattern`. /// /// # Fields /// /// * `pattern_len` - The length (in bytes) of `pattern`. /// * `pattern` - A font pattern, for example "-misc-fixed-*". /// /// The asterisk (*) is a wildcard for any number of characters. The question mark /// (?) is a wildcard for a single character. Use of uppercase or lowercase does /// not matter. /// * `max_names` - The maximum number of fonts to be returned. pub fn list_fonts_with_info<'c, 'input, Conn>(conn: &'c Conn, max_names: u16, pattern: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListFontsWithInfoRequest { max_names, pattern: Cow::Borrowed(pattern), }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0]), IoSlice::new(&bytes[1]), IoSlice::new(&bytes[2])]; assert_eq!(slices.len(), bytes.len()); Ok(ListFontsWithInfoCookie::new(conn.send_request_with_reply(&slices, fds)?)) } pub fn set_font_path<'c, 'input, Conn>(conn: &'c Conn, font: &'input [Str]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetFontPathRequest { font: Cow::Borrowed(font), }; let (bytes, fds) = request0.serialize(); 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_font_path(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetFontPathRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// Creates a pixmap. /// /// Creates a pixmap. The pixmap can only be used on the same screen as `drawable` /// is on and only with drawables of the same `depth`. /// /// # Fields /// /// * `depth` - TODO /// * `pid` - The ID with which you will refer to the new pixmap, created by /// `xcb_generate_id`. /// * `drawable` - Drawable to get the screen from. /// * `width` - The width of the new pixmap. /// * `height` - The height of the new pixmap. /// /// # Errors /// /// * `Value` - TODO: reasons? /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # See /// /// * `xcb_generate_id`: function pub fn create_pixmap(conn: &Conn, depth: u8, pid: Pixmap, drawable: Drawable, width: u16, height: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreatePixmapRequest { depth, pid, drawable, width, height, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Destroys a pixmap. /// /// Deletes the association between the pixmap ID and the pixmap. The pixmap /// storage will be freed when there are no more references to it. /// /// # Fields /// /// * `pixmap` - The pixmap to destroy. /// /// # Errors /// /// * `Pixmap` - The specified pixmap does not exist. pub fn free_pixmap(conn: &Conn, pixmap: Pixmap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FreePixmapRequest { pixmap, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Creates a graphics context. /// /// Creates a graphics context. The graphics context can be used with any drawable /// that has the same root and depth as the specified drawable. /// /// # Fields /// /// * `cid` - The ID with which you will refer to the graphics context, created by /// `xcb_generate_id`. /// * `drawable` - Drawable to get the root/depth from. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `Match` - TODO: reasons? /// * `Font` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # See /// /// * `xcb_generate_id`: function pub fn create_gc<'c, 'input, Conn>(conn: &'c Conn, cid: Gcontext, drawable: Drawable, value_list: &'input CreateGCAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateGCRequest { cid, drawable, value_list: Cow::Borrowed(value_list), }; let (bytes, fds) = request0.serialize(); 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) } /// change graphics context components. /// /// Changes the components specified by `value_mask` for the specified graphics context. /// /// # Fields /// /// * `gc` - The graphics context to change. /// * `value_mask` - /// * `value_list` - Values for each of the components specified in the bitmask `value_mask`. The /// order has to correspond to the order of possible `value_mask` bits. See the /// example. /// /// # Errors /// /// * `Font` - TODO: reasons? /// * `GContext` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # Example /// /// ```text /// /* /// * Changes the foreground color component of the specified graphics context. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_gcontext_t gc, uint32_t fg, uint32_t bg) { /// /* C99 allows us to use a compact way of changing a single component: */ /// xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){ fg }); /// /// /* The more explicit way. Beware that the order of values is important! */ /// uint32_t mask = 0; /// mask |= XCB_GC_FOREGROUND; /// mask |= XCB_GC_BACKGROUND; /// /// uint32_t values[] = { /// fg, /// bg /// }; /// xcb_change_gc(conn, gc, mask, values); /// xcb_flush(conn); /// } /// ``` pub fn change_gc<'c, 'input, Conn>(conn: &'c Conn, gc: Gcontext, value_list: &'input ChangeGCAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeGCRequest { gc, value_list: Cow::Borrowed(value_list), }; let (bytes, fds) = request0.serialize(); 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_gc(conn: &Conn, src_gc: Gcontext, dst_gc: Gcontext, value_mask: GC) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CopyGCRequest { src_gc, dst_gc, value_mask, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn set_dashes<'c, 'input, Conn>(conn: &'c Conn, gc: Gcontext, dash_offset: u16, dashes: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetDashesRequest { gc, dash_offset, dashes: Cow::Borrowed(dashes), }; let (bytes, fds) = request0.serialize(); 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_clip_rectangles<'c, 'input, Conn>(conn: &'c Conn, ordering: ClipOrdering, gc: Gcontext, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [Rectangle]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetClipRectanglesRequest { ordering, gc, clip_x_origin, clip_y_origin, rectangles: Cow::Borrowed(rectangles), }; let (bytes, fds) = request0.serialize(); 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) } /// Destroys a graphics context. /// /// Destroys the specified `gc` and all associated storage. /// /// # Fields /// /// * `gc` - The graphics context to destroy. /// /// # Errors /// /// * `GContext` - The specified graphics context does not exist. pub fn free_gc(conn: &Conn, gc: Gcontext) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FreeGCRequest { gc, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn clear_area(conn: &Conn, exposures: bool, window: Window, x: i16, y: i16, width: u16, height: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ClearAreaRequest { exposures, window, x, y, width, height, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// copy areas. /// /// Copies the specified rectangle from `src_drawable` to `dst_drawable`. /// /// # Fields /// /// * `dst_drawable` - The destination drawable (Window or Pixmap). /// * `src_drawable` - The source drawable (Window or Pixmap). /// * `gc` - The graphics context to use. /// * `src_x` - The source X coordinate. /// * `src_y` - The source Y coordinate. /// * `dst_x` - The destination X coordinate. /// * `dst_y` - The destination Y coordinate. /// * `width` - The width of the area to copy (in pixels). /// * `height` - The height of the area to copy (in pixels). /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - `src_drawable` has a different root or depth than `dst_drawable`. pub fn copy_area(conn: &Conn, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CopyAreaRequest { src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn copy_plane(conn: &Conn, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16, bit_plane: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CopyPlaneRequest { src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height, bit_plane, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn poly_point<'c, 'input, Conn>(conn: &'c Conn, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyPointRequest { coordinate_mode, drawable, gc, points: Cow::Borrowed(points), }; let (bytes, fds) = request0.serialize(); 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) } /// draw lines. /// /// Draws `points_len`-1 lines between each pair of points (point[i], point[i+1]) /// in the `points` array. The lines are drawn in the order listed in the array. /// They join correctly at all intermediate points, and if the first and last /// points coincide, the first and last lines also join correctly. For any given /// line, a pixel is not drawn more than once. If thin (zero line-width) lines /// intersect, the intersecting pixels are drawn multiple times. If wide lines /// intersect, the intersecting pixels are drawn only once, as though the entire /// request were a single, filled shape. /// /// # Fields /// /// * `drawable` - The drawable to draw the line(s) on. /// * `gc` - The graphics context to use. /// * `points_len` - The number of `xcb_point_t` structures in `points`. /// * `points` - An array of points. /// * `coordinate_mode` - /// /// # Errors /// /// * `Drawable` - TODO: reasons? /// * `GContext` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Value` - TODO: reasons? /// /// # Example /// /// ```text /// /* /// * Draw a straight line. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc) { /// xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2, /// (xcb_point_t[]) { {10, 10}, {100, 10} }); /// xcb_flush(conn); /// } /// ``` pub fn poly_line<'c, 'input, Conn>(conn: &'c Conn, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyLineRequest { coordinate_mode, drawable, gc, points: Cow::Borrowed(points), }; let (bytes, fds) = request0.serialize(); 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) } /// draw lines. /// /// Draws multiple, unconnected lines. For each segment, a line is drawn between /// (x1, y1) and (x2, y2). The lines are drawn in the order listed in the array of /// `xcb_segment_t` structures and does not perform joining at coincident /// endpoints. For any given line, a pixel is not drawn more than once. If lines /// intersect, the intersecting pixels are drawn multiple times. /// /// TODO: include the xcb_segment_t data structure /// /// TODO: an example /// /// # Fields /// /// * `drawable` - A drawable (Window or Pixmap) to draw on. /// * `gc` - The graphics context to use. /// /// TODO: document which attributes of a gc are used /// * `segments_len` - The number of `xcb_segment_t` structures in `segments`. /// * `segments` - An array of `xcb_segment_t` structures. /// /// # Errors /// /// * `Drawable` - The specified `drawable` does not exist. /// * `GContext` - The specified `gc` does not exist. /// * `Match` - TODO: reasons? pub fn poly_segment<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, segments: &'input [Segment]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolySegmentRequest { drawable, gc, segments: Cow::Borrowed(segments), }; let (bytes, fds) = request0.serialize(); 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 poly_rectangle<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyRectangleRequest { drawable, gc, rectangles: Cow::Borrowed(rectangles), }; let (bytes, fds) = request0.serialize(); 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 poly_arc<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyArcRequest { drawable, gc, arcs: Cow::Borrowed(arcs), }; let (bytes, fds) = request0.serialize(); 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_poly<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, shape: PolyShape, coordinate_mode: CoordMode, points: &'input [Point]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FillPolyRequest { drawable, gc, shape, coordinate_mode, points: Cow::Borrowed(points), }; let (bytes, fds) = request0.serialize(); 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) } /// Fills rectangles. /// /// Fills the specified rectangle(s) in the order listed in the array. For any /// given rectangle, each pixel is not drawn more than once. If rectangles /// intersect, the intersecting pixels are drawn multiple times. /// /// # Fields /// /// * `drawable` - The drawable (Window or Pixmap) to draw on. /// * `gc` - The graphics context to use. /// /// The following graphics context components are used: function, plane-mask, /// fill-style, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. /// /// The following graphics context mode-dependent components are used: /// foreground, background, tile, stipple, tile-stipple-x-origin, and /// tile-stipple-y-origin. /// * `rectangles_len` - The number of `xcb_rectangle_t` structures in `rectangles`. /// * `rectangles` - The rectangles to fill. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - TODO: reasons? pub fn poly_fill_rectangle<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyFillRectangleRequest { drawable, gc, rectangles: Cow::Borrowed(rectangles), }; let (bytes, fds) = request0.serialize(); 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 poly_fill_arc<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyFillArcRequest { drawable, gc, arcs: Cow::Borrowed(arcs), }; let (bytes, fds) = request0.serialize(); 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 put_image<'c, 'input, Conn>(conn: &'c Conn, format: ImageFormat, drawable: Drawable, gc: Gcontext, width: u16, height: u16, dst_x: i16, dst_y: i16, left_pad: u8, depth: u8, data: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PutImageRequest { format, drawable, gc, width, height, dst_x, dst_y, left_pad, depth, data: Cow::Borrowed(data), }; let (bytes, fds) = request0.serialize(); 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_image(conn: &Conn, format: ImageFormat, drawable: Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetImageRequest { format, drawable, x, y, width, height, plane_mask, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn poly_text8<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyText8Request { drawable, gc, x, y, items: Cow::Borrowed(items), }; let (bytes, fds) = request0.serialize(); 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 poly_text16<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = PolyText16Request { drawable, gc, x, y, items: Cow::Borrowed(items), }; let (bytes, fds) = request0.serialize(); 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) } /// Draws text. /// /// Fills the destination rectangle with the background pixel from `gc`, then /// paints the text with the foreground pixel from `gc`. The upper-left corner of /// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, /// the height is font-ascent + font-descent. The overall-width, font-ascent and /// font-descent are as returned by `xcb_query_text_extents` (TODO). /// /// Note that using X core fonts is deprecated (but still supported) in favor of /// client-side rendering using Xft. /// /// # Fields /// /// * `drawable` - The drawable (Window or Pixmap) to draw text on. /// * `string_len` - The length of the `string`. Note that this parameter limited by 255 due to /// using 8 bits! /// * `string` - The string to draw. Only the first 255 characters are relevant due to the data /// type of `string_len`. /// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. /// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. /// * `gc` - The graphics context to use. /// /// The following graphics context components are used: plane-mask, foreground, /// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - TODO: reasons? /// /// # See /// /// * `ImageText16`: request pub fn image_text8<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ImageText8Request { drawable, gc, x, y, string: Cow::Borrowed(string), }; let (bytes, fds) = request0.serialize(); 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) } /// Draws text. /// /// Fills the destination rectangle with the background pixel from `gc`, then /// paints the text with the foreground pixel from `gc`. The upper-left corner of /// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, /// the height is font-ascent + font-descent. The overall-width, font-ascent and /// font-descent are as returned by `xcb_query_text_extents` (TODO). /// /// Note that using X core fonts is deprecated (but still supported) in favor of /// client-side rendering using Xft. /// /// # Fields /// /// * `drawable` - The drawable (Window or Pixmap) to draw text on. /// * `string_len` - The length of the `string` in characters. Note that this parameter limited by /// 255 due to using 8 bits! /// * `string` - The string to draw. Only the first 255 characters are relevant due to the data /// type of `string_len`. Every character uses 2 bytes (hence the 16 in this /// request's name). /// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. /// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. /// * `gc` - The graphics context to use. /// /// The following graphics context components are used: plane-mask, foreground, /// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - TODO: reasons? /// /// # See /// /// * `ImageText8`: request pub fn image_text16<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [Char2b]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ImageText16Request { drawable, gc, x, y, string: Cow::Borrowed(string), }; let (bytes, fds) = request0.serialize(); 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_colormap(conn: &Conn, alloc: ColormapAlloc, mid: Colormap, window: Window, visual: Visualid) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CreateColormapRequest { alloc, mid, window, visual, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn free_colormap(conn: &Conn, cmap: Colormap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FreeColormapRequest { cmap, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn copy_colormap_and_free(conn: &Conn, mid: Colormap, src_cmap: Colormap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = CopyColormapAndFreeRequest { mid, src_cmap, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn install_colormap(conn: &Conn, cmap: Colormap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = InstallColormapRequest { cmap, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn uninstall_colormap(conn: &Conn, cmap: Colormap) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = UninstallColormapRequest { cmap, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn list_installed_colormaps(conn: &Conn, window: Window) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListInstalledColormapsRequest { window, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// Allocate a color. /// /// Allocates a read-only colormap entry corresponding to the closest RGB value /// supported by the hardware. If you are using TrueColor, you can take a shortcut /// and directly calculate the color pixel value to avoid the round trip. But, for /// example, on 16-bit color setups (VNC), you can easily get the closest supported /// RGB value to the RGB value you are specifying. /// /// # Fields /// /// * `cmap` - TODO /// * `red` - The red value of your color. /// * `green` - The green value of your color. /// * `blue` - The blue value of your color. /// /// # Errors /// /// * `Colormap` - The specified colormap `cmap` does not exist. pub fn alloc_color(conn: &Conn, cmap: Colormap, red: u16, green: u16, blue: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = AllocColorRequest { cmap, red, green, blue, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn alloc_named_color<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = AllocNamedColorRequest { cmap, name: Cow::Borrowed(name), }; let (bytes, fds) = request0.serialize(); 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 alloc_color_cells(conn: &Conn, contiguous: bool, cmap: Colormap, colors: u16, planes: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = AllocColorCellsRequest { contiguous, cmap, colors, planes, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn alloc_color_planes(conn: &Conn, contiguous: bool, cmap: Colormap, colors: u16, reds: u16, greens: u16, blues: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = AllocColorPlanesRequest { contiguous, cmap, colors, reds, greens, blues, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn free_colors<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, plane_mask: u32, pixels: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FreeColorsRequest { cmap, plane_mask, pixels: Cow::Borrowed(pixels), }; let (bytes, fds) = request0.serialize(); 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 store_colors<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, items: &'input [Coloritem]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = StoreColorsRequest { cmap, items: Cow::Borrowed(items), }; let (bytes, fds) = request0.serialize(); 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 store_named_color<'c, 'input, Conn>(conn: &'c Conn, flags: ColorFlag, cmap: Colormap, pixel: u32, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = StoreNamedColorRequest { flags, cmap, pixel, name: Cow::Borrowed(name), }; let (bytes, fds) = request0.serialize(); 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 query_colors<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, pixels: &'input [u32]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryColorsRequest { cmap, pixels: Cow::Borrowed(pixels), }; let (bytes, fds) = request0.serialize(); 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 lookup_color<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = LookupColorRequest { cmap, name: Cow::Borrowed(name), }; let (bytes, fds) = request0.serialize(); 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 create_cursor(conn: &Conn, cid: Cursor, source: Pixmap, mask: A, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let mask: Pixmap = mask.into(); let request0 = CreateCursorRequest { cid, source, mask, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, x, y, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// create cursor. /// /// Creates a cursor from a font glyph. X provides a set of standard cursor shapes /// in a special font named cursor. Applications are encouraged to use this /// interface for their cursors because the font can be customized for the /// individual display type. /// /// All pixels which are set to 1 in the source will use the foreground color (as /// specified by `fore_red`, `fore_green` and `fore_blue`). All pixels set to 0 /// will use the background color (as specified by `back_red`, `back_green` and /// `back_blue`). /// /// # Fields /// /// * `cid` - The ID with which you will refer to the cursor, created by `xcb_generate_id`. /// * `source_font` - In which font to look for the cursor glyph. /// * `mask_font` - In which font to look for the mask glyph. /// * `source_char` - The glyph of `source_font` to use. /// * `mask_char` - The glyph of `mask_font` to use as a mask: Pixels which are set to 1 define /// which source pixels are displayed. All pixels which are set to 0 are not /// displayed. /// * `fore_red` - The red value of the foreground color. /// * `fore_green` - The green value of the foreground color. /// * `fore_blue` - The blue value of the foreground color. /// * `back_red` - The red value of the background color. /// * `back_green` - The green value of the background color. /// * `back_blue` - The blue value of the background color. /// /// # Errors /// /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// * `Font` - The specified `source_font` or `mask_font` does not exist. /// * `Value` - Either `source_char` or `mask_char` are not defined in `source_font` or `mask_font`, respectively. pub fn create_glyph_cursor(conn: &Conn, cid: Cursor, source_font: Font, mask_font: A, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let mask_font: Font = mask_font.into(); let request0 = CreateGlyphCursorRequest { cid, source_font, mask_font, source_char, mask_char, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// Deletes a cursor. /// /// Deletes the association between the cursor resource ID and the specified /// cursor. The cursor is freed when no other resource references it. /// /// # Fields /// /// * `cursor` - The cursor to destroy. /// /// # Errors /// /// * `Cursor` - The specified cursor does not exist. pub fn free_cursor(conn: &Conn, cursor: Cursor) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = FreeCursorRequest { cursor, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn recolor_cursor(conn: &Conn, cursor: Cursor, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = RecolorCursorRequest { cursor, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, }; let (bytes, fds) = request0.serialize(); 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, class: QueryShapeOf, drawable: Drawable, width: u16, height: u16) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryBestSizeRequest { class, drawable, width, height, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } /// check if extension is present. /// /// Determines if the specified extension is present on this X11 server. /// /// Every extension has a unique `major_opcode` to identify requests, the minor /// opcodes and request formats are extension-specific. If the extension provides /// events and errors, the `first_event` and `first_error` fields in the reply are /// set accordingly. /// /// There should rarely be a need to use this request directly, XCB provides the /// `xcb_get_extension_data` function instead. /// /// # Fields /// /// * `name_len` - The length of `name` in bytes. /// * `name` - The name of the extension to query, for example "RANDR". This is case /// sensitive! /// /// # See /// /// * `xdpyinfo`: program /// * `xcb_get_extension_data`: function pub fn query_extension<'c, 'input, Conn>(conn: &'c Conn, name: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = QueryExtensionRequest { name: Cow::Borrowed(name), }; let (bytes, fds) = request0.serialize(); 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 list_extensions(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListExtensionsRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn change_keyboard_mapping<'c, 'input, Conn>(conn: &'c Conn, keycode_count: u8, first_keycode: Keycode, keysyms_per_keycode: u8, keysyms: &'input [Keysym]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeKeyboardMappingRequest { keycode_count, first_keycode, keysyms_per_keycode, keysyms: Cow::Borrowed(keysyms), }; let (bytes, fds) = request0.serialize(); 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_keyboard_mapping(conn: &Conn, first_keycode: Keycode, count: u8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetKeyboardMappingRequest { first_keycode, count, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn change_keyboard_control<'c, 'input, Conn>(conn: &'c Conn, value_list: &'input ChangeKeyboardControlAux) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeKeyboardControlRequest { value_list: Cow::Borrowed(value_list), }; let (bytes, fds) = request0.serialize(); 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_keyboard_control(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetKeyboardControlRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn bell(conn: &Conn, percent: i8) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = BellRequest { percent, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn change_pointer_control(conn: &Conn, acceleration_numerator: i16, acceleration_denominator: i16, threshold: i16, do_acceleration: bool, do_threshold: bool) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangePointerControlRequest { acceleration_numerator, acceleration_denominator, threshold, do_acceleration, do_threshold, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn get_pointer_control(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetPointerControlRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn set_screen_saver(conn: &Conn, timeout: i16, interval: i16, prefer_blanking: Blanking, allow_exposures: Exposures) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetScreenSaverRequest { timeout, interval, prefer_blanking, allow_exposures, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn get_screen_saver(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetScreenSaverRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn change_hosts<'c, 'input, Conn>(conn: &'c Conn, mode: HostMode, family: Family, address: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ChangeHostsRequest { mode, family, address: Cow::Borrowed(address), }; let (bytes, fds) = request0.serialize(); 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 list_hosts(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ListHostsRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn set_access_control(conn: &Conn, mode: AccessControl) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetAccessControlRequest { mode, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn set_close_down_mode(conn: &Conn, mode: CloseDown) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetCloseDownModeRequest { mode, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } /// kills a client. /// /// Forces a close down of the client that created the specified `resource`. /// /// # Fields /// /// * `resource` - Any resource belonging to the client (for example a Window), used to identify /// the client connection. /// /// The special value of `XCB_KILL_ALL_TEMPORARY`, the resources of all clients /// that have terminated in `RetainTemporary` (TODO) are destroyed. /// /// # Errors /// /// * `Value` - The specified `resource` does not exist. /// /// # See /// /// * `xkill`: program pub fn kill_client(conn: &Conn, resource: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { let resource: u32 = resource.into(); let request0 = KillClientRequest { resource, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn rotate_properties<'c, 'input, Conn>(conn: &'c Conn, window: Window, delta: i16, atoms: &'input [Atom]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = RotatePropertiesRequest { window, delta, atoms: Cow::Borrowed(atoms), }; let (bytes, fds) = request0.serialize(); 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 force_screen_saver(conn: &Conn, mode: ScreenSaver) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = ForceScreenSaverRequest { mode, }; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_without_reply(&slices, fds) } pub fn set_pointer_mapping<'c, 'input, Conn>(conn: &'c Conn, map: &'input [u8]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetPointerMappingRequest { map: Cow::Borrowed(map), }; let (bytes, fds) = request0.serialize(); 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_pointer_mapping(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetPointerMappingRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn set_modifier_mapping<'c, 'input, Conn>(conn: &'c Conn, keycodes: &'input [Keycode]) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = SetModifierMappingRequest { keycodes: Cow::Borrowed(keycodes), }; let (bytes, fds) = request0.serialize(); 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_modifier_mapping(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = GetModifierMappingRequest; let (bytes, fds) = request0.serialize(); let slices = [IoSlice::new(&bytes[0])]; assert_eq!(slices.len(), bytes.len()); conn.send_request_with_reply(&slices, fds) } pub fn no_operation(conn: &Conn) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, { let request0 = NoOperationRequest; let (bytes, fds) = request0.serialize(); 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 { /// Creates a window. /// /// Creates an unmapped window as child of the specified `parent` window. A /// CreateNotify event will be generated. The new window is placed on top in the /// stacking order with respect to siblings. /// /// The coordinate system has the X axis horizontal and the Y axis vertical with /// the origin [0, 0] at the upper-left corner. Coordinates are integral, in terms /// of pixels, and coincide with pixel centers. Each window and pixmap has its own /// coordinate system. For a window, the origin is inside the border at the inside, /// upper-left corner. /// /// The created window is not yet displayed (mapped), call `xcb_map_window` to /// display it. /// /// The created window will initially use the same cursor as its parent. /// /// # Fields /// /// * `wid` - The ID with which you will refer to the new window, created by /// `xcb_generate_id`. /// * `depth` - Specifies the new window's depth (TODO: what unit?). /// /// The special value `XCB_COPY_FROM_PARENT` means the depth is taken from the /// `parent` window. /// * `visual` - Specifies the id for the new window's visual. /// /// The special value `XCB_COPY_FROM_PARENT` means the visual is taken from the /// `parent` window. /// * `class` - /// * `parent` - The parent window of the new window. /// * `border_width` - TODO: /// /// Must be zero if the `class` is `InputOnly` or a `xcb_match_error_t` occurs. /// * `x` - The X coordinate of the new window. /// * `y` - The Y coordinate of the new window. /// * `width` - The width of the new window. /// * `height` - The height of the new window. /// /// # Errors /// /// * `Colormap` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Cursor` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Window` - TODO: reasons? /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # See /// /// * `xcb_generate_id`: function /// * `MapWindow`: request /// * `CreateNotify`: event fn create_window<'c, 'input>(&'c self, depth: u8, wid: Window, parent: Window, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: WindowClass, visual: Visualid, value_list: &'input CreateWindowAux) -> Result, ConnectionError> { create_window(self, depth, wid, parent, x, y, width, height, border_width, class, visual, value_list) } /// change window attributes. /// /// Changes the attributes specified by `value_mask` for the specified `window`. /// /// # Fields /// /// * `window` - The window to change. /// * `value_mask` - /// * `value_list` - Values for each of the attributes specified in the bitmask `value_mask`. The /// order has to correspond to the order of possible `value_mask` bits. See the /// example. /// /// # Errors /// /// * `Access` - TODO: reasons? /// * `Colormap` - TODO: reasons? /// * `Cursor` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. fn change_window_attributes<'c, 'input>(&'c self, window: Window, value_list: &'input ChangeWindowAttributesAux) -> Result, ConnectionError> { change_window_attributes(self, window, value_list) } /// Gets window attributes. /// /// Gets the current attributes for the specified `window`. /// /// # Fields /// /// * `window` - The window to get the attributes from. /// /// # Errors /// /// * `Window` - The specified `window` does not exist. /// * `Drawable` - TODO: reasons? fn get_window_attributes(&self, window: Window) -> Result, ConnectionError> { get_window_attributes(self, window) } /// Destroys a window. /// /// Destroys the specified window and all of its subwindows. A DestroyNotify event /// is generated for each destroyed window (a DestroyNotify event is first generated /// for any given window's inferiors). If the window was mapped, it will be /// automatically unmapped before destroying. /// /// Calling DestroyWindow on the root window will do nothing. /// /// # Fields /// /// * `window` - The window to destroy. /// /// # Errors /// /// * `Window` - The specified window does not exist. /// /// # See /// /// * `DestroyNotify`: event /// * `MapWindow`: request /// * `UnmapWindow`: request fn destroy_window(&self, window: Window) -> Result, ConnectionError> { destroy_window(self, window) } fn destroy_subwindows(&self, window: Window) -> Result, ConnectionError> { destroy_subwindows(self, window) } /// Changes a client's save set. /// /// TODO: explain what the save set is for. /// /// This function either adds or removes the specified window to the client's (your /// application's) save set. /// /// # Fields /// /// * `mode` - Insert to add the specified window to the save set or Delete to delete it from the save set. /// * `window` - The window to add or delete to/from your save set. /// /// # Errors /// /// * `Match` - You created the specified window. This does not make sense, you can only add /// windows created by other clients to your save set. /// * `Value` - You specified an invalid mode. /// * `Window` - The specified window does not exist. /// /// # See /// /// * `ReparentWindow`: request fn change_save_set(&self, mode: SetMode, window: Window) -> Result, ConnectionError> { change_save_set(self, mode, window) } /// Reparents a window. /// /// Makes the specified window a child of the specified parent window. If the /// window is mapped, it will automatically be unmapped before reparenting and /// re-mapped after reparenting. The window is placed in the stacking order on top /// with respect to sibling windows. /// /// After reparenting, a ReparentNotify event is generated. /// /// # Fields /// /// * `window` - The window to reparent. /// * `parent` - The new parent of the window. /// * `x` - The X position of the window within its new parent. /// * `y` - The Y position of the window within its new parent. /// /// # Errors /// /// * `Match` - The new parent window is not on the same screen as the old parent window. /// /// The new parent window is the specified window or an inferior of the specified window. /// /// The new parent is InputOnly and the window is not. /// /// The specified window has a ParentRelative background and the new parent window is not the same depth as the specified window. /// * `Window` - The specified window does not exist. /// /// # See /// /// * `ReparentNotify`: event /// * `MapWindow`: request /// * `UnmapWindow`: request fn reparent_window(&self, window: Window, parent: Window, x: i16, y: i16) -> Result, ConnectionError> { reparent_window(self, window, parent, x, y) } /// Makes a window visible. /// /// Maps the specified window. This means making the window visible (as long as its /// parent is visible). /// /// This MapWindow request will be translated to a MapRequest request if a window /// manager is running. The window manager then decides to either map the window or /// not. Set the override-redirect window attribute to true if you want to bypass /// this mechanism. /// /// If the window manager decides to map the window (or if no window manager is /// running), a MapNotify event is generated. /// /// If the window becomes viewable and no earlier contents for it are remembered, /// the X server tiles the window with its background. If the window's background /// is undefined, the existing screen contents are not altered, and the X server /// generates zero or more Expose events. /// /// If the window type is InputOutput, an Expose event will be generated when the /// window becomes visible. The normal response to an Expose event should be to /// repaint the window. /// /// # Fields /// /// * `window` - The window to make visible. /// /// # Errors /// /// * `Match` - The specified window does not exist. /// /// # See /// /// * `MapNotify`: event /// * `Expose`: event /// * `UnmapWindow`: request fn map_window(&self, window: Window) -> Result, ConnectionError> { map_window(self, window) } fn map_subwindows(&self, window: Window) -> Result, ConnectionError> { map_subwindows(self, window) } /// Makes a window invisible. /// /// Unmaps the specified window. This means making the window invisible (and all /// its child windows). /// /// Unmapping a window leads to the `UnmapNotify` event being generated. Also, /// `Expose` events are generated for formerly obscured windows. /// /// # Fields /// /// * `window` - The window to make invisible. /// /// # Errors /// /// * `Window` - The specified window does not exist. /// /// # See /// /// * `UnmapNotify`: event /// * `Expose`: event /// * `MapWindow`: request fn unmap_window(&self, window: Window) -> Result, ConnectionError> { unmap_window(self, window) } fn unmap_subwindows(&self, window: Window) -> Result, ConnectionError> { unmap_subwindows(self, window) } /// Configures window attributes. /// /// Configures a window's size, position, border width and stacking order. /// /// # Fields /// /// * `window` - The window to configure. /// * `value_mask` - Bitmask of attributes to change. /// * `value_list` - New values, corresponding to the attributes in value_mask. The order has to /// correspond to the order of possible `value_mask` bits. See the example. /// /// # Errors /// /// * `Match` - You specified a Sibling without also specifying StackMode or the window is not /// actually a Sibling. /// * `Window` - The specified window does not exist. TODO: any other reason? /// * `Value` - TODO: reasons? /// /// # See /// /// * `MapNotify`: event /// * `Expose`: event /// /// # Example /// /// ```text /// /* /// * Configures the given window to the left upper corner /// * with a size of 1024x768 pixels. /// * /// */ /// void my_example(xcb_connection_t *c, xcb_window_t window) { /// uint16_t mask = 0; /// /// mask |= XCB_CONFIG_WINDOW_X; /// mask |= XCB_CONFIG_WINDOW_Y; /// mask |= XCB_CONFIG_WINDOW_WIDTH; /// mask |= XCB_CONFIG_WINDOW_HEIGHT; /// /// const uint32_t values[] = { /// 0, /* x */ /// 0, /* y */ /// 1024, /* width */ /// 768 /* height */ /// }; /// /// xcb_configure_window(c, window, mask, values); /// xcb_flush(c); /// } /// ``` fn configure_window<'c, 'input>(&'c self, window: Window, value_list: &'input ConfigureWindowAux) -> Result, ConnectionError> { configure_window(self, window, value_list) } /// Change window stacking order. /// /// If `direction` is `XCB_CIRCULATE_RAISE_LOWEST`, the lowest mapped child (if /// any) will be raised to the top of the stack. /// /// If `direction` is `XCB_CIRCULATE_LOWER_HIGHEST`, the highest mapped child will /// be lowered to the bottom of the stack. /// /// # Fields /// /// * `direction` - /// * `window` - The window to raise/lower (depending on `direction`). /// /// # Errors /// /// * `Window` - The specified `window` does not exist. /// * `Value` - The specified `direction` is invalid. fn circulate_window(&self, direction: Circulate, window: Window) -> Result, ConnectionError> { circulate_window(self, direction, window) } /// Get current window geometry. /// /// Gets the current geometry of the specified drawable (either `Window` or `Pixmap`). /// /// # Fields /// /// * `drawable` - The drawable (`Window` or `Pixmap`) of which the geometry will be received. /// /// # Errors /// /// * `Drawable` - TODO: reasons? /// * `Window` - TODO: reasons? /// /// # See /// /// * `xwininfo`: program /// /// # Example /// /// ```text /// /* /// * Displays the x and y position of the given window. /// * /// */ /// void my_example(xcb_connection_t *c, xcb_window_t window) { /// xcb_get_geometry_cookie_t cookie; /// xcb_get_geometry_reply_t *reply; /// /// cookie = xcb_get_geometry(c, window); /// /* ... do other work here if possible ... */ /// if ((reply = xcb_get_geometry_reply(c, cookie, NULL))) { /// printf("This window is at %d, %d\\n", reply->x, reply->y); /// } /// free(reply); /// } /// ``` fn get_geometry(&self, drawable: Drawable) -> Result, ConnectionError> { get_geometry(self, drawable) } /// query the window tree. /// /// Gets the root window ID, parent window ID and list of children windows for the /// specified `window`. The children are listed in bottom-to-top stacking order. /// /// # Fields /// /// * `window` - The `window` to query. /// /// # See /// /// * `xwininfo`: program /// /// # Example /// /// ```text /// /* /// * Displays the root, parent and children of the specified window. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_window_t window) { /// xcb_query_tree_cookie_t cookie; /// xcb_query_tree_reply_t *reply; /// /// cookie = xcb_query_tree(conn, window); /// if ((reply = xcb_query_tree_reply(conn, cookie, NULL))) { /// printf("root = 0x%08x\\n", reply->root); /// printf("parent = 0x%08x\\n", reply->parent); /// /// xcb_window_t *children = xcb_query_tree_children(reply); /// for (int i = 0; i < xcb_query_tree_children_length(reply); i++) /// printf("child window = 0x%08x\\n", children[i]); /// /// free(reply); /// } /// } /// ``` fn query_tree(&self, window: Window) -> Result, ConnectionError> { query_tree(self, window) } /// Get atom identifier by name. /// /// Retrieves the identifier (xcb_atom_t TODO) for the atom with the specified /// name. Atoms are used in protocols like EWMH, for example to store window titles /// (`_NET_WM_NAME` atom) as property of a window. /// /// If `only_if_exists` is 0, the atom will be created if it does not already exist. /// If `only_if_exists` is 1, `XCB_ATOM_NONE` will be returned if the atom does /// not yet exist. /// /// # Fields /// /// * `name_len` - The length of the following `name`. /// * `name` - The name of the atom. /// * `only_if_exists` - Return a valid atom id only if the atom already exists. /// /// # Errors /// /// * `Alloc` - TODO: reasons? /// * `Value` - A value other than 0 or 1 was specified for `only_if_exists`. /// /// # See /// /// * `xlsatoms`: program /// * `GetAtomName`: request /// /// # Example /// /// ```text /// /* /// * Resolves the _NET_WM_NAME atom. /// * /// */ /// void my_example(xcb_connection_t *c) { /// xcb_intern_atom_cookie_t cookie; /// xcb_intern_atom_reply_t *reply; /// /// cookie = xcb_intern_atom(c, 0, strlen("_NET_WM_NAME"), "_NET_WM_NAME"); /// /* ... do other work here if possible ... */ /// if ((reply = xcb_intern_atom_reply(c, cookie, NULL))) { /// printf("The _NET_WM_NAME atom has ID %u\n", reply->atom); /// free(reply); /// } /// } /// ``` fn intern_atom<'c, 'input>(&'c self, only_if_exists: bool, name: &'input [u8]) -> Result, ConnectionError> { intern_atom(self, only_if_exists, name) } fn get_atom_name(&self, atom: Atom) -> Result, ConnectionError> { get_atom_name(self, atom) } /// Changes a window property. /// /// Sets or updates a property on the specified `window`. Properties are for /// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). /// Protocols such as EWMH also use properties - for example EWMH defines the /// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. /// /// # Fields /// /// * `window` - The window whose property you want to change. /// * `mode` - /// * `property` - The property you want to change (an atom). /// * `type` - The type of the property you want to change (an atom). /// * `format` - Specifies whether the data should be viewed as a list of 8-bit, 16-bit or /// 32-bit quantities. Possible values are 8, 16 and 32. This information allows /// the X server to correctly perform byte-swap operations as necessary. /// * `data_len` - Specifies the number of elements (see `format`). /// * `data` - The property data. /// /// # Errors /// /// * `Match` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. /// * `Atom` - `property` or `type` do not refer to a valid atom. /// * `Alloc` - The X server could not store the property (no memory?). /// /// # See /// /// * `InternAtom`: request /// * `xprop`: program /// /// # Example /// /// ```text /// /* /// * Sets the WM_NAME property of the window to "XCB Example". /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_window_t window) { /// xcb_change_property(conn, /// XCB_PROP_MODE_REPLACE, /// window, /// XCB_ATOM_WM_NAME, /// XCB_ATOM_STRING, /// 8, /// strlen("XCB Example"), /// "XCB Example"); /// xcb_flush(conn); /// } /// ``` fn change_property<'c, 'input, A, B>(&'c self, mode: PropMode, window: Window, property: A, type_: B, format: u8, data_len: u32, data: &'input [u8]) -> Result, ConnectionError> where A: Into, B: Into, { change_property(self, mode, window, property, type_, format, data_len, data) } fn delete_property(&self, window: Window, property: Atom) -> Result, ConnectionError> { delete_property(self, window, property) } /// Gets a window property. /// /// Gets the specified `property` from the specified `window`. Properties are for /// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). /// Protocols such as EWMH also use properties - for example EWMH defines the /// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. /// /// TODO: talk about `type` /// /// TODO: talk about `delete` /// /// TODO: talk about the offset/length thing. what's a valid use case? /// /// # Fields /// /// * `window` - The window whose property you want to get. /// * `delete` - Whether the property should actually be deleted. For deleting a property, the /// specified `type` has to match the actual property type. /// * `property` - The property you want to get (an atom). /// * `type` - The type of the property you want to get (an atom). /// * `long_offset` - Specifies the offset (in 32-bit multiples) in the specified property where the /// data is to be retrieved. /// * `long_length` - Specifies how many 32-bit multiples of data should be retrieved (e.g. if you /// set `long_length` to 4, you will receive 16 bytes of data). /// /// # Errors /// /// * `Window` - The specified `window` does not exist. /// * `Atom` - `property` or `type` do not refer to a valid atom. /// * `Value` - The specified `long_offset` is beyond the actual property length (e.g. the /// property has a length of 3 bytes and you are setting `long_offset` to 1, /// resulting in a byte offset of 4). /// /// # See /// /// * `InternAtom`: request /// * `xprop`: program /// /// # Example /// /// ```text /// /* /// * Prints the WM_NAME property of the window. /// * /// */ /// void my_example(xcb_connection_t *c, xcb_window_t window) { /// xcb_get_property_cookie_t cookie; /// xcb_get_property_reply_t *reply; /// /// /* These atoms are predefined in the X11 protocol. */ /// xcb_atom_t property = XCB_ATOM_WM_NAME; /// xcb_atom_t type = XCB_ATOM_STRING; /// /// // TODO: a reasonable long_length for WM_NAME? /// cookie = xcb_get_property(c, 0, window, property, type, 0, 0); /// if ((reply = xcb_get_property_reply(c, cookie, NULL))) { /// int len = xcb_get_property_value_length(reply); /// if (len == 0) { /// printf("TODO\\n"); /// free(reply); /// return; /// } /// printf("WM_NAME is %.*s\\n", len, /// (char*)xcb_get_property_value(reply)); /// } /// free(reply); /// } /// ``` fn get_property(&self, delete: bool, window: Window, property: A, type_: B, long_offset: u32, long_length: u32) -> Result, ConnectionError> where A: Into, B: Into, { get_property(self, delete, window, property, type_, long_offset, long_length) } fn list_properties(&self, window: Window) -> Result, ConnectionError> { list_properties(self, window) } /// Sets the owner of a selection. /// /// Makes `window` the owner of the selection `selection` and updates the /// last-change time of the specified selection. /// /// TODO: briefly explain what a selection is. /// /// # Fields /// /// * `selection` - The selection. /// * `owner` - The new owner of the selection. /// /// The special value `XCB_NONE` means that the selection will have no owner. /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The selection will not be changed if `time` is earlier than the current /// last-change time of the `selection` or is later than the current X server time. /// Otherwise, the last-change time is set to the specified time. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// /// # Errors /// /// * `Atom` - `selection` does not refer to a valid atom. /// /// # See /// /// * `SetSelectionOwner`: request fn set_selection_owner(&self, owner: A, selection: Atom, time: B) -> Result, ConnectionError> where A: Into, B: Into, { set_selection_owner(self, owner, selection, time) } /// Gets the owner of a selection. /// /// Gets the owner of the specified selection. /// /// TODO: briefly explain what a selection is. /// /// # Fields /// /// * `selection` - The selection. /// /// # Errors /// /// * `Atom` - `selection` does not refer to a valid atom. /// /// # See /// /// * `SetSelectionOwner`: request fn get_selection_owner(&self, selection: Atom) -> Result, ConnectionError> { get_selection_owner(self, selection) } fn convert_selection(&self, requestor: Window, selection: Atom, target: Atom, property: A, time: B) -> Result, ConnectionError> where A: Into, B: Into, { convert_selection(self, requestor, selection, target, property, time) } /// send an event. /// /// Identifies the `destination` window, determines which clients should receive /// the specified event and ignores any active grabs. /// /// The `event` must be one of the core events or an event defined by an extension, /// so that the X server can correctly byte-swap the contents as necessary. The /// contents of `event` are otherwise unaltered and unchecked except for the /// `send_event` field which is forced to 'true'. /// /// # Fields /// /// * `destination` - The window to send this event to. Every client which selects any event within /// `event_mask` on `destination` will get the event. /// /// The special value `XCB_SEND_EVENT_DEST_POINTER_WINDOW` refers to the window /// that contains the mouse pointer. /// /// The special value `XCB_SEND_EVENT_DEST_ITEM_FOCUS` refers to the window which /// has the keyboard focus. /// * `event_mask` - Event_mask for determining which clients should receive the specified event. /// See `destination` and `propagate`. /// * `propagate` - If `propagate` is true and no clients have selected any event on `destination`, /// the destination is replaced with the closest ancestor of `destination` for /// which some client has selected a type in `event_mask` and for which no /// intervening window has that type in its do-not-propagate-mask. If no such /// window exists or if the window is an ancestor of the focus window and /// `InputFocus` was originally specified as the destination, the event is not sent /// to any clients. Otherwise, the event is reported to every client selecting on /// the final destination any of the types specified in `event_mask`. /// * `event` - The event to send to the specified `destination`. /// /// # Errors /// /// * `Window` - The specified `destination` window does not exist. /// * `Value` - The given `event` is neither a core event nor an event defined by an extension. /// /// # See /// /// * `ConfigureNotify`: event /// /// # Example /// /// ```text /// /* /// * Tell the given window that it was configured to a size of 800x600 pixels. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_window_t window) { /// /* Every X11 event is 32 bytes long. Therefore, XCB will copy 32 bytes. /// * In order to properly initialize these bytes, we allocate 32 bytes even /// * though we only need less for an xcb_configure_notify_event_t */ /// xcb_configure_notify_event_t *event = calloc(32, 1); /// /// event->event = window; /// event->window = window; /// event->response_type = XCB_CONFIGURE_NOTIFY; /// /// event->x = 0; /// event->y = 0; /// event->width = 800; /// event->height = 600; /// /// event->border_width = 0; /// event->above_sibling = XCB_NONE; /// event->override_redirect = false; /// /// xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, /// (char*)event); /// xcb_flush(conn); /// free(event); /// } /// ``` fn send_event(&self, propagate: bool, destination: A, event_mask: EventMask, event: B) -> Result, ConnectionError> where A: Into, B: Into<[u8; 32]>, { send_event(self, propagate, destination, event_mask, event) } /// Grab the pointer. /// /// Actively grabs control of the pointer. Further pointer events are reported only to the grabbing client. Overrides any active pointer grab by this client. /// /// # Fields /// /// * `event_mask` - Specifies which pointer events are reported to the client. /// /// TODO: which values? /// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to /// move the pointer out of that window). /// /// The special value `XCB_NONE` means don't confine the pointer. /// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the /// cursor. /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the pointer should be grabbed. /// * `time` - The time argument allows you to avoid certain circumstances that come up if /// applications take a long time to respond or if there are long network delays. /// Consider a situation where you have two applications, both of which normally /// grab the pointer when clicked on. If both applications specify the timestamp /// from the event, the second application may wake up faster and successfully grab /// the pointer before the first application. The first application then will get /// an indication that the other application grabbed the pointer before its request /// was processed. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// * `pointer_mode` - /// * `keyboard_mode` - /// /// # Errors /// /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. /// /// # See /// /// * `GrabKeyboard`: request /// /// # Example /// /// ```text /// /* /// * Grabs the pointer actively /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { /// xcb_grab_pointer_cookie_t cookie; /// xcb_grab_pointer_reply_t *reply; /// /// cookie = xcb_grab_pointer( /// conn, /// false, /* get all pointer events specified by the following mask */ /// screen->root, /* grab the root window */ /// XCB_NONE, /* which events to let through */ /// XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */ /// XCB_GRAB_MODE_ASYNC, /* keyboard mode */ /// XCB_NONE, /* confine_to = in which window should the cursor stay */ /// cursor, /* we change the cursor to whatever the user wanted */ /// XCB_CURRENT_TIME /// ); /// /// if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL))) { /// if (reply->status == XCB_GRAB_STATUS_SUCCESS) /// printf("successfully grabbed the pointer\\n"); /// free(reply); /// } /// } /// ``` fn grab_pointer(&self, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, time: C) -> Result, ConnectionError> where A: Into, B: Into, C: Into, { grab_pointer(self, owner_events, grab_window, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time) } /// release the pointer. /// /// Releases the pointer and any queued events if you actively grabbed the pointer /// before using `xcb_grab_pointer`, `xcb_grab_button` or within a normal button /// press. /// /// EnterNotify and LeaveNotify events are generated. /// /// # Fields /// /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The pointer will not be released if `time` is earlier than the /// last-pointer-grab time or later than the current X server time. /// * `name_len` - Length (in bytes) of `name`. /// * `name` - A pattern describing an X core font. /// /// # See /// /// * `GrabPointer`: request /// * `GrabButton`: request /// * `EnterNotify`: event /// * `LeaveNotify`: event fn ungrab_pointer(&self, time: A) -> Result, ConnectionError> where A: Into, { ungrab_pointer(self, time) } /// Grab pointer button(s). /// /// This request establishes a passive grab. The pointer is actively grabbed as /// described in GrabPointer, the last-pointer-grab time is set to the time at /// which the button was pressed (as transmitted in the ButtonPress event), and the /// ButtonPress event is reported if all of the following conditions are true: /// /// The pointer is not grabbed and the specified button is logically pressed when /// the specified modifier keys are logically down, and no other buttons or /// modifier keys are logically down. /// /// The grab-window contains the pointer. /// /// The confine-to window (if any) is viewable. /// /// A passive grab on the same button/key combination does not exist on any /// ancestor of grab-window. /// /// The interpretation of the remaining arguments is the same as for GrabPointer. /// The active grab is terminated automatically when the logical state of the /// pointer has all buttons released, independent of the logical state of modifier /// keys. Note that the logical state of a device (as seen by means of the /// protocol) may lag the physical state if device event processing is frozen. This /// request overrides all previous passive grabs by the same client on the same /// button/key combinations on the same window. A modifier of AnyModifier is /// equivalent to issuing the request for all possible modifier combinations /// (including the combination of no modifiers). It is not required that all /// specified modifiers have currently assigned keycodes. A button of AnyButton is /// equivalent to issuing the request for all possible buttons. Otherwise, it is /// not required that the button specified currently be assigned to a physical /// button. /// /// An Access error is generated if some other client has already issued a /// GrabButton request with the same button/key combination on the same window. /// When using AnyModifier or AnyButton, the request fails completely (no grabs are /// established), and an Access error is generated if there is a conflicting grab /// for any combination. The request has no effect on an active grab. /// /// # Fields /// /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the pointer should be grabbed. /// * `event_mask` - Specifies which pointer events are reported to the client. /// /// TODO: which values? /// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to /// move the pointer out of that window). /// /// The special value `XCB_NONE` means don't confine the pointer. /// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the /// cursor. /// * `modifiers` - The modifiers to grab. /// /// Using the special value `XCB_MOD_MASK_ANY` means grab the pointer with all /// possible modifier combinations. /// * `pointer_mode` - /// * `keyboard_mode` - /// * `button` - /// /// # Errors /// /// * `Access` - Another client has already issued a GrabButton with the same button/key /// combination on the same window. /// * `Value` - TODO: reasons? /// * `Cursor` - The specified `cursor` does not exist. /// * `Window` - The specified `window` does not exist. fn grab_button(&self, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, button: ButtonIndex, modifiers: ModMask) -> Result, ConnectionError> where A: Into, B: Into, { grab_button(self, owner_events, grab_window, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, button, modifiers) } fn ungrab_button(&self, button: ButtonIndex, grab_window: Window, modifiers: ModMask) -> Result, ConnectionError> { ungrab_button(self, button, grab_window, modifiers) } fn change_active_pointer_grab(&self, cursor: A, time: B, event_mask: EventMask) -> Result, ConnectionError> where A: Into, B: Into, { change_active_pointer_grab(self, cursor, time, event_mask) } /// Grab the keyboard. /// /// Actively grabs control of the keyboard and generates FocusIn and FocusOut /// events. Further key events are reported only to the grabbing client. /// /// Any active keyboard grab by this client is overridden. If the keyboard is /// actively grabbed by some other client, `AlreadyGrabbed` is returned. If /// `grab_window` is not viewable, `GrabNotViewable` is returned. If the keyboard /// is frozen by an active grab of another client, `GrabFrozen` is returned. If the /// specified `time` is earlier than the last-keyboard-grab time or later than the /// current X server time, `GrabInvalidTime` is returned. Otherwise, the /// last-keyboard-grab time is set to the specified time. /// /// # Fields /// /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the pointer should be grabbed. /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// * `pointer_mode` - /// * `keyboard_mode` - /// /// # Errors /// /// * `Value` - TODO: reasons? /// * `Window` - The specified `window` does not exist. /// /// # See /// /// * `GrabPointer`: request /// /// # Example /// /// ```text /// /* /// * Grabs the keyboard actively /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_screen_t *screen) { /// xcb_grab_keyboard_cookie_t cookie; /// xcb_grab_keyboard_reply_t *reply; /// /// cookie = xcb_grab_keyboard( /// conn, /// true, /* report events */ /// screen->root, /* grab the root window */ /// XCB_CURRENT_TIME, /// XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ /// XCB_GRAB_MODE_ASYNC /// ); /// /// if ((reply = xcb_grab_keyboard_reply(conn, cookie, NULL))) { /// if (reply->status == XCB_GRAB_STATUS_SUCCESS) /// printf("successfully grabbed the keyboard\\n"); /// /// free(reply); /// } /// } /// ``` fn grab_keyboard(&self, owner_events: bool, grab_window: Window, time: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Result, ConnectionError> where A: Into, { grab_keyboard(self, owner_events, grab_window, time, pointer_mode, keyboard_mode) } fn ungrab_keyboard(&self, time: A) -> Result, ConnectionError> where A: Into, { ungrab_keyboard(self, time) } /// Grab keyboard key(s). /// /// Establishes a passive grab on the keyboard. In the future, the keyboard is /// actively grabbed (as for `GrabKeyboard`), the last-keyboard-grab time is set to /// the time at which the key was pressed (as transmitted in the KeyPress event), /// and the KeyPress event is reported if all of the following conditions are true: /// /// The keyboard is not grabbed and the specified key (which can itself be a /// modifier key) is logically pressed when the specified modifier keys are /// logically down, and no other modifier keys are logically down. /// /// Either the grab_window is an ancestor of (or is) the focus window, or the /// grab_window is a descendant of the focus window and contains the pointer. /// /// A passive grab on the same key combination does not exist on any ancestor of /// grab_window. /// /// The interpretation of the remaining arguments is as for XGrabKeyboard. The active grab is terminated /// automatically when the logical state of the keyboard has the specified key released (independent of the /// logical state of the modifier keys), at which point a KeyRelease event is reported to the grabbing window. /// /// Note that the logical state of a device (as seen by client applications) may lag the physical state if /// device event processing is frozen. /// /// A modifiers argument of AnyModifier is equivalent to issuing the request for all possible modifier combinations (including the combination of no modifiers). It is not required that all modifiers specified /// have currently assigned KeyCodes. A keycode argument of AnyKey is equivalent to issuing the request for /// all possible KeyCodes. Otherwise, the specified keycode must be in the range specified by min_keycode /// and max_keycode in the connection setup, or a BadValue error results. /// /// If some other client has issued a XGrabKey with the same key combination on the same window, a BadAccess /// error results. When using AnyModifier or AnyKey, the request fails completely, and a BadAccess error /// results (no grabs are established) if there is a conflicting grab for any combination. /// /// # Fields /// /// * `owner_events` - If 1, the `grab_window` will still get the key events. If 0, events are not /// reported to the `grab_window`. /// * `grab_window` - Specifies the window on which the key should be grabbed. /// * `key` - The keycode of the key to grab. /// /// The special value `XCB_GRAB_ANY` means grab any key. /// * `modifiers` - The modifiers to grab. /// /// Using the special value `XCB_MOD_MASK_ANY` means grab the key with all /// possible modifier combinations. /// * `pointer_mode` - /// * `keyboard_mode` - /// /// # Errors /// /// * `Access` - Another client has already issued a GrabKey with the same button/key /// combination on the same window. /// * `Value` - The key is not `XCB_GRAB_ANY` and not in the range specified by `min_keycode` /// and `max_keycode` in the connection setup. /// * `Window` - The specified `window` does not exist. /// /// # See /// /// * `GrabKeyboard`: request fn grab_key(&self, owner_events: bool, grab_window: Window, modifiers: ModMask, key: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Result, ConnectionError> where A: Into, { grab_key(self, owner_events, grab_window, modifiers, key, pointer_mode, keyboard_mode) } /// release a key combination. /// /// Releases the key combination on `grab_window` if you grabbed it using /// `xcb_grab_key` before. /// /// # Fields /// /// * `key` - The keycode of the specified key combination. /// /// Using the special value `XCB_GRAB_ANY` means releasing all possible key codes. /// * `grab_window` - The window on which the grabbed key combination will be released. /// * `modifiers` - The modifiers of the specified key combination. /// /// Using the special value `XCB_MOD_MASK_ANY` means releasing the key combination /// with every possible modifier combination. /// /// # Errors /// /// * `Window` - The specified `grab_window` does not exist. /// * `Value` - TODO: reasons? /// /// # See /// /// * `GrabKey`: request /// * `xev`: program fn ungrab_key(&self, key: A, grab_window: Window, modifiers: ModMask) -> Result, ConnectionError> where A: Into, { ungrab_key(self, key, grab_window, modifiers) } /// release queued events. /// /// Releases queued events if the client has caused a device (pointer/keyboard) to /// freeze due to grabbing it actively. This request has no effect if `time` is /// earlier than the last-grab time of the most recent active grab for this client /// or if `time` is later than the current X server time. /// /// # Fields /// /// * `mode` - /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// /// # Errors /// /// * `Value` - You specified an invalid `mode`. fn allow_events(&self, mode: Allow, time: A) -> Result, ConnectionError> where A: Into, { allow_events(self, mode, time) } fn grab_server(&self) -> Result, ConnectionError> { grab_server(self) } fn ungrab_server(&self) -> Result, ConnectionError> { ungrab_server(self) } /// get pointer coordinates. /// /// Gets the root window the pointer is logically on and the pointer coordinates /// relative to the root window's origin. /// /// # Fields /// /// * `window` - A window to check if the pointer is on the same screen as `window` (see the /// `same_screen` field in the reply). /// /// # Errors /// /// * `Window` - The specified `window` does not exist. fn query_pointer(&self, window: Window) -> Result, ConnectionError> { query_pointer(self, window) } fn get_motion_events(&self, window: Window, start: A, stop: B) -> Result, ConnectionError> where A: Into, B: Into, { get_motion_events(self, window, start, stop) } fn translate_coordinates(&self, src_window: Window, dst_window: Window, src_x: i16, src_y: i16) -> Result, ConnectionError> { translate_coordinates(self, src_window, dst_window, src_x, src_y) } /// move mouse pointer. /// /// Moves the mouse pointer to the specified position. /// /// If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the /// pointer is inside `src_window` and within the rectangle specified by (`src_x`, /// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to /// `src_window`. /// /// If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the /// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is /// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) /// relative to the current position of the pointer. /// /// # Fields /// /// * `src_window` - If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the /// pointer is inside `src_window` and within the rectangle specified by (`src_x`, /// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to /// `src_window`. /// * `dst_window` - If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the /// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is /// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) /// relative to the current position of the pointer. /// /// # Errors /// /// * `Window` - TODO: reasons? /// /// # See /// /// * `SetInputFocus`: request fn warp_pointer(&self, src_window: A, dst_window: B, src_x: i16, src_y: i16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16) -> Result, ConnectionError> where A: Into, B: Into, { warp_pointer(self, src_window, dst_window, src_x, src_y, src_width, src_height, dst_x, dst_y) } /// Sets input focus. /// /// Changes the input focus and the last-focus-change time. If the specified `time` /// is earlier than the current last-focus-change time, the request is ignored (to /// avoid race conditions when running X over the network). /// /// A FocusIn and FocusOut event is generated when focus is changed. /// /// # Fields /// /// * `focus` - The window to focus. All keyboard events will be reported to this window. The /// window must be viewable (TODO), or a `xcb_match_error_t` occurs (TODO). /// /// If `focus` is `XCB_NONE` (TODO), all keyboard events are /// discarded until a new focus window is set. /// /// If `focus` is `XCB_POINTER_ROOT` (TODO), focus is on the root window of the /// screen on which the pointer is on currently. /// * `time` - Timestamp to avoid race conditions when running X over the network. /// /// The special value `XCB_CURRENT_TIME` will be replaced with the current server /// time. /// * `revert_to` - Specifies what happens when the `focus` window becomes unviewable (if `focus` /// is neither `XCB_NONE` nor `XCB_POINTER_ROOT`). /// /// # Errors /// /// * `Window` - The specified `focus` window does not exist. /// * `Match` - The specified `focus` window is not viewable. /// * `Value` - TODO: Reasons? /// /// # See /// /// * `FocusIn`: event /// * `FocusOut`: event fn set_input_focus(&self, revert_to: InputFocus, focus: A, time: B) -> Result, ConnectionError> where A: Into, B: Into, { set_input_focus(self, revert_to, focus, time) } fn get_input_focus(&self) -> Result, ConnectionError> { get_input_focus(self) } fn query_keymap(&self) -> Result, ConnectionError> { query_keymap(self) } /// opens a font. /// /// Opens any X core font matching the given `name` (for example "-misc-fixed-*"). /// /// Note that X core fonts are deprecated (but still supported) in favor of /// client-side rendering using Xft. /// /// # Fields /// /// * `fid` - The ID with which you will refer to the font, created by `xcb_generate_id`. /// * `name_len` - Length (in bytes) of `name`. /// * `name` - A pattern describing an X core font. /// /// # Errors /// /// * `Name` - No font matches the given `name`. /// /// # See /// /// * `xcb_generate_id`: function fn open_font<'c, 'input>(&'c self, fid: Font, name: &'input [u8]) -> Result, ConnectionError> { open_font(self, fid, name) } fn close_font(&self, font: Font) -> Result, ConnectionError> { close_font(self, font) } /// query font metrics. /// /// Queries information associated with the font. /// /// # Fields /// /// * `font` - The fontable (Font or Graphics Context) to query. fn query_font(&self, font: Fontable) -> Result, ConnectionError> { query_font(self, font) } /// get text extents. /// /// Query text extents from the X11 server. This request returns the bounding box /// of the specified 16-bit character string in the specified `font` or the font /// contained in the specified graphics context. /// /// `font_ascent` is set to the maximum of the ascent metrics of all characters in /// the string. `font_descent` is set to the maximum of the descent metrics. /// `overall_width` is set to the sum of the character-width metrics of all /// characters in the string. For each character in the string, let W be the sum of /// the character-width metrics of all characters preceding it in the string. Let L /// be the left-side-bearing metric of the character plus W. Let R be the /// right-side-bearing metric of the character plus W. The lbearing member is set /// to the minimum L of all characters in the string. The rbearing member is set to /// the maximum R. /// /// For fonts defined with linear indexing rather than 2-byte matrix indexing, each /// `xcb_char2b_t` structure is interpreted as a 16-bit number with byte1 as the /// most significant byte. If the font has no defined default character, undefined /// characters in the string are taken to have all zero metrics. /// /// Characters with all zero metrics are ignored. If the font has no defined /// default_char, the undefined characters in the string are also ignored. /// /// # Fields /// /// * `font` - The `font` to calculate text extents in. You can also pass a graphics context. /// * `string_len` - The number of characters in `string`. /// * `string` - The text to get text extents for. /// /// # Errors /// /// * `GContext` - The specified graphics context does not exist. /// * `Font` - The specified `font` does not exist. fn query_text_extents<'c, 'input>(&'c self, font: Fontable, string: &'input [Char2b]) -> Result, ConnectionError> { query_text_extents(self, font, string) } /// get matching font names. /// /// Gets a list of available font names which match the given `pattern`. /// /// # Fields /// /// * `pattern_len` - The length (in bytes) of `pattern`. /// * `pattern` - A font pattern, for example "-misc-fixed-*". /// /// The asterisk (*) is a wildcard for any number of characters. The question mark /// (?) is a wildcard for a single character. Use of uppercase or lowercase does /// not matter. /// * `max_names` - The maximum number of fonts to be returned. fn list_fonts<'c, 'input>(&'c self, max_names: u16, pattern: &'input [u8]) -> Result, ConnectionError> { list_fonts(self, max_names, pattern) } /// get matching font names and information. /// /// Gets a list of available font names which match the given `pattern`. /// /// # Fields /// /// * `pattern_len` - The length (in bytes) of `pattern`. /// * `pattern` - A font pattern, for example "-misc-fixed-*". /// /// The asterisk (*) is a wildcard for any number of characters. The question mark /// (?) is a wildcard for a single character. Use of uppercase or lowercase does /// not matter. /// * `max_names` - The maximum number of fonts to be returned. fn list_fonts_with_info<'c, 'input>(&'c self, max_names: u16, pattern: &'input [u8]) -> Result, ConnectionError> { list_fonts_with_info(self, max_names, pattern) } fn set_font_path<'c, 'input>(&'c self, font: &'input [Str]) -> Result, ConnectionError> { set_font_path(self, font) } fn get_font_path(&self) -> Result, ConnectionError> { get_font_path(self) } /// Creates a pixmap. /// /// Creates a pixmap. The pixmap can only be used on the same screen as `drawable` /// is on and only with drawables of the same `depth`. /// /// # Fields /// /// * `depth` - TODO /// * `pid` - The ID with which you will refer to the new pixmap, created by /// `xcb_generate_id`. /// * `drawable` - Drawable to get the screen from. /// * `width` - The width of the new pixmap. /// * `height` - The height of the new pixmap. /// /// # Errors /// /// * `Value` - TODO: reasons? /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # See /// /// * `xcb_generate_id`: function fn create_pixmap(&self, depth: u8, pid: Pixmap, drawable: Drawable, width: u16, height: u16) -> Result, ConnectionError> { create_pixmap(self, depth, pid, drawable, width, height) } /// Destroys a pixmap. /// /// Deletes the association between the pixmap ID and the pixmap. The pixmap /// storage will be freed when there are no more references to it. /// /// # Fields /// /// * `pixmap` - The pixmap to destroy. /// /// # Errors /// /// * `Pixmap` - The specified pixmap does not exist. fn free_pixmap(&self, pixmap: Pixmap) -> Result, ConnectionError> { free_pixmap(self, pixmap) } /// Creates a graphics context. /// /// Creates a graphics context. The graphics context can be used with any drawable /// that has the same root and depth as the specified drawable. /// /// # Fields /// /// * `cid` - The ID with which you will refer to the graphics context, created by /// `xcb_generate_id`. /// * `drawable` - Drawable to get the root/depth from. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `Match` - TODO: reasons? /// * `Font` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # See /// /// * `xcb_generate_id`: function fn create_gc<'c, 'input>(&'c self, cid: Gcontext, drawable: Drawable, value_list: &'input CreateGCAux) -> Result, ConnectionError> { create_gc(self, cid, drawable, value_list) } /// change graphics context components. /// /// Changes the components specified by `value_mask` for the specified graphics context. /// /// # Fields /// /// * `gc` - The graphics context to change. /// * `value_mask` - /// * `value_list` - Values for each of the components specified in the bitmask `value_mask`. The /// order has to correspond to the order of possible `value_mask` bits. See the /// example. /// /// # Errors /// /// * `Font` - TODO: reasons? /// * `GContext` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Pixmap` - TODO: reasons? /// * `Value` - TODO: reasons? /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// /// # Example /// /// ```text /// /* /// * Changes the foreground color component of the specified graphics context. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_gcontext_t gc, uint32_t fg, uint32_t bg) { /// /* C99 allows us to use a compact way of changing a single component: */ /// xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){ fg }); /// /// /* The more explicit way. Beware that the order of values is important! */ /// uint32_t mask = 0; /// mask |= XCB_GC_FOREGROUND; /// mask |= XCB_GC_BACKGROUND; /// /// uint32_t values[] = { /// fg, /// bg /// }; /// xcb_change_gc(conn, gc, mask, values); /// xcb_flush(conn); /// } /// ``` fn change_gc<'c, 'input>(&'c self, gc: Gcontext, value_list: &'input ChangeGCAux) -> Result, ConnectionError> { change_gc(self, gc, value_list) } fn copy_gc(&self, src_gc: Gcontext, dst_gc: Gcontext, value_mask: GC) -> Result, ConnectionError> { copy_gc(self, src_gc, dst_gc, value_mask) } fn set_dashes<'c, 'input>(&'c self, gc: Gcontext, dash_offset: u16, dashes: &'input [u8]) -> Result, ConnectionError> { set_dashes(self, gc, dash_offset, dashes) } fn set_clip_rectangles<'c, 'input>(&'c self, ordering: ClipOrdering, gc: Gcontext, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [Rectangle]) -> Result, ConnectionError> { set_clip_rectangles(self, ordering, gc, clip_x_origin, clip_y_origin, rectangles) } /// Destroys a graphics context. /// /// Destroys the specified `gc` and all associated storage. /// /// # Fields /// /// * `gc` - The graphics context to destroy. /// /// # Errors /// /// * `GContext` - The specified graphics context does not exist. fn free_gc(&self, gc: Gcontext) -> Result, ConnectionError> { free_gc(self, gc) } fn clear_area(&self, exposures: bool, window: Window, x: i16, y: i16, width: u16, height: u16) -> Result, ConnectionError> { clear_area(self, exposures, window, x, y, width, height) } /// copy areas. /// /// Copies the specified rectangle from `src_drawable` to `dst_drawable`. /// /// # Fields /// /// * `dst_drawable` - The destination drawable (Window or Pixmap). /// * `src_drawable` - The source drawable (Window or Pixmap). /// * `gc` - The graphics context to use. /// * `src_x` - The source X coordinate. /// * `src_y` - The source Y coordinate. /// * `dst_x` - The destination X coordinate. /// * `dst_y` - The destination Y coordinate. /// * `width` - The width of the area to copy (in pixels). /// * `height` - The height of the area to copy (in pixels). /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - `src_drawable` has a different root or depth than `dst_drawable`. fn copy_area(&self, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Result, ConnectionError> { copy_area(self, src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height) } fn copy_plane(&self, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16, bit_plane: u32) -> Result, ConnectionError> { copy_plane(self, src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height, bit_plane) } fn poly_point<'c, 'input>(&'c self, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Result, ConnectionError> { poly_point(self, coordinate_mode, drawable, gc, points) } /// draw lines. /// /// Draws `points_len`-1 lines between each pair of points (point[i], point[i+1]) /// in the `points` array. The lines are drawn in the order listed in the array. /// They join correctly at all intermediate points, and if the first and last /// points coincide, the first and last lines also join correctly. For any given /// line, a pixel is not drawn more than once. If thin (zero line-width) lines /// intersect, the intersecting pixels are drawn multiple times. If wide lines /// intersect, the intersecting pixels are drawn only once, as though the entire /// request were a single, filled shape. /// /// # Fields /// /// * `drawable` - The drawable to draw the line(s) on. /// * `gc` - The graphics context to use. /// * `points_len` - The number of `xcb_point_t` structures in `points`. /// * `points` - An array of points. /// * `coordinate_mode` - /// /// # Errors /// /// * `Drawable` - TODO: reasons? /// * `GContext` - TODO: reasons? /// * `Match` - TODO: reasons? /// * `Value` - TODO: reasons? /// /// # Example /// /// ```text /// /* /// * Draw a straight line. /// * /// */ /// void my_example(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc) { /// xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2, /// (xcb_point_t[]) { {10, 10}, {100, 10} }); /// xcb_flush(conn); /// } /// ``` fn poly_line<'c, 'input>(&'c self, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Result, ConnectionError> { poly_line(self, coordinate_mode, drawable, gc, points) } /// draw lines. /// /// Draws multiple, unconnected lines. For each segment, a line is drawn between /// (x1, y1) and (x2, y2). The lines are drawn in the order listed in the array of /// `xcb_segment_t` structures and does not perform joining at coincident /// endpoints. For any given line, a pixel is not drawn more than once. If lines /// intersect, the intersecting pixels are drawn multiple times. /// /// TODO: include the xcb_segment_t data structure /// /// TODO: an example /// /// # Fields /// /// * `drawable` - A drawable (Window or Pixmap) to draw on. /// * `gc` - The graphics context to use. /// /// TODO: document which attributes of a gc are used /// * `segments_len` - The number of `xcb_segment_t` structures in `segments`. /// * `segments` - An array of `xcb_segment_t` structures. /// /// # Errors /// /// * `Drawable` - The specified `drawable` does not exist. /// * `GContext` - The specified `gc` does not exist. /// * `Match` - TODO: reasons? fn poly_segment<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, segments: &'input [Segment]) -> Result, ConnectionError> { poly_segment(self, drawable, gc, segments) } fn poly_rectangle<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Result, ConnectionError> { poly_rectangle(self, drawable, gc, rectangles) } fn poly_arc<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Result, ConnectionError> { poly_arc(self, drawable, gc, arcs) } fn fill_poly<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, shape: PolyShape, coordinate_mode: CoordMode, points: &'input [Point]) -> Result, ConnectionError> { fill_poly(self, drawable, gc, shape, coordinate_mode, points) } /// Fills rectangles. /// /// Fills the specified rectangle(s) in the order listed in the array. For any /// given rectangle, each pixel is not drawn more than once. If rectangles /// intersect, the intersecting pixels are drawn multiple times. /// /// # Fields /// /// * `drawable` - The drawable (Window or Pixmap) to draw on. /// * `gc` - The graphics context to use. /// /// The following graphics context components are used: function, plane-mask, /// fill-style, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. /// /// The following graphics context mode-dependent components are used: /// foreground, background, tile, stipple, tile-stipple-x-origin, and /// tile-stipple-y-origin. /// * `rectangles_len` - The number of `xcb_rectangle_t` structures in `rectangles`. /// * `rectangles` - The rectangles to fill. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - TODO: reasons? fn poly_fill_rectangle<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Result, ConnectionError> { poly_fill_rectangle(self, drawable, gc, rectangles) } fn poly_fill_arc<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Result, ConnectionError> { poly_fill_arc(self, drawable, gc, arcs) } fn put_image<'c, 'input>(&'c self, format: ImageFormat, drawable: Drawable, gc: Gcontext, width: u16, height: u16, dst_x: i16, dst_y: i16, left_pad: u8, depth: u8, data: &'input [u8]) -> Result, ConnectionError> { put_image(self, format, drawable, gc, width, height, dst_x, dst_y, left_pad, depth, data) } fn get_image(&self, format: ImageFormat, drawable: Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32) -> Result, ConnectionError> { get_image(self, format, drawable, x, y, width, height, plane_mask) } fn poly_text8<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Result, ConnectionError> { poly_text8(self, drawable, gc, x, y, items) } fn poly_text16<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Result, ConnectionError> { poly_text16(self, drawable, gc, x, y, items) } /// Draws text. /// /// Fills the destination rectangle with the background pixel from `gc`, then /// paints the text with the foreground pixel from `gc`. The upper-left corner of /// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, /// the height is font-ascent + font-descent. The overall-width, font-ascent and /// font-descent are as returned by `xcb_query_text_extents` (TODO). /// /// Note that using X core fonts is deprecated (but still supported) in favor of /// client-side rendering using Xft. /// /// # Fields /// /// * `drawable` - The drawable (Window or Pixmap) to draw text on. /// * `string_len` - The length of the `string`. Note that this parameter limited by 255 due to /// using 8 bits! /// * `string` - The string to draw. Only the first 255 characters are relevant due to the data /// type of `string_len`. /// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. /// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. /// * `gc` - The graphics context to use. /// /// The following graphics context components are used: plane-mask, foreground, /// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - TODO: reasons? /// /// # See /// /// * `ImageText16`: request fn image_text8<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [u8]) -> Result, ConnectionError> { image_text8(self, drawable, gc, x, y, string) } /// Draws text. /// /// Fills the destination rectangle with the background pixel from `gc`, then /// paints the text with the foreground pixel from `gc`. The upper-left corner of /// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, /// the height is font-ascent + font-descent. The overall-width, font-ascent and /// font-descent are as returned by `xcb_query_text_extents` (TODO). /// /// Note that using X core fonts is deprecated (but still supported) in favor of /// client-side rendering using Xft. /// /// # Fields /// /// * `drawable` - The drawable (Window or Pixmap) to draw text on. /// * `string_len` - The length of the `string` in characters. Note that this parameter limited by /// 255 due to using 8 bits! /// * `string` - The string to draw. Only the first 255 characters are relevant due to the data /// type of `string_len`. Every character uses 2 bytes (hence the 16 in this /// request's name). /// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. /// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. /// * `gc` - The graphics context to use. /// /// The following graphics context components are used: plane-mask, foreground, /// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. /// /// # Errors /// /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. /// * `GContext` - The specified graphics context does not exist. /// * `Match` - TODO: reasons? /// /// # See /// /// * `ImageText8`: request fn image_text16<'c, 'input>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [Char2b]) -> Result, ConnectionError> { image_text16(self, drawable, gc, x, y, string) } fn create_colormap(&self, alloc: ColormapAlloc, mid: Colormap, window: Window, visual: Visualid) -> Result, ConnectionError> { create_colormap(self, alloc, mid, window, visual) } fn free_colormap(&self, cmap: Colormap) -> Result, ConnectionError> { free_colormap(self, cmap) } fn copy_colormap_and_free(&self, mid: Colormap, src_cmap: Colormap) -> Result, ConnectionError> { copy_colormap_and_free(self, mid, src_cmap) } fn install_colormap(&self, cmap: Colormap) -> Result, ConnectionError> { install_colormap(self, cmap) } fn uninstall_colormap(&self, cmap: Colormap) -> Result, ConnectionError> { uninstall_colormap(self, cmap) } fn list_installed_colormaps(&self, window: Window) -> Result, ConnectionError> { list_installed_colormaps(self, window) } /// Allocate a color. /// /// Allocates a read-only colormap entry corresponding to the closest RGB value /// supported by the hardware. If you are using TrueColor, you can take a shortcut /// and directly calculate the color pixel value to avoid the round trip. But, for /// example, on 16-bit color setups (VNC), you can easily get the closest supported /// RGB value to the RGB value you are specifying. /// /// # Fields /// /// * `cmap` - TODO /// * `red` - The red value of your color. /// * `green` - The green value of your color. /// * `blue` - The blue value of your color. /// /// # Errors /// /// * `Colormap` - The specified colormap `cmap` does not exist. fn alloc_color(&self, cmap: Colormap, red: u16, green: u16, blue: u16) -> Result, ConnectionError> { alloc_color(self, cmap, red, green, blue) } fn alloc_named_color<'c, 'input>(&'c self, cmap: Colormap, name: &'input [u8]) -> Result, ConnectionError> { alloc_named_color(self, cmap, name) } fn alloc_color_cells(&self, contiguous: bool, cmap: Colormap, colors: u16, planes: u16) -> Result, ConnectionError> { alloc_color_cells(self, contiguous, cmap, colors, planes) } fn alloc_color_planes(&self, contiguous: bool, cmap: Colormap, colors: u16, reds: u16, greens: u16, blues: u16) -> Result, ConnectionError> { alloc_color_planes(self, contiguous, cmap, colors, reds, greens, blues) } fn free_colors<'c, 'input>(&'c self, cmap: Colormap, plane_mask: u32, pixels: &'input [u32]) -> Result, ConnectionError> { free_colors(self, cmap, plane_mask, pixels) } fn store_colors<'c, 'input>(&'c self, cmap: Colormap, items: &'input [Coloritem]) -> Result, ConnectionError> { store_colors(self, cmap, items) } fn store_named_color<'c, 'input>(&'c self, flags: ColorFlag, cmap: Colormap, pixel: u32, name: &'input [u8]) -> Result, ConnectionError> { store_named_color(self, flags, cmap, pixel, name) } fn query_colors<'c, 'input>(&'c self, cmap: Colormap, pixels: &'input [u32]) -> Result, ConnectionError> { query_colors(self, cmap, pixels) } fn lookup_color<'c, 'input>(&'c self, cmap: Colormap, name: &'input [u8]) -> Result, ConnectionError> { lookup_color(self, cmap, name) } fn create_cursor(&self, cid: Cursor, source: Pixmap, mask: A, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) -> Result, ConnectionError> where A: Into, { create_cursor(self, cid, source, mask, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, x, y) } /// create cursor. /// /// Creates a cursor from a font glyph. X provides a set of standard cursor shapes /// in a special font named cursor. Applications are encouraged to use this /// interface for their cursors because the font can be customized for the /// individual display type. /// /// All pixels which are set to 1 in the source will use the foreground color (as /// specified by `fore_red`, `fore_green` and `fore_blue`). All pixels set to 0 /// will use the background color (as specified by `back_red`, `back_green` and /// `back_blue`). /// /// # Fields /// /// * `cid` - The ID with which you will refer to the cursor, created by `xcb_generate_id`. /// * `source_font` - In which font to look for the cursor glyph. /// * `mask_font` - In which font to look for the mask glyph. /// * `source_char` - The glyph of `source_font` to use. /// * `mask_char` - The glyph of `mask_font` to use as a mask: Pixels which are set to 1 define /// which source pixels are displayed. All pixels which are set to 0 are not /// displayed. /// * `fore_red` - The red value of the foreground color. /// * `fore_green` - The green value of the foreground color. /// * `fore_blue` - The blue value of the foreground color. /// * `back_red` - The red value of the background color. /// * `back_green` - The green value of the background color. /// * `back_blue` - The blue value of the background color. /// /// # Errors /// /// * `Alloc` - The X server could not allocate the requested resources (no memory?). /// * `Font` - The specified `source_font` or `mask_font` does not exist. /// * `Value` - Either `source_char` or `mask_char` are not defined in `source_font` or `mask_font`, respectively. fn create_glyph_cursor(&self, cid: Cursor, source_font: Font, mask_font: A, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result, ConnectionError> where A: Into, { create_glyph_cursor(self, cid, source_font, mask_font, source_char, mask_char, fore_red, fore_green, fore_blue, back_red, back_green, back_blue) } /// Deletes a cursor. /// /// Deletes the association between the cursor resource ID and the specified /// cursor. The cursor is freed when no other resource references it. /// /// # Fields /// /// * `cursor` - The cursor to destroy. /// /// # Errors /// /// * `Cursor` - The specified cursor does not exist. fn free_cursor(&self, cursor: Cursor) -> Result, ConnectionError> { free_cursor(self, cursor) } fn recolor_cursor(&self, cursor: Cursor, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result, ConnectionError> { recolor_cursor(self, cursor, fore_red, fore_green, fore_blue, back_red, back_green, back_blue) } fn query_best_size(&self, class: QueryShapeOf, drawable: Drawable, width: u16, height: u16) -> Result, ConnectionError> { query_best_size(self, class, drawable, width, height) } /// check if extension is present. /// /// Determines if the specified extension is present on this X11 server. /// /// Every extension has a unique `major_opcode` to identify requests, the minor /// opcodes and request formats are extension-specific. If the extension provides /// events and errors, the `first_event` and `first_error` fields in the reply are /// set accordingly. /// /// There should rarely be a need to use this request directly, XCB provides the /// `xcb_get_extension_data` function instead. /// /// # Fields /// /// * `name_len` - The length of `name` in bytes. /// * `name` - The name of the extension to query, for example "RANDR". This is case /// sensitive! /// /// # See /// /// * `xdpyinfo`: program /// * `xcb_get_extension_data`: function fn query_extension<'c, 'input>(&'c self, name: &'input [u8]) -> Result, ConnectionError> { query_extension(self, name) } fn list_extensions(&self) -> Result, ConnectionError> { list_extensions(self) } fn change_keyboard_mapping<'c, 'input>(&'c self, keycode_count: u8, first_keycode: Keycode, keysyms_per_keycode: u8, keysyms: &'input [Keysym]) -> Result, ConnectionError> { change_keyboard_mapping(self, keycode_count, first_keycode, keysyms_per_keycode, keysyms) } fn get_keyboard_mapping(&self, first_keycode: Keycode, count: u8) -> Result, ConnectionError> { get_keyboard_mapping(self, first_keycode, count) } fn change_keyboard_control<'c, 'input>(&'c self, value_list: &'input ChangeKeyboardControlAux) -> Result, ConnectionError> { change_keyboard_control(self, value_list) } fn get_keyboard_control(&self) -> Result, ConnectionError> { get_keyboard_control(self) } fn bell(&self, percent: i8) -> Result, ConnectionError> { bell(self, percent) } fn change_pointer_control(&self, acceleration_numerator: i16, acceleration_denominator: i16, threshold: i16, do_acceleration: bool, do_threshold: bool) -> Result, ConnectionError> { change_pointer_control(self, acceleration_numerator, acceleration_denominator, threshold, do_acceleration, do_threshold) } fn get_pointer_control(&self) -> Result, ConnectionError> { get_pointer_control(self) } fn set_screen_saver(&self, timeout: i16, interval: i16, prefer_blanking: Blanking, allow_exposures: Exposures) -> Result, ConnectionError> { set_screen_saver(self, timeout, interval, prefer_blanking, allow_exposures) } fn get_screen_saver(&self) -> Result, ConnectionError> { get_screen_saver(self) } fn change_hosts<'c, 'input>(&'c self, mode: HostMode, family: Family, address: &'input [u8]) -> Result, ConnectionError> { change_hosts(self, mode, family, address) } fn list_hosts(&self) -> Result, ConnectionError> { list_hosts(self) } fn set_access_control(&self, mode: AccessControl) -> Result, ConnectionError> { set_access_control(self, mode) } fn set_close_down_mode(&self, mode: CloseDown) -> Result, ConnectionError> { set_close_down_mode(self, mode) } /// kills a client. /// /// Forces a close down of the client that created the specified `resource`. /// /// # Fields /// /// * `resource` - Any resource belonging to the client (for example a Window), used to identify /// the client connection. /// /// The special value of `XCB_KILL_ALL_TEMPORARY`, the resources of all clients /// that have terminated in `RetainTemporary` (TODO) are destroyed. /// /// # Errors /// /// * `Value` - The specified `resource` does not exist. /// /// # See /// /// * `xkill`: program fn kill_client(&self, resource: A) -> Result, ConnectionError> where A: Into, { kill_client(self, resource) } fn rotate_properties<'c, 'input>(&'c self, window: Window, delta: i16, atoms: &'input [Atom]) -> Result, ConnectionError> { rotate_properties(self, window, delta, atoms) } fn force_screen_saver(&self, mode: ScreenSaver) -> Result, ConnectionError> { force_screen_saver(self, mode) } fn set_pointer_mapping<'c, 'input>(&'c self, map: &'input [u8]) -> Result, ConnectionError> { set_pointer_mapping(self, map) } fn get_pointer_mapping(&self) -> Result, ConnectionError> { get_pointer_mapping(self) } fn set_modifier_mapping<'c, 'input>(&'c self, keycodes: &'input [Keycode]) -> Result, ConnectionError> { set_modifier_mapping(self, keycodes) } fn get_modifier_mapping(&self) -> Result, ConnectionError> { get_modifier_mapping(self) } fn no_operation(&self) -> Result, ConnectionError> { no_operation(self) } } impl ConnectionExt for C {} /// A RAII-like wrapper around a [Pixmap]. /// /// Instances of this struct represent a Pixmap 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 PixmapWrapper(C, Pixmap); impl PixmapWrapper { /// Assume ownership of the given resource and destroy it in `Drop`. pub fn for_pixmap(conn: C, id: Pixmap) -> Self { PixmapWrapper(conn, id) } /// Get the XID of the wrapped resource pub fn pixmap(&self) -> Pixmap { self.1 } /// Assume ownership of the XID of the wrapped resource /// /// This function destroys this wrapper without freeing the underlying resource. pub fn into_pixmap(self) -> Pixmap { let id = self.1; std::mem::forget(self); id } } impl<'c, C: X11Connection> PixmapWrapper<&'c C> { /// Create a new Pixmap and return a Pixmap wrapper and a cookie. /// /// This is a thin wrapper around [create_pixmap] that allocates an id for the Pixmap. /// This function returns the resulting `PixmapWrapper` that owns the created Pixmap and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [create_pixmap]. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_pixmap]. pub fn create_pixmap_and_get_cookie(conn: &'c C, depth: u8, drawable: Drawable, width: u16, height: u16) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> { let pid = conn.generate_id()?; let cookie = create_pixmap(conn, depth, pid, drawable, width, height)?; Ok((Self::for_pixmap(conn, pid), cookie)) } } impl PixmapWrapper { /// Create a new Pixmap and return a Pixmap wrapper /// /// This is a thin wrapper around [create_pixmap] that allocates an id for the Pixmap. /// This function returns the resulting `PixmapWrapper` that owns the created Pixmap and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_pixmap]. pub fn create_pixmap(conn: C, depth: u8, drawable: Drawable, width: u16, height: u16) -> Result { let pid = conn.generate_id()?; let _ = create_pixmap(&conn, depth, pid, drawable, width, height)?; Ok(Self::for_pixmap(conn, pid)) } } impl From<&PixmapWrapper> for Pixmap { fn from(from: &PixmapWrapper) -> Self { from.1 } } impl Drop for PixmapWrapper { fn drop(&mut self) { let _ = free_pixmap(&self.0, self.1); } } /// A RAII-like wrapper around a [Window]. /// /// Instances of this struct represent a Window 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 WindowWrapper(C, Window); impl WindowWrapper { /// Assume ownership of the given resource and destroy it in `Drop`. pub fn for_window(conn: C, id: Window) -> Self { WindowWrapper(conn, id) } /// Get the XID of the wrapped resource pub fn window(&self) -> Window { self.1 } /// Assume ownership of the XID of the wrapped resource /// /// This function destroys this wrapper without freeing the underlying resource. pub fn into_window(self) -> Window { let id = self.1; std::mem::forget(self); id } } impl<'c, C: X11Connection> WindowWrapper<&'c C> { /// Create a new Window and return a Window wrapper and a cookie. /// /// This is a thin wrapper around [create_window] that allocates an id for the Window. /// This function returns the resulting `WindowWrapper` that owns the created Window and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [create_window]. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_window]. pub fn create_window_and_get_cookie(conn: &'c C, depth: u8, parent: Window, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: WindowClass, visual: Visualid, value_list: &CreateWindowAux) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> { let wid = conn.generate_id()?; let cookie = create_window(conn, depth, wid, parent, x, y, width, height, border_width, class, visual, value_list)?; Ok((Self::for_window(conn, wid), cookie)) } } impl WindowWrapper { /// Create a new Window and return a Window wrapper /// /// This is a thin wrapper around [create_window] that allocates an id for the Window. /// This function returns the resulting `WindowWrapper` that owns the created Window and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_window]. pub fn create_window(conn: C, depth: u8, parent: Window, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: WindowClass, visual: Visualid, value_list: &CreateWindowAux) -> Result { let wid = conn.generate_id()?; let _ = create_window(&conn, depth, wid, parent, x, y, width, height, border_width, class, visual, value_list)?; Ok(Self::for_window(conn, wid)) } } impl From<&WindowWrapper> for Window { fn from(from: &WindowWrapper) -> Self { from.1 } } impl Drop for WindowWrapper { fn drop(&mut self) { let _ = destroy_window(&self.0, self.1); } } /// A RAII-like wrapper around a [Font]. /// /// Instances of this struct represent a Font 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 FontWrapper(C, Font); impl FontWrapper { /// Assume ownership of the given resource and destroy it in `Drop`. pub fn for_font(conn: C, id: Font) -> Self { FontWrapper(conn, id) } /// Get the XID of the wrapped resource pub fn font(&self) -> Font { self.1 } /// Assume ownership of the XID of the wrapped resource /// /// This function destroys this wrapper without freeing the underlying resource. pub fn into_font(self) -> Font { let id = self.1; std::mem::forget(self); id } } impl<'c, C: X11Connection> FontWrapper<&'c C> { /// Create a new Font and return a Font wrapper and a cookie. /// /// This is a thin wrapper around [open_font] that allocates an id for the Font. /// This function returns the resulting `FontWrapper` that owns the created Font and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [open_font]. /// /// Errors can come from the call to [X11Connection::generate_id] or [open_font]. pub fn open_font_and_get_cookie(conn: &'c C, name: &[u8]) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> { let fid = conn.generate_id()?; let cookie = open_font(conn, fid, name)?; Ok((Self::for_font(conn, fid), cookie)) } } impl FontWrapper { /// Create a new Font and return a Font wrapper /// /// This is a thin wrapper around [open_font] that allocates an id for the Font. /// This function returns the resulting `FontWrapper` that owns the created Font and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [open_font]. pub fn open_font(conn: C, name: &[u8]) -> Result { let fid = conn.generate_id()?; let _ = open_font(&conn, fid, name)?; Ok(Self::for_font(conn, fid)) } } impl From<&FontWrapper> for Font { fn from(from: &FontWrapper) -> Self { from.1 } } impl Drop for FontWrapper { fn drop(&mut self) { let _ = close_font(&self.0, self.1); } } /// A RAII-like wrapper around a [Gcontext]. /// /// Instances of this struct represent a Gcontext 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 GcontextWrapper(C, Gcontext); impl GcontextWrapper { /// Assume ownership of the given resource and destroy it in `Drop`. pub fn for_gcontext(conn: C, id: Gcontext) -> Self { GcontextWrapper(conn, id) } /// Get the XID of the wrapped resource pub fn gcontext(&self) -> Gcontext { self.1 } /// Assume ownership of the XID of the wrapped resource /// /// This function destroys this wrapper without freeing the underlying resource. pub fn into_gcontext(self) -> Gcontext { let id = self.1; std::mem::forget(self); id } } impl<'c, C: X11Connection> GcontextWrapper<&'c C> { /// Create a new Gcontext and return a Gcontext wrapper and a cookie. /// /// This is a thin wrapper around [create_gc] that allocates an id for the Gcontext. /// This function returns the resulting `GcontextWrapper` that owns the created Gcontext and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [create_gc]. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_gc]. pub fn create_gc_and_get_cookie(conn: &'c C, drawable: Drawable, value_list: &CreateGCAux) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> { let cid = conn.generate_id()?; let cookie = create_gc(conn, cid, drawable, value_list)?; Ok((Self::for_gcontext(conn, cid), cookie)) } } impl GcontextWrapper { /// Create a new Gcontext and return a Gcontext wrapper /// /// This is a thin wrapper around [create_gc] that allocates an id for the Gcontext. /// This function returns the resulting `GcontextWrapper` that owns the created Gcontext and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_gc]. pub fn create_gc(conn: C, drawable: Drawable, value_list: &CreateGCAux) -> Result { let cid = conn.generate_id()?; let _ = create_gc(&conn, cid, drawable, value_list)?; Ok(Self::for_gcontext(conn, cid)) } } impl From<&GcontextWrapper> for Gcontext { fn from(from: &GcontextWrapper) -> Self { from.1 } } impl Drop for GcontextWrapper { fn drop(&mut self) { let _ = free_gc(&self.0, self.1); } } /// A RAII-like wrapper around a [Colormap]. /// /// Instances of this struct represent a Colormap 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 ColormapWrapper(C, Colormap); impl ColormapWrapper { /// Assume ownership of the given resource and destroy it in `Drop`. pub fn for_colormap(conn: C, id: Colormap) -> Self { ColormapWrapper(conn, id) } /// Get the XID of the wrapped resource pub fn colormap(&self) -> Colormap { self.1 } /// Assume ownership of the XID of the wrapped resource /// /// This function destroys this wrapper without freeing the underlying resource. pub fn into_colormap(self) -> Colormap { let id = self.1; std::mem::forget(self); id } } impl<'c, C: X11Connection> ColormapWrapper<&'c C> { /// Create a new Colormap and return a Colormap wrapper and a cookie. /// /// This is a thin wrapper around [create_colormap] that allocates an id for the Colormap. /// This function returns the resulting `ColormapWrapper` that owns the created Colormap and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [create_colormap]. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_colormap]. pub fn create_colormap_and_get_cookie(conn: &'c C, alloc: ColormapAlloc, window: Window, visual: Visualid) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> { let mid = conn.generate_id()?; let cookie = create_colormap(conn, alloc, mid, window, visual)?; Ok((Self::for_colormap(conn, mid), cookie)) } } impl ColormapWrapper { /// Create a new Colormap and return a Colormap wrapper /// /// This is a thin wrapper around [create_colormap] that allocates an id for the Colormap. /// This function returns the resulting `ColormapWrapper` that owns the created Colormap and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_colormap]. pub fn create_colormap(conn: C, alloc: ColormapAlloc, window: Window, visual: Visualid) -> Result { let mid = conn.generate_id()?; let _ = create_colormap(&conn, alloc, mid, window, visual)?; Ok(Self::for_colormap(conn, mid)) } } impl From<&ColormapWrapper> for Colormap { fn from(from: &ColormapWrapper) -> Self { from.1 } } impl Drop for ColormapWrapper { fn drop(&mut self) { let _ = free_colormap(&self.0, self.1); } } /// A RAII-like wrapper around a [Cursor]. /// /// Instances of this struct represent a Cursor 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 CursorWrapper(C, Cursor); impl CursorWrapper { /// Assume ownership of the given resource and destroy it in `Drop`. pub fn for_cursor(conn: C, id: Cursor) -> Self { CursorWrapper(conn, id) } /// Get the XID of the wrapped resource pub fn cursor(&self) -> Cursor { self.1 } /// Assume ownership of the XID of the wrapped resource /// /// This function destroys this wrapper without freeing the underlying resource. pub fn into_cursor(self) -> Cursor { let id = self.1; std::mem::forget(self); id } } impl<'c, C: X11Connection> CursorWrapper<&'c C> { /// Create a new Cursor and return a Cursor wrapper and a cookie. /// /// This is a thin wrapper around [create_cursor] that allocates an id for the Cursor. /// This function returns the resulting `CursorWrapper` that owns the created Cursor and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [create_cursor]. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_cursor]. pub fn create_cursor_and_get_cookie(conn: &'c C, source: Pixmap, mask: A, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> where A: Into, { let cid = conn.generate_id()?; let cookie = create_cursor(conn, cid, source, mask, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, x, y)?; Ok((Self::for_cursor(conn, cid), cookie)) } } impl CursorWrapper { /// Create a new Cursor and return a Cursor wrapper /// /// This is a thin wrapper around [create_cursor] that allocates an id for the Cursor. /// This function returns the resulting `CursorWrapper` that owns the created Cursor and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_cursor]. pub fn create_cursor(conn: C, source: Pixmap, mask: A, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) -> Result where A: Into, { let cid = conn.generate_id()?; let _ = create_cursor(&conn, cid, source, mask, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, x, y)?; Ok(Self::for_cursor(conn, cid)) } } impl<'c, C: X11Connection> CursorWrapper<&'c C> { /// Create a new Cursor and return a Cursor wrapper and a cookie. /// /// This is a thin wrapper around [create_glyph_cursor] that allocates an id for the Cursor. /// This function returns the resulting `CursorWrapper` that owns the created Cursor and frees /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to /// [create_glyph_cursor]. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_glyph_cursor]. pub fn create_glyph_cursor_and_get_cookie(conn: &'c C, source_font: Font, mask_font: A, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError> where A: Into, { let cid = conn.generate_id()?; let cookie = create_glyph_cursor(conn, cid, source_font, mask_font, source_char, mask_char, fore_red, fore_green, fore_blue, back_red, back_green, back_blue)?; Ok((Self::for_cursor(conn, cid), cookie)) } } impl CursorWrapper { /// Create a new Cursor and return a Cursor wrapper /// /// This is a thin wrapper around [create_glyph_cursor] that allocates an id for the Cursor. /// This function returns the resulting `CursorWrapper` that owns the created Cursor and frees /// it in `Drop`. /// /// Errors can come from the call to [X11Connection::generate_id] or [create_glyph_cursor]. pub fn create_glyph_cursor(conn: C, source_font: Font, mask_font: A, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result where A: Into, { let cid = conn.generate_id()?; let _ = create_glyph_cursor(&conn, cid, source_font, mask_font, source_char, mask_char, fore_red, fore_green, fore_blue, back_red, back_green, back_blue)?; Ok(Self::for_cursor(conn, cid)) } } impl From<&CursorWrapper> for Cursor { fn from(from: &CursorWrapper) -> Self { from.1 } } impl Drop for CursorWrapper { fn drop(&mut self) { let _ = free_cursor(&self.0, self.1); } } x11rb-0.13.0/src/protocol/xselinux.rs000064400000000000000000000404621046102023000155250ustar 00000000000000// 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: &Conn) -> Result { 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, client_major: u8, client_minor: u8) -> Result, 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, 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) -> Result, 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, 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, device: u32) -> Result, 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, 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) -> Result, 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, window: xproto::Window) -> Result, 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, 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) -> Result, 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, 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) -> Result, 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, window: xproto::Window, property: xproto::Atom) -> Result, 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, window: xproto::Window, property: xproto::Atom) -> Result, 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, window: xproto::Window) -> Result, 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, 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) -> Result, 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, 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) -> Result, 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, selection: xproto::Atom) -> Result, 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, selection: xproto::Atom) -> Result, 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) -> Result, 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, resource: u32) -> Result, 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, ConnectionError> { query_version(self, client_major, client_minor) } fn xselinux_set_device_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result, ConnectionError> { set_device_create_context(self, context) } fn xselinux_get_device_create_context(&self) -> Result, ConnectionError> { get_device_create_context(self) } fn xselinux_set_device_context<'c, 'input>(&'c self, device: u32, context: &'input [u8]) -> Result, ConnectionError> { set_device_context(self, device, context) } fn xselinux_get_device_context(&self, device: u32) -> Result, ConnectionError> { get_device_context(self, device) } fn xselinux_set_window_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result, ConnectionError> { set_window_create_context(self, context) } fn xselinux_get_window_create_context(&self) -> Result, ConnectionError> { get_window_create_context(self) } fn xselinux_get_window_context(&self, window: xproto::Window) -> Result, ConnectionError> { get_window_context(self, window) } fn xselinux_set_property_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result, ConnectionError> { set_property_create_context(self, context) } fn xselinux_get_property_create_context(&self) -> Result, ConnectionError> { get_property_create_context(self) } fn xselinux_set_property_use_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result, ConnectionError> { set_property_use_context(self, context) } fn xselinux_get_property_use_context(&self) -> Result, ConnectionError> { get_property_use_context(self) } fn xselinux_get_property_context(&self, window: xproto::Window, property: xproto::Atom) -> Result, ConnectionError> { get_property_context(self, window, property) } fn xselinux_get_property_data_context(&self, window: xproto::Window, property: xproto::Atom) -> Result, ConnectionError> { get_property_data_context(self, window, property) } fn xselinux_list_properties(&self, window: xproto::Window) -> Result, ConnectionError> { list_properties(self, window) } fn xselinux_set_selection_create_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result, ConnectionError> { set_selection_create_context(self, context) } fn xselinux_get_selection_create_context(&self) -> Result, ConnectionError> { get_selection_create_context(self) } fn xselinux_set_selection_use_context<'c, 'input>(&'c self, context: &'input [u8]) -> Result, ConnectionError> { set_selection_use_context(self, context) } fn xselinux_get_selection_use_context(&self) -> Result, ConnectionError> { get_selection_use_context(self) } fn xselinux_get_selection_context(&self, selection: xproto::Atom) -> Result, ConnectionError> { get_selection_context(self, selection) } fn xselinux_get_selection_data_context(&self, selection: xproto::Atom) -> Result, ConnectionError> { get_selection_data_context(self, selection) } fn xselinux_list_selections(&self) -> Result, ConnectionError> { list_selections(self) } fn xselinux_get_client_context(&self, resource: u32) -> Result, ConnectionError> { get_client_context(self, resource) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xtest.rs000064400000000000000000000100151046102023000150040ustar 00000000000000// 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: &Conn) -> Result { 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, major_version: u8, minor_version: u16) -> Result, 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, window: xproto::Window, cursor: xproto::Cursor) -> Result, 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, type_: u8, detail: u8, time: u32, root: xproto::Window, root_x: i16, root_y: i16, deviceid: u8) -> Result, 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, impervious: bool) -> Result, 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, ConnectionError> { get_version(self, major_version, minor_version) } fn xtest_compare_cursor(&self, window: xproto::Window, cursor: xproto::Cursor) -> Result, 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, ConnectionError> { fake_input(self, type_, detail, time, root, root_x, root_y, deviceid) } fn xtest_grab_control(&self, impervious: bool) -> Result, ConnectionError> { grab_control(self, impervious) } } impl ConnectionExt for C {} x11rb-0.13.0/src/protocol/xv.rs000064400000000000000000000421521046102023000143010ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, window: xproto::Window) -> Result, 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, port: Port) -> Result, 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: &Conn, port: Port, time: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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: &Conn, port: Port, time: A) -> Result, ConnectionError> where Conn: RequestConnection + ?Sized, A: Into, { 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, 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, 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, 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, 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, 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, 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, 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, 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, port: Port, drawable: xproto::Drawable) -> Result, 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, drawable: xproto::Drawable, onoff: bool) -> Result, 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, port: Port, onoff: bool) -> Result, 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, port: Port, vid_w: u16, vid_h: u16, drw_w: u16, drw_h: u16, motion: bool) -> Result, 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, port: Port, attribute: xproto::Atom, value: i32) -> Result, 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, port: Port, attribute: xproto::Atom) -> Result, 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, port: Port) -> Result, 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, port: Port) -> Result, 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, port: Port, id: u32, width: u16, height: u16) -> Result, 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, 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, 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, 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, ConnectionError> { query_extension(self) } fn xv_query_adaptors(&self, window: xproto::Window) -> Result, ConnectionError> { query_adaptors(self, window) } fn xv_query_encodings(&self, port: Port) -> Result, ConnectionError> { query_encodings(self, port) } fn xv_grab_port(&self, port: Port, time: A) -> Result, ConnectionError> where A: Into, { grab_port(self, port, time) } fn xv_ungrab_port(&self, port: Port, time: A) -> Result, ConnectionError> where A: Into, { 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, 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, 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, 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, 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, ConnectionError> { stop_video(self, port, drawable) } fn xv_select_video_notify(&self, drawable: xproto::Drawable, onoff: bool) -> Result, ConnectionError> { select_video_notify(self, drawable, onoff) } fn xv_select_port_notify(&self, port: Port, onoff: bool) -> Result, 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, 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, ConnectionError> { set_port_attribute(self, port, attribute, value) } fn xv_get_port_attribute(&self, port: Port, attribute: xproto::Atom) -> Result, ConnectionError> { get_port_attribute(self, port, attribute) } fn xv_query_port_attributes(&self, port: Port) -> Result, ConnectionError> { query_port_attributes(self, port) } fn xv_list_image_formats(&self, port: Port) -> Result, ConnectionError> { list_image_formats(self, port) } fn xv_query_image_attributes(&self, port: Port, id: u32, width: u16, height: u16) -> Result, 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, 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, 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 ConnectionExt for C {} x11rb-0.13.0/src/protocol/xvmc.rs000064400000000000000000000164331046102023000146240ustar 00000000000000// 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: &Conn) -> Result { 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) -> Result, 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, port_id: xv::Port) -> Result, 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, context_id: Context, port_id: xv::Port, surface_id: Surface, width: u16, height: u16, flags: u32) -> Result, 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, context_id: Context) -> Result, 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, surface_id: Surface, context_id: Context) -> Result, 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, surface_id: Surface) -> Result, 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, subpicture_id: Subpicture, context: Context, xvimage_id: u32, width: u16, height: u16) -> Result, 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, subpicture_id: Subpicture) -> Result, 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, port_id: xv::Port, surface_id: Surface) -> Result, 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, ConnectionError> { query_version(self) } fn xvmc_list_surface_types(&self, port_id: xv::Port) -> Result, 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, ConnectionError> { create_context(self, context_id, port_id, surface_id, width, height, flags) } fn xvmc_destroy_context(&self, context_id: Context) -> Result, ConnectionError> { destroy_context(self, context_id) } fn xvmc_create_surface(&self, surface_id: Surface, context_id: Context) -> Result, ConnectionError> { create_surface(self, surface_id, context_id) } fn xvmc_destroy_surface(&self, surface_id: Surface) -> Result, ConnectionError> { destroy_surface(self, surface_id) } fn xvmc_create_subpicture(&self, subpicture_id: Subpicture, context: Context, xvimage_id: u32, width: u16, height: u16) -> Result, ConnectionError> { create_subpicture(self, subpicture_id, context, xvimage_id, width, height) } fn xvmc_destroy_subpicture(&self, subpicture_id: Subpicture) -> Result, ConnectionError> { destroy_subpicture(self, subpicture_id) } fn xvmc_list_subpicture_types(&self, port_id: xv::Port, surface_id: Surface) -> Result, ConnectionError> { list_subpicture_types(self, port_id, surface_id) } } impl ConnectionExt for C {} x11rb-0.13.0/src/resource_manager/mod.rs000064400000000000000000000060111046102023000160750ustar 00000000000000//! 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, 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 { 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, 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 { Ok(Database::new_from_default( &send_request(conn)?, crate::hostname(), )) } x11rb-0.13.0/src/rust_connection/mod.rs000064400000000000000000001013611046102023000157740ustar 00000000000000//! A pure-rust implementation of a connection to an X11 server. use std::convert::TryInto; use std::io::IoSlice; use std::mem::drop; 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 = ::Buf; /// A combination of a buffer and a list of file descriptors for use by [`RustConnection`]. pub type BufWithFds = crate::connection::BufWithFds; #[derive(Debug)] enum MaxRequestBytes { Unknown, Requested(Option), 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 { inner: Mutex, 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, reader_condition: Condvar, setup: Setup, extension_manager: Mutex, maximum_request_bytes: Mutex, id_allocator: Mutex, } // 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 { /// 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 RustConnection { /// 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::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, auth_data: Vec, ) -> Result { 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 { 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, kind: ReplyFdKind, ) -> Result { 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, 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, ) -> std::io::Result> { 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> { // 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, 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 RequestConnection for RustConnection { type Buf = Vec; fn send_request_with_reply( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, ConnectionError> where Reply: TryParse, { Ok(Cookie::new( self, self.send_request(bufs, fds, ReplyFdKind::ReplyWithoutFDs)?, )) } fn send_request_with_reply_with_fds( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, 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, ) -> Result, 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, ConnectionError> { self.extension_manager .lock() .unwrap() .extension_information(self, extension_name) } fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, ) -> Result>, 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>, 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, 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, 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_value()); 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 { let ext_mgr = self.extension_manager.lock().unwrap(); crate::x11_utils::X11Error::try_parse(error, &*ext_mgr) } fn parse_event(&self, event: &[u8]) -> Result { let ext_mgr = self.extension_manager.lock().unwrap(); crate::protocol::Event::parse(event, &*ext_mgr) } } impl Connection for RustConnection { fn wait_for_raw_event_with_sequence( &self, ) -> Result>, 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>>, 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 { 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, 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 ) ) } } } x11rb-0.13.0/src/rust_connection/packet_reader.rs000064400000000000000000000147421046102023000200140ustar 00000000000000//! Read X11 packets from a reader use std::io::{Error, ErrorKind, Result}; use std::{cmp, fmt, io}; 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>, fd_storage: &mut Vec, ) -> 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() == io::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() == io::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 struct TestStream { data: RefCell>, } impl TestStream { fn new(data: Vec) -> Self { Self { data: RefCell::new(data), } } } impl Stream for TestStream { fn read(&self, buf: &mut [u8], _: &mut Vec) -> Result { let mut data = self.data.borrow_mut(); if data.len() == 0 { 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) -> Result { unreachable!() } } fn test_packet(packet: Vec) { 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); } } x11rb-0.13.0/src/rust_connection/stream.rs000064400000000000000000000466471046102023000165270ustar 00000000000000use 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) -> Result; /// 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) -> Result; /// 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) -> Result { 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); 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 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 for OwnedSocket { fn from(stream: DefaultStream) -> Self { stream.inner.into() } } #[cfg(unix)] fn do_write( stream: &DefaultStream, bufs: &[IoSlice<'_>], fds: &mut Vec, ) -> Result { use rustix::io::Errno; use rustix::net::{sendmsg, SendAncillaryBuffer, SendAncillaryMessage, SendFlags}; fn sendmsg_wrapper( fd: BorrowedFd<'_>, iov: &[IoSlice<'_>], cmsgs: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> Result { 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::>(); let rights = SendAncillaryMessage::ScmRights(&fds); let mut cmsg_space = vec![0u8; 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, -1) { 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) -> Result { #[cfg(unix)] { use rustix::io::Errno; use rustix::net::{recvmsg, RecvAncillaryBuffer, RecvAncillaryMessage}; use std::io::IoSliceMut; // 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 = [0u8; 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) -> Result { #[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() == std::io::ErrorKind::Interrupted => {} Err(e) => return Err(e), } } } } fn write_vectored(&self, bufs: &[IoSlice<'_>], fds: &mut Vec) -> Result { #[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() == std::io::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 { use rustix::fs::{fcntl_getfl, fcntl_setfl, OFlags}; use rustix::net::{ connect_unix, socket_with, AddressFamily, SocketAddrUnix, SocketFlags, SocketType, }; let socket = socket_with( AddressFamily::UNIX, SocketType::STREAM, SocketFlags::CLOEXEC, None, )?; connect_unix(&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 + 'a, _cloexec_error: &'a mut Result<(), rustix::io::Errno>, ) -> impl Iterator + '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 + 'a, cloexec_error: &'a mut rustix::io::Result<()>, ) -> impl Iterator + '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 = crate::hostname() .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()) } } } x11rb-0.13.0/src/rust_connection/write_buffer.rs000064400000000000000000000170471046102023000177070ustar 00000000000000use std::collections::VecDeque; use std::io::IoSlice; use super::Stream; use crate::utils::RawFdContainer; #[derive(Debug)] pub(super) struct WriteBuffer { data_buf: VecDeque, fd_buf: Vec, } 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( &mut self, stream: &W, fds: &mut Vec, write_buffer: F, write_inner: G, first_buffer: &[u8], to_write_length: usize, ) -> std::io::Result where F: FnOnce(&mut VecDeque), G: FnOnce(&W, &mut Vec) -> std::io::Result, { 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, ) -> std::io::Result { 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, ) -> std::io::Result { 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) -> Result { unimplemented!(); } fn write(&self, _buf: &[u8], _fds: &mut Vec) -> Result { 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), } } } x11rb-0.13.0/src/test.rs000064400000000000000000000031411046102023000127550ustar 00000000000000use 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( conn: &Arc, ) -> Result>, ReplyOrIdError> { FontWrapper::open_font(Arc::clone(conn), b"font") } fn _compile_test_rc_in_wrapper( conn: &Rc, window: Window, visual: Visualid, ) -> Result>, ReplyOrIdError> { ColormapWrapper::create_colormap(Rc::clone(conn), ColormapAlloc::NONE, window, visual) } x11rb-0.13.0/src/tracing.rs000064400000000000000000000100031046102023000134200ustar 00000000000000//! 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)*) }; } 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)*) }; } 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; x11rb-0.13.0/src/utils.rs000064400000000000000000000054701046102023000131450ustar 00000000000000//! 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 Index 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; x11rb-0.13.0/src/wrapper.rs000064400000000000000000000102201046102023000134520ustar 00000000000000//! Some wrappers around the generated code to simplify use. use std::convert::TryInto; 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( &self, mode: PropMode, window: Window, property: A, type_: B, data: &[u8], ) -> Result, ConnectionError> where A: Into, B: Into, { 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( &self, mode: PropMode, window: Window, property: A, type_: B, data: &[u16], ) -> Result, ConnectionError> where A: Into, B: Into, { 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( &self, mode: PropMode, window: Window, property: A, type_: B, data: &[u32], ) -> Result, ConnectionError> where A: Into, B: Into, { 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 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 { // Grab the server, return any errors, ignore the resulting VoidCookie drop(conn.grab_server()?); Ok(Self(conn)) } } impl Drop for GrabServer<'_, C> { fn drop(&mut self) { let _ = (self.0).ungrab_server(); } } x11rb-0.13.0/src/x11_utils.rs000064400000000000000000000115011046102023000136260ustar 00000000000000//! 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> { /// 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( /// conn: &C, /// ) -> Result, ConnectionError> { /// 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 { /// 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> { phantom: std::marker::PhantomData<&'a C>, $( $field_name: $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( _conn: &C, ) -> ::std::result::Result<$cookie_name<'_, C>, $crate::errors::ConnectionError> { Ok($cookie_name { phantom: std::marker::PhantomData, $( $field_name: _conn.intern_atom( false, $crate::__atom_manager_atom_value!($field_name$(: $atom_value)?), )?, )* }) } } impl<'a, C: $crate::protocol::xproto::ConnectionExt> $cookie_name<'a, C> { $vis fn reply(self) -> ::std::result::Result<$struct_name, $crate::errors::ReplyError> { Ok($struct_name { $( $field_name: self.$field_name.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 }; } x11rb-0.13.0/src/xcb_ffi/atomic_u64.rs000064400000000000000000000016731046102023000153600ustar 00000000000000//! 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); 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; x11rb-0.13.0/src/xcb_ffi/mod.rs000064400000000000000000000632161046102023000141660ustar 00000000000000//! 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::convert::TryInto; 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 = ::Buf; /// The raw bytes of an event received by [`XCBConnection`] and its sequence number. pub type RawEventAndSeqNumber = x11rb_protocol::RawEventAndSeqNumber; /// A combination of a buffer and a list of file descriptors for use by [`XCBConnection`]. pub type BufWithFds = crate::connection::BufWithFds; /// 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, setup: Setup, ext_mgr: Mutex, errors: pending_errors::PendingErrors, maximum_sequence_received: AtomicU64, } impl XCBConnection { 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 } } /// 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 { let ptr = ptr as *mut raw_ffi::xcb_connection_t; let conn = raw_ffi::XcbConnectionWrapper::new(ptr, should_drop); let setup = raw_ffi::xcb_get_setup(ptr); Ok(XCBConnection { conn, setup: Self::parse_setup(setup)?, ext_mgr: Default::default(), errors: Default::default(), maximum_sequence_received: AtomicU64::new(0), }) } unsafe fn parse_setup(setup: *const raw_ffi::xcb_setup_t) -> Result { 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, has_reply: bool, reply_has_fds: bool, ) -> Result { 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.conn.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.conn.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.conn.as_ptr())) } } else { Ok(seqno) } } /// Check if the underlying XCB connection is in an error state. pub fn has_error(&self) -> Option { unsafe { let error = raw_ffi::xcb_connection_has_error(self.conn.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.conn.as_ptr() as _ } /// 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, ()> { unsafe { let mut reply = null_mut(); let mut error = null_mut(); let found = raw_ffi::xcb_poll_for_reply64(self.conn.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 { 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 RequestConnection for XCBConnection { type Buf = CSlice; fn send_request_with_reply( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, ConnectionError> where R: TryParse, { Ok(Cookie::new( self, self.send_request(bufs, fds, true, false)?, )) } fn send_request_with_reply_with_fds( &self, bufs: &[IoSlice<'_>], fds: Vec, ) -> Result, 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, ) -> Result, 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.conn.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, ConnectionError> { self.ext_mgr .lock() .unwrap() .extension_information(self, extension_name) } fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, ) -> Result, ConnectionError> { unsafe { let mut error = null_mut(); let reply = raw_ffi::xcb_wait_for_reply64(self.conn.as_ptr(), sequence, &mut error); match (reply.is_null(), error.is_null()) { (true, true) => Err(Self::connection_error_from_connection(self.conn.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, 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, 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, ConnectionError> { unimplemented!("FD passing is currently only implemented on Unix-like systems") } fn check_for_raw_error( &self, sequence: SequenceNumber, ) -> Result, ConnectionError> { let cookie = raw_ffi::xcb_void_cookie_t { sequence: sequence as _, }; let error = unsafe { raw_ffi::xcb_request_check(self.conn.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.conn.as_ptr()) as usize } } fn prefetch_maximum_request_bytes(&self) { unsafe { raw_ffi::xcb_prefetch_maximum_request_length(self.conn.as_ptr()) }; } fn parse_error(&self, error: &[u8]) -> Result { let ext_mgr = self.ext_mgr.lock().unwrap(); crate::x11_utils::X11Error::try_parse(error, &*ext_mgr) } fn parse_event(&self, event: &[u8]) -> Result { 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 { 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, 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 { 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_value()`). if id == u32::max_value() { 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()) } } } // 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_value()); 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| { if value > recent { value - recent } else { recent - value } }) .unwrap(); // Just because: Check that the result matches the passed-in value in the low bits assert_eq!( result & SequenceNumber::from(u32::max_value()), 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_value(); let max32_: u64 = max32.into(); let max32_p1 = max32_ + 1; let large_offset = max32_p1 * u64::from(u16::max_value()); 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({:x}, {:x}) == {:x}, but was {:x}", recent, value, expected, actual, ); } } } x11rb-0.13.0/src/xcb_ffi/pending_errors.rs000064400000000000000000000043451046102023000164250ustar 00000000000000//! 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>, pending: VecDeque<(SequenceNumber, Buffer)>, } /// A management struct for pending X11 errors #[derive(Debug, Default)] pub(crate) struct PendingErrors { inner: Mutex, } 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 } } x11rb-0.13.0/src/xcb_ffi/raw_ffi/ffi.rs000064400000000000000000000157011046102023000155640ustar 00000000000000//! 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 { // 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> = 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 { 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; } x11rb-0.13.0/src/xcb_ffi/raw_ffi/mod.rs000064400000000000000000000067631046102023000156070ustar 00000000000000//! 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)] pub(crate) struct XcbConnectionWrapper { ptr: NonNull, should_drop: bool, } // 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::*; x11rb-0.13.0/src/xcb_ffi/raw_ffi/test.rs000064400000000000000000000104141046102023000157730ustar 00000000000000//! 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, } // 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!(); } x11rb-0.13.0/tests/multithread_test.rs000064400000000000000000000171221046102023000157360ustar 00000000000000use 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, 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 { 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, condvar: Condvar, } #[derive(Debug)] struct FakeStreamInner { read: FakeStreamRead, write: FakeStreamWrite, } #[derive(Debug)] struct FakeStreamRead { recv: Receiver, pending: Vec, } #[derive(Debug)] pub(crate) struct FakeStreamWrite { send: Sender, 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, ) -> std::io::Result { 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) -> std::io::Result { 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()) } } } x11rb-0.13.0/tests/regression_tests.rs000064400000000000000000000230661046102023000157630ustar 00000000000000use 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, } impl SavedRequest { fn new(has_reply: bool, data: &[IoSlice]) -> SavedRequest { let data = data .iter() .flat_map(|slice| slice.deref()) .copied() .collect::>(); SavedRequest { has_reply, data } } } #[derive(Debug, Default)] struct FakeConnection(RefCell>); impl FakeConnection { fn check_requests(&self, expected: &[(bool, Vec)]) { 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, ) -> Result { 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; fn send_request_with_reply( &self, bufs: &[IoSlice], fds: Vec, ) -> Result, ConnectionError> where R: TryParse, { Ok(Cookie::new(self, self.internal_send_request(bufs, fds)?)) } fn send_request_with_reply_with_fds( &self, _bufs: &[IoSlice], _fds: Vec, ) -> Result, ConnectionError> where R: TryParseFd, { unimplemented!() } fn send_request_without_reply( &self, bufs: &[IoSlice], fds: Vec, ) -> Result, 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, ConnectionError> { unimplemented!() } fn wait_for_reply_or_raw_error( &self, _sequence: SequenceNumber, ) -> Result>, ConnectionError> { unimplemented!() } fn wait_for_reply( &self, _sequence: SequenceNumber, ) -> Result>, ConnectionError> { unimplemented!() } fn wait_for_reply_with_fds_raw( &self, _sequence: SequenceNumber, ) -> Result>, Vec>, ConnectionError> { unimplemented!() } fn check_for_raw_error( &self, _sequence: SequenceNumber, ) -> Result>, 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 { unimplemented!() } fn parse_event(&self, _event: &[u8]) -> Result { 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::>())?; // 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); } x11rb-0.13.0/tests/resource_manager.rs000064400000000000000000000214511046102023000156760ustar 00000000000000#[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: impl AsRef, 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) -> 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 \"{}\" and expected {:?}, but got {:?}", query, expected, 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>); impl RequestConnection for MockConnection { type Buf = Vec; fn send_request_with_reply( &self, _: &[IoSlice<'_>], _: Vec, ) -> Result, ConnectionError> where R: TryParse, { Ok(Cookie::new(self, 42)) } fn send_request_with_reply_with_fds( &self, _: &[IoSlice<'_>], _: Vec, ) -> Result, ConnectionError> where R: TryParseFd, { unimplemented!() } fn send_request_without_reply( &self, _: &[IoSlice<'_>], _: Vec, ) -> Result, 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, ConnectionError> { unimplemented!() } fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, ) -> Result, 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, ConnectionError> { unimplemented!() } fn wait_for_reply_with_fds_raw( &self, _: SequenceNumber, ) -> Result, Self::Buf>, ConnectionError> { unimplemented!() } fn check_for_raw_error( &self, _: SequenceNumber, ) -> Result, ConnectionError> { unimplemented!() } fn prefetch_maximum_request_bytes(&self) { unimplemented!() } fn maximum_request_bytes(&self) -> usize { unimplemented!() } fn parse_error(&self, _: &[u8]) -> Result { unimplemented!() } fn parse_event(&self, _: &[u8]) -> Result { unimplemented!() } } impl Connection for MockConnection { fn wait_for_raw_event_with_sequence( &self, ) -> Result, ConnectionError> { unimplemented!() } fn poll_for_raw_event_with_sequence( &self, ) -> Result>, ConnectionError> { unimplemented!() } fn flush(&self) -> Result<(), ConnectionError> { unimplemented!() } fn setup(&self) -> &Setup { &self.0 } fn generate_id(&self) -> Result { unimplemented!() } } }