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