winit/platform/
wayland.rs

1//! # Wayland
2//!
3//! **Note:** Windows don't appear on Wayland until you draw/present to them.
4//!
5//! By default, Winit loads system libraries using `dlopen`. This can be
6//! disabled by disabling the `"wayland-dlopen"` cargo feature.
7//!
8//! ## Client-side decorations
9//!
10//! Winit provides client-side decorations by default, but the behaviour can
11//! be controlled with the following feature flags:
12//!
13//! * `wayland-csd-adwaita` (default).
14//! * `wayland-csd-adwaita-crossfont`.
15//! * `wayland-csd-adwaita-notitle`.
16use std::marker::PhantomData;
17use std::os::raw::c_void;
18use std::ptr::NonNull;
19
20use rwh_06::HandleError;
21use sctk::reexports::csd_frame::WindowState;
22
23use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
24use crate::monitor::MonitorHandle;
25pub use crate::window::Theme;
26use crate::window::{Window as CoreWindow, WindowAttributes};
27
28/// Additional methods on [`ActiveEventLoop`] that are specific to Wayland.
29pub trait ActiveEventLoopExtWayland {
30    /// True if the [`ActiveEventLoop`] uses Wayland.
31    fn is_wayland(&self) -> bool;
32}
33
34impl ActiveEventLoopExtWayland for dyn ActiveEventLoop + '_ {
35    #[inline]
36    fn is_wayland(&self) -> bool {
37        self.as_any().downcast_ref::<crate::platform_impl::wayland::ActiveEventLoop>().is_some()
38    }
39}
40
41/// Additional methods on [`EventLoop`] that are specific to Wayland.
42pub trait EventLoopExtWayland {
43    /// True if the [`EventLoop`] uses Wayland.
44    fn is_wayland(&self) -> bool;
45}
46
47impl EventLoopExtWayland for EventLoop {
48    #[inline]
49    fn is_wayland(&self) -> bool {
50        self.event_loop.is_wayland()
51    }
52}
53
54/// Additional methods on [`EventLoopBuilder`] that are specific to Wayland.
55pub trait EventLoopBuilderExtWayland {
56    /// Force using Wayland.
57    fn with_wayland(&mut self) -> &mut Self;
58
59    /// Whether to allow the event loop to be created off of the main thread.
60    ///
61    /// By default, the window is only allowed to be created on the main
62    /// thread, to make platform compatibility easier.
63    fn with_any_thread(&mut self, any_thread: bool) -> &mut Self;
64}
65
66impl EventLoopBuilderExtWayland for EventLoopBuilder {
67    #[inline]
68    fn with_wayland(&mut self) -> &mut Self {
69        self.platform_specific.forced_backend = Some(crate::platform_impl::Backend::Wayland);
70        self
71    }
72
73    #[inline]
74    fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
75        self.platform_specific.any_thread = any_thread;
76        self
77    }
78}
79
80pub struct XdgSurfaceHandle<'a> {
81    raw: NonNull<c_void>,
82    _marker: PhantomData<&'a ()>,
83}
84
85impl<'a> XdgSurfaceHandle<'a> {
86    /// Create a `XdgSurfaceHandle` from a [`NonNull<c_void>`]
87    pub unsafe fn borrow_raw(raw: NonNull<c_void>) -> Self {
88        Self { raw, _marker: PhantomData }
89    }
90
91    /// Get the underlying raw xdg_surface handle.
92    pub fn as_raw(&self) -> NonNull<c_void> {
93        self.raw
94    }
95}
96
97pub trait HasXdgSurfaceHandle {
98    fn xdg_surface_handle(&self) -> Result<XdgSurfaceHandle<'_>, HandleError>;
99}
100
101pub struct XdgToplevelHandle<'a> {
102    raw: NonNull<c_void>,
103    _marker: PhantomData<&'a ()>,
104}
105
106impl<'a> XdgToplevelHandle<'a> {
107    /// Create a `XdgToplevelHandle` from a [`NonNull<c_void>`]
108    pub unsafe fn borrow_raw(raw: NonNull<c_void>) -> Self {
109        Self { raw, _marker: PhantomData }
110    }
111
112    /// Get the underlying raw xdg_toplevel handle.
113    pub fn as_raw(&self) -> NonNull<c_void> {
114        self.raw
115    }
116}
117
118pub trait HasXdgToplevelHandle {
119    fn xdg_toplevel_handle(&self) -> Result<XdgToplevelHandle<'_>, HandleError>;
120}
121
122/// Additional methods on [`Window`] that are specific to Wayland.
123///
124/// [`Window`]: crate::window::Window
125pub trait WindowExtWayland {
126    fn xdg_surface_handle<'a>(&'a self) -> Option<&dyn HasXdgSurfaceHandle>;
127    fn xdg_toplevel_handle<'a>(&'a self) -> Option<&dyn HasXdgToplevelHandle>;
128    /// Get the state of the window
129    fn window_state(&self) -> Option<WindowState>;
130}
131
132impl WindowExtWayland for dyn CoreWindow + '_ {
133    fn xdg_surface_handle(&self) -> Option<&dyn HasXdgSurfaceHandle> {
134        let window = self.as_any().downcast_ref::<crate::platform_impl::wayland::Window>();
135        window.map(|w| w as &dyn HasXdgSurfaceHandle)
136    }
137
138    fn xdg_toplevel_handle(&self) -> Option<&dyn HasXdgToplevelHandle> {
139        let window = self.as_any().downcast_ref::<crate::platform_impl::wayland::Window>();
140        window.map(|w| w as &dyn HasXdgToplevelHandle)
141    }
142
143    fn window_state(&self) -> Option<WindowState> {
144        let window = self.as_any().downcast_ref::<crate::platform_impl::wayland::Window>();
145        window.and_then(|w| w.xdg_window_state())
146    }
147}
148
149/// Additional methods on [`WindowAttributes`] that are specific to Wayland.
150pub trait WindowAttributesExtWayland {
151    /// Build window with the given name.
152    ///
153    /// The `general` name sets an application ID, which should match the `.desktop`
154    /// file distributed with your program. The `instance` is a `no-op`.
155    ///
156    /// For details about application ID conventions, see the
157    /// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
158    fn with_name(self, general: impl Into<String>, instance: impl Into<String>) -> Self;
159}
160
161impl WindowAttributesExtWayland for WindowAttributes {
162    #[inline]
163    fn with_name(mut self, general: impl Into<String>, instance: impl Into<String>) -> Self {
164        self.platform_specific.name =
165            Some(crate::platform_impl::ApplicationName::new(general.into(), instance.into()));
166        self
167    }
168}
169
170/// Additional methods on `MonitorHandle` that are specific to Wayland.
171pub trait MonitorHandleExtWayland {
172    /// Returns the inner identifier of the monitor.
173    fn native_id(&self) -> u32;
174}
175
176impl MonitorHandleExtWayland for MonitorHandle {
177    #[inline]
178    fn native_id(&self) -> u32 {
179        self.inner.native_identifier()
180    }
181}