[go: up one dir, main page]

xcb/
base.rs

1use crate::error::{self, ProtocolError};
2use crate::event::{self, Event};
3use crate::ext::{Extension, ExtensionData};
4#[cfg(feature = "present")]
5use crate::present;
6use crate::x::{Atom, Keysym, Setup, Timestamp};
7#[cfg(feature = "xinput")]
8use crate::xinput;
9use crate::{cache_extensions_data, ffi::*};
10
11#[cfg(feature = "xlib_xcb")]
12use x11::xlib;
13
14use bitflags::bitflags;
15
16use libc::{c_char, c_int};
17
18use std::cell::RefCell;
19use std::ffi::{c_void, CStr, CString};
20use std::fmt::{self, Display, Formatter};
21use std::marker::{self, PhantomData};
22use std::mem;
23use std::os::fd::{IntoRawFd, OwnedFd};
24use std::os::unix::prelude::{AsRawFd, RawFd};
25use std::ptr;
26use std::result;
27use std::slice;
28
29/// A X resource trait
30pub trait Xid {
31    /// Build a null X resource
32    fn none() -> Self;
33
34    /// Get the underlying id of the resource
35    fn resource_id(&self) -> u32;
36
37    /// Check whether this resource is null or not
38    fn is_none(&self) -> bool {
39        self.resource_id() == 0
40    }
41}
42
43/// Trait for X resources that can be created directly from `Connection::generate_id`
44///
45/// The resources that cannot be created that way are the Xid unions, which are created
46/// from their underlying resource.
47pub trait XidNew: Xid {
48    /// Build a new X resource
49    ///
50    /// # Safety
51    /// res_id must be obtained from `xcb_generate_id`. `0` is also a valid value to create a null resource.
52    /// Users should not use this function directly but rather use
53    /// `Connection::generate_id`
54    unsafe fn new(res_id: u32) -> Self;
55}
56
57/// Trait for types that own a C allocated pointer and are represented by the data pointed to.
58pub trait Raw<T>: Sized {
59    /// Build `Self` from a raw pointer
60    ///
61    /// # Safety
62    /// `raw` must be a valid pointer to the representation of Self, and be allocated with `libc::malloc`
63    unsafe fn from_raw(raw: *mut T) -> Self;
64
65    /// Convert self into a raw pointer
66    ///
67    /// Returned value should be freed with `libc::free` or sent back to `from_raw` to avoid memory leak.
68    fn into_raw(self) -> *mut T {
69        let raw = self.as_raw();
70        mem::forget(self);
71        raw
72    }
73
74    /// Obtain the raw pointer representation
75    fn as_raw(&self) -> *mut T;
76}
77
78/// Trait for base events (aka. non GE_GENERIC events)
79pub trait BaseEvent: Raw<xcb_generic_event_t> {
80    /// The extension associated to this event, or `None` for the main protocol
81    const EXTENSION: Option<Extension>;
82
83    /// The number associated to this event
84    const NUMBER: u32;
85
86    /// Check whether this event was emitted by the SendEvent request
87    /// See `[crate::x::SendEvent]`.
88    fn is_from_send_event(&self) -> bool {
89        let ev = self.as_raw();
90        let response_type = unsafe { (*ev).response_type };
91        (response_type & 0x80) != 0
92    }
93}
94
95/// A trait for GE_GENERIC events
96///
97/// A GE_GENERIC event is an extension event that does not follow
98/// the regular `response_type` offset.
99/// This system was introduced because the protocol eventually run
100/// out of event numbers.
101///
102/// This should be completely transparent to the user, as [Event] is
103/// resolving all types of events together.
104pub trait GeEvent: Raw<xcb_ge_generic_event_t> {
105    /// The extension associated to this event
106    const EXTENSION: Extension;
107
108    /// The number associated to this event
109    const NUMBER: u32;
110}
111
112/// A trait to designate base protocol errors.
113///
114/// The base errors follow the usual resolution idiom of `error_code` offset.
115///
116/// This should be completely transparent to the user, as [ProtocolError] is
117/// resolving all types of errors together.
118pub trait BaseError: Raw<xcb_generic_error_t> {
119    /// The extension associated to this error, or `None` for the main protocol
120    const EXTENSION: Option<Extension>;
121
122    /// The number associated to this error
123    const NUMBER: u32;
124}
125
126/// Trait for the resolution of raw wire event to a unified event enum.
127///
128/// `Self` is normally an enum of several event subtypes.
129/// See [crate::x::Event] and [crate::Event]
130pub(crate) trait ResolveWireEvent: Sized {
131    /// Resolve a pointer to `xcb_generic_event_t` to `Self`, inferring the correct subtype
132    /// using `response_type` field and `first_event`
133    ///
134    /// # Safety
135    /// `event` must be a valid, non-null event returned by `xcb_wait_for_event`
136    /// or similar function
137    unsafe fn resolve_wire_event(first_event: u8, event: *mut xcb_generic_event_t) -> Option<Self>;
138}
139
140/// Trait for the resolution of raw wire GE_GENERIC event to a unified event enum.
141///
142/// `Self` is normally an enum of several event subtypes.
143/// See [crate::xinput::Event] and [crate::Event]
144pub(crate) trait ResolveWireGeEvent: Sized {
145    /// Resolve a pointer to `xcb_ge_generic_event_t` to `Self`, inferring the correct subtype
146    /// using `event_type` field.
147    ///
148    /// # Panics
149    /// Panics if the event subtype cannot be resolved for `Self`. That is, `event_type`
150    /// must be checked beforehand to be in range.
151    ///
152    /// # Safety
153    /// `event` must be a valid, non-null event returned by `xcb_wait_for_event`
154    /// or similar function
155    unsafe fn resolve_wire_ge_event(event: *mut xcb_ge_generic_event_t) -> Self;
156}
157
158/// Trait for the resolution of raw wire error to a unified error enum.
159///
160/// `Self` is normally an enum of several event subtypes.
161/// See [crate::x::Error] and [crate::ProtocolError]
162pub(crate) trait ResolveWireError: Sized {
163    /// Convert a pointer to `xcb_generic_error_t` to `Self`, inferring the correct subtype
164    /// using `response_type` field and `first_error`.
165    ///
166    /// # Safety
167    /// `err` must be a valid, non-null error obtained by `xcb_wait_for_reply`
168    /// or similar function
169    unsafe fn resolve_wire_error(first_error: u8, error: *mut xcb_generic_error_t) -> Option<Self>;
170}
171
172/// Trait for types that can serialize themselves to the X wire.
173///
174/// This trait is used internally for requests serialization.
175pub(crate) trait WiredOut {
176    /// Compute the length of wired serialized data of self
177    fn wire_len(&self) -> usize;
178
179    /// Serialize `self` over the X wire and returns how many bytes were written.
180    ///
181    /// `wire_buf` must be larger or as long as the value returned by `wire_len`.
182    /// `serialize` MUST write the data in its entirety at once, at the begining of `wire_buf`.
183    /// That is, it returns the same value as `wire_len`.
184    /// The interest in returning the value is that it is easy to compute in `serialize` and allow
185    /// to easily chain serialization of fields in a struct.
186    ///
187    /// # Panics
188    /// Panics if `wire_buf` is too small to contain the serialized representation of `self`.
189    fn serialize(&self, wire_buf: &mut [u8]) -> usize;
190}
191
192/// Trait for types that can unserialize themselves from the X wire.
193pub(crate) trait WiredIn {
194    /// type of external context necessary to figure out the representation of the data
195    type Params: Copy;
196
197    /// Compute the length of serialized data of an instance starting by `ptr`.
198    ///
199    /// # Safety
200    /// This function is highly unsafe as the pointer must point to data that is a valid
201    /// wired representation of `Self`. Failure to respect this will lead to dereferencing invalid memory.
202    unsafe fn compute_wire_len(ptr: *const u8, params: Self::Params) -> usize;
203
204    /// Unserialize an instance of `Self` from the X wire
205    ///
206    /// `offset` value is increased by the number of bytes corresponding to the representation of `Self`.
207    /// This allows for efficient chaining of unserialization as the data offset is either known at
208    /// compile time, or has to be computed anyway.
209    ///
210    /// # Safety
211    /// This function is highly unsafe as the pointer must point to data that is a valid
212    /// wired representation of `Self`. Failure to respect this will lead to dereferencing invalid memory.
213    unsafe fn unserialize(ptr: *const u8, params: Self::Params, offset: &mut usize) -> Self;
214}
215
216macro_rules! impl_wired_simple {
217    ($typ:ty) => {
218        impl WiredOut for $typ {
219            fn wire_len(&self) -> usize {
220                mem::size_of::<Self>()
221            }
222
223            fn serialize(&self, wire_buf: &mut [u8]) -> usize {
224                debug_assert!(wire_buf.len() >= mem::size_of::<Self>());
225                let buf_size = self.wire_len();
226                let src =
227                    unsafe { slice::from_raw_parts(self as *const Self as *const u8, buf_size) };
228                wire_buf[..buf_size].copy_from_slice(src);
229                buf_size
230            }
231        }
232
233        impl WiredIn for $typ {
234            type Params = ();
235
236            unsafe fn compute_wire_len(_ptr: *const u8, _params: Self::Params) -> usize {
237                mem::size_of::<Self>()
238            }
239
240            unsafe fn unserialize(
241                ptr: *const u8,
242                _params: Self::Params,
243                offset: &mut usize,
244            ) -> Self {
245                *offset += mem::size_of::<Self>();
246                *(ptr as *const Self)
247            }
248        }
249    };
250}
251
252impl_wired_simple!(u8);
253impl_wired_simple!(u16);
254impl_wired_simple!(u32);
255impl_wired_simple!(u64);
256impl_wired_simple!(i8);
257impl_wired_simple!(i16);
258impl_wired_simple!(i32);
259impl_wired_simple!(f32);
260
261impl<T: Xid> WiredOut for T {
262    fn wire_len(&self) -> usize {
263        4
264    }
265
266    fn serialize(&self, wire_buf: &mut [u8]) -> usize {
267        debug_assert!(wire_buf.len() >= 4);
268        let buf_size = self.wire_len();
269        let resource_id = self.resource_id();
270        let src =
271            unsafe { slice::from_raw_parts(&resource_id as *const u32 as *const u8, buf_size) };
272        wire_buf[..buf_size].copy_from_slice(src);
273        buf_size
274    }
275}
276
277impl<T: XidNew> WiredIn for T {
278    type Params = ();
279
280    unsafe fn compute_wire_len(_ptr: *const u8, _params: Self::Params) -> usize {
281        4
282    }
283
284    unsafe fn unserialize(ptr: *const u8, _params: Self::Params, offset: &mut usize) -> Self {
285        *offset += 4;
286        let xid = *(ptr as *const u32);
287        T::new(xid)
288    }
289}
290
291/// Trait for request replies
292pub trait Reply {
293    /// Build the reply struct from a raw pointer.
294    ///
295    /// # Safety
296    /// `raw` must be a pointer to a valid wire representation of `Self`, allocated with [`libc::malloc`].
297    unsafe fn from_raw(raw: *const u8) -> Self;
298
299    /// Consume the reply struct into a raw pointer.
300    ///
301    /// # Safety
302    /// The returned pointer must be freed with [`libc::free`] to avoid any memory leak, or be used
303    /// to build another reply.
304    unsafe fn into_raw(self) -> *const u8;
305
306    /// Get the raw pointer of the XCB reply.
307    ///
308    /// # Safety
309    /// The returned pointer must NOT be freed. Passing this pointer to [`libc::free`] will result in a double free
310    /// when the reply is dropped.
311    unsafe fn as_raw(&self) -> *const u8;
312}
313
314/// General trait for cookies returned by requests.
315pub trait Cookie {
316    /// # Safety
317    /// `seq` must be a valid cookie for a given `Request` or `Reply`.
318    unsafe fn from_sequence(seq: u64) -> Self;
319
320    /// The raw sequence number associated with the cookie.
321    fn sequence(&self) -> u64;
322}
323
324/// A marker trait for a cookie that allows synchronized error checking.
325///
326/// # Safety
327/// Cookies not implementing this trait acknowledge that the error is sent to the event loop
328///
329/// See also [Connection::send_request], [Connection::send_request_checked] and [Connection::check_request]
330pub unsafe trait CookieChecked: Cookie {}
331
332/// A trait for checked cookies of requests that send a reply.
333///
334/// # Safety
335/// Cookies implementing this trait acknowledge that their error is checked when the reply is fetched from the server.
336/// This is the default cookie type for requests with reply.
337///
338/// See also [Connection::send_request], [Connection::wait_for_reply]
339pub unsafe trait CookieWithReplyChecked: CookieChecked {
340    /// The reply type associated with the cookie
341    type Reply: Reply;
342}
343
344/// A trait for unchecked cookies of requests that send a reply.
345///
346/// # Safety
347/// Cookies implementing this trait acknowledge that their error is not checked when the reply is fetched from the server
348/// but in the event loop.
349///
350/// See also [Connection::send_request_unchecked], [Connection::wait_for_event]
351pub unsafe trait CookieWithReplyUnchecked: Cookie {
352    /// The reply type associated with the cookie
353    type Reply: Reply;
354}
355
356/// The default cookie type returned by void-requests.
357///
358/// See [Connection::send_request]
359#[derive(Debug)]
360pub struct VoidCookie {
361    seq: u64,
362}
363
364impl Cookie for VoidCookie {
365    unsafe fn from_sequence(seq: u64) -> Self {
366        VoidCookie { seq }
367    }
368
369    fn sequence(&self) -> u64 {
370        self.seq
371    }
372}
373
374/// The checked cookie type returned by void-requests.
375///
376/// See [Connection::send_request_checked]
377#[derive(Debug)]
378pub struct VoidCookieChecked {
379    seq: u64,
380}
381
382impl Cookie for VoidCookieChecked {
383    unsafe fn from_sequence(seq: u64) -> Self {
384        VoidCookieChecked { seq }
385    }
386
387    fn sequence(&self) -> u64 {
388        self.seq
389    }
390}
391
392unsafe impl CookieChecked for VoidCookieChecked {}
393
394/// Trait implemented by all requests to send the serialized data over the wire.
395///
396/// # Safety
397/// Types implementing this trait acknowledge that the returned value of `raw_request` correspond
398/// to a cookie for `Self` request and is checked or unchecked depending on the `checked` flag value.
399pub unsafe trait RawRequest {
400    /// Actual implementation of the request sending
401    ///
402    /// Send the request over the `conn` wire and return a cookie sequence fitting with the `checked` flag
403    /// of `Self`
404    fn raw_request(&self, conn: &Connection, checked: bool) -> u64;
405}
406
407/// Trait implemented by requests types.
408///
409/// See [crate::x::CreateWindow] as an example.
410pub trait Request: RawRequest {
411    /// The default cookie associated to this request.
412    type Cookie: Cookie;
413
414    /// `false` if the request returns a reply, `true` otherwise.
415    const IS_VOID: bool;
416}
417
418/// Marker trait for requests that do not return a reply.
419///
420/// These trait is implicitely associated with [`VoidCookie`] and [`VoidCookieChecked`].
421pub trait RequestWithoutReply: Request {}
422
423/// Trait for requests that return a reply.
424pub trait RequestWithReply: Request {
425    /// Reply associated with the request
426    type Reply: Reply;
427    /// Default cookie type for the request, as returned by [Connection::send_request].
428    type Cookie: CookieWithReplyChecked<Reply = Self::Reply>;
429    /// Unchecked cookie type for the request, as returned by [Connection::send_request_unchecked].
430    type CookieUnchecked: CookieWithReplyUnchecked<Reply = Self::Reply>;
431}
432
433/// Determines whether Xlib or XCB owns the event queue of [`Connection`].
434///
435/// This item is behind the `xlib_xcb` cargo feature.
436///
437/// See [`Connection::set_event_queue_owner`].
438#[cfg(feature = "xlib_xcb")]
439#[derive(Debug)]
440pub enum EventQueueOwner {
441    /// XCB owns the event queue
442    Xcb,
443    /// Xlib owns the event queue
444    Xlib,
445}
446
447/// Container for authentication information to connect to the X server
448///
449/// See [Connection::connect_to_display_with_auth_info] and [Connection::connect_to_fd].
450#[derive(Copy, Clone, Debug)]
451pub struct AuthInfo<'a> {
452    /// String containing the authentication protocol name,
453    /// such as "MIT-MAGIC-COOKIE-1" or "XDM-AUTHORIZATION-1".
454    pub name: &'a str,
455    /// data interpreted in a protocol specific manner
456    pub data: &'a str,
457}
458
459/// Display info returned by [`parse_display`]
460#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
461pub struct DisplayInfo {
462    /// The hostname
463    pub host: String,
464    /// The display number
465    pub display: i32,
466    /// The screen number
467    pub screen: i32,
468}
469
470/// Parses a display string in the form documented by [X (7x)](https://linux.die.net/man/7/x).
471///
472/// Returns `Some(DisplayInfo)` on success and `None` otherwise.
473/// Has no side effects on failure.
474///
475/// If `name` empty, it uses the environment variable `DISPLAY`.
476///
477/// If `name` does not contain a screen number, `DisplayInfo::screen` is set to `0`.
478///
479/// # Example
480/// ```
481/// use xcb::{DisplayInfo, parse_display};
482///
483/// assert_eq!(parse_display(":0"), Some(DisplayInfo {
484///     host: "".to_string(),
485///     display: 0,
486///     screen: 0,
487/// }));
488/// assert_eq!(parse_display("localhost:0.1"), Some(DisplayInfo {
489///     host: "localhost".to_string(),
490///     display: 0,
491///     screen: 1,
492/// }));
493///
494/// assert!(parse_display("0").is_none());
495/// ```
496pub fn parse_display(name: &str) -> Option<DisplayInfo> {
497    let name = CString::new(name).unwrap();
498    let mut hostp: *mut c_char = ptr::null_mut();
499    let mut display = 0i32;
500    let mut screen = 0i32;
501
502    let success = unsafe {
503        xcb_parse_display(
504            name.as_ptr(),
505            &mut hostp as *mut _,
506            &mut display as *mut _,
507            &mut screen as *mut _,
508        )
509    };
510
511    if success != 0 {
512        let host = unsafe { CStr::from_ptr(hostp as *const _) }
513            .to_str()
514            .unwrap()
515            .to_string();
516
517        unsafe {
518            libc::free(hostp as *mut _);
519        }
520
521        Some(DisplayInfo {
522            host,
523            display,
524            screen,
525        })
526    } else {
527        None
528    }
529}
530
531/// A struct that serve as an identifier for internal special queue in XCB
532///
533/// See [Connection::register_for_special_xge].
534#[deprecated(note = "Broken API: use `SpecialEvent` instead")]
535#[cfg(any(feature = "xinput", feature = "present"))]
536#[derive(Debug)]
537pub struct SpecialEventId {
538    raw: *mut xcb_special_event_t,
539    stamp: Timestamp,
540}
541
542#[allow(deprecated)]
543#[cfg(any(feature = "xinput", feature = "present"))]
544impl SpecialEventId {
545    /// The X timestamp associated with this special event Id
546    pub fn stamp(&self) -> Timestamp {
547        self.stamp
548    }
549}
550
551/// A struct that serve as an identifier for internal special queue in XCB
552///
553/// See [Connection::register_for_special_event].
554#[cfg(any(feature = "xinput", feature = "present"))]
555#[derive(Debug)]
556pub struct SpecialEvent {
557    raw: *mut xcb_special_event_t,
558}
559
560// safe because XCB is thread safe.
561#[cfg(any(feature = "xinput", feature = "present"))]
562unsafe impl Send for SpecialEvent {}
563
564#[cfg(any(feature = "xinput", feature = "present"))]
565unsafe impl Sync for SpecialEvent {}
566
567/// Error type that is returned by `Connection::has_error`.
568#[derive(Debug)]
569pub enum ConnError {
570    /// xcb connection errors because of socket, pipe and other stream errors.
571    Connection,
572    /// xcb connection shutdown because of extension not supported
573    ClosedExtNotSupported,
574    /// malloc(), calloc() and realloc() error upon failure, for eg ENOMEM
575    ClosedMemInsufficient,
576    /// Connection closed, exceeding request length that server accepts.
577    ClosedReqLenExceed,
578    /// Connection closed, error during parsing display string.
579    ClosedParseErr,
580    /// Connection closed because the server does not have a screen
581    /// matching the display.
582    ClosedInvalidScreen,
583    /// Connection closed because some file descriptor passing operation failed.
584    ClosedFdPassingFailed,
585    /// XOpenDisplay returned NULL
586    #[cfg(feature = "xlib_xcb")]
587    XOpenDisplay,
588}
589
590impl ConnError {
591    fn to_str(&self) -> &str {
592        match *self {
593            ConnError::Connection => "Connection error, possible I/O error",
594            ConnError::ClosedExtNotSupported => "Connection closed, X extension not supported",
595            ConnError::ClosedMemInsufficient => "Connection closed, insufficient memory",
596            ConnError::ClosedReqLenExceed => {
597                "Connection closed, exceeded request length that server accepts."
598            }
599            ConnError::ClosedParseErr => "Connection closed, error during parsing display string",
600            ConnError::ClosedInvalidScreen => {
601                "Connection closed, the server does not have a screen matching the display"
602            }
603            ConnError::ClosedFdPassingFailed => {
604                "Connection closed, some file descriptor passing operation failed"
605            }
606            #[cfg(feature = "xlib_xcb")]
607            ConnError::XOpenDisplay => {
608                "XOpenDisplay failed to open a display. Check the $DISPLAY env var"
609            }
610        }
611    }
612}
613
614impl Display for ConnError {
615    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
616        self.to_str().fmt(f)
617    }
618}
619
620impl std::error::Error for ConnError {
621    fn description(&self) -> &str {
622        self.to_str()
623    }
624}
625
626/// The result type associated with [ConnError].
627pub type ConnResult<T> = result::Result<T, ConnError>;
628
629/// The result type associated with [ProtocolError].
630pub type ProtocolResult<T> = result::Result<T, ProtocolError>;
631
632/// The general error type for Rust-XCB.
633#[derive(Debug)]
634pub enum Error {
635    /// I/O error issued from the connection.
636    Connection(ConnError),
637    /// A protocol related error issued by the X server.
638    Protocol(ProtocolError),
639}
640
641impl Display for Error {
642    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
643        match self {
644            Error::Connection(_) => f.write_str("xcb connection error"),
645            Error::Protocol(_) => f.write_str("xcb protocol error"),
646        }
647    }
648}
649
650impl std::error::Error for Error {
651    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
652        match self {
653            Error::Connection(err) => Some(err),
654            Error::Protocol(err) => Some(err),
655        }
656    }
657}
658
659impl From<ConnError> for Error {
660    fn from(err: ConnError) -> Error {
661        Error::Connection(err)
662    }
663}
664
665impl From<ProtocolError> for Error {
666    fn from(err: ProtocolError) -> Error {
667        Error::Protocol(err)
668    }
669}
670
671/// The general result type for Rust-XCB.
672pub type Result<T> = result::Result<T, Error>;
673
674/// `Connection` is the central object of XCB.
675///
676/// It handles all communications with the X server.
677/// It dispatches the requests, receives the replies, poll/wait the events.
678/// It also resolves the errors and events from X server.
679///
680/// `Connection` is thread safe.
681///
682/// It internally wraps an `xcb_connection_t` object and
683/// will call `xcb_disconnect` when the `Connection` goes out of scope.
684pub struct Connection {
685    c: *mut xcb_connection_t,
686
687    #[cfg(feature = "xlib_xcb")]
688    dpy: *mut xlib::Display,
689
690    ext_data: Vec<ExtensionData>,
691
692    // Following field is used to handle the
693    // rare (if existing) cases of multiple connections
694    // per application.
695    // Only the first established connections is used
696    // to print the name of atoms during Debug
697    #[cfg(feature = "debug_atom_names")]
698    dbg_atom_names: bool,
699}
700
701unsafe impl Send for Connection {}
702unsafe impl Sync for Connection {}
703
704impl Connection {
705    /// Connects to the X server.
706    ///
707    /// Connects to the X server specified by `display_name.` If
708    /// `display_name` is `None,` uses the value of the `DISPLAY` environment
709    /// variable.
710    ///
711    /// If no screen is preferred, the second member of the tuple is set to 0.
712    ///
713    /// # Example
714    /// ```no_run
715    /// fn main() -> xcb::Result<()> {
716    ///     let (conn, screen) = xcb::Connection::connect(None)?;
717    ///     Ok(())
718    /// }
719    /// ```
720    pub fn connect(display_name: Option<&str>) -> ConnResult<(Connection, i32)> {
721        Self::connect_with_extensions(display_name, &[], &[])
722    }
723
724    /// Connects to the X server and cache extension data.
725    ///
726    /// Connects to the X server specified by `display_name.` If
727    /// `display_name` is `None,` uses the value of the `DISPLAY` environment
728    /// variable.
729    ///
730    /// Extension data specified by `mandatory` and `optional` is cached to allow
731    /// the resolution of events and errors in these extensions.
732    ///
733    /// If no screen is preferred, the second member of the tuple is set to 0.
734    ///
735    /// # Panics
736    /// Panics if one of the mandatory extension is not present.
737    ///
738    /// # Example
739    /// ```no_run
740    /// fn main() -> xcb::Result<()> {
741    ///     let (conn, screen) = xcb::Connection::connect_with_extensions(
742    ///         None, &[xcb::Extension::Input, xcb::Extension::Xkb], &[]
743    ///     )?;
744    ///     Ok(())
745    /// }
746    /// ```
747    pub fn connect_with_extensions(
748        display_name: Option<&str>,
749        mandatory: &[Extension],
750        optional: &[Extension],
751    ) -> ConnResult<(Connection, i32)> {
752        let mut screen_num: c_int = 0;
753        let displayname = display_name.map(|s| CString::new(s).unwrap());
754        unsafe {
755            let conn = if let Some(display) = displayname {
756                xcb_connect(display.as_ptr(), &mut screen_num)
757            } else {
758                xcb_connect(ptr::null(), &mut screen_num)
759            };
760
761            check_connection_error(conn)?;
762
763            let conn = Self::from_raw_conn_and_extensions(conn, mandatory, optional);
764            conn.has_error().map(|_| (conn, screen_num as i32))
765        }
766    }
767
768    /// Open a new connection with Xlib.
769    ///
770    /// The event queue owner defaults to Xlib.
771    /// One would need to open an XCB connection with Xlib in order to use
772    /// OpenGL.
773    ///
774    /// This function is behind the `xlib_xcb` cargo feature.
775    #[cfg(feature = "xlib_xcb")]
776    pub fn connect_with_xlib_display() -> ConnResult<(Connection, i32)> {
777        unsafe {
778            let dpy = xlib::XOpenDisplay(ptr::null());
779            if dpy.is_null() {
780                return Err(ConnError::XOpenDisplay);
781            }
782
783            check_connection_error(XGetXCBConnection(dpy))?;
784
785            let conn = Self::from_xlib_display(dpy);
786
787            conn.has_error()
788                .map(|_| (conn, xlib::XDefaultScreen(dpy) as i32))
789        }
790    }
791
792    /// Open a new connection with Xlib and cache the provided extensions data.
793    ///
794    /// Data of extensions specified by `mandatory` and `optional` is cached to allow
795    /// the resolution of events and errors in these extensions.
796    ///
797    /// The event queue owner defaults to Xlib.
798    /// One would need to open an XCB connection with Xlib in order to use
799    /// OpenGL.
800    ///
801    /// This function is behind the `xlib_xcb` cargo feature.
802    ///
803    /// # Panics
804    /// Panics if one of the mandatory extension is not present.
805    #[cfg(feature = "xlib_xcb")]
806    pub fn connect_with_xlib_display_and_extensions(
807        mandatory: &[Extension],
808        optional: &[Extension],
809    ) -> ConnResult<(Connection, i32)> {
810        unsafe {
811            let dpy = xlib::XOpenDisplay(ptr::null());
812            if dpy.is_null() {
813                return Err(ConnError::XOpenDisplay);
814            }
815
816            check_connection_error(XGetXCBConnection(dpy))?;
817
818            let conn = Self::from_xlib_display_and_extensions(dpy, mandatory, optional);
819
820            conn.has_error()
821                .map(|_| (conn, xlib::XDefaultScreen(dpy) as i32))
822        }
823    }
824
825    /// Connects to the X server with an open socket file descriptor and optional authentification info.
826    ///
827    /// Connects to an X server, given the open socket fd and the
828    /// `auth_info`. The file descriptor `fd` is bidirectionally connected to an X server.
829    /// If the connection should be unauthenticated, `auth_info` must be `None`.
830    #[deprecated(note = "unsound API, use `connect_with_fd` instead")]
831    #[doc(hidden)]
832    pub fn connect_to_fd(fd: RawFd, auth_info: Option<AuthInfo<'_>>) -> ConnResult<Self> {
833        #[allow(deprecated)]
834        Self::connect_to_fd_with_extensions(fd, auth_info, &[], &[])
835    }
836
837    /// Connects to the X server with an open socket file descriptor and optional authentification info.
838    ///
839    /// Extension data specified by `mandatory` and `optional` is cached to allow
840    /// the resolution of events and errors in these extensions.
841    ///
842    /// Connects to an X server, given the open socket fd and the
843    /// `auth_info`. The file descriptor `fd` is bidirectionally connected to an X server.
844    /// If the connection should be unauthenticated, `auth_info` must be `None`.
845    ///
846    /// # Panics
847    /// Panics if one of the mandatory extension is not present.
848    #[deprecated(note = "unsound API, use `connect_with_fd_and_extensions` instead")]
849    #[doc(hidden)]
850    pub fn connect_to_fd_with_extensions(
851        fd: RawFd,
852        auth_info: Option<AuthInfo<'_>>,
853        mandatory: &[Extension],
854        optional: &[Extension],
855    ) -> ConnResult<Self> {
856        let mut auth_info = auth_info.map(|auth_info| {
857            let auth_name = CString::new(auth_info.name).unwrap();
858            let auth_data = CString::new(auth_info.data).unwrap();
859
860            let auth_info = xcb_auth_info_t {
861                namelen: auth_name.as_bytes().len() as _,
862                name: auth_name.as_ptr() as *mut _,
863                datalen: auth_data.as_bytes().len() as _,
864                data: auth_data.as_ptr() as *mut _,
865            };
866            // return the strings too otherwise they would drop
867            (auth_info, auth_name, auth_data)
868        });
869
870        let ai_ptr = if let Some(auth_info) = auth_info.as_mut() {
871            &mut auth_info.0 as *mut _
872        } else {
873            ptr::null_mut()
874        };
875
876        let conn = unsafe {
877            let conn = xcb_connect_to_fd(fd, ai_ptr);
878            check_connection_error(conn)?;
879
880            Self::from_raw_conn_and_extensions(conn, mandatory, optional)
881        };
882
883        conn.has_error().map(|_| conn)
884    }
885
886    /// Connects to the X server with an open socket file descriptor and optional authentification info.
887    ///
888    /// Connects to an X server, given the open socket fd and the
889    /// `auth_info`. The file descriptor `fd` is bidirectionally connected to an X server.
890    /// If the connection should be unauthenticated, `auth_info` must be `None`.
891    pub fn connect_with_fd(fd: OwnedFd, auth_info: Option<AuthInfo<'_>>) -> ConnResult<Self> {
892        Self::connect_with_fd_and_extensions(fd, auth_info, &[], &[])
893    }
894
895    /// Connects to the X server with an open socket file descriptor and optional authentification info.
896    ///
897    /// Extension data specified by `mandatory` and `optional` is cached to allow
898    /// the resolution of events and errors in these extensions.
899    ///
900    /// Connects to an X server, given the open socket fd and the
901    /// `auth_info`. The file descriptor `fd` is bidirectionally connected to an X server.
902    /// If the connection should be unauthenticated, `auth_info` must be `None`.
903    ///
904    /// # Panics
905    /// Panics if one of the mandatory extension is not present.
906    pub fn connect_with_fd_and_extensions(
907        fd: OwnedFd,
908        auth_info: Option<AuthInfo<'_>>,
909        mandatory: &[Extension],
910        optional: &[Extension],
911    ) -> ConnResult<Self> {
912        let mut auth_info = auth_info.map(|auth_info| {
913            let auth_name = CString::new(auth_info.name).unwrap();
914            let auth_data = CString::new(auth_info.data).unwrap();
915
916            let auth_info = xcb_auth_info_t {
917                namelen: auth_name.as_bytes().len() as _,
918                name: auth_name.as_ptr() as *mut _,
919                datalen: auth_data.as_bytes().len() as _,
920                data: auth_data.as_ptr() as *mut _,
921            };
922            // return the strings too otherwise they would drop
923            (auth_info, auth_name, auth_data)
924        });
925
926        let ai_ptr = if let Some(auth_info) = auth_info.as_mut() {
927            &mut auth_info.0 as *mut _
928        } else {
929            ptr::null_mut()
930        };
931
932        let fd = fd.into_raw_fd();
933
934        let conn = unsafe {
935            let conn = xcb_connect_to_fd(fd, ai_ptr);
936            check_connection_error(conn)?;
937
938            Self::from_raw_conn_and_extensions(conn, mandatory, optional)
939        };
940
941        conn.has_error().map(|_| conn)
942    }
943
944    /// Connects to the X server, using an authorization information.
945    ///
946    /// Connects to the X server specified by `display_name`, using the
947    /// authorization `auth_info`. If a particular screen on that server, it is
948    /// returned in the second tuple member, which is otherwise set to `0`.
949    pub fn connect_to_display_with_auth_info(
950        display_name: Option<&str>,
951        auth_info: AuthInfo<'_>,
952    ) -> ConnResult<(Connection, i32)> {
953        Self::connect_to_display_with_auth_info_and_extensions(display_name, auth_info, &[], &[])
954    }
955
956    /// Connects to the X server, using an authorization information.
957    ///
958    /// Extension data specified by `mandatory` and `optional` is cached to allow
959    /// the resolution of events and errors in these extensions.
960    ///
961    /// Connects to the X server specified by `display_name`, using the
962    /// authorization `auth_info`. If a particular screen on that server, it is
963    /// returned in the second tuple member, which is otherwise set to `0`.
964    ///
965    /// # Panics
966    /// Panics if one of the mandatory extension is not present.
967    pub fn connect_to_display_with_auth_info_and_extensions(
968        display_name: Option<&str>,
969        auth_info: AuthInfo<'_>,
970        mandatory: &[Extension],
971        optional: &[Extension],
972    ) -> ConnResult<(Connection, i32)> {
973        let mut screen_num: c_int = 0;
974        let display_name = display_name.map(|s| CString::new(s).unwrap());
975
976        unsafe {
977            let display_name = if let Some(display_name) = &display_name {
978                display_name.as_ptr()
979            } else {
980                ptr::null()
981            };
982
983            let auth_name = CString::new(auth_info.name).unwrap();
984            let auth_data = CString::new(auth_info.data).unwrap();
985
986            let mut auth_info = xcb_auth_info_t {
987                namelen: auth_name.as_bytes().len() as _,
988                name: auth_name.as_ptr() as *mut _,
989                datalen: auth_data.as_bytes().len() as _,
990                data: auth_data.as_ptr() as *mut _,
991            };
992
993            let conn = xcb_connect_to_display_with_auth_info(
994                display_name,
995                &mut auth_info as *mut _,
996                &mut screen_num as *mut _,
997            );
998
999            check_connection_error(conn)?;
1000
1001            let conn = Self::from_raw_conn_and_extensions(conn, mandatory, optional);
1002            conn.has_error().map(|_| (conn, screen_num as i32))
1003        }
1004    }
1005
1006    /// builds a new Connection object from an available connection
1007    ///
1008    /// # Safety
1009    /// The `conn` pointer must point to a valid `xcb_connection_t`
1010    pub unsafe fn from_raw_conn(conn: *mut xcb_connection_t) -> Connection {
1011        Self::from_raw_conn_and_extensions(conn, &[], &[])
1012    }
1013
1014    /// Builds a new `Connection` object from an available connection and cache the extension data
1015    ///
1016    /// Extension data specified by `mandatory` and `optional` is cached to allow
1017    /// the resolution of events and errors in these extensions.
1018    ///
1019    /// # Panics
1020    /// Panics if the connection is null or in error state.
1021    /// Panics if one of the mandatory extension is not present.
1022    ///
1023    /// # Safety
1024    /// The `conn` pointer must point to a valid `xcb_connection_t`
1025    pub unsafe fn from_raw_conn_and_extensions(
1026        conn: *mut xcb_connection_t,
1027        mandatory: &[Extension],
1028        optional: &[Extension],
1029    ) -> Connection {
1030        assert!(!conn.is_null());
1031        assert!(check_connection_error(conn).is_ok());
1032
1033        #[cfg(feature = "debug_atom_names")]
1034        let dbg_atom_names = {
1035            if dan::DAN_CONN.is_null() {
1036                dan::DAN_CONN = conn;
1037                true
1038            } else {
1039                false
1040            }
1041        };
1042
1043        let ext_data = cache_extensions_data(conn, mandatory, optional);
1044
1045        #[cfg(not(feature = "xlib_xcb"))]
1046        #[cfg(not(feature = "debug_atom_names"))]
1047        return Connection { c: conn, ext_data };
1048
1049        #[cfg(not(feature = "xlib_xcb"))]
1050        #[cfg(feature = "debug_atom_names")]
1051        return Connection {
1052            c: conn,
1053            ext_data,
1054            dbg_atom_names,
1055        };
1056
1057        #[cfg(feature = "xlib_xcb")]
1058        #[cfg(not(feature = "debug_atom_names"))]
1059        return Connection {
1060            c: conn,
1061            dpy: ptr::null_mut(),
1062            ext_data,
1063        };
1064
1065        #[cfg(feature = "xlib_xcb")]
1066        #[cfg(feature = "debug_atom_names")]
1067        return Connection {
1068            c: conn,
1069            dpy: ptr::null_mut(),
1070            ext_data,
1071            dbg_atom_names,
1072        };
1073    }
1074
1075    /// Initialize a new `Connection` from an existing Xlib display.
1076    ///
1077    /// Wraps a `xlib::Display` and get an XCB connection from an exisiting object
1078    /// `xlib::XCloseDisplay` will be called when the returned object is dropped.
1079    ///
1080    /// This function is behind the `xlib_xcb` cargo feature.
1081    ///
1082    /// # Safety
1083    /// The `dpy` pointer must be a pointer to a valid `xlib::Display`
1084    #[cfg(feature = "xlib_xcb")]
1085    pub unsafe fn from_xlib_display(dpy: *mut xlib::Display) -> Connection {
1086        Self::from_xlib_display_and_extensions(dpy, &[], &[])
1087    }
1088
1089    /// Initialize a new `Connection` from an existing Xlib display.
1090    ///
1091    /// Wraps a `xlib::Display` and get an XCB connection from an exisiting object
1092    /// `xlib::XCloseDisplay` will be called when the returned object is dropped.
1093    ///
1094    /// Extension data specified by `mandatory` and `optional` is cached to allow
1095    /// the resolution of events and errors in these extensions.
1096    ///
1097    /// This function is behind the `xlib_xcb` cargo feature.
1098    ///
1099    /// # Panics
1100    /// Panics if the connection is null or in error state.
1101    ///
1102    /// # Safety
1103    /// The `dpy` pointer must be a pointer to a valid `xlib::Display`.
1104    #[cfg(feature = "xlib_xcb")]
1105    pub unsafe fn from_xlib_display_and_extensions(
1106        dpy: *mut xlib::Display,
1107        mandatory: &[Extension],
1108        optional: &[Extension],
1109    ) -> Connection {
1110        assert!(!dpy.is_null(), "attempt connect with null display");
1111        let c = XGetXCBConnection(dpy);
1112
1113        assert!(check_connection_error(c).is_ok());
1114
1115        #[cfg(feature = "debug_atom_names")]
1116        let dbg_atom_names = {
1117            if dan::DAN_CONN.is_null() {
1118                dan::DAN_CONN = c;
1119                true
1120            } else {
1121                false
1122            }
1123        };
1124
1125        let ext_data = cache_extensions_data(c, mandatory, optional);
1126
1127        #[cfg(feature = "debug_atom_names")]
1128        return Connection {
1129            c,
1130            dpy,
1131            ext_data,
1132            dbg_atom_names,
1133        };
1134
1135        #[cfg(not(feature = "debug_atom_names"))]
1136        return Connection { c, dpy, ext_data };
1137    }
1138
1139    /// Get the extensions activated for this connection.
1140    ///
1141    /// You may use this to check if an optional extension is present or not.
1142    ///
1143    /// # Example
1144    /// ```no_run
1145    /// # fn main() -> xcb::Result<()> {
1146    ///     // Xkb is mandatory, Input is optional
1147    ///     let (conn, screen) = xcb::Connection::connect_with_extensions(
1148    ///         None, &[xcb::Extension::Xkb], &[xcb::Extension::Input]
1149    ///     )?;
1150    ///     // now we check if Input is present or not
1151    ///     let has_input_ext = conn.active_extensions().any(|e| e == xcb::Extension::Input);
1152    /// #   Ok(())
1153    /// # }
1154    /// ```
1155    pub fn active_extensions(&self) -> impl Iterator<Item = Extension> + '_ {
1156        self.ext_data.iter().map(|eed| eed.ext)
1157    }
1158
1159    /// Get the data of the extensions activated for this connection.
1160    ///
1161    /// You may use this to manually resolve an event or an error with
1162    /// `xcb::event::resolve_event` or `xcb::error::resolve_error`.
1163    pub fn active_extensions_data(&self) -> &[ExtensionData] {
1164        &self.ext_data
1165    }
1166
1167    /// Returns the inner ffi `xcb_connection_t` pointer
1168    pub fn get_raw_conn(&self) -> *mut xcb_connection_t {
1169        self.c
1170    }
1171
1172    /// Consumes this object, returning the inner ffi `xcb_connection_t` pointer
1173    pub fn into_raw_conn(self) -> *mut xcb_connection_t {
1174        let c = self.c;
1175        mem::forget(self);
1176        c
1177    }
1178
1179    /// Returns the inner ffi `xlib::Display` pointer.
1180    ///
1181    /// This function is behind the `xlib_xcb` cargo feature.
1182    #[cfg(feature = "xlib_xcb")]
1183    pub fn get_raw_dpy(&self) -> *mut xlib::Display {
1184        self.dpy
1185    }
1186
1187    /// Sets the owner of the event queue in the case if the connection is opened
1188    /// with the Xlib interface. In that case, the default owner is Xlib.
1189    ///
1190    /// This function is behind the `xlib_xcb` cargo feature.
1191    #[cfg(feature = "xlib_xcb")]
1192    pub fn set_event_queue_owner(&self, owner: EventQueueOwner) {
1193        debug_assert!(!self.dpy.is_null());
1194        unsafe {
1195            XSetEventQueueOwner(
1196                self.dpy,
1197                match owner {
1198                    EventQueueOwner::Xcb => XCBOwnsEventQueue,
1199                    EventQueueOwner::Xlib => XlibOwnsEventQueue,
1200                },
1201            );
1202        }
1203    }
1204
1205    /// Returns the maximum request length that this server accepts.
1206    ///
1207    /// In the absence of the BIG-REQUESTS extension, returns the
1208    /// maximum request length field from the connection setup data, which
1209    /// may be as much as 65535. If the server supports BIG-REQUESTS, then
1210    /// the maximum request length field from the reply to the
1211    /// BigRequestsEnable request will be returned instead.
1212    ///
1213    /// Note that this length is measured in four-byte units, making the
1214    /// theoretical maximum lengths roughly 256kB without BIG-REQUESTS and
1215    /// 16GB with.
1216    pub fn get_maximum_request_length(&self) -> u32 {
1217        unsafe { xcb_get_maximum_request_length(self.c) }
1218    }
1219
1220    /// Prefetch the maximum request length without blocking.
1221    ///
1222    /// Without blocking, does as much work as possible toward computing
1223    /// the maximum request length accepted by the X server.
1224    ///
1225    /// Invoking this function may send the [crate::bigreq::Enable] request,
1226    /// but will not block waiting for the reply.
1227    /// [Connection::get_maximum_request_length] will return the prefetched data
1228    /// after possibly blocking while the reply is retrieved.
1229    ///
1230    /// Note that in order for this function to be fully non-blocking, the
1231    /// application must previously have called [crate::bigreq::prefetch_extension_data].
1232    pub fn prefetch_maximum_request_length(&self) {
1233        unsafe {
1234            xcb_prefetch_maximum_request_length(self.c);
1235        }
1236    }
1237
1238    /// Allocates an XID for a new object.
1239    ///
1240    /// Returned value is typically used in requests such as `CreateWindow`.
1241    ///
1242    /// # Example
1243    /// ```no_run
1244    /// # use xcb::x;
1245    /// # fn main() -> xcb::Result<()> {
1246    /// # let conn = xcb::Connection::connect(None)?.0;
1247    /// let window: x::Window = conn.generate_id();
1248    /// # Ok(())
1249    /// # }
1250    /// ```
1251    pub fn generate_id<T: XidNew>(&self) -> T {
1252        unsafe { XidNew::new(xcb_generate_id(self.c)) }
1253    }
1254
1255    /// Forces any buffered output to be written to the server.
1256    ///
1257    /// Forces any buffered output to be written to the server. Blocks
1258    /// until the write is complete.
1259    ///
1260    /// There are several occasions ones want to flush the connection.
1261    /// One of them is before entering or re-entering the event loop after performing unchecked requests.
1262    ///
1263    /// The main difference between `flush` and `check_request` is that `flush` will not report protocol errors.
1264    /// If a protocol error is emitted by an unchecked void request, it will be reported through the event loop.
1265    ///
1266    /// See also: [wait_for_event](Connection::wait_for_event), [check_request](Connection::check_request),
1267    /// [send_and_check_request](Connection::send_and_check_request).
1268    pub fn flush(&self) -> ConnResult<()> {
1269        unsafe {
1270            let ret = xcb_flush(self.c);
1271            if ret > 0 {
1272                Ok(())
1273            } else {
1274                self.has_error()?;
1275                unreachable!()
1276            }
1277        }
1278    }
1279
1280    /// Resolve an xcb_generic_event_t pointer into an Event.
1281    /// # Safety
1282    /// The caller is repsonsible to ensure that the `ev` pointer is not NULL.
1283    /// The ownership of the pointer is effectively transferred to the
1284    /// returned Event and it will be destroyed when the Event is
1285    /// dropped.
1286    pub unsafe fn resolve_event(&self, ev: &mut xcb_generic_event_t) -> Event {
1287        event::resolve_event(ev, &self.ext_data)
1288    }
1289
1290    /// Resolve an xcb_generic_error_t pointer into an Error.
1291    /// # Safety
1292    /// The caller is repsonsible to ensure that the `err` pointer is not NULL.
1293    /// The ownership of the pointer is effectively transferred to the
1294    /// returned Error and it will be destroyed when the Error is
1295    /// dropped.
1296    pub unsafe fn resolve_error(&self, err: &mut xcb_generic_error_t) -> error::ProtocolError {
1297        error::resolve_error(err, &self.ext_data)
1298    }
1299
1300    /// Blocks and returns the next event or error from the server.
1301    ///
1302    /// # Example
1303    /// ```no_run
1304    /// use xcb::x;
1305    /// fn main() -> xcb::Result<()> {
1306    /// #   let conn = xcb::Connection::connect(None)?.0;
1307    ///     // ...
1308    ///     loop {
1309    ///         let event = match conn.wait_for_event() {
1310    ///             Err(xcb::Error::Connection(err)) => {
1311    ///                 panic!("unexpected I/O error: {}", err);
1312    ///             }
1313    ///             Err(xcb::Error::Protocol(xcb::ProtocolError::X(x::Error::Font(err), _req_name))) => {
1314    ///                 // may be this particular error is fine?
1315    ///                 continue;
1316    ///             }
1317    ///             Err(xcb::Error::Protocol(err)) => {
1318    ///                 panic!("unexpected protocol error: {:#?}", err);
1319    ///             }
1320    ///             Ok(event) => event,
1321    ///         };
1322    ///         match event {
1323    ///             xcb::Event::X(x::Event::KeyPress(ev)) => {
1324    ///                 // do stuff with the key press
1325    ///             }
1326    ///             // handle other events
1327    ///             _ => {
1328    ///                 break Ok(());
1329    ///             }
1330    ///         }
1331    ///     }
1332    ///  }
1333    /// ```
1334    pub fn wait_for_event(&self) -> Result<Event> {
1335        unsafe {
1336            let ev = xcb_wait_for_event(self.c);
1337            self.handle_wait_for_event(ev)
1338        }
1339    }
1340
1341    /// Returns the next event or error from the server without blocking.
1342    ///
1343    /// Returns the next event or error from the server, if one is
1344    /// available. If no event is available, that
1345    /// might be because an I/O error like connection close occurred while
1346    /// attempting to read the next event, in which case the connection is
1347    /// shut down when this function returns.
1348    pub fn poll_for_event(&self) -> Result<Option<Event>> {
1349        unsafe {
1350            let ev = xcb_poll_for_event(self.c);
1351            self.handle_poll_for_event(ev)
1352        }
1353    }
1354
1355    /// Returns the next event without reading from the connection.
1356    ///
1357    /// This is a version of [Connection::poll_for_event] that only examines the
1358    /// event queue for new events. The function doesn't try to read new
1359    /// events from the connection if no queued events are found.
1360    ///
1361    /// This function is useful for callers that know in advance that all
1362    /// interesting events have already been read from the connection. For
1363    /// example, callers might use [Connection::wait_for_reply] and be interested
1364    /// only of events that preceded a specific reply.
1365    pub fn poll_for_queued_event(&self) -> ProtocolResult<Option<Event>> {
1366        unsafe {
1367            let ev = xcb_poll_for_queued_event(self.c);
1368            if ev.is_null() {
1369                Ok(None)
1370            } else if is_error(ev) {
1371                Err(error::resolve_error(ev as *mut _, &self.ext_data))
1372            } else {
1373                Ok(Some(event::resolve_event(ev, &self.ext_data)))
1374            }
1375        }
1376    }
1377
1378    /// Start listening for a special event.
1379    ///
1380    /// Effectively creates an internal special queue for this event
1381    /// XGE events are only defined in the `xinput` and `present` extensions
1382    ///
1383    /// This function is present only if either of the `xinput` or `present` cargo features are active.
1384    #[deprecated(note = "Broken API: use `register_for_special_event` instead")]
1385    #[cfg(any(feature = "xinput", feature = "present"))]
1386    #[allow(deprecated)]
1387    pub fn register_for_special_xge<XGE: GeEvent>(&self) -> SpecialEventId {
1388        unsafe {
1389            let ext: *mut xcb_extension_t = match XGE::EXTENSION {
1390                #[cfg(feature = "xinput")]
1391                Extension::Input => ptr::addr_of_mut!(xinput::FFI_EXT),
1392                #[cfg(feature = "present")]
1393                Extension::Present => ptr::addr_of_mut!(present::FFI_EXT),
1394                _ => unreachable!("only Input and Present have XGE events"),
1395            };
1396
1397            let mut stamp: Timestamp = 0;
1398
1399            let raw = xcb_register_for_special_xge(self.c, ext, XGE::NUMBER, &mut stamp as *mut _);
1400
1401            SpecialEventId { raw, stamp }
1402        }
1403    }
1404
1405    /// Stop listening to a special event
1406    #[deprecated(note = "use `unregister_for_special_event` instead")]
1407    #[cfg(any(feature = "xinput", feature = "present"))]
1408    #[allow(deprecated)]
1409    pub fn unregister_for_special_xge(&self, se: SpecialEventId) {
1410        unsafe {
1411            xcb_unregister_for_special_event(self.c, se.raw);
1412        }
1413    }
1414
1415    /// Returns the next event from a special queue, blocking until one arrives
1416    #[deprecated(note = "Broken API: use `wait_for_special_event2` instead")]
1417    #[cfg(any(feature = "xinput", feature = "present"))]
1418    #[allow(deprecated)]
1419    pub fn wait_for_special_event(&self, se: SpecialEventId) -> Result<Event> {
1420        unsafe {
1421            let ev = xcb_wait_for_special_event(self.c, se.raw);
1422            self.handle_wait_for_event(ev)
1423        }
1424    }
1425
1426    /// Returns the next event from a special queue
1427    #[deprecated(note = "Broken API: use `poll_for_special_event2` instead")]
1428    #[cfg(any(feature = "xinput", feature = "present"))]
1429    #[allow(deprecated)]
1430    pub fn poll_for_special_event(&self, se: SpecialEventId) -> Result<Option<Event>> {
1431        unsafe {
1432            let ev = xcb_poll_for_special_event(self.c, se.raw);
1433            self.handle_poll_for_event(ev)
1434        }
1435    }
1436
1437    /// Start listening for a special event.
1438    ///
1439    /// Effectively creates an internal special queue for this event
1440    /// XGE events are only defined in the `xinput` and `present` extensions
1441    ///
1442    /// This function is present only if either of the `xinput` or `present` cargo features are active.
1443    #[cfg(any(feature = "xinput", feature = "present"))]
1444    pub fn register_for_special_event<EID: Xid>(
1445        &self,
1446        extension: Extension,
1447        eid: EID,
1448    ) -> SpecialEvent {
1449        unsafe {
1450            let ext: *mut xcb_extension_t = match extension {
1451                #[cfg(feature = "xinput")]
1452                Extension::Input => ptr::addr_of_mut!(xinput::FFI_EXT),
1453                #[cfg(feature = "present")]
1454                Extension::Present => ptr::addr_of_mut!(present::FFI_EXT),
1455                _ => unreachable!("only Input and Present have XGE events"),
1456            };
1457
1458            let raw = xcb_register_for_special_xge(self.c, ext, eid.resource_id(), ptr::null_mut());
1459
1460            SpecialEvent { raw }
1461        }
1462    }
1463
1464    /// Stop listening to a special event
1465    #[cfg(any(feature = "xinput", feature = "present"))]
1466    pub fn unregister_for_special_event(&self, se: SpecialEvent) {
1467        unsafe {
1468            xcb_unregister_for_special_event(self.c, se.raw);
1469        }
1470    }
1471
1472    /// Returns the next event from a special queue, blocking until one arrives
1473    #[cfg(any(feature = "xinput", feature = "present"))]
1474    pub fn wait_for_special_event2(&self, se: &SpecialEvent) -> Result<Event> {
1475        unsafe {
1476            let ev = xcb_wait_for_special_event(self.c, se.raw);
1477            self.handle_wait_for_event(ev)
1478        }
1479    }
1480
1481    /// Returns the next event from a special queue
1482    #[cfg(any(feature = "xinput", feature = "present"))]
1483    pub fn poll_for_special_event2(&self, se: &SpecialEvent) -> Result<Option<Event>> {
1484        unsafe {
1485            let ev = xcb_poll_for_special_event(self.c, se.raw);
1486            self.handle_poll_for_event(ev)
1487        }
1488    }
1489
1490    /// Discards the reply for a request.
1491    ///
1492    /// Discards the reply for a request. Additionally, any error generated
1493    /// by the request is also discarded (unless it was an _unchecked request
1494    /// and the error has already arrived).
1495    ///
1496    /// This function will not block even if the reply is not yet available.
1497    fn discard_reply<C: Cookie>(&self, cookie: C) {
1498        unsafe {
1499            xcb_discard_reply64(self.c, cookie.sequence());
1500        }
1501    }
1502
1503    /// Access the data returned by the server.
1504    ///
1505    /// Accessor for the data returned by the server when the connection
1506    /// was initialized. This data includes
1507    /// - the server's required format for images,
1508    /// - a list of available visuals,
1509    /// - a list of available screens,
1510    /// - the server's maximum request length (in the absence of the
1511    /// BIG-REQUESTS extension),
1512    /// - and other assorted information.
1513    ///
1514    /// See the X protocol specification for more details.
1515    pub fn get_setup(&self) -> &Setup {
1516        unsafe {
1517            let ptr = xcb_get_setup(self.c);
1518            // let len = <&Setup as WiredIn>::compute_wire_len(ptr, ());
1519            let mut _offset = 0;
1520            <&Setup as WiredIn>::unserialize(ptr, (), &mut _offset)
1521        }
1522    }
1523
1524    /// Test whether the connection has shut down due to a fatal error.
1525    ///
1526    /// Some errors that occur in the context of a connection
1527    /// are unrecoverable. When such an error occurs, the
1528    /// connection is shut down and further operations on the
1529    /// connection have no effect.
1530    pub fn has_error(&self) -> ConnResult<()> {
1531        unsafe { check_connection_error(self.c) }
1532    }
1533
1534    /// Send a request to the X server.
1535    ///
1536    /// This function never blocks. A cookie is returned to keep track of the request.
1537    /// If the request expect a reply, the cookie can be used to retrieve the reply with
1538    /// [Connection::wait_for_reply].
1539    ///
1540    /// # Example
1541    /// ```no_run
1542    /// # use xcb::x;
1543    /// # fn main() -> xcb::Result<()> {
1544    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1545    /// #   let setup = conn.get_setup();
1546    /// #   let screen = setup.roots().nth(screen_num as usize).unwrap();
1547    /// #   let window: x::Window = conn.generate_id();
1548    ///     // Example of void request.
1549    ///     // Error (if any) will be sent to the event loop (see `wait_for_event`).
1550    ///     // In this case, the cookie can be discarded.
1551    ///     conn.send_request(&x::CreateWindow {
1552    ///         depth: x::COPY_FROM_PARENT as u8,
1553    ///         wid: window,
1554    ///         parent: screen.root(),
1555    ///         x: 0,
1556    ///         y: 0,
1557    ///         width: 150,
1558    ///         height: 150,
1559    ///         border_width: 10,
1560    ///         class: x::WindowClass::InputOutput,
1561    ///         visual: screen.root_visual(),
1562    ///         value_list: &[
1563    ///             x::Cw::BackPixel(screen.white_pixel()),
1564    ///             x::Cw::EventMask(x::EventMask::EXPOSURE | x::EventMask::KEY_PRESS),
1565    ///         ],
1566    ///     });
1567    ///
1568    ///     // Example of request with reply. The error (if any) is obtained with the reply.
1569    ///     let cookie = conn.send_request(&x::InternAtom {
1570    ///         only_if_exists: true,
1571    ///         name: b"WM_PROTOCOLS",
1572    ///     });
1573    ///     let wm_protocols_atom: x::Atom = conn
1574    ///             .wait_for_reply(cookie)?
1575    ///             .atom();
1576    /// #   Ok(())
1577    /// # }
1578    /// ```
1579    pub fn send_request<R>(&self, req: &R) -> R::Cookie
1580    where
1581        R: Request,
1582    {
1583        unsafe { R::Cookie::from_sequence(req.raw_request(self, !R::IS_VOID)) }
1584    }
1585
1586    /// Send a checked request to the X server.
1587    ///
1588    /// Checked requests do not expect a reply, but the returned cookie can be used to check for
1589    /// errors using `Connection::check_request`.
1590    ///
1591    /// # Example
1592    /// ```no_run
1593    /// # use xcb::x;
1594    /// # fn main() -> xcb::Result<()> {
1595    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1596    /// #   let window: x::Window = conn.generate_id();
1597    ///     let cookie = conn.send_request_checked(&x::MapWindow { window });
1598    ///     conn.check_request(cookie)?;
1599    /// #   Ok(())
1600    /// # }
1601    /// ```
1602    pub fn send_request_checked<R>(&self, req: &R) -> VoidCookieChecked
1603    where
1604        R: RequestWithoutReply,
1605    {
1606        unsafe { VoidCookieChecked::from_sequence(req.raw_request(self, true)) }
1607    }
1608
1609    /// Send an unchecked request to the X server.
1610    ///
1611    /// Unchecked requests expect a reply that is to be retrieved by [Connection::wait_for_reply_unchecked].
1612    /// Unchecked means that the error is not checked when the reply is fetched. Instead, the error will
1613    /// be sent to the event loop
1614    ///
1615    /// # Example
1616    /// ```no_run
1617    /// # use xcb::x;
1618    /// # fn main() -> xcb::Result<()> {
1619    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1620    ///     let cookie = conn.send_request_unchecked(&x::InternAtom {
1621    ///         only_if_exists: true,
1622    ///         name: b"WM_PROTOCOLS",
1623    ///     });
1624    ///     let wm_protocols_atom: Option<x::Atom> = conn
1625    ///             .wait_for_reply_unchecked(cookie)?
1626    ///             .map(|rep| rep.atom());
1627    /// #   Ok(())
1628    /// # }
1629    /// ```
1630    pub fn send_request_unchecked<R>(&self, req: &R) -> R::CookieUnchecked
1631    where
1632        R: RequestWithReply,
1633    {
1634        unsafe { R::CookieUnchecked::from_sequence(req.raw_request(self, false)) }
1635    }
1636
1637    /// Check a checked request for errors.
1638    ///
1639    /// The cookie supplied to this function must have resulted
1640    /// from a call to [Connection::send_request_checked].  This function will block
1641    /// until one of two conditions happens.  If an error is received, it will be
1642    /// returned.  If a reply to a subsequent request has already arrived, no error
1643    /// can arrive for this request, so this function will return `Ok(())`.
1644    ///
1645    /// Note that this function will perform a sync if needed to ensure that the
1646    /// sequence number will advance beyond that provided in cookie; this is a
1647    /// convenience to avoid races in determining whether the sync is needed.
1648    ///
1649    /// # Example
1650    /// ```no_run
1651    /// # use xcb::x;
1652    /// # fn main() -> xcb::Result<()> {
1653    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1654    /// #   let window: x::Window = conn.generate_id();
1655    ///     conn.check_request(conn.send_request_checked(&x::MapWindow { window }))?;
1656    /// #   Ok(())
1657    /// # }
1658    /// ```
1659    pub fn check_request(&self, cookie: VoidCookieChecked) -> ProtocolResult<()> {
1660        let cookie = xcb_void_cookie_t {
1661            seq: cookie.sequence() as u32,
1662        };
1663        let error = unsafe { xcb_request_check(self.c, cookie) };
1664        if error.is_null() {
1665            Ok(())
1666        } else {
1667            unsafe {
1668                let res = error::resolve_error(error, &self.ext_data);
1669                Err(res)
1670            }
1671        }
1672    }
1673
1674    /// Send the request to the server and check it.
1675    ///
1676    /// This is a sugar for `conn.check_request(conn.send_request_checked(req))`
1677    ///
1678    /// This method is useful as well in place of code sending a void request
1679    /// and flushing the connection right after. Checking the request effectively
1680    /// flushes the connection, but in addition reports possible protocol errors
1681    /// at the calling site instead of reporting them through the event loop.
1682    ///
1683    /// # Example
1684    /// ```no_run
1685    /// # use xcb::x;
1686    /// # fn main() -> xcb::Result<()> {
1687    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1688    /// #   let window: x::Window = conn.generate_id();
1689    ///     conn.send_and_check_request(&x::MapWindow { window })?;
1690    /// #   Ok(())
1691    /// # }
1692    /// ```
1693    pub fn send_and_check_request<R>(&self, req: &R) -> ProtocolResult<()>
1694    where
1695        R: RequestWithoutReply,
1696    {
1697        self.check_request(self.send_request_checked(req))
1698    }
1699
1700    /// Gets the reply of a previous request, or an error if one occurred.
1701    ///
1702    /// This is blocking; it does not return until the reply has been received. For the non-blocking
1703    /// version, see [`poll_for_reply`].
1704    ///
1705    /// # Example
1706    /// ```no_run
1707    /// # use xcb::x;
1708    /// # fn main() -> xcb::Result<()> {
1709    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1710    ///     let cookie = conn.send_request(&x::InternAtom {
1711    ///         only_if_exists: true,
1712    ///         name: b"WM_PROTOCOLS",
1713    ///     });
1714    ///     let wm_protocols_atom: x::Atom = conn
1715    ///             .wait_for_reply(cookie)?
1716    ///             .atom();
1717    /// #   Ok(())
1718    /// # }
1719    /// ```
1720    ///
1721    /// [`poll_for_reply`]: Self::poll_for_reply
1722    pub fn wait_for_reply<C>(&self, cookie: C) -> Result<C::Reply>
1723    where
1724        C: CookieWithReplyChecked,
1725    {
1726        unsafe {
1727            let mut error: *mut xcb_generic_error_t = ptr::null_mut();
1728            let reply = xcb_wait_for_reply64(self.c, cookie.sequence(), &mut error as *mut _);
1729            self.handle_reply_checked::<C>(reply, error)
1730        }
1731    }
1732
1733    /// Get the reply of a previous unchecked request.
1734    ///
1735    /// If an error occurred, `None` is returned and the error will be delivered to the event loop.
1736    ///
1737    /// This is blocking; it does not return until the reply has been received. For the non-blocking
1738    /// version, see [`poll_for_reply_unchecked`].
1739    ///
1740    /// # Example
1741    /// ```no_run
1742    /// # use xcb::x;
1743    /// # fn main() -> xcb::Result<()> {
1744    /// #   let (conn, screen_num) = xcb::Connection::connect(None)?;
1745    ///     let cookie = conn.send_request_unchecked(&x::InternAtom {
1746    ///         only_if_exists: true,
1747    ///         name: b"WM_PROTOCOLS",
1748    ///     });
1749    ///     let wm_protocols_atom: Option<x::Atom> = conn
1750    ///             .wait_for_reply_unchecked(cookie)?  // connection error may happen
1751    ///             .map(|rep| rep.atom());
1752    /// #   Ok(())
1753    /// # }
1754    /// ```
1755    ///
1756    /// [`poll_for_reply_unchecked`]: Self::poll_for_reply_unchecked
1757    pub fn wait_for_reply_unchecked<C>(&self, cookie: C) -> ConnResult<Option<C::Reply>>
1758    where
1759        C: CookieWithReplyUnchecked,
1760    {
1761        unsafe {
1762            let reply = xcb_wait_for_reply64(self.c, cookie.sequence(), ptr::null_mut());
1763            self.handle_reply_unchecked::<C>(reply)
1764        }
1765    }
1766
1767    /// Gets the reply of a previous request if it has been received, or an error if one occurred.
1768    ///
1769    /// This is non-blocking; if no reply has been received yet, it returns [`None`]. For the
1770    /// blocking version, see [`wait_for_reply`].
1771    ///
1772    /// # Examples
1773    /// ```no_run
1774    /// # use xcb::x;
1775    /// # fn main() -> xcb::Result<()> {
1776    /// #     let (conn, screen_num) = xcb::Connection::connect(None)?;
1777    /// let (wm_protocols_cookie, wm_name_cookie) = (
1778    ///     conn.send_request(&x::InternAtom {
1779    ///         only_if_exists: true,
1780    ///         name: b"WM_PROTOCOLS",
1781    ///     }),
1782    ///     conn.send_request(&x::InternAtom {
1783    ///         only_if_exists: true,
1784    ///         name: b"WM_NAME",
1785    ///     }),
1786    /// );
1787    /// let (wm_protocols_atom, wm_name_atom) = {
1788    ///     let (
1789    ///         mut wm_protocols_atom,
1790    ///         mut wm_name_atom,
1791    ///     ) = (None, None);
1792    ///
1793    ///     loop {
1794    ///         // If `wm_protocols_atom` is yet to be received, poll for it.
1795    ///         if wm_protocols_atom.is_none() {
1796    ///             wm_protocols_atom = conn
1797    ///                 .poll_for_reply(&wm_protocols_cookie)
1798    ///                 .transpose()?
1799    ///                 .map(|reply| reply.atom());
1800    ///         }
1801    ///         // If `wm_name_atom` is yet to be received, poll for it.
1802    ///         if wm_name_atom.is_none() {
1803    ///             wm_name_atom = conn
1804    ///                 .poll_for_reply(&wm_name_cookie)
1805    ///                 .transpose()?
1806    ///                 .map(|reply| reply.atom());
1807    ///         }
1808    ///
1809    ///         // If both `wm_protocols_atom` and `wm_name_atom` have been
1810    ///         // received, break from the loop.
1811    ///         if let (
1812    ///             Some(wm_protocols_atom),
1813    ///             Some(wm_name_atom),
1814    ///         ) = (wm_protocols_atom, wm_name_atom) {
1815    ///             break (wm_protocols_atom, wm_name_atom);
1816    ///         }
1817    ///     }
1818    /// };
1819    /// #     Ok(())
1820    /// # }
1821    /// ```
1822    ///
1823    /// [`wait_for_reply`]: Self::wait_for_reply
1824    pub fn poll_for_reply<C>(&self, cookie: &C) -> Option<Result<C::Reply>>
1825    where
1826        C: CookieWithReplyChecked,
1827    {
1828        unsafe {
1829            let mut error: *mut xcb_generic_error_t = ptr::null_mut();
1830            let mut reply: *mut c_void = ptr::null_mut();
1831
1832            let received = xcb_poll_for_reply64(
1833                self.c,
1834                cookie.sequence(),
1835                &mut reply as *mut _,
1836                &mut error as *mut _,
1837            );
1838
1839            match received {
1840                0 => None,
1841                1 => Some(self.handle_reply_checked::<C>(reply, error)),
1842                _ => panic!("unexpected return value from xcb_poll_for_reply64"),
1843            }
1844        }
1845    }
1846
1847    /// Gets the reply of a previous unchecked request if it has been received.
1848    ///
1849    /// If an error occurred, [`None`] is returned and the error is delivered to the event loop.
1850    ///
1851    /// This is non-blocking; if no reply has been received yet, it returns
1852    /// <code>[Some]\([None])</code>. For the blocking version, see [`wait_for_reply_unchecked`].
1853    ///
1854    /// # Examples
1855    /// ```no_run
1856    /// # use xcb::x;
1857    /// # fn main() -> xcb::Result<()> {
1858    /// #     let (conn, screen_num) = xcb::Connection::connect(None)?;
1859    /// let (wm_protocols_cookie, wm_name_cookie) = (
1860    ///     conn.send_request_unchecked(&x::InternAtom {
1861    ///         only_if_exists: true,
1862    ///         name: b"WM_PROTOCOLS",
1863    ///     }),
1864    ///     conn.send_request_unchecked(&x::InternAtom {
1865    ///         only_if_exists: true,
1866    ///         name: b"WM_NAME",
1867    ///     }),
1868    /// );
1869    /// let (wm_protocols_atom, wm_name_atom) = {
1870    ///     let (
1871    ///         mut wm_protocols_atom,
1872    ///         mut wm_name_atom,
1873    ///     ) = (Some(None), Some(None));
1874    ///
1875    ///     loop {
1876    ///         // If `wm_protocols_atom` is yet to be received, poll for it.
1877    ///         if let Some(None) = wm_protocols_atom {
1878    ///             wm_protocols_atom = conn
1879    ///                 // connection error may happen
1880    ///                 .poll_for_reply_unchecked(&wm_protocols_cookie)
1881    ///                 .transpose()?
1882    ///                 .map(|result| result.map(|reply| reply.atom()));
1883    ///         }
1884    ///         // If `wm_name_atom` is yet to be received, poll for it.
1885    ///         if let Some(None) = wm_name_atom {
1886    ///             wm_name_atom = conn
1887    ///                 // connection error may happen
1888    ///                 .poll_for_reply_unchecked(&wm_name_cookie)
1889    ///                 .transpose()?
1890    ///                 .map(|result| result.map(|reply| reply.atom()));
1891    ///         }
1892    ///
1893    ///         match (wm_protocols_atom, wm_name_atom) {
1894    ///             // If either `wm_protocols_atom` or `wm_name_atom` hasn't
1895    ///             // been received, continue the loop.
1896    ///             (Some(None), _) | (_, Some(None)) => continue,
1897    ///
1898    ///             // Otherwise, if both have been received, break from the
1899    ///             // loop.
1900    ///             (
1901    ///                 wm_protocols_atom,
1902    ///                 wm_name_atom,
1903    ///             ) => break (
1904    ///                 wm_protocols_atom.flatten(),
1905    ///                 wm_name_atom.flatten(),
1906    ///             ),
1907    ///         }
1908    ///     }
1909    /// };
1910    /// #     Ok(())
1911    /// # }
1912    /// ```
1913    ///
1914    /// [`wait_for_reply_unchecked`]: Self::wait_for_reply_unchecked
1915    pub fn poll_for_reply_unchecked<C>(&self, cookie: &C) -> Option<ConnResult<Option<C::Reply>>>
1916    where
1917        C: CookieWithReplyUnchecked,
1918    {
1919        unsafe {
1920            let mut reply: *mut c_void = ptr::null_mut();
1921
1922            let received = xcb_poll_for_reply64(
1923                self.c,
1924                cookie.sequence(),
1925                &mut reply as *mut _,
1926                ptr::null_mut(),
1927            );
1928
1929            match received {
1930                0 => None,
1931                1 => Some(self.handle_reply_unchecked::<C>(reply)),
1932                _ => panic!("unexpected return value from xcb_poll_for_reply64"),
1933            }
1934        }
1935    }
1936
1937    /// Obtain number of bytes read from the connection.
1938    ///
1939    /// Returns cumulative number of bytes received from the connection.
1940    ///
1941    /// This retrieves the total number of bytes read from this connection,
1942    /// to be used for diagnostic/monitoring/informative purposes.
1943    ///
1944    /// Since: libxcb 1.14
1945    #[cfg(feature = "libxcb_v1_14")]
1946    pub fn total_read(&self) -> usize {
1947        unsafe { xcb_total_read(self.c) as usize }
1948    }
1949
1950    /// Obtain number of bytes written to the connection.
1951    ///
1952    /// Returns cumulative number of bytes sent to the connection.
1953    ///
1954    /// This retrieves the total number of bytes written to this connection,
1955    /// to be used for diagnostic/monitoring/informative purposes.
1956    ///
1957    /// Since: libxcb 1.14
1958    #[cfg(feature = "libxcb_v1_14")]
1959    pub fn total_written(&self) -> usize {
1960        unsafe { xcb_total_written(self.c) as usize }
1961    }
1962}
1963
1964impl Connection {
1965    unsafe fn handle_wait_for_event(&self, ev: *mut xcb_generic_event_t) -> Result<Event> {
1966        if ev.is_null() {
1967            self.has_error()?;
1968            panic!("xcb_wait_for_event returned null with I/O error");
1969        } else if is_error(ev) {
1970            Err(error::resolve_error(ev as *mut _, &self.ext_data).into())
1971        } else {
1972            Ok(event::resolve_event(ev, &self.ext_data))
1973        }
1974    }
1975
1976    unsafe fn handle_poll_for_event(&self, ev: *mut xcb_generic_event_t) -> Result<Option<Event>> {
1977        if ev.is_null() {
1978            self.has_error()?;
1979            Ok(None)
1980        } else if is_error(ev) {
1981            Err(error::resolve_error(ev as *mut _, &self.ext_data).into())
1982        } else {
1983            Ok(Some(event::resolve_event(ev, &self.ext_data)))
1984        }
1985    }
1986
1987    unsafe fn handle_reply_checked<C>(
1988        &self,
1989        reply: *mut c_void,
1990        error: *mut xcb_generic_error_t,
1991    ) -> Result<C::Reply>
1992    where
1993        C: CookieWithReplyChecked,
1994    {
1995        match (reply.is_null(), error.is_null()) {
1996            (true, true) => {
1997                self.has_error()?;
1998                unreachable!("xcb_wait_for_reply64 returned null without I/O error");
1999            }
2000            (true, false) => {
2001                let error = error::resolve_error(error, &self.ext_data);
2002                Err(error.into())
2003            }
2004            (false, true) => Ok(C::Reply::from_raw(reply as *const u8)),
2005            (false, false) => unreachable!("xcb_wait_for_reply64 returned two pointers"),
2006        }
2007    }
2008
2009    unsafe fn handle_reply_unchecked<C>(&self, reply: *mut c_void) -> ConnResult<Option<C::Reply>>
2010    where
2011        C: CookieWithReplyUnchecked,
2012    {
2013        if reply.is_null() {
2014            self.has_error()?;
2015            Ok(None)
2016        } else {
2017            Ok(Some(C::Reply::from_raw(reply as *const u8)))
2018        }
2019    }
2020}
2021
2022impl AsRef<Connection> for Connection {
2023    fn as_ref(&self) -> &Connection {
2024        self
2025    }
2026}
2027
2028impl AsRawFd for Connection {
2029    fn as_raw_fd(&self) -> RawFd {
2030        unsafe { xcb_get_file_descriptor(self.c) }
2031    }
2032}
2033
2034// SAFETY: We provide a valid xcb_connection_t that is valid for as long as required by the trait.
2035#[cfg(feature = "as-raw-xcb-connection")]
2036unsafe impl as_raw_xcb_connection::AsRawXcbConnection for Connection {
2037    fn as_raw_xcb_connection(&self) -> *mut as_raw_xcb_connection::xcb_connection_t {
2038        self.get_raw_conn().cast()
2039    }
2040}
2041
2042impl Drop for Connection {
2043    fn drop(&mut self) {
2044        #[cfg(feature = "debug_atom_names")]
2045        if self.dbg_atom_names {
2046            unsafe {
2047                dan::DAN_CONN = ptr::null_mut();
2048            }
2049        }
2050
2051        #[cfg(not(feature = "xlib_xcb"))]
2052        unsafe {
2053            xcb_disconnect(self.c);
2054        }
2055
2056        #[cfg(feature = "xlib_xcb")]
2057        unsafe {
2058            if self.dpy.is_null() {
2059                xcb_disconnect(self.c);
2060            } else {
2061                xlib::XCloseDisplay(self.dpy);
2062            }
2063        }
2064    }
2065}
2066
2067#[cfg(feature = "debug_atom_names")]
2068mod dan {
2069    use super::{Connection, Xid};
2070    use crate::ffi::base::xcb_connection_t;
2071    use crate::x;
2072
2073    use std::fmt;
2074    use std::mem;
2075    use std::ptr;
2076    use std::str;
2077
2078    pub(crate) static mut DAN_CONN: *mut xcb_connection_t = ptr::null_mut();
2079
2080    impl fmt::Debug for x::Atom {
2081        #[allow(clippy::print_in_format_impl)]
2082        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2083            if self.resource_id() == 0 {
2084                return f.write_str("ATOM_NONE");
2085            }
2086
2087            let conn = unsafe { Connection::from_raw_conn(DAN_CONN) };
2088
2089            let cookie = conn.send_request(&x::GetAtomName { atom: *self });
2090            let reply = conn.wait_for_reply(cookie).map_err(|err| {
2091                eprintln!(
2092                    "Error during fmt::Debug of x::Atom (fetching atom name): {:#?}",
2093                    err
2094                );
2095                fmt::Error
2096            })?;
2097
2098            let name = reply.name().to_utf8();
2099            f.write_fmt(format_args!("Atom(\"{}\" ; {})", name, self.resource_id()))?;
2100
2101            mem::forget(conn);
2102            Ok(())
2103        }
2104    }
2105}
2106
2107unsafe fn check_connection_error(conn: *mut xcb_connection_t) -> ConnResult<()> {
2108    match xcb_connection_has_error(conn) {
2109        0 => Ok(()),
2110        XCB_CONN_ERROR => Err(ConnError::Connection),
2111        XCB_CONN_CLOSED_EXT_NOTSUPPORTED => Err(ConnError::ClosedExtNotSupported),
2112        XCB_CONN_CLOSED_MEM_INSUFFICIENT => Err(ConnError::ClosedMemInsufficient),
2113        XCB_CONN_CLOSED_REQ_LEN_EXCEED => Err(ConnError::ClosedReqLenExceed),
2114        XCB_CONN_CLOSED_PARSE_ERR => Err(ConnError::ClosedParseErr),
2115        XCB_CONN_CLOSED_INVALID_SCREEN => Err(ConnError::ClosedInvalidScreen),
2116        XCB_CONN_CLOSED_FDPASSING_FAILED => Err(ConnError::ClosedFdPassingFailed),
2117        code => unreachable!("unexpected error code from XCB: {}", code),
2118    }
2119}
2120
2121unsafe fn is_error(ev: *mut xcb_generic_event_t) -> bool {
2122    debug_assert!(!ev.is_null());
2123    (*ev).response_type == 0
2124}
2125
2126bitflags! {
2127    pub(crate) struct RequestFlags: u32 {
2128        const NONE = 0;
2129        const CHECKED = 1;
2130        const RAW = 2;
2131        const DISCARD_REPLY = 4;
2132        const REPLY_FDS = 8;
2133    }
2134}
2135
2136/// Compute the necessary padding after `base` to have `align` alignment
2137pub(crate) fn align_pad(base: usize, align: usize) -> usize {
2138    debug_assert!(align.is_power_of_two(), "`align` must be a power of two");
2139
2140    let base = base as isize;
2141    let align = align as isize;
2142    (-base & (align - 1)) as usize
2143}
2144
2145#[test]
2146fn test_align_pad() {
2147    // align 1
2148    assert_eq!(align_pad(0, 1), 0);
2149    assert_eq!(align_pad(1234, 1), 0);
2150    assert_eq!(align_pad(1235, 1), 0);
2151    // align 2
2152    assert_eq!(align_pad(0, 2), 0);
2153    assert_eq!(align_pad(1233, 2), 1);
2154    assert_eq!(align_pad(1234, 2), 0);
2155    // align 4
2156    assert_eq!(align_pad(0, 4), 0);
2157    assert_eq!(align_pad(12, 4), 0);
2158    assert_eq!(align_pad(13, 4), 3);
2159    assert_eq!(align_pad(14, 4), 2);
2160    assert_eq!(align_pad(15, 4), 1);
2161    assert_eq!(align_pad(16, 4), 0);
2162}