xcb/
ext.rs

1use crate::base::{Connection, Reply};
2use crate::ffi::{
3    xcb_connection_t, xcb_extension_t, xcb_get_extension_data, xcb_prefetch_extension_data,
4};
5use crate::x;
6
7use std::fmt;
8use std::mem;
9use std::ptr;
10
11/// Refers to a X protocol extension.
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub enum Extension {
14    /// The `BIG-REQUESTS` extension.
15    BigRequests,
16
17    /// The `XCMISC` extension.
18    XcMisc,
19
20    #[cfg(feature = "composite")]
21    /// The `Composite` extension.
22    /// Available with the `composite` cargo feature.
23    Composite,
24
25    #[cfg(feature = "damage")]
26    /// The `DAMAGE` extension.
27    /// Available with the `damage` cargo feature.
28    Damage,
29
30    #[cfg(feature = "dpms")]
31    /// The `DPMS` extension.
32    /// Available with the `dpms` cargo feature.
33    Dpms,
34
35    #[cfg(feature = "dri2")]
36    /// The `DRI2` extension.
37    /// Available with the `dri2` cargo feature.
38    Dri2,
39
40    #[cfg(feature = "dri3")]
41    /// The `DRI3` extension.
42    /// Available with the `dri3` cargo feature.
43    Dri3,
44
45    #[cfg(feature = "ge")]
46    /// The `Generic Event Extension` extension.
47    /// Available with the `ge` cargo feature.
48    GenericEvent,
49
50    #[cfg(feature = "glx")]
51    /// The `GLX` extension.
52    /// Available with the `glx` cargo feature.
53    Glx,
54
55    #[cfg(feature = "present")]
56    /// The `Present` extension.
57    /// Available with the `present` cargo feature.
58    Present,
59
60    #[cfg(feature = "randr")]
61    /// The `RANDR` extension.
62    /// Available with the `randr` cargo feature.
63    RandR,
64
65    #[cfg(feature = "record")]
66    /// The `RECORD` extension.
67    /// Available with the `record` cargo feature.
68    Record,
69
70    #[cfg(feature = "render")]
71    /// The `RENDER` extension.
72    /// Available with the `render` cargo feature.
73    Render,
74
75    #[cfg(feature = "res")]
76    /// The `X-Resource` extension.
77    /// Available with the `res` cargo feature.
78    Res,
79
80    #[cfg(feature = "screensaver")]
81    /// The `MIT-SCREEN-SAVER` extension.
82    /// Available with the `screensaver` cargo feature.
83    ScreenSaver,
84
85    #[cfg(feature = "shape")]
86    /// The `SHAPE` extension.
87    /// Available with the `shape` cargo feature.
88    Shape,
89
90    #[cfg(feature = "shm")]
91    /// The `MIT-SHM` extension.
92    /// Available with the `shm` cargo feature.
93    Shm,
94
95    #[cfg(feature = "sync")]
96    /// The `SYNC` extension.
97    /// Available with the `sync` cargo feature.
98    Sync,
99
100    #[cfg(feature = "xevie")]
101    /// The `XEVIE` extension.
102    /// Available with the `xevie` cargo feature.
103    Xevie,
104
105    #[cfg(feature = "xf86dri")]
106    /// The `XFree86-DRI` extension.
107    /// Available with the `xf86dri` cargo feature.
108    Xf86Dri,
109
110    #[cfg(feature = "xf86vidmode")]
111    /// The `XFree86-VidModeExtension` extension.
112    /// Available with the `xf86vidmode` cargo feature.
113    Xf86VidMode,
114
115    #[cfg(feature = "xfixes")]
116    /// The `XFIXES` extension.
117    /// Available with the `xfixes` cargo feature.
118    XFixes,
119
120    #[cfg(feature = "xinerama")]
121    /// The `XINERAMA` extension.
122    /// Available with the `xinerama` cargo feature.
123    Xinerama,
124
125    #[cfg(feature = "xinput")]
126    /// The `XInputExtension` extension.
127    /// Available with the `xinput` cargo feature.
128    Input,
129
130    #[cfg(feature = "xkb")]
131    /// The `XKEYBOARD` extension.
132    /// Available with the `xkb` cargo feature.
133    Xkb,
134
135    #[cfg(feature = "xprint")]
136    /// The `XpExtension` extension.
137    /// Available with the `xprint` cargo feature.
138    XPrint,
139
140    #[cfg(feature = "xselinux")]
141    /// The `SELinux` extension.
142    /// Available with the `xselinux` cargo feature.
143    SeLinux,
144
145    #[cfg(feature = "xtest")]
146    /// The `XTEST` extension.
147    /// Available with the `xtest` cargo feature.
148    Test,
149
150    #[cfg(feature = "xv")]
151    /// The `XVideo` extension.
152    /// Available with the `xv` cargo feature.
153    Xv,
154
155    #[cfg(feature = "xvmc")]
156    /// The `XVideo-MotionCompensation` extension.
157    /// Available with the `xvmc` cargo feature.
158    XvMc,
159}
160
161impl Extension {
162    /// Returns the official X-Name of the extension,
163    /// such as `"BIG-REQUESTS"`.
164    fn xname(&self) -> &'static str {
165        match self {
166            Extension::BigRequests => crate::bigreq::XNAME,
167            Extension::XcMisc => crate::xc_misc::XNAME,
168
169            #[cfg(feature = "composite")]
170            Extension::Composite => crate::composite::XNAME,
171
172            #[cfg(feature = "damage")]
173            Extension::Damage => crate::damage::XNAME,
174
175            #[cfg(feature = "dpms")]
176            Extension::Dpms => crate::dpms::XNAME,
177
178            #[cfg(feature = "dri2")]
179            Extension::Dri2 => crate::dri2::XNAME,
180
181            #[cfg(feature = "dri3")]
182            Extension::Dri3 => crate::dri3::XNAME,
183
184            #[cfg(feature = "ge")]
185            Extension::GenericEvent => crate::ge::XNAME,
186
187            #[cfg(feature = "glx")]
188            Extension::Glx => crate::glx::XNAME,
189
190            #[cfg(feature = "present")]
191            Extension::Present => crate::present::XNAME,
192
193            #[cfg(feature = "randr")]
194            Extension::RandR => crate::randr::XNAME,
195
196            #[cfg(feature = "record")]
197            Extension::Record => crate::record::XNAME,
198
199            #[cfg(feature = "render")]
200            Extension::Render => crate::render::XNAME,
201
202            #[cfg(feature = "res")]
203            Extension::Res => crate::res::XNAME,
204
205            #[cfg(feature = "screensaver")]
206            Extension::ScreenSaver => crate::screensaver::XNAME,
207
208            #[cfg(feature = "shape")]
209            Extension::Shape => crate::shape::XNAME,
210
211            #[cfg(feature = "shm")]
212            Extension::Shm => crate::shm::XNAME,
213
214            #[cfg(feature = "sync")]
215            Extension::Sync => crate::sync::XNAME,
216
217            #[cfg(feature = "xevie")]
218            Extension::Xevie => crate::xevie::XNAME,
219
220            #[cfg(feature = "xf86dri")]
221            Extension::Xf86Dri => crate::xf86dri::XNAME,
222
223            #[cfg(feature = "xf86vidmode")]
224            Extension::Xf86VidMode => crate::xf86vidmode::XNAME,
225
226            #[cfg(feature = "xfixes")]
227            Extension::XFixes => crate::xfixes::XNAME,
228
229            #[cfg(feature = "xinerama")]
230            Extension::Xinerama => crate::xinerama::XNAME,
231
232            #[cfg(feature = "xinput")]
233            Extension::Input => crate::xinput::XNAME,
234
235            #[cfg(feature = "xkb")]
236            Extension::Xkb => crate::xkb::XNAME,
237
238            #[cfg(feature = "xprint")]
239            Extension::XPrint => crate::xprint::XNAME,
240
241            #[cfg(feature = "xselinux")]
242            Extension::SeLinux => crate::xselinux::XNAME,
243
244            #[cfg(feature = "xtest")]
245            Extension::Test => crate::xtest::XNAME,
246
247            #[cfg(feature = "xv")]
248            Extension::Xv => crate::xv::XNAME,
249
250            #[cfg(feature = "xvmc")]
251            Extension::XvMc => crate::xvmc::XNAME,
252        }
253    }
254}
255
256impl fmt::Display for Extension {
257    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258        self.xname().fmt(f)
259    }
260}
261
262/// Extension data as returned by each extensions `get_extension_data`.
263///
264/// See [crate::bigreq::get_extension_data] as example.
265#[derive(Debug)]
266pub struct ExtensionData {
267    pub ext: Extension,
268    pub major_opcode: u8,
269    pub first_event: u8,
270    pub first_error: u8,
271}
272
273/// Returns the extension data for the given extensions.
274/// This function may block as the data will be queried from the server
275/// if not already cached.
276///
277/// #Panics
278/// This function will panic if a mandatory extension is not present on the server.
279pub fn cache_extensions_data(
280    conn: *mut xcb_connection_t,
281    mandatory: &[Extension],
282    optional: &[Extension],
283) -> Vec<ExtensionData> {
284    unsafe {
285        for ext in mandatory {
286            let ext_id = get_extension_id(*ext);
287            xcb_prefetch_extension_data(conn, ext_id);
288        }
289        for ext in optional {
290            let ext_id = get_extension_id(*ext);
291            xcb_prefetch_extension_data(conn, ext_id);
292        }
293
294        let mut ext_data = Vec::new();
295
296        for ext in mandatory {
297            let ext_id = get_extension_id(*ext);
298            let raw = xcb_get_extension_data(conn, ext_id);
299            let reply = x::QueryExtensionReply::from_raw(raw);
300
301            assert!(
302                reply.present(),
303                "mandatory extension {} is not present on this system",
304                ext
305            );
306            ext_data.push(ExtensionData {
307                ext: *ext,
308                major_opcode: reply.major_opcode(),
309                first_event: reply.first_event(),
310                first_error: reply.first_error(),
311            });
312            mem::forget(reply);
313        }
314
315        for ext in optional {
316            let ext_id = get_extension_id(*ext);
317            let raw = xcb_get_extension_data(conn, ext_id);
318            let reply = x::QueryExtensionReply::from_raw(raw);
319
320            if !reply.present() {
321                mem::forget(reply);
322                continue;
323            }
324
325            ext_data.push(ExtensionData {
326                ext: *ext,
327                major_opcode: reply.major_opcode(),
328                first_event: reply.first_event(),
329                first_error: reply.first_error(),
330            });
331            mem::forget(reply);
332        }
333
334        // we sort by event in reverse order to optimize the event algo
335        ext_data.sort_by(|a, b| b.first_event.cmp(&a.first_event));
336
337        ext_data
338    }
339}
340
341unsafe fn get_extension_id(ext: Extension) -> *mut xcb_extension_t {
342    match ext {
343        Extension::BigRequests => ptr::addr_of_mut!(crate::bigreq::FFI_EXT),
344        Extension::XcMisc => ptr::addr_of_mut!(crate::xc_misc::FFI_EXT),
345
346        #[cfg(feature = "composite")]
347        Extension::Composite => ptr::addr_of_mut!(crate::composite::FFI_EXT),
348
349        #[cfg(feature = "damage")]
350        Extension::Damage => ptr::addr_of_mut!(crate::damage::FFI_EXT),
351
352        #[cfg(feature = "dpms")]
353        Extension::Dpms => ptr::addr_of_mut!(crate::dpms::FFI_EXT),
354
355        #[cfg(feature = "dri2")]
356        Extension::Dri2 => ptr::addr_of_mut!(crate::dri2::FFI_EXT),
357
358        #[cfg(feature = "dri3")]
359        Extension::Dri3 => ptr::addr_of_mut!(crate::dri3::FFI_EXT),
360
361        #[cfg(feature = "ge")]
362        Extension::GenericEvent => ptr::addr_of_mut!(crate::ge::FFI_EXT),
363
364        #[cfg(feature = "glx")]
365        Extension::Glx => ptr::addr_of_mut!(crate::glx::FFI_EXT),
366
367        #[cfg(feature = "present")]
368        Extension::Present => ptr::addr_of_mut!(crate::present::FFI_EXT),
369
370        #[cfg(feature = "randr")]
371        Extension::RandR => ptr::addr_of_mut!(crate::randr::FFI_EXT),
372
373        #[cfg(feature = "record")]
374        Extension::Record => ptr::addr_of_mut!(crate::record::FFI_EXT),
375
376        #[cfg(feature = "render")]
377        Extension::Render => ptr::addr_of_mut!(crate::render::FFI_EXT),
378
379        #[cfg(feature = "res")]
380        Extension::Res => ptr::addr_of_mut!(crate::res::FFI_EXT),
381
382        #[cfg(feature = "screensaver")]
383        Extension::ScreenSaver => ptr::addr_of_mut!(crate::screensaver::FFI_EXT),
384
385        #[cfg(feature = "shape")]
386        Extension::Shape => ptr::addr_of_mut!(crate::shape::FFI_EXT),
387
388        #[cfg(feature = "shm")]
389        Extension::Shm => ptr::addr_of_mut!(crate::shm::FFI_EXT),
390
391        #[cfg(feature = "sync")]
392        Extension::Sync => ptr::addr_of_mut!(crate::sync::FFI_EXT),
393
394        #[cfg(feature = "xevie")]
395        Extension::Xevie => ptr::addr_of_mut!(crate::xevie::FFI_EXT),
396
397        #[cfg(feature = "xf86dri")]
398        Extension::Xf86Dri => ptr::addr_of_mut!(crate::xf86dri::FFI_EXT),
399
400        #[cfg(feature = "xf86vidmode")]
401        Extension::Xf86VidMode => ptr::addr_of_mut!(crate::xf86vidmode::FFI_EXT),
402
403        #[cfg(feature = "xfixes")]
404        Extension::XFixes => ptr::addr_of_mut!(crate::xfixes::FFI_EXT),
405
406        #[cfg(feature = "xinerama")]
407        Extension::Xinerama => ptr::addr_of_mut!(crate::xinerama::FFI_EXT),
408
409        #[cfg(feature = "xinput")]
410        Extension::Input => ptr::addr_of_mut!(crate::xinput::FFI_EXT),
411
412        #[cfg(feature = "xkb")]
413        Extension::Xkb => ptr::addr_of_mut!(crate::xkb::FFI_EXT),
414
415        #[cfg(feature = "xprint")]
416        Extension::XPrint => ptr::addr_of_mut!(crate::xprint::FFI_EXT),
417
418        #[cfg(feature = "xselinux")]
419        Extension::SeLinux => ptr::addr_of_mut!(crate::xselinux::FFI_EXT),
420
421        #[cfg(feature = "xtest")]
422        Extension::Test => ptr::addr_of_mut!(crate::xtest::FFI_EXT),
423
424        #[cfg(feature = "xv")]
425        Extension::Xv => ptr::addr_of_mut!(crate::xv::FFI_EXT),
426
427        #[cfg(feature = "xvmc")]
428        Extension::XvMc => ptr::addr_of_mut!(crate::xvmc::FFI_EXT),
429    }
430}