xcb/lib.rs
1/*
2 * Copyright (C) 2013 James Miller <james@aatch.net>
3 * Copyright (c) 2016
4 * Remi Thebault <remi.thebault@gmail.com>
5 * Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com>
6 * Copyright (c) 2017-2021 Remi Thebault <remi.thebault@gmail.com>
7 *
8 * Permission is hereby granted, free of charge, to any
9 * person obtaining a copy of this software and associated
10 * documentation files (the "Software"), to deal in the
11 * Software without restriction, including without
12 * limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of
14 * the Software, and to permit persons to whom the Software
15 * is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice
19 * shall be included in all copies or substantial portions
20 * of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
23 * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
24 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
26 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
29 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 * DEALINGS IN THE SOFTWARE.
31 */
32
33#![allow(dead_code)]
34#![allow(unused_imports)]
35#![allow(unused_parens)]
36#![allow(clippy::len_without_is_empty)]
37#![allow(clippy::diverging_sub_expression)]
38
39//! Rust bindings to the XCB library.
40//!
41//! The X protocol C-language Binding (XCB - <https://xcb.freedesktop.org/>) is
42//! a replacement for Xlib featuring a small footprint, latency hiding, direct
43//! access to the protocol, improved threading support, and extensibility.
44//!
45//! The communication is established with the X server by the creation of a
46//! [Connection] object.
47//!
48//! A client communicates with the server by sending requests. There are 2 types
49//! of requests:
50//!
51//! - void requests: requests that do not expect an answer
52//! (e.g. [x::ChangeProperty])
53//! - non-void requests: requests that need a `Reply` (e.g. [x::GetProperty])
54//!
55//! Requests are passed to the server by filling a request structure e.g.
56//! [x::CreateWindow] and passing it to [Connection::send_request].
57//!
58//! The server can also communicate with clients by sending `Event`s.
59//! The client listens to events with calls such as [Connection::wait_for_event]
60//! (blocking) or [Connection::poll_for_event] (non-blocking).
61//!
62//! The [x] module contains definitions of the core X protocol.
63//! Each extension is defined in its own module such as [xkb] or [render], and
64//! is activated by a cargo feature of the same name.
65//!
66//! # Example
67//!
68//! Here is a walk-through of a simple `xcb` client.
69//! ```no_run
70//! // we import the necessary modules (only the core X module in this application).
71//! use xcb::{x};
72//! // we need to import the `Xid` trait for the `resource_id` call down there.
73//! use xcb::{Xid};
74//!
75//! // Many xcb functions return a `xcb::Result` or compatible result.
76//! fn main() -> xcb::Result<()> {
77//! // Connect to the X server.
78//! let (conn, screen_num) = xcb::Connection::connect(None)?;
79//!
80//! // Fetch the `x::Setup` and get the main `x::Screen` object.
81//! let setup = conn.get_setup();
82//! let screen = setup.roots().nth(screen_num as usize).unwrap();
83//!
84//! // Generate an `Xid` for the client window.
85//! // The type inference is needed here.
86//! let window: x::Window = conn.generate_id();
87//!
88//! // We can now create a window. For this we pass a `Request`
89//! // object to the `send_request_checked` method. The method
90//! // returns a cookie that will be used to check for success.
91//! let cookie = conn.send_request_checked(&x::CreateWindow {
92//! depth: x::COPY_FROM_PARENT as u8,
93//! wid: window,
94//! parent: screen.root(),
95//! x: 0,
96//! y: 0,
97//! width: 150,
98//! height: 150,
99//! border_width: 0,
100//! class: x::WindowClass::InputOutput,
101//! visual: screen.root_visual(),
102//! // this list must be in same order than `Cw` enum order
103//! value_list: &[
104//! x::Cw::BackPixel(screen.white_pixel()),
105//! x::Cw::EventMask(x::EventMask::EXPOSURE | x::EventMask::KEY_PRESS)
106//! ],
107//! });
108//! // We now check if the window creation worked.
109//! // A cookie can't be cloned; it is moved to the function.
110//! conn.check_request(cookie)?;
111//!
112//! // Let's change the window title
113//! let cookie = conn.send_request_checked(&x::ChangeProperty {
114//! mode: x::PropMode::Replace,
115//! window,
116//! property: x::ATOM_WM_NAME,
117//! r#type: x::ATOM_STRING,
118//! data: b"My XCB Window",
119//! });
120//! // And check for success again
121//! conn.check_request(cookie)?;
122//!
123//! // We now show ("map" in X terminology) the window.
124//! // This time we do not check for success, so we discard the cookie.
125//! conn.send_request(&x::MapWindow {
126//! window,
127//! });
128//!
129//! // We need a few atoms for our application.
130//! // We send a few requests in a row and wait for the replies after.
131//! let (wm_protocols, wm_del_window, wm_state, wm_state_maxv, wm_state_maxh) = {
132//! let cookies = (
133//! conn.send_request(&x::InternAtom {
134//! only_if_exists: true,
135//! name: b"WM_PROTOCOLS",
136//! }),
137//! conn.send_request(&x::InternAtom {
138//! only_if_exists: true,
139//! name: b"WM_DELETE_WINDOW",
140//! }),
141//! conn.send_request(&x::InternAtom {
142//! only_if_exists: true,
143//! name: b"_NET_WM_STATE",
144//! }),
145//! conn.send_request(&x::InternAtom {
146//! only_if_exists: true,
147//! name: b"_NET_WM_STATE_MAXIMIZED_VERT",
148//! }),
149//! conn.send_request(&x::InternAtom {
150//! only_if_exists: true,
151//! name: b"_NET_WM_STATE_MAXIMIZED_HORZ",
152//! }),
153//! );
154//! (
155//! conn.wait_for_reply(cookies.0)?.atom(),
156//! conn.wait_for_reply(cookies.1)?.atom(),
157//! conn.wait_for_reply(cookies.2)?.atom(),
158//! conn.wait_for_reply(cookies.3)?.atom(),
159//! conn.wait_for_reply(cookies.4)?.atom(),
160//! )
161//! };
162//!
163//! // We now activate the window close event by sending the following request.
164//! // If we don't do this we can still close the window by clicking on the "x" button,
165//! // but the event loop is notified through a connection shutdown error.
166//! conn.check_request(conn.send_request_checked(&x::ChangeProperty {
167//! mode: x::PropMode::Replace,
168//! window,
169//! property: wm_protocols,
170//! r#type: x::ATOM_ATOM,
171//! data: &[wm_del_window],
172//! }))?;
173//!
174//! // Previous request was checked, so a flush is not necessary in this case.
175//! // Otherwise, here is how to perform a connection flush.
176//! conn.flush()?;
177//!
178//! let mut maximized = false;
179//!
180//! // We enter the main event loop
181//! loop {
182//! match conn.wait_for_event()? {
183//! xcb::Event::X(x::Event::KeyPress(ev)) => {
184//! if ev.detail() == 0x3a {
185//! // The M key was pressed
186//! // (M only on qwerty keyboards. Keymap support is done
187//! // with the `xkb` extension and the `xkbcommon-rs` crate)
188//!
189//! // We toggle maximized state, for this we send a message
190//! // by building a `x::ClientMessageEvent` with the proper
191//! // atoms and send it to the server.
192//!
193//! let data = x::ClientMessageData::Data32([
194//! if maximized { 0 } else { 1 },
195//! wm_state_maxv.resource_id(),
196//! wm_state_maxh.resource_id(),
197//! 0,
198//! 0,
199//! ]);
200//! let event = x::ClientMessageEvent::new(window, wm_state, data);
201//! let cookie = conn.send_request_checked(&x::SendEvent {
202//! propagate: false,
203//! destination: x::SendEventDest::Window(screen.root()),
204//! event_mask: x::EventMask::STRUCTURE_NOTIFY,
205//! event: &event,
206//! });
207//! conn.check_request(cookie)?;
208//!
209//! // Same as before, if we don't check for error, we have to flush
210//! // the connection.
211//! // conn.flush()?;
212//!
213//! maximized = !maximized;
214//! } else if ev.detail() == 0x18 {
215//! // Q (on qwerty)
216//!
217//! // We exit the event loop (and the program)
218//! break Ok(());
219//! }
220//! }
221//! xcb::Event::X(x::Event::ClientMessage(ev)) => {
222//! // We have received a message from the server
223//! if let x::ClientMessageData::Data32([atom, ..]) = ev.data() {
224//! if atom == wm_del_window.resource_id() {
225//! // The received atom is "WM_DELETE_WINDOW".
226//! // We can check here if the user needs to save before
227//! // exit, or in our case, exit right away.
228//! break Ok(());
229//! }
230//! }
231//! }
232//! _ => {}
233//! }
234//! }
235//! }
236//! ```
237//!
238//! # Cargo features
239//!
240//! The following Cargo features are available
241//!
242//! ## `xlib_xcb`
243//!
244//! This feature activates the use of `xlib::Display` to connect to XCB, therefore making
245//! available both Xlib and XCB functions to the same connection.
246//! While XCB is sufficient to handle all communication with the X server, some things can
247//! still only be done by Xlib. E.g. hardware initialization for OpenGL is done by Xlib only.
248//!
249//! ## `debug_atom_names`
250//!
251//! When this feature is activated, the `fmt::Debug` implementation for `x::Atom` will print
252//! out the name of the atom in addition to its value.
253//!
254//! E.g. the feature would turn `Atom { res_id: 303 }` into `Atom("Abs Pressure" ; 303)`.
255//!
256//! This can be useful in situations where you are not sure which atom you have to intern
257//! in order to look up some data in a reply.
258//!
259//! It should be noted that the feature sets global variable to have access to
260//! the connection in the `fmt::Debug` implementation, and that the `Debug` print
261//! have side effects (`x::GetAtomName` requests) which can sometimes not be desirable.
262//! The feature should therefore only be activated when needed.
263//!
264//! ## `libxcb_v1_14`
265//!
266//! This feature is enabled by default and activates the libxcb API version 1.14.
267//! To use a version of the libxcb API prior to 1.14, you must disable it.
268//!
269//! ## Extension features
270//!
271//! The following X extensions are activated by a cargo feature:
272//!
273//! | Extension name | Cargo feature |
274//! |-------------------------------|---------------|
275//! | `Composite` | `composite` |
276//! | `DAMAGE` | `damage` |
277//! | `DPMS` | `dpms` |
278//! | `DRI2` | `dri2` |
279//! | `DRI3` | `dri3` |
280//! | `Generic Event Extension` | `ge` |
281//! | `GLX` | `glx` |
282//! | `Present` | `present` |
283//! | `RANDR` | `randr` |
284//! | `RECORD` | `record` |
285//! | `RENDER` | `render` |
286//! | `X-Resource` | `res` |
287//! | `MIT-SCREEN-SAVER` | `screensaver` |
288//! | `SHAPE` | `shape` |
289//! | `MIT-SHM` | `shm` |
290//! | `SYNC` | `sync` |
291//! | `XEVIE` | `xevie` |
292//! | `XFree86-DRI` | `xf86dri` |
293//! | `XFree86-VidModeExtension` | `xf86vidmode` |
294//! | `XFIXES` | `xfixes` |
295//! | `XINERAMA` | `xinerama` |
296//! | `XInputExtension` | `xinput` |
297//! | `XKEYBOARD` | `xkb` |
298//! | `XpExtension` | `xprint` |
299//! | `SELinux` | `xselinux` |
300//! | `TEST` | `xtest` |
301//! | `XVideo` | `xv` |
302//! | `XVideo-MotionCompensation` | `xvmc` |
303
304mod base;
305mod error;
306mod event;
307mod ext;
308mod lat1_str;
309
310pub use base::*;
311pub use error::*;
312pub use event::*;
313pub use ext::*;
314pub use lat1_str::*;
315
316pub mod x {
317 //! The core X protocol definitions
318
319 pub use super::xproto::*;
320}
321
322pub mod ffi {
323 //! Module for Foreign Function Interface bindings.
324
325 #![allow(non_camel_case_types)]
326 #![allow(improper_ctypes)]
327
328 pub(crate) mod base;
329 pub(crate) mod ext;
330
331 #[cfg(feature = "xlib_xcb")]
332 pub(crate) mod xlib_xcb;
333
334 pub use base::*;
335 pub use ext::*;
336
337 #[cfg(feature = "xlib_xcb")]
338 pub use xlib_xcb::*;
339}
340
341#[cfg(test)]
342mod test;
343
344mod xproto {
345 #![allow(unused_variables)]
346 #![allow(clippy::unit_arg)]
347 #![allow(clippy::new_ret_no_self)]
348 #![allow(clippy::too_many_arguments)]
349
350 /// `COPY_FROM_PARENT` can be used for many `CreateWindow` fields
351 pub const COPY_FROM_PARENT: u32 = 0;
352
353 /// `CURRENT_TIME` can be used in most requests that take a `Timestamp`
354 pub const CURRENT_TIME: Timestamp = 0;
355
356 /// `NO_SYMBOL` fills in unused entries in `Keysym` tables
357 pub const NO_SYMBOL: Keysym = 0;
358
359 /// `GRAB_ANY` can be used in various requests such as `GrabKey`, `UngrabKey`, `xinput::GrabDeviceKey`...
360 pub const GRAB_ANY: Keycode = 0;
361
362 pub const ATOM_ANY: Atom = Atom { res_id: 0 };
363
364 /// Trait for element in a property list
365 ///
366 /// In events (e.g. `GetProperty::value`), it allows to assert that the format
367 /// correspond to the type cast and therefore to do the cast safely at runtime.
368 ///
369 /// In request (e.g. `ChangeProperty::data`), it allows to infer the format value
370 /// from the type of passed data.
371 pub trait PropEl {
372 const FORMAT: u8;
373 }
374
375 impl PropEl for u8 {
376 const FORMAT: u8 = 8;
377 }
378
379 impl PropEl for u16 {
380 const FORMAT: u8 = 16;
381 }
382
383 impl PropEl for u32 {
384 const FORMAT: u8 = 32;
385 }
386
387 impl PropEl for Atom {
388 const FORMAT: u8 = 32;
389 }
390
391 impl PropEl for Window {
392 // _NET_CLIENT_LIST returns a list of windows
393 const FORMAT: u8 = 32;
394 }
395
396 include!(concat!(env!("OUT_DIR"), "/xproto.rs"));
397}
398
399/// An helper macro that generate a struct of atoms.
400///
401/// The struct provide a constructor `intern_all` that takes a `Connection` as parameter,
402/// interns all the atoms and return `xcb::Result<[struct name]>`.
403/// `intern_all` takes advantage of XCB asynchronous design by sending all the
404/// [`x::InternAtom`] requests before starting to wait for the first reply.
405/// Fields that refer to atoms not existing in the server are set to `x::ATOM_NONE`
406/// (i.e. `only_if_exists` is always set to `true`).
407///
408/// Both the struct and each field can receive visibility attributes.
409///
410/// # Example
411/// ```no_run
412/// # use xcb::x;
413/// xcb::atoms_struct! {
414/// #[derive(Copy, Clone, Debug)]
415/// pub(crate) struct Atoms {
416/// pub wm_protocols => b"WM_PROTOCOLS",
417/// pub wm_del_window => b"WM_DELETE_WINDOW",
418/// /// Supported EWMH hints
419/// pub net_supported => b"_NET_SUPPORTED",
420///
421/// // You can also explicitly set the `only_if_exists` argument when interning
422/// // each atom with the following syntax (the default is `true`):
423/// pub custom_atom => b"MY_CUSTOM_ATOM" only_if_exists = false,
424/// }
425/// }
426///
427/// fn main() -> xcb::Result<()> {
428/// # let (conn, screen_num) = xcb::Connection::connect(None)?;
429/// # let window = conn.generate_id();
430/// // ...
431/// let atoms = Atoms::intern_all(&conn)?;
432///
433/// conn.check_request(conn.send_request_checked(&x::ChangeProperty {
434/// mode: x::PropMode::Replace,
435/// window,
436/// property: atoms.wm_protocols,
437/// r#type: x::ATOM_ATOM,
438/// data: &[atoms.wm_del_window],
439/// }))?;
440/// // ...
441/// # Ok(())
442/// }
443/// ```
444#[macro_export]
445macro_rules! atoms_struct {
446 (
447 $(#[$outer:meta])*
448 $vis:vis struct $Atoms:ident {
449 $(
450 $(#[$fmeta:meta])* $fvis:vis $field:ident => $name:tt $( only_if_exists = $only_if_exists:expr)?,
451 )*
452 }
453 ) => {
454 $(#[$outer])*
455 $vis struct $Atoms {
456 $($(#[$fmeta])* $fvis $field: xcb::x::Atom,)*
457 }
458 impl $Atoms {
459 #[allow(dead_code)]
460 pub fn intern_all(conn: &xcb::Connection) -> xcb::Result<$Atoms> {
461 $(
462 #[allow(unused_assignments)]
463 let mut only_if_exists = true;
464 $( only_if_exists = $only_if_exists; )?
465 let $field = conn.send_request(&xcb::x::InternAtom {
466 only_if_exists,
467 name: $name,
468 });
469 )*
470 $(
471 let $field = conn.wait_for_reply($field)?.atom();
472 )*
473 Ok($Atoms {
474 $($field,)*
475 })
476 }
477 }
478 };
479}
480
481pub mod bigreq {
482 //! The `BIG-REQUESTS` extension.
483 include!(concat!(env!("OUT_DIR"), "/bigreq.rs"));
484}
485
486pub mod xc_misc {
487 //! The `XC-MISC` extension.
488 include!(concat!(env!("OUT_DIR"), "/xc_misc.rs"));
489}
490
491#[cfg(feature = "composite")]
492pub mod composite {
493 //! The `Composite` X extension.
494 //!
495 //! Accessible with the `composite` cargo feature.
496 include!(concat!(env!("OUT_DIR"), "/composite.rs"));
497}
498
499#[cfg(feature = "damage")]
500pub mod damage {
501 //! The `DAMAGE` X extension.
502 //!
503 //! Accessible with the `damage` cargo feature.
504 include!(concat!(env!("OUT_DIR"), "/damage.rs"));
505
506 impl NotifyEvent {
507 /// Returns the raw level/continuation byte (2nd byte of the on-wire structure).
508 fn raw_level(&self) -> u8 {
509 // level / continuation byte is the 2nd byte of the on-wire structure
510 unsafe { std::ptr::read_unaligned(self.wire_ptr().add(1) as *const u8) }
511 }
512
513 /// Returns `true` when the server indicates that more
514 /// `NotifyEvent`s belonging to the same logical notification
515 /// follow this one (bit 7 of the level byte is set).
516 pub fn more(&self) -> bool {
517 self.raw_level() & 0x80 != 0
518 }
519
520 /// Return the `ReportLevel` of the event.
521 /// Only the lower 7 bits are considered, the 8th bit is a continuation flag.
522 pub fn level(&self) -> ReportLevel {
523 match (self.raw_level() & 0x7F) as u32 {
524 0 => ReportLevel::RawRectangles,
525 1 => ReportLevel::DeltaRectangles,
526 2 => ReportLevel::BoundingBox,
527 3 => ReportLevel::NonEmpty,
528 _ => unimplemented!(
529 "unknown damage::ReportLevel value {}",
530 self.raw_level() & 0x7F
531 ),
532 }
533 }
534 }
535}
536
537#[cfg(feature = "dpms")]
538pub mod dpms {
539 //! The `DPMS` X extension.
540 //!
541 //! Accessible with the `dpms` cargo feature.
542 include!(concat!(env!("OUT_DIR"), "/dpms.rs"));
543}
544
545#[cfg(feature = "dri2")]
546pub mod dri2 {
547 //! The `DRI2` X extension.
548 //!
549 //! Accessible with the `dri2` cargo feature.
550 #![allow(clippy::too_many_arguments)]
551 include!(concat!(env!("OUT_DIR"), "/dri2.rs"));
552}
553
554#[cfg(feature = "dri3")]
555pub mod dri3 {
556 //! The `DRI3` X extension.
557 //!
558 //! Accessible with the `dri3` cargo feature.
559 include!(concat!(env!("OUT_DIR"), "/dri3.rs"));
560}
561
562#[cfg(feature = "ge")]
563pub mod ge {
564 //! The `Generic Event Extension` X extension.
565 //!
566 //! Accessible with the `ge` cargo feature.
567 include!(concat!(env!("OUT_DIR"), "/ge.rs"));
568}
569
570#[cfg(feature = "glx")]
571pub mod glx {
572 //! The `GLX` X extension.
573 //!
574 //! Accessible with the `glx` cargo feature.
575 #![allow(clippy::too_many_arguments)]
576 include!(concat!(env!("OUT_DIR"), "/glx.rs"));
577}
578
579#[cfg(feature = "xinput")]
580pub mod xinput {
581 //! The `XInputExtension` X extension.
582 //!
583 //! Accessible with the `xinput` cargo feature.
584 #![allow(unused_variables)]
585 #![allow(unused_mut)]
586 #![allow(clippy::unit_arg)]
587 #![allow(clippy::too_many_arguments)]
588
589 #[derive(Copy, Clone, Debug)]
590 pub enum Device {
591 All,
592 AllMaster,
593 Id(u16),
594 }
595
596 impl Device {
597 pub fn from_id(id: u16) -> Self {
598 match id {
599 0 => Device::All,
600 1 => Device::AllMaster,
601 id => Device::Id(id),
602 }
603 }
604
605 pub fn id(&self) -> u16 {
606 match self {
607 Device::All => 0,
608 Device::AllMaster => 1,
609 Device::Id(id) => *id,
610 }
611 }
612 }
613
614 impl WiredOut for Device {
615 fn wire_len(&self) -> usize {
616 2
617 }
618 fn serialize(&self, wire_buf: &mut [u8]) -> usize {
619 assert!(wire_buf.len() >= 2);
620 unsafe {
621 *(wire_buf.as_mut_ptr() as *mut u16) = self.id();
622 }
623 2
624 }
625 }
626
627 impl WiredIn for Device {
628 type Params = ();
629 unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize {
630 2
631 }
632 unsafe fn unserialize(ptr: *const u8, params: Self::Params, offset: &mut usize) -> Self {
633 *offset = 2;
634 let id = *(ptr as *const u16);
635 Device::from_id(id)
636 }
637 }
638
639 include!(concat!(env!("OUT_DIR"), "/xinput.rs"));
640}
641
642#[cfg(feature = "present")]
643pub mod present {
644 //! The `Present` X extension.
645 //!
646 //! Accessible with the `present` cargo feature.
647 #![allow(clippy::unit_arg)]
648 include!(concat!(env!("OUT_DIR"), "/present.rs"));
649}
650
651#[cfg(feature = "randr")]
652pub mod randr {
653 //! The `RANDR` X extension.
654 //!
655 //! Accessible with the `randr` cargo feature.
656 #![allow(clippy::unit_arg)]
657 #![allow(clippy::too_many_arguments)]
658 include!(concat!(env!("OUT_DIR"), "/randr.rs"));
659
660 /// For information on what the various properties mean, see the [RandR specification][randr-spec]
661 ///
662 /// [randr-spec]: https://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt#n1860
663 pub mod property {
664 #[doc(alias = "RR_PROPERTY_BACKLIGHT")]
665 pub const BACKLIGHT: &str = "Backlight";
666
667 #[doc(alias = "RR_PROPERTY_CLONE_LIST")]
668 pub const CLONE_LIST: &str = "CloneList";
669
670 #[doc(alias = "RR_PROPERTY_COMPATIBILITY_LIST")]
671 pub const COMPATIBILITY_LIST: &str = "CompatibilityList";
672
673 #[doc(alias = "RR_PROPERTY_CONNECTOR_NUMBER")]
674 pub const CONNECTOR_NUMBER: &str = "ConnectorNumber";
675
676 #[doc(alias = "RR_PROPERTY_CONNECTOR_TYPE")]
677 pub const CONNECTOR_TYPE: &str = "ConnectorType";
678
679 #[doc(alias = "RR_PROPERTY_RANDR_EDID")]
680 pub const EDID: &str = "EDID";
681
682 #[doc(alias = "RR_PROPERTY_SIGNAL_FORMAT")]
683 pub const SIGNAL_FORMAT: &str = "SignalFormat";
684
685 #[doc(alias = "RR_PROPERTY_SIGNAL_PROPERTIES")]
686 pub const SIGNAL_PROPERTIES: &str = "SignalProperties";
687
688 #[doc(alias = "RR_PROPERTY_BORDER")]
689 pub const BORDER: &str = "Border";
690
691 #[doc(alias = "RR_PROPERTY_BORDER_DIMENSIONS")]
692 pub const BORDER_DIMENSIONS: &str = "BorderDimensions";
693
694 #[doc(alias = "RR_PROPERTY_GUID")]
695 pub const GUID: &str = "GUID";
696
697 #[doc(alias = "RR_PROPERTY_RANDR_TILE")]
698 pub const TILE: &str = "TILE";
699
700 #[doc(alias = "RR_PROPERTY_NON_DESKTOP")]
701 pub const NON_DESKTOP: &str = "non-desktop";
702 }
703}
704
705#[cfg(feature = "record")]
706pub mod record {
707 //! The `RECORD` X extension.
708 //!
709 //! Accessible with the `record` cargo feature.
710 #![allow(clippy::unit_arg)]
711 #![allow(clippy::too_many_arguments)]
712 include!(concat!(env!("OUT_DIR"), "/record.rs"));
713}
714
715#[cfg(feature = "render")]
716pub mod render {
717 //! The `RENDER` X extension.
718 //!
719 //! Accessible with the `render` cargo feature.
720 #![allow(unused_variables)]
721 #![allow(clippy::unit_arg)]
722 include!(concat!(env!("OUT_DIR"), "/render.rs"));
723}
724
725#[cfg(feature = "res")]
726pub mod res {
727 //! The `X-Resource` X extension.
728 //!
729 //! Accessible with the `res` cargo feature.
730 #![allow(unused_variables)]
731 #![allow(clippy::unit_arg)]
732 include!(concat!(env!("OUT_DIR"), "/res.rs"));
733}
734
735#[cfg(feature = "screensaver")]
736pub mod screensaver {
737 //! The `MIT-SCREEN-SAVER` X extension.
738 //!
739 //! Accessible with the `screensaver` cargo feature.
740 #![allow(unused_variables)]
741 include!(concat!(env!("OUT_DIR"), "/screensaver.rs"));
742}
743
744#[cfg(feature = "xselinux")]
745pub mod xselinux {
746 //! The `SELinux` X extension.
747 //!
748 //! Accessible with the `xselinux` cargo feature.
749 #![allow(clippy::unit_arg)]
750 include!(concat!(env!("OUT_DIR"), "/xselinux.rs"));
751}
752
753#[cfg(feature = "shape")]
754pub mod shape {
755 //! The `SHAPE` X extension.
756 //!
757 //! Accessible with the `shape` cargo feature.
758 #![allow(clippy::too_many_arguments)]
759 include!(concat!(env!("OUT_DIR"), "/shape.rs"));
760}
761
762#[cfg(feature = "shm")]
763pub mod shm {
764 //! The `MIT-SHM` X extension.
765 //!
766 //! Accessible with the `shm` cargo feature.
767 include!(concat!(env!("OUT_DIR"), "/shm.rs"));
768}
769
770#[cfg(feature = "sync")]
771pub mod sync {
772 //! The `SYNC` X extension.
773 //!
774 //! Accessible with the `sync` cargo feature.
775 #![allow(unused_variables)]
776 #![allow(clippy::unit_arg)]
777 #![allow(clippy::too_many_arguments)]
778 include!(concat!(env!("OUT_DIR"), "/sync.rs"));
779}
780
781#[cfg(feature = "xtest")]
782pub mod xtest {
783 //! The `XTEST` X extension.
784 //!
785 //! Accessible with the `xtest` cargo feature.
786 include!(concat!(env!("OUT_DIR"), "/xtest.rs"));
787}
788
789#[cfg(feature = "xprint")]
790pub mod xprint {
791 //! The `XpExtension` X extension.
792 //!
793 //! Accessible with the `xprint` cargo feature.
794 #![allow(clippy::unit_arg)]
795 include!(concat!(env!("OUT_DIR"), "/xprint.rs"));
796}
797
798#[cfg(feature = "xevie")]
799pub mod xevie {
800 //! The `XEVIE` X extension.
801 //!
802 //! Accessible with the `xevie` cargo feature.
803 include!(concat!(env!("OUT_DIR"), "/xevie.rs"));
804}
805
806#[cfg(feature = "xf86dri")]
807pub mod xf86dri {
808 //! The `XFree86-DRI` X extension.
809 //!
810 //! Accessible with the `xf86dri` cargo feature.
811 include!(concat!(env!("OUT_DIR"), "/xf86dri.rs"));
812}
813
814#[cfg(feature = "xf86vidmode")]
815pub mod xf86vidmode {
816 //! The `XFree86-VidModeExtension` X extension.
817 //!
818 //! Accessible with the `xf86vidmode` cargo feature.
819 #![allow(clippy::too_many_arguments)]
820 include!(concat!(env!("OUT_DIR"), "/xf86vidmode.rs"));
821}
822
823#[cfg(feature = "xfixes")]
824pub mod xfixes {
825 //! The `XFIXES` X extension.
826 //!
827 //! Accessible with the `xfixes` cargo feature.
828 include!(concat!(env!("OUT_DIR"), "/xfixes.rs"));
829}
830
831#[cfg(feature = "xinerama")]
832pub mod xinerama {
833 //! The `XINERAMA` X extension.
834 //!
835 //! Accessible with the `xinerama` cargo feature.
836 include!(concat!(env!("OUT_DIR"), "/xinerama.rs"));
837}
838
839#[cfg(feature = "xkb")]
840pub mod xkb {
841 //! The `XKEYBOARD` X extension.
842 //!
843 //! Accessible with the `xkb` cargo feature.
844 #![allow(unused_variables)]
845 #![allow(clippy::let_unit_value)]
846 #![allow(clippy::unit_arg)]
847 #![allow(clippy::too_many_arguments)]
848 include!(concat!(env!("OUT_DIR"), "/xkb.rs"));
849}
850
851#[cfg(feature = "xv")]
852pub mod xv {
853 //! The `XVideo` X extension.
854 //!
855 //! Accessible with the `xv` cargo feature.
856 #![allow(clippy::unit_arg)]
857 #![allow(clippy::too_many_arguments)]
858 include!(concat!(env!("OUT_DIR"), "/xv.rs"));
859}
860
861#[cfg(feature = "xvmc")]
862pub mod xvmc {
863 //! The `XVideo-MotionCompensation` X extension.
864 //!
865 //! Accessible with the `xvmc` cargo feature.
866 include!(concat!(env!("OUT_DIR"), "/xvmc.rs"));
867}