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}