winit/platform/
x11.rs

1//! # X11
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
6use crate::monitor::MonitorHandle;
7use crate::window::{Window, WindowAttributes};
8
9use crate::dpi::Size;
10
11/// X window type. Maps directly to
12/// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html).
13#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub enum WindowType {
16    /// A desktop feature. This can include a single window containing desktop icons with the same
17    /// dimensions as the screen, allowing the desktop environment to have full control of the
18    /// desktop, without the need for proxying root window clicks.
19    Desktop,
20    /// A dock or panel feature. Typically a Window Manager would keep such windows on top of all
21    /// other windows.
22    Dock,
23    /// Toolbar windows. "Torn off" from the main application.
24    Toolbar,
25    /// Pinnable menu windows. "Torn off" from the main application.
26    Menu,
27    /// A small persistent utility window, such as a palette or toolbox.
28    Utility,
29    /// The window is a splash screen displayed as an application is starting up.
30    Splash,
31    /// This is a dialog window.
32    Dialog,
33    /// A dropdown menu that usually appears when the user clicks on an item in a menu bar.
34    /// This property is typically used on override-redirect windows.
35    DropdownMenu,
36    /// A popup menu that usually appears when the user right clicks on an object.
37    /// This property is typically used on override-redirect windows.
38    PopupMenu,
39    /// A tooltip window. Usually used to show additional information when hovering over an object
40    /// with the cursor. This property is typically used on override-redirect windows.
41    Tooltip,
42    /// The window is a notification.
43    /// This property is typically used on override-redirect windows.
44    Notification,
45    /// This should be used on the windows that are popped up by combo boxes.
46    /// This property is typically used on override-redirect windows.
47    Combo,
48    /// This indicates the window is being dragged.
49    /// This property is typically used on override-redirect windows.
50    Dnd,
51    /// This is a normal, top-level window.
52    #[default]
53    Normal,
54}
55
56/// The first argument in the provided hook will be the pointer to `XDisplay`
57/// and the second one the pointer to [`XErrorEvent`]. The returned `bool` is an
58/// indicator whether the error was handled by the callback.
59///
60/// [`XErrorEvent`]: https://linux.die.net/man/3/xerrorevent
61pub type XlibErrorHook =
62    Box<dyn Fn(*mut std::ffi::c_void, *mut std::ffi::c_void) -> bool + Send + Sync>;
63
64/// A unique identifier for an X11 visual.
65pub type XVisualID = u32;
66
67/// A unique identifier for an X11 window.
68pub type XWindow = u32;
69
70/// Hook to winit's xlib error handling callback.
71///
72/// This method is provided as a safe way to handle the errors coming from X11
73/// when using xlib in external crates, like glutin for GLX access. Trying to
74/// handle errors by speculating with `XSetErrorHandler` is [`unsafe`].
75///
76/// **Be aware that your hook is always invoked and returning `true` from it will
77/// prevent `winit` from getting the error itself. It's wise to always return
78/// `false` if you're not initiated the `Sync`.**
79///
80/// [`unsafe`]: https://www.remlab.net/op/xlib.shtml
81#[inline]
82pub fn register_xlib_error_hook(hook: XlibErrorHook) {
83    // Append new hook.
84    crate::platform_impl::XLIB_ERROR_HOOKS.lock().unwrap().push(hook);
85}
86
87/// Additional methods on [`ActiveEventLoop`] that are specific to X11.
88pub trait ActiveEventLoopExtX11 {
89    /// True if the [`ActiveEventLoop`] uses X11.
90    fn is_x11(&self) -> bool;
91}
92
93impl ActiveEventLoopExtX11 for ActiveEventLoop {
94    #[inline]
95    fn is_x11(&self) -> bool {
96        !self.p.is_wayland()
97    }
98}
99
100/// Additional methods on [`EventLoop`] that are specific to X11.
101pub trait EventLoopExtX11 {
102    /// True if the [`EventLoop`] uses X11.
103    fn is_x11(&self) -> bool;
104}
105
106impl<T: 'static> EventLoopExtX11 for EventLoop<T> {
107    #[inline]
108    fn is_x11(&self) -> bool {
109        !self.event_loop.is_wayland()
110    }
111}
112
113/// Additional methods on [`EventLoopBuilder`] that are specific to X11.
114pub trait EventLoopBuilderExtX11 {
115    /// Force using X11.
116    fn with_x11(&mut self) -> &mut Self;
117
118    /// Whether to allow the event loop to be created off of the main thread.
119    ///
120    /// By default, the window is only allowed to be created on the main
121    /// thread, to make platform compatibility easier.
122    fn with_any_thread(&mut self, any_thread: bool) -> &mut Self;
123}
124
125impl<T> EventLoopBuilderExtX11 for EventLoopBuilder<T> {
126    #[inline]
127    fn with_x11(&mut self) -> &mut Self {
128        self.platform_specific.forced_backend = Some(crate::platform_impl::Backend::X);
129        self
130    }
131
132    #[inline]
133    fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
134        self.platform_specific.any_thread = any_thread;
135        self
136    }
137}
138
139/// Additional methods on [`Window`] that are specific to X11.
140pub trait WindowExtX11 {}
141
142impl WindowExtX11 for Window {}
143
144/// Additional methods on [`WindowAttributes`] that are specific to X11.
145pub trait WindowAttributesExtX11 {
146    /// Create this window with a specific X11 visual.
147    fn with_x11_visual(self, visual_id: XVisualID) -> Self;
148
149    fn with_x11_screen(self, screen_id: i32) -> Self;
150
151    /// Build window with the given `general` and `instance` names.
152    ///
153    /// The `general` sets general class of `WM_CLASS(STRING)`, while `instance` set the
154    /// instance part of it. The resulted property looks like `WM_CLASS(STRING) = "instance",
155    /// "general"`.
156    ///
157    /// For details about application ID conventions, see the
158    /// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
159    fn with_name(self, general: impl Into<String>, instance: impl Into<String>) -> Self;
160
161    /// Build window with override-redirect flag; defaults to false.
162    fn with_override_redirect(self, override_redirect: bool) -> Self;
163
164    /// Build window with `_NET_WM_WINDOW_TYPE` hints; defaults to `Normal`.
165    fn with_x11_window_type(self, x11_window_type: Vec<WindowType>) -> Self;
166
167    /// Build window with base size hint.
168    ///
169    /// ```
170    /// # use winit::dpi::{LogicalSize, PhysicalSize};
171    /// # use winit::window::Window;
172    /// # use winit::platform::x11::WindowAttributesExtX11;
173    /// // Specify the size in logical dimensions like this:
174    /// Window::default_attributes().with_base_size(LogicalSize::new(400.0, 200.0));
175    ///
176    /// // Or specify the size in physical dimensions like this:
177    /// Window::default_attributes().with_base_size(PhysicalSize::new(400, 200));
178    /// ```
179    fn with_base_size<S: Into<Size>>(self, base_size: S) -> Self;
180
181    /// Embed this window into another parent window.
182    ///
183    /// # Example
184    ///
185    /// ```no_run
186    /// use winit::window::Window;
187    /// use winit::event_loop::ActiveEventLoop;
188    /// use winit::platform::x11::{XWindow, WindowAttributesExtX11};
189    /// # fn create_window(event_loop: &ActiveEventLoop) -> Result<(), Box<dyn std::error::Error>> {
190    /// let parent_window_id = std::env::args().nth(1).unwrap().parse::<XWindow>()?;
191    /// let window_attributes = Window::default_attributes().with_embed_parent_window(parent_window_id);
192    /// let window = event_loop.create_window(window_attributes)?;
193    /// # Ok(()) }
194    /// ```
195    fn with_embed_parent_window(self, parent_window_id: XWindow) -> Self;
196}
197
198impl WindowAttributesExtX11 for WindowAttributes {
199    #[inline]
200    fn with_x11_visual(mut self, visual_id: XVisualID) -> Self {
201        self.platform_specific.x11.visual_id = Some(visual_id);
202        self
203    }
204
205    #[inline]
206    fn with_x11_screen(mut self, screen_id: i32) -> Self {
207        self.platform_specific.x11.screen_id = Some(screen_id);
208        self
209    }
210
211    #[inline]
212    fn with_name(mut self, general: impl Into<String>, instance: impl Into<String>) -> Self {
213        self.platform_specific.name =
214            Some(crate::platform_impl::ApplicationName::new(general.into(), instance.into()));
215        self
216    }
217
218    #[inline]
219    fn with_override_redirect(mut self, override_redirect: bool) -> Self {
220        self.platform_specific.x11.override_redirect = override_redirect;
221        self
222    }
223
224    #[inline]
225    fn with_x11_window_type(mut self, x11_window_types: Vec<WindowType>) -> Self {
226        self.platform_specific.x11.x11_window_types = x11_window_types;
227        self
228    }
229
230    #[inline]
231    fn with_base_size<S: Into<Size>>(mut self, base_size: S) -> Self {
232        self.platform_specific.x11.base_size = Some(base_size.into());
233        self
234    }
235
236    #[inline]
237    fn with_embed_parent_window(mut self, parent_window_id: XWindow) -> Self {
238        self.platform_specific.x11.embed_window = Some(parent_window_id);
239        self
240    }
241}
242
243/// Additional methods on `MonitorHandle` that are specific to X11.
244pub trait MonitorHandleExtX11 {
245    /// Returns the inner identifier of the monitor.
246    fn native_id(&self) -> u32;
247}
248
249impl MonitorHandleExtX11 for MonitorHandle {
250    #[inline]
251    fn native_id(&self) -> u32 {
252        self.inner.native_identifier()
253    }
254}