1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![allow(clippy::new_without_default)]
4#![deny(unsafe_op_in_unsafe_fn)]
5
6//! Interoperability library for Rust Windowing applications.
7//!
8//! This library provides standard types for accessing a window's platform-specific raw window
9//! handle and platforms display handle. This does not provide any utilities for creating and
10//! managing windows; instead, it provides a common interface that window creation libraries (e.g.
11//! Winit, SDL) can use to easily talk with graphics libraries (e.g. gfx-hal).
12//!
13//! ## Safety guarantees
14//!
15//! Please see the docs of [`HasWindowHandle`] and [`HasDisplayHandle`].
16//!
17//! ## Platform handle initialization
18//!
19//! Each platform handle struct is purposefully non-exhaustive, so that additional fields may be
20//! added without breaking backwards compatibility. Each struct provides an `empty` method that may
21//! be used along with the struct update syntax to construct it. See each specific struct for
22//! examples.
23//!
24//! ## Display Handles
25//!
26//! Some windowing systems use a separate display handle for some operations. The display usually
27//! represents a connection to some display server, but it is not necessarily tied to a particular
28//! window. See [`RawDisplayHandle`] for more details.
29
30#[cfg(feature = "alloc")]
31extern crate alloc;
32
33#[cfg(feature = "std")]
34extern crate std;
35
36mod android;
37mod appkit;
38mod borrowed;
39mod haiku;
40mod redox;
41mod uikit;
42mod unix;
43mod web;
44mod windows;
45
46pub use android::{AndroidDisplayHandle, AndroidNdkWindowHandle};
47pub use appkit::{AppKitDisplayHandle, AppKitWindowHandle};
48pub use borrowed::{DisplayHandle, HasDisplayHandle, HasWindowHandle, WindowHandle};
49pub use haiku::{HaikuDisplayHandle, HaikuWindowHandle};
50pub use redox::{OrbitalDisplayHandle, OrbitalWindowHandle};
51pub use uikit::{UiKitDisplayHandle, UiKitWindowHandle};
52pub use unix::{
53 DrmDisplayHandle, DrmWindowHandle, GbmDisplayHandle, GbmWindowHandle, WaylandDisplayHandle,
54 WaylandWindowHandle, XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle,
55};
56pub use web::{
57 WebCanvasWindowHandle, WebDisplayHandle, WebOffscreenCanvasWindowHandle, WebWindowHandle,
58};
59pub use windows::{Win32WindowHandle, WinRtWindowHandle, WindowsDisplayHandle};
60
61use core::fmt;
62
63/// Window that wraps around a raw window handle.
64///
65/// # Safety
66///
67/// Users can safely assume that pointers and non-zero fields are valid, and it is up to the
68/// implementer of this trait to ensure that condition is upheld.
69///
70/// Despite that qualification, implementers should still make a best-effort attempt to fill in all
71/// available fields. If an implementation doesn't, and a downstream user needs the field, it should
72/// try to derive the field from other fields the implementer *does* provide via whatever methods the
73/// platform provides.
74///
75/// The exact handles returned by `raw_window_handle` must remain consistent between multiple calls
76/// to `raw_window_handle` as long as not indicated otherwise by platform specific events.
77#[deprecated = "Use `HasWindowHandle` instead"]
78pub unsafe trait HasRawWindowHandle {
79 fn raw_window_handle(&self) -> Result<RawWindowHandle, HandleError>;
80}
81
82#[allow(deprecated)]
83unsafe impl<T: HasWindowHandle + ?Sized> HasRawWindowHandle for T {
84 fn raw_window_handle(&self) -> Result<RawWindowHandle, HandleError> {
85 self.window_handle().map(op:Into::into)
86 }
87}
88
89/// A window handle for a particular windowing system.
90///
91/// Each variant contains a struct with fields specific to that windowing system
92/// (e.g. [`Win32WindowHandle`] will include a [HWND], [`WaylandWindowHandle`] uses [wl_surface],
93/// etc.)
94///
95/// [HWND]: https://learn.microsoft.com/en-us/windows/win32/winmsg/about-windows#window-handle
96/// [wl_surface]: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_surface
97///
98/// # Variant Availability
99///
100/// Note that all variants are present on all targets (none are disabled behind
101/// `#[cfg]`s), but see the "Availability Hints" section on each variant for
102/// some hints on where this variant might be expected.
103///
104/// Note that these "Availability Hints" are not normative. That is to say, a
105/// [`HasWindowHandle`] implementor is completely allowed to return something
106/// unexpected. (For example, it's legal for someone to return a
107/// [`RawWindowHandle::Xlib`] on macOS, it would just be weird, and probably
108/// requires something like XQuartz be used).
109#[non_exhaustive]
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub enum RawWindowHandle {
112 /// A raw window handle for UIKit (Apple's non-macOS windowing library).
113 ///
114 /// ## Availability Hints
115 /// This variant is likely to be used on iOS, tvOS, (in theory) watchOS, and
116 /// Mac Catalyst (`$arch-apple-ios-macabi` targets, which can notably use
117 /// UIKit *or* AppKit), as these are the targets that (currently) support
118 /// UIKit.
119 UiKit(UiKitWindowHandle),
120 /// A raw window handle for AppKit.
121 ///
122 /// ## Availability Hints
123 /// This variant is likely to be used on macOS, although Mac Catalyst
124 /// (`$arch-apple-ios-macabi` targets, which can notably use UIKit *or*
125 /// AppKit) can also use it despite being `target_os = "ios"`.
126 AppKit(AppKitWindowHandle),
127 /// A raw window handle for the Redox operating system.
128 ///
129 /// ## Availability Hints
130 /// This variant is used by the Orbital Windowing System in the Redox
131 /// operating system.
132 Orbital(OrbitalWindowHandle),
133 /// A raw window handle for Xlib.
134 ///
135 /// ## Availability Hints
136 /// This variant is likely to show up anywhere someone manages to get X11
137 /// working that Xlib can be built for, which is to say, most (but not all)
138 /// Unix systems.
139 Xlib(XlibWindowHandle),
140 /// A raw window handle for Xcb.
141 ///
142 /// ## Availability Hints
143 /// This variant is likely to show up anywhere someone manages to get X11
144 /// working that XCB can be built for, which is to say, most (but not all)
145 /// Unix systems.
146 Xcb(XcbWindowHandle),
147 /// A raw window handle for Wayland.
148 ///
149 /// ## Availability Hints
150 /// This variant should be expected anywhere Wayland works, which is
151 /// currently some subset of unix systems.
152 Wayland(WaylandWindowHandle),
153 /// A raw window handle for the Linux Kernel Mode Set/Direct Rendering Manager
154 ///
155 /// ## Availability Hints
156 /// This variant is used on Linux when neither X nor Wayland are available
157 Drm(DrmWindowHandle),
158 /// A raw window handle for the Linux Generic Buffer Manager.
159 ///
160 /// ## Availability Hints
161 /// This variant is present regardless of windowing backend and likely to be used with
162 /// EGL_MESA_platfrom_gbm or EGL_KHR_platfrom_gbm.
163 Gbm(GbmWindowHandle),
164 /// A raw window handle for Win32.
165 ///
166 /// ## Availability Hints
167 /// This variant is used on Windows systems.
168 Win32(Win32WindowHandle),
169 /// A raw window handle for WinRT.
170 ///
171 /// ## Availability Hints
172 /// This variant is used on Windows systems.
173 WinRt(WinRtWindowHandle),
174 /// A raw window handle for the Web.
175 ///
176 /// ## Availability Hints
177 /// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
178 Web(WebWindowHandle),
179 /// A raw window handle for a Web canvas registered via [`wasm-bindgen`].
180 ///
181 /// ## Availability Hints
182 /// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
183 ///
184 /// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
185 WebCanvas(WebCanvasWindowHandle),
186 /// A raw window handle for a Web offscreen canvas registered via [`wasm-bindgen`].
187 ///
188 /// ## Availability Hints
189 /// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
190 ///
191 /// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
192 WebOffscreenCanvas(WebOffscreenCanvasWindowHandle),
193 /// A raw window handle for Android NDK.
194 ///
195 /// ## Availability Hints
196 /// This variant is used on Android targets.
197 AndroidNdk(AndroidNdkWindowHandle),
198 /// A raw window handle for Haiku.
199 ///
200 /// ## Availability Hints
201 /// This variant is used on HaikuOS.
202 Haiku(HaikuWindowHandle),
203}
204
205/// Display that wraps around a raw display handle.
206///
207/// # Safety
208///
209/// Users can safely assume that pointers and non-zero fields are valid, and it is up to the
210/// implementer of this trait to ensure that condition is upheld.
211///
212/// Despite that qualification, implementers should still make a best-effort attempt to fill in all
213/// available fields. If an implementation doesn't, and a downstream user needs the field, it should
214/// try to derive the field from other fields the implementer *does* provide via whatever methods the
215/// platform provides.
216///
217/// The exact handles returned by `raw_display_handle` must remain consistent between multiple calls
218/// to `raw_display_handle` as long as not indicated otherwise by platform specific events.
219#[deprecated = "Use `HasDisplayHandle` instead"]
220pub unsafe trait HasRawDisplayHandle {
221 fn raw_display_handle(&self) -> Result<RawDisplayHandle, HandleError>;
222}
223
224#[allow(deprecated)]
225unsafe impl<T: HasDisplayHandle + ?Sized> HasRawDisplayHandle for T {
226 fn raw_display_handle(&self) -> Result<RawDisplayHandle, HandleError> {
227 self.display_handle().map(op:Into::into)
228 }
229}
230
231/// A display server handle for a particular windowing system.
232///
233/// The display usually represents a connection to some display server, but it is not necessarily
234/// tied to a particular window. Some APIs can use the display handle without ever creating a window
235/// handle (e.g. offscreen rendering, headless event handling).
236///
237/// Each variant contains a struct with fields specific to that windowing system
238/// (e.g. [`XlibDisplayHandle`] contains a [Display] connection to an X Server,
239/// [`WaylandDisplayHandle`] uses [wl_display] to connect to a compositor). Not all windowing
240/// systems have a separate display handle (or they haven't been implemented yet) and their variants
241/// contain empty structs.
242///
243/// [Display]: https://www.x.org/releases/current/doc/libX11/libX11/libX11.html#Display_Functions
244/// [wl_display]: https://wayland.freedesktop.org/docs/html/apb.html#Client-classwl__display
245///
246/// # Variant Availability
247///
248/// Note that all variants are present on all targets (none are disabled behind
249/// `#[cfg]`s), but see the "Availability Hints" section on each variant for
250/// some hints on where this variant might be expected.
251///
252/// Note that these "Availability Hints" are not normative. That is to say, a
253/// [`HasDisplayHandle`] implementor is completely allowed to return something
254/// unexpected. (For example, it's legal for someone to return a
255/// [`RawDisplayHandle::Xlib`] on macOS, it would just be weird, and probably
256/// requires something like XQuartz be used).
257#[non_exhaustive]
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
259pub enum RawDisplayHandle {
260 /// A raw display handle for UIKit (Apple's non-macOS windowing library).
261 ///
262 /// ## Availability Hints
263 /// This variant is likely to be used on iOS, tvOS, (in theory) watchOS, and
264 /// Mac Catalyst (`$arch-apple-ios-macabi` targets, which can notably use
265 /// UIKit *or* AppKit), as these are the targets that (currently) support
266 /// UIKit.
267 UiKit(UiKitDisplayHandle),
268 /// A raw display handle for AppKit.
269 ///
270 /// ## Availability Hints
271 /// This variant is likely to be used on macOS, although Mac Catalyst
272 /// (`$arch-apple-ios-macabi` targets, which can notably use UIKit *or*
273 /// AppKit) can also use it despite being `target_os = "ios"`.
274 AppKit(AppKitDisplayHandle),
275 /// A raw display handle for the Redox operating system.
276 ///
277 /// ## Availability Hints
278 /// This variant is used by the Orbital Windowing System in the Redox
279 /// operating system.
280 Orbital(OrbitalDisplayHandle),
281 /// A raw display handle for Xlib.
282 ///
283 /// ## Availability Hints
284 /// This variant is likely to show up anywhere someone manages to get X11
285 /// working that Xlib can be built for, which is to say, most (but not all)
286 /// Unix systems.
287 Xlib(XlibDisplayHandle),
288 /// A raw display handle for Xcb.
289 ///
290 /// ## Availability Hints
291 /// This variant is likely to show up anywhere someone manages to get X11
292 /// working that XCB can be built for, which is to say, most (but not all)
293 /// Unix systems.
294 Xcb(XcbDisplayHandle),
295 /// A raw display handle for Wayland.
296 ///
297 /// ## Availability Hints
298 /// This variant should be expected anywhere Wayland works, which is
299 /// currently some subset of unix systems.
300 Wayland(WaylandDisplayHandle),
301 /// A raw display handle for the Linux Kernel Mode Set/Direct Rendering Manager
302 ///
303 /// ## Availability Hints
304 /// This variant is used on Linux when neither X nor Wayland are available
305 Drm(DrmDisplayHandle),
306 /// A raw display handle for the Linux Generic Buffer Manager.
307 ///
308 /// ## Availability Hints
309 /// This variant is present regardless of windowing backend and likely to be used with
310 /// EGL_MESA_platform_gbm or EGL_KHR_platform_gbm.
311 Gbm(GbmDisplayHandle),
312 /// A raw display handle for Win32.
313 ///
314 /// ## Availability Hints
315 /// This variant is used on Windows systems.
316 Windows(WindowsDisplayHandle),
317 /// A raw display handle for the Web.
318 ///
319 /// ## Availability Hints
320 /// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
321 Web(WebDisplayHandle),
322 /// A raw display handle for Android NDK.
323 ///
324 /// ## Availability Hints
325 /// This variant is used on Android targets.
326 Android(AndroidDisplayHandle),
327 /// A raw display handle for Haiku.
328 ///
329 /// ## Availability Hints
330 /// This variant is used on HaikuOS.
331 Haiku(HaikuDisplayHandle),
332}
333
334/// An error that can occur while fetching a display or window handle.
335#[derive(Debug, Clone)]
336#[non_exhaustive]
337pub enum HandleError {
338 /// The underlying handle cannot be represented using the types in this crate.
339 ///
340 /// This may be returned if the underlying window system does not support any of the
341 /// representative C window handles in this crate. For instance, if you were using a pure Rust
342 /// library to set up X11 (like [`x11rb`]), you would not be able to use any of the
343 /// [`RawWindowHandle`] variants, as they all represent C types.
344 ///
345 /// Another example would be a system that isn't supported by `raw-window-handle` yet,
346 /// like some game consoles.
347 ///
348 /// In the event that this error is returned, you should try to use the underlying window
349 /// system's native API to get the handle you need.
350 ///
351 /// [`x11rb`]: https://crates.io/crates/x11rb
352 NotSupported,
353
354 /// The underlying handle is not available.
355 ///
356 /// In some cases the underlying window handle may become temporarily unusable. For example, on
357 /// Android, the native window pointer can arbitrarily be replaced or removed by the system. In
358 /// this case, returning a window handle would be disingenuous, as it would not be usable. A
359 /// similar situation can occur on Wayland for the layer shell windows.
360 ///
361 /// In the event that this error is returned, you should wait until the handle becomes available
362 /// again.
363 Unavailable,
364}
365
366impl fmt::Display for HandleError {
367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368 match self {
369 Self::NotSupported => write!(
370 f,
371 "the underlying handle cannot be represented using the types in this crate"
372 ),
373 Self::Unavailable => write!(f, "the underlying handle is not available"),
374 }
375 }
376}
377
378#[cfg(feature = "std")]
379impl std::error::Error for HandleError {}
380
381macro_rules! from_impl {
382 ($($to:ident, $enum:ident, $from:ty)*) => ($(
383 impl From<$from> for $to {
384 fn from(value: $from) -> Self {
385 $to::$enum(value)
386 }
387 }
388 )*)
389}
390
391from_impl!(RawDisplayHandle, UiKit, UiKitDisplayHandle);
392from_impl!(RawDisplayHandle, AppKit, AppKitDisplayHandle);
393from_impl!(RawDisplayHandle, Orbital, OrbitalDisplayHandle);
394from_impl!(RawDisplayHandle, Xlib, XlibDisplayHandle);
395from_impl!(RawDisplayHandle, Xcb, XcbDisplayHandle);
396from_impl!(RawDisplayHandle, Wayland, WaylandDisplayHandle);
397from_impl!(RawDisplayHandle, Drm, DrmDisplayHandle);
398from_impl!(RawDisplayHandle, Gbm, GbmDisplayHandle);
399from_impl!(RawDisplayHandle, Windows, WindowsDisplayHandle);
400from_impl!(RawDisplayHandle, Web, WebDisplayHandle);
401from_impl!(RawDisplayHandle, Android, AndroidDisplayHandle);
402from_impl!(RawDisplayHandle, Haiku, HaikuDisplayHandle);
403
404from_impl!(RawWindowHandle, UiKit, UiKitWindowHandle);
405from_impl!(RawWindowHandle, AppKit, AppKitWindowHandle);
406from_impl!(RawWindowHandle, Orbital, OrbitalWindowHandle);
407from_impl!(RawWindowHandle, Xlib, XlibWindowHandle);
408from_impl!(RawWindowHandle, Xcb, XcbWindowHandle);
409from_impl!(RawWindowHandle, Wayland, WaylandWindowHandle);
410from_impl!(RawWindowHandle, Drm, DrmWindowHandle);
411from_impl!(RawWindowHandle, Gbm, GbmWindowHandle);
412from_impl!(RawWindowHandle, Win32, Win32WindowHandle);
413from_impl!(RawWindowHandle, WinRt, WinRtWindowHandle);
414from_impl!(RawWindowHandle, Web, WebWindowHandle);
415from_impl!(RawWindowHandle, WebCanvas, WebCanvasWindowHandle);
416from_impl!(
417 RawWindowHandle,
418 WebOffscreenCanvas,
419 WebOffscreenCanvasWindowHandle
420);
421from_impl!(RawWindowHandle, AndroidNdk, AndroidNdkWindowHandle);
422from_impl!(RawWindowHandle, Haiku, HaikuWindowHandle);
423