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" )]
|
31 | extern crate alloc;
|
32 |
|
33 | #[cfg (feature = "std" )]
|
34 | extern crate std;
|
35 |
|
36 | mod android;
|
37 | mod appkit;
|
38 | mod borrowed;
|
39 | mod haiku;
|
40 | mod redox;
|
41 | mod uikit;
|
42 | mod unix;
|
43 | mod web;
|
44 | mod windows;
|
45 |
|
46 | pub use android::{AndroidDisplayHandle, AndroidNdkWindowHandle};
|
47 | pub use appkit::{AppKitDisplayHandle, AppKitWindowHandle};
|
48 | pub use borrowed::{DisplayHandle, HasDisplayHandle, HasWindowHandle, WindowHandle};
|
49 | pub use haiku::{HaikuDisplayHandle, HaikuWindowHandle};
|
50 | pub use redox::{OrbitalDisplayHandle, OrbitalWindowHandle};
|
51 | pub use uikit::{UiKitDisplayHandle, UiKitWindowHandle};
|
52 | pub use unix::{
|
53 | DrmDisplayHandle, DrmWindowHandle, GbmDisplayHandle, GbmWindowHandle, WaylandDisplayHandle,
|
54 | WaylandWindowHandle, XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle,
|
55 | };
|
56 | pub use web::{
|
57 | WebCanvasWindowHandle, WebDisplayHandle, WebOffscreenCanvasWindowHandle, WebWindowHandle,
|
58 | };
|
59 | pub use windows::{Win32WindowHandle, WinRtWindowHandle, WindowsDisplayHandle};
|
60 |
|
61 | use 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" ]
|
78 | pub unsafe trait HasRawWindowHandle {
|
79 | fn raw_window_handle(&self) -> Result<RawWindowHandle, HandleError>;
|
80 | }
|
81 |
|
82 | #[allow (deprecated)]
|
83 | unsafe 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)]
|
111 | pub 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" ]
|
220 | pub unsafe trait HasRawDisplayHandle {
|
221 | fn raw_display_handle(&self) -> Result<RawDisplayHandle, HandleError>;
|
222 | }
|
223 |
|
224 | #[allow (deprecated)]
|
225 | unsafe 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)]
|
259 | pub 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 ]
|
337 | pub 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 |
|
366 | impl 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" )]
|
379 | impl std::error::Error for HandleError {}
|
380 |
|
381 | macro_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 |
|
391 | from_impl!(RawDisplayHandle, UiKit, UiKitDisplayHandle);
|
392 | from_impl!(RawDisplayHandle, AppKit, AppKitDisplayHandle);
|
393 | from_impl!(RawDisplayHandle, Orbital, OrbitalDisplayHandle);
|
394 | from_impl!(RawDisplayHandle, Xlib, XlibDisplayHandle);
|
395 | from_impl!(RawDisplayHandle, Xcb, XcbDisplayHandle);
|
396 | from_impl!(RawDisplayHandle, Wayland, WaylandDisplayHandle);
|
397 | from_impl!(RawDisplayHandle, Drm, DrmDisplayHandle);
|
398 | from_impl!(RawDisplayHandle, Gbm, GbmDisplayHandle);
|
399 | from_impl!(RawDisplayHandle, Windows, WindowsDisplayHandle);
|
400 | from_impl!(RawDisplayHandle, Web, WebDisplayHandle);
|
401 | from_impl!(RawDisplayHandle, Android, AndroidDisplayHandle);
|
402 | from_impl!(RawDisplayHandle, Haiku, HaikuDisplayHandle);
|
403 |
|
404 | from_impl!(RawWindowHandle, UiKit, UiKitWindowHandle);
|
405 | from_impl!(RawWindowHandle, AppKit, AppKitWindowHandle);
|
406 | from_impl!(RawWindowHandle, Orbital, OrbitalWindowHandle);
|
407 | from_impl!(RawWindowHandle, Xlib, XlibWindowHandle);
|
408 | from_impl!(RawWindowHandle, Xcb, XcbWindowHandle);
|
409 | from_impl!(RawWindowHandle, Wayland, WaylandWindowHandle);
|
410 | from_impl!(RawWindowHandle, Drm, DrmWindowHandle);
|
411 | from_impl!(RawWindowHandle, Gbm, GbmWindowHandle);
|
412 | from_impl!(RawWindowHandle, Win32, Win32WindowHandle);
|
413 | from_impl!(RawWindowHandle, WinRt, WinRtWindowHandle);
|
414 | from_impl!(RawWindowHandle, Web, WebWindowHandle);
|
415 | from_impl!(RawWindowHandle, WebCanvas, WebCanvasWindowHandle);
|
416 | from_impl!(
|
417 | RawWindowHandle,
|
418 | WebOffscreenCanvas,
|
419 | WebOffscreenCanvasWindowHandle
|
420 | );
|
421 | from_impl!(RawWindowHandle, AndroidNdk, AndroidNdkWindowHandle);
|
422 | from_impl!(RawWindowHandle, Haiku, HaikuWindowHandle);
|
423 | |