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::*;
149