glutin/platform/
x11.rs

1//! Utilities to access X11 specific config properties.
2
3use std::mem;
4
5use once_cell::sync::Lazy;
6use x11_dl::xlib::{Display, XVisualInfo, Xlib};
7#[cfg(egl_backend)]
8use x11_dl::xlib::{VisualIDMask, XID};
9use x11_dl::xrender::Xrender;
10
11/// The XLIB handle.
12pub(crate) static XLIB: Lazy<Option<Xlib>> = Lazy::new(|| Xlib::open().ok());
13
14/// The XRENDER handle.
15static XRENDER: Lazy<Option<Xrender>> = Lazy::new(|| Xrender::open().ok());
16
17/// The GlConfig extension trait to get X11 specific properties from a config.
18pub trait X11GlConfigExt {
19    /// The `X11VisualInfo` that must be used to initialize the Xlib window.
20    fn x11_visual(&self) -> Option<X11VisualInfo>;
21}
22
23/// The X11 visual info.
24///
25/// This must be used when building X11 window, so it'll be compatible with the
26/// underlying Api.
27#[derive(Debug)]
28pub struct X11VisualInfo {
29    raw: *const XVisualInfo,
30    transparency: bool,
31}
32
33impl X11VisualInfo {
34    #[cfg(egl_backend)]
35    pub(crate) unsafe fn from_xid(display: *mut Display, xid: XID) -> Option<Self> {
36        let xlib = XLIB.as_ref().unwrap();
37
38        if xid == 0 {
39            return None;
40        }
41
42        let raw = unsafe {
43            let mut raw: XVisualInfo = std::mem::zeroed();
44            raw.visualid = xid;
45
46            let mut num_visuals = 0;
47            (xlib.XGetVisualInfo)(display, VisualIDMask, &mut raw, &mut num_visuals)
48        };
49
50        if raw.is_null() {
51            return None;
52        }
53
54        let transparency = Self::has_non_zero_alpha(display, raw);
55
56        Some(Self { raw, transparency })
57    }
58
59    #[cfg(glx_backend)]
60    pub(crate) unsafe fn from_raw(display: *mut Display, raw: *const XVisualInfo) -> Self {
61        let transparency = Self::has_non_zero_alpha(display, raw);
62        Self { raw, transparency }
63    }
64
65    /// Returns `true` if the visual has non-zero alpha mask.
66    pub fn supports_transparency(&self) -> bool {
67        self.transparency
68    }
69
70    /// Get XID of for this visual.
71    pub fn visual_id(&self) -> std::ffi::c_ulong {
72        unsafe { (*self.raw).visualid }
73    }
74
75    /// Convert the visual to the raw pointer.
76    ///
77    /// You must clear it with `XFree` after the use.
78    pub fn into_raw(self) -> *const std::ffi::c_void {
79        let raw = self.raw as *const _;
80        mem::forget(self);
81        raw
82    }
83
84    pub(crate) fn has_non_zero_alpha(display: *mut Display, raw: *const XVisualInfo) -> bool {
85        let xrender = XRENDER.as_ref().unwrap();
86        unsafe {
87            let visual_format = (xrender.XRenderFindVisualFormat)(display, (*raw).visual);
88
89            (!visual_format.is_null())
90                .then(|| (*visual_format).direct.alphaMask != 0)
91                .unwrap_or(false)
92        }
93    }
94}
95
96impl Drop for X11VisualInfo {
97    fn drop(&mut self) {
98        unsafe {
99            (XLIB.as_ref().unwrap().XFree)(self.raw as *mut _);
100        }
101    }
102}