x11rb/xcb_ffi/raw_ffi/
mod.rs

1//! The low-level foreign function interface to interact with libxcb.
2//!
3//! This module contains some `#[repr(C)]` type definitions that match libxcb's definitions. The
4//! actual functions are defined in the `ffi` submodule. There is also a `test` submodule that
5//! contains a mock of the interface that is used for unit tests.
6
7use std::ptr::NonNull;
8
9#[cfg(not(all(test, unix)))]
10use libc::c_void;
11#[cfg(unix)]
12pub(crate) use libc::iovec;
13use libc::{c_char, c_int, c_uint};
14
15// As defined in xcb_windefs.h
16#[cfg(not(unix))]
17#[derive(Copy, Clone, Debug)]
18#[repr(C)]
19pub(crate) struct iovec {
20    pub(crate) iov_base: *mut c_void,
21    pub(crate) iov_len: c_int,
22}
23
24#[allow(non_camel_case_types)]
25#[repr(C)]
26pub(crate) struct xcb_connection_t {
27    _unused: [u8; 0],
28}
29
30#[derive(Debug)]
31#[doc(hidden)]
32pub struct XcbConnectionWrapper {
33    ptr: NonNull<xcb_connection_t>,
34    should_drop: bool,
35}
36
37unsafe impl as_raw_xcb_connection::AsRawXcbConnection for XcbConnectionWrapper {
38    fn as_raw_xcb_connection(&self) -> *mut as_raw_xcb_connection::xcb_connection_t {
39        self.ptr.as_ptr().cast()
40    }
41}
42
43// libxcb is fully thread-safe (well, except for xcb_disconnect()), so the following is
44// actually fine and safe:
45unsafe impl Send for XcbConnectionWrapper {}
46unsafe impl Sync for XcbConnectionWrapper {}
47
48impl Drop for XcbConnectionWrapper {
49    fn drop(&mut self) {
50        if self.should_drop {
51            unsafe {
52                xcb_disconnect(self.ptr.as_ptr());
53            }
54        }
55    }
56}
57
58impl XcbConnectionWrapper {
59    pub(crate) unsafe fn new(ptr: *mut xcb_connection_t, should_drop: bool) -> Self {
60        Self {
61            ptr: NonNull::new_unchecked(ptr),
62            should_drop,
63        }
64    }
65
66    pub(crate) fn as_ptr(&self) -> *mut xcb_connection_t {
67        self.ptr.as_ptr()
68    }
69}
70
71#[allow(non_camel_case_types)]
72#[repr(C)]
73pub(crate) struct xcb_generic_event_t {
74    pub(crate) response_type: u8,
75    pub(crate) pad0: u8,
76    pub(crate) sequence: u16,
77    pub(crate) pad: [u32; 7],
78    pub(crate) full_sequence: u32,
79}
80
81#[allow(non_camel_case_types)]
82#[repr(C)]
83pub(crate) struct xcb_generic_error_t {
84    pub(crate) response_type: u8,
85    pub(crate) error_code: u8,
86    pub(crate) sequence: u16,
87    pub(crate) resource_id: u32,
88    pub(crate) minor_code: u16,
89    pub(crate) major_code: u8,
90    pub(crate) pad0: u8,
91    pub(crate) pad: [u32; 5],
92    pub(crate) full_sequence: u32,
93}
94
95#[derive(Clone, Copy)]
96#[allow(non_camel_case_types)]
97#[repr(C)]
98pub(crate) struct xcb_void_cookie_t {
99    pub(crate) sequence: c_uint,
100}
101
102#[allow(non_camel_case_types)]
103#[repr(C)]
104pub(crate) struct xcb_extension_t {
105    pub(crate) name: *const c_char,
106    pub(crate) global_id: c_int,
107}
108
109#[allow(non_camel_case_types)]
110#[repr(C)]
111pub(crate) struct xcb_protocol_request_t {
112    pub(crate) count: usize,
113    pub(crate) ext: *mut xcb_extension_t,
114    pub(crate) opcode: u8,
115    pub(crate) isvoid: u8,
116}
117
118#[allow(non_camel_case_types)]
119#[repr(C)]
120pub(crate) struct xcb_setup_t {
121    _unused: [u8; 0],
122}
123
124pub(crate) mod connection_errors {
125    use std::os::raw::c_int;
126
127    pub(crate) const ERROR: c_int = 1;
128    pub(crate) const EXT_NOTSUPPORTED: c_int = 2;
129    pub(crate) const MEM_INSUFFICIENT: c_int = 3;
130    pub(crate) const REQ_LEN_EXCEED: c_int = 4;
131    pub(crate) const PARSE_ERR: c_int = 5;
132    pub(crate) const INVALID_SCREEN: c_int = 6;
133    pub(crate) const FDPASSING_FAILED: c_int = 7;
134}
135
136pub(crate) mod send_request_flags {
137    use libc::c_int;
138
139    pub(crate) const CHECKED: c_int = 1;
140    pub(crate) const RAW: c_int = 2;
141    //pub(crate) const DISCARD_REPLY: c_int = 4;
142    pub(crate) const REPLY_FDS: c_int = 8;
143}
144
145#[cfg(not(test))]
146mod ffi;
147
148#[cfg(not(test))]
149pub(crate) use ffi::*;
150
151#[cfg(test)]
152mod test;
153
154#[cfg(test)]
155pub(crate) use test::*;