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)]
31pub(crate) struct XcbConnectionWrapper {
32    ptr: NonNull<xcb_connection_t>,
33    should_drop: bool,
34}
35
36// libxcb is fully thread-safe (well, except for xcb_disconnect()), so the following is
37// actually fine and safe:
38unsafe impl Send for XcbConnectionWrapper {}
39unsafe impl Sync for XcbConnectionWrapper {}
40
41impl Drop for XcbConnectionWrapper {
42    fn drop(&mut self) {
43        if self.should_drop {
44            unsafe {
45                xcb_disconnect(self.ptr.as_ptr());
46            }
47        }
48    }
49}
50
51impl XcbConnectionWrapper {
52    pub(crate) unsafe fn new(ptr: *mut xcb_connection_t, should_drop: bool) -> Self {
53        Self {
54            ptr: NonNull::new_unchecked(ptr),
55            should_drop,
56        }
57    }
58
59    pub(crate) fn as_ptr(&self) -> *mut xcb_connection_t {
60        self.ptr.as_ptr()
61    }
62}
63
64#[allow(non_camel_case_types)]
65#[repr(C)]
66pub(crate) struct xcb_generic_event_t {
67    pub(crate) response_type: u8,
68    pub(crate) pad0: u8,
69    pub(crate) sequence: u16,
70    pub(crate) pad: [u32; 7],
71    pub(crate) full_sequence: u32,
72}
73
74#[allow(non_camel_case_types)]
75#[repr(C)]
76pub(crate) struct xcb_generic_error_t {
77    pub(crate) response_type: u8,
78    pub(crate) error_code: u8,
79    pub(crate) sequence: u16,
80    pub(crate) resource_id: u32,
81    pub(crate) minor_code: u16,
82    pub(crate) major_code: u8,
83    pub(crate) pad0: u8,
84    pub(crate) pad: [u32; 5],
85    pub(crate) full_sequence: u32,
86}
87
88#[derive(Clone, Copy)]
89#[allow(non_camel_case_types)]
90#[repr(C)]
91pub(crate) struct xcb_void_cookie_t {
92    pub(crate) sequence: c_uint,
93}
94
95#[allow(non_camel_case_types)]
96#[repr(C)]
97pub(crate) struct xcb_extension_t {
98    pub(crate) name: *const c_char,
99    pub(crate) global_id: c_int,
100}
101
102#[allow(non_camel_case_types)]
103#[repr(C)]
104pub(crate) struct xcb_protocol_request_t {
105    pub(crate) count: usize,
106    pub(crate) ext: *mut xcb_extension_t,
107    pub(crate) opcode: u8,
108    pub(crate) isvoid: u8,
109}
110
111#[allow(non_camel_case_types)]
112#[repr(C)]
113pub(crate) struct xcb_setup_t {
114    _unused: [u8; 0],
115}
116
117pub(crate) mod connection_errors {
118    use std::os::raw::c_int;
119
120    pub(crate) const ERROR: c_int = 1;
121    pub(crate) const EXT_NOTSUPPORTED: c_int = 2;
122    pub(crate) const MEM_INSUFFICIENT: c_int = 3;
123    pub(crate) const REQ_LEN_EXCEED: c_int = 4;
124    pub(crate) const PARSE_ERR: c_int = 5;
125    pub(crate) const INVALID_SCREEN: c_int = 6;
126    pub(crate) const FDPASSING_FAILED: c_int = 7;
127}
128
129pub(crate) mod send_request_flags {
130    use libc::c_int;
131
132    pub(crate) const CHECKED: c_int = 1;
133    pub(crate) const RAW: c_int = 2;
134    //pub(crate) const DISCARD_REPLY: c_int = 4;
135    pub(crate) const REPLY_FDS: c_int = 8;
136}
137
138#[cfg(not(test))]
139mod ffi;
140
141#[cfg(not(test))]
142pub(crate) use ffi::*;
143
144#[cfg(test)]
145mod test;
146
147#[cfg(test)]
148pub(crate) use test::*;