From 69d9eac14401e1a8868d14febe30583f9ea70a98 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 31 Aug 2023 17:25:31 +0200 Subject: [PATCH] Change how handles are constructed, so that we can ensure non-null handles (#136) * Change how handles are constructed, to ensure non-null handles * Make Win32WindowHandle.hinstance properly optional * Add changelog entries * breaking: Make integer handles use non-zero types * Make X display and connection handles nullable This is a conservative choice for now; we can later iterate on this decision, and figure out if the handles should actually be non-null. --- CHANGELOG.md | 2 + src/android.rs | 51 ++++--- src/appkit.rs | 51 ++++--- src/haiku.rs | 55 ++++--- src/lib.rs | 4 +- src/redox.rs | 53 ++++--- src/uikit.rs | 55 ++++--- src/unix.rs | 378 +++++++++++++++++++++++++++++-------------------- src/web.rs | 43 +++--- src/windows.rs | 94 +++++++----- 10 files changed, 462 insertions(+), 324 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fef5a5..e928fcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* **Breaking:** Raw pointer handles now use `NonNull` where appropriate, to avoid null pointer dereferences. +* **Breaking:** Renamed `empty` methods to `new`, and take parameters in most of those, to better match normal Rust semantics. * **Breaking:** `HasRaw(Display/Window)Handle::raw_(display/window)_handle` returns a result indicating if fetching the window handle failed (#122). * **Breaking:** Remove the `Active/ActiveHandle` types from the public API (#126). * **Breaking:** Remove `AppKitWindowHandle::ns_window` and `UiKitWindowHandle::ui_window` since they can be retrieved from the view (#129). diff --git a/src/android.rs b/src/android.rs index e4504ce..fc10ecb 100644 --- a/src/android.rs +++ b/src/android.rs @@ -1,43 +1,50 @@ use core::ffi::c_void; -use core::ptr; +use core::ptr::NonNull; /// Raw display handle for Android. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::AndroidDisplayHandle; -/// let mut display_handle = AndroidDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct AndroidDisplayHandle; +pub struct AndroidDisplayHandle {} impl AndroidDisplayHandle { - pub fn empty() -> Self { + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::AndroidDisplayHandle; + /// let handle = AndroidDisplayHandle::new(); + /// ``` + pub fn new() -> Self { Self {} } } /// Raw window handle for Android NDK. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::AndroidNdkWindowHandle; -/// let mut window_handle = AndroidNdkWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AndroidNdkWindowHandle { /// A pointer to an `ANativeWindow`. - pub a_native_window: *mut c_void, + pub a_native_window: NonNull, } impl AndroidNdkWindowHandle { - pub fn empty() -> Self { - Self { - a_native_window: ptr::null_mut(), - } + /// Create a new handle to an `ANativeWindow`. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ptr::NonNull; + /// # use raw_window_handle::AndroidNdkWindowHandle; + /// # type ANativeWindow = (); + /// # + /// let ptr: NonNull; + /// # ptr = NonNull::from(&()); + /// let handle = AndroidNdkWindowHandle::new(ptr.cast()); + /// ``` + pub fn new(a_native_window: NonNull) -> Self { + Self { a_native_window } } } diff --git a/src/appkit.rs b/src/appkit.rs index d3e66a8..3b05810 100644 --- a/src/appkit.rs +++ b/src/appkit.rs @@ -1,43 +1,50 @@ use core::ffi::c_void; -use core::ptr; +use core::ptr::NonNull; /// Raw display handle for AppKit. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::AppKitDisplayHandle; -/// let mut display_handle = AppKitDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct AppKitDisplayHandle; +pub struct AppKitDisplayHandle {} impl AppKitDisplayHandle { - pub fn empty() -> Self { + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::AppKitDisplayHandle; + /// let handle = AppKitDisplayHandle::new(); + /// ``` + pub fn new() -> Self { Self {} } } /// Raw window handle for AppKit. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::AppKitWindowHandle; -/// let mut window_handle = AppKitWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AppKitWindowHandle { /// A pointer to an `NSView` object. - pub ns_view: *mut c_void, + pub ns_view: NonNull, } impl AppKitWindowHandle { - pub fn empty() -> Self { - Self { - ns_view: ptr::null_mut(), - } + /// Create a new handle to a view. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ptr::NonNull; + /// # use raw_window_handle::AppKitWindowHandle; + /// # type NSView = (); + /// # + /// let view: &NSView; + /// # view = &(); + /// let handle = AppKitWindowHandle::new(NonNull::from(view).cast()); + /// ``` + pub fn new(ns_view: NonNull) -> Self { + Self { ns_view } } } diff --git a/src/haiku.rs b/src/haiku.rs index d44e8c2..ef010ee 100644 --- a/src/haiku.rs +++ b/src/haiku.rs @@ -1,46 +1,57 @@ use core::ffi::c_void; -use core::ptr; +use core::ptr::NonNull; /// Raw display handle for Haiku. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::HaikuDisplayHandle; -/// let mut display_handle = HaikuDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct HaikuDisplayHandle; +pub struct HaikuDisplayHandle {} impl HaikuDisplayHandle { - pub fn empty() -> Self { + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::HaikuDisplayHandle; + /// let handle = HaikuDisplayHandle::new(); + /// ``` + pub fn new() -> Self { Self {} } } /// Raw window handle for Haiku. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::HaikuWindowHandle; -/// let mut window_handle = HaikuWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct HaikuWindowHandle { /// A pointer to a BWindow object - pub b_window: *mut c_void, + pub b_window: NonNull, /// A pointer to a BDirectWindow object that might be null - pub b_direct_window: *mut c_void, + pub b_direct_window: Option>, } impl HaikuWindowHandle { - pub fn empty() -> Self { + /// Create a new handle to a window. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ptr::NonNull; + /// # use raw_window_handle::HaikuWindowHandle; + /// # type BWindow = (); + /// # + /// let b_window: NonNull; + /// # b_window = NonNull::from(&()); + /// let mut handle = HaikuWindowHandle::new(b_window.cast()); + /// // Optionally set `b_direct_window`. + /// handle.b_direct_window = None; + /// ``` + pub fn new(b_window: NonNull) -> Self { Self { - b_window: ptr::null_mut(), - b_direct_window: ptr::null_mut(), + b_window, + b_direct_window: None, } } } diff --git a/src/lib.rs b/src/lib.rs index 2253b76..3b81564 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ use core::fmt; /// /// # Safety /// -/// Users can safely assume that non-`null`/`0` fields are valid handles, and it is up to the +/// 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 @@ -205,7 +205,7 @@ pub enum RawWindowHandle { /// /// # Safety /// -/// Users can safely assume that non-`null`/`0` fields are valid handles, and it is up to the +/// 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 diff --git a/src/redox.rs b/src/redox.rs index 5faa985..7562756 100644 --- a/src/redox.rs +++ b/src/redox.rs @@ -1,43 +1,52 @@ use core::ffi::c_void; -use core::ptr; +use core::ptr::NonNull; /// Raw display handle for the Redox operating system. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::OrbitalDisplayHandle; -/// let mut display_handle = OrbitalDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct OrbitalDisplayHandle; +pub struct OrbitalDisplayHandle {} impl OrbitalDisplayHandle { - pub fn empty() -> Self { + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::OrbitalDisplayHandle; + /// let handle = OrbitalDisplayHandle::new(); + /// ``` + pub fn new() -> Self { Self {} } } /// Raw window handle for the Redox operating system. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::OrbitalWindowHandle; -/// let mut window_handle = OrbitalWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct OrbitalWindowHandle { /// A pointer to an orbclient window. - pub window: *mut c_void, + // TODO(madsmtm): I think this is a file descriptor, so perhaps it should + // actually use `std::os::fd::RawFd`, or some sort of integer instead? + pub window: NonNull, } impl OrbitalWindowHandle { - pub fn empty() -> Self { - Self { - window: ptr::null_mut(), - } + /// Create a new handle to a window. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ptr::NonNull; + /// # use raw_window_handle::OrbitalWindowHandle; + /// # type Window = (); + /// # + /// let window: NonNull; + /// # window = NonNull::from(&()); + /// let mut handle = OrbitalWindowHandle::new(window.cast()); + /// ``` + pub fn new(window: NonNull) -> Self { + Self { window } } } diff --git a/src/uikit.rs b/src/uikit.rs index 47f7afb..1f4895e 100644 --- a/src/uikit.rs +++ b/src/uikit.rs @@ -1,46 +1,57 @@ use core::ffi::c_void; -use core::ptr; +use core::ptr::NonNull; /// Raw display handle for UIKit. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::UiKitDisplayHandle; -/// let mut display_handle = UiKitDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct UiKitDisplayHandle; +pub struct UiKitDisplayHandle {} impl UiKitDisplayHandle { - pub fn empty() -> Self { + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::UiKitDisplayHandle; + /// let handle = UiKitDisplayHandle::new(); + /// ``` + pub fn new() -> Self { Self {} } } /// Raw window handle for UIKit. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::UiKitWindowHandle; -/// let mut window_handle = UiKitWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UiKitWindowHandle { /// A pointer to an `UIView` object. - pub ui_view: *mut c_void, + pub ui_view: NonNull, /// A pointer to an `UIViewController` object, if the view has one. - pub ui_view_controller: *mut c_void, + pub ui_view_controller: Option>, } impl UiKitWindowHandle { - pub fn empty() -> Self { + /// Create a new handle to a view. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ptr::NonNull; + /// # use raw_window_handle::UiKitWindowHandle; + /// # type UIView = (); + /// # + /// let view: &UIView; + /// # view = &(); + /// let mut handle = UiKitWindowHandle::new(NonNull::from(view).cast()); + /// // Optionally set the view controller. + /// handle.ui_view_controller = None; + /// ``` + pub fn new(ui_view: NonNull) -> Self { Self { - ui_view: ptr::null_mut(), - ui_view_controller: ptr::null_mut(), + ui_view, + ui_view_controller: None, } } } diff --git a/src/unix.rs b/src/unix.rs index e220b2d..e1d5023 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -1,19 +1,16 @@ use core::ffi::{c_int, c_ulong, c_void}; -use core::ptr; +use core::num::NonZeroU32; +use core::ptr::NonNull; /// Raw display handle for Xlib. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::XlibDisplayHandle; -/// let display_handle = XlibDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct XlibDisplayHandle { /// A pointer to an Xlib `Display`. - pub display: *mut c_void, + /// + /// It is strongly recommended to set this value, however it may be set to + /// `None` to request the default display when using EGL. + pub display: Option>, /// An X11 screen to use with this display handle. /// @@ -23,14 +20,29 @@ pub struct XlibDisplayHandle { pub screen: c_int, } +impl XlibDisplayHandle { + /// Create a new handle to a display. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_void; + /// # use core::ptr::NonNull; + /// # use raw_window_handle::XlibDisplayHandle; + /// # + /// let display: NonNull; + /// let screen; + /// # display = NonNull::from(&()).cast(); + /// # screen = 0; + /// let handle = XlibDisplayHandle::new(Some(display), screen); + /// ``` + pub fn new(display: Option>, screen: c_int) -> Self { + Self { display, screen } + } +} + /// Raw window handle for Xlib. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::XlibWindowHandle; -/// let window_handle = XlibWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct XlibWindowHandle { @@ -40,19 +52,39 @@ pub struct XlibWindowHandle { pub visual_id: c_ulong, } +impl XlibWindowHandle { + /// Create a new handle to a window. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_ulong; + /// # use raw_window_handle::XlibWindowHandle; + /// # + /// let window: c_ulong; + /// # window = 0; + /// let mut handle = XlibWindowHandle::new(window); + /// // Optionally set the visual ID. + /// handle.visual_id = 0; + /// ``` + pub fn new(window: c_ulong) -> Self { + Self { + window, + visual_id: 0, + } + } +} + /// Raw display handle for Xcb. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::XcbDisplayHandle; -/// let display_handle = XcbDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct XcbDisplayHandle { /// A pointer to an X server `xcb_connection_t`. - pub connection: *mut c_void, + /// + /// It is strongly recommended to set this value, however it may be set to + /// `None` to request the default display when using EGL. + pub connection: Option>, /// An X11 screen to use with this display handle. /// @@ -62,76 +94,146 @@ pub struct XcbDisplayHandle { pub screen: c_int, } +impl XcbDisplayHandle { + /// Create a new handle to a connection and screen. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_void; + /// # use core::ptr::NonNull; + /// # use raw_window_handle::XcbDisplayHandle; + /// # + /// let connection: NonNull; + /// let screen; + /// # connection = NonNull::from(&()).cast(); + /// # screen = 0; + /// let handle = XcbDisplayHandle::new(Some(connection), screen); + /// ``` + pub fn new(connection: Option>, screen: c_int) -> Self { + Self { connection, screen } + } +} + /// Raw window handle for Xcb. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::XcbWindowHandle; -/// let window_handle = XcbWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct XcbWindowHandle { /// An X11 `xcb_window_t`. - pub window: u32, // Based on xproto.h - /// An X11 `xcb_visualid_t`, or 0 if unknown. - pub visual_id: u32, + pub window: NonZeroU32, // Based on xproto.h + /// An X11 `xcb_visualid_t`. + pub visual_id: Option, +} + +impl XcbWindowHandle { + /// Create a new handle to a window. + /// + /// + /// # Example + /// + /// ``` + /// # use core::num::NonZeroU32; + /// # use raw_window_handle::XcbWindowHandle; + /// # + /// let window: NonZeroU32; + /// # window = NonZeroU32::new(1).unwrap(); + /// let mut handle = XcbWindowHandle::new(window); + /// // Optionally set the visual ID. + /// handle.visual_id = None; + /// ``` + pub fn new(window: NonZeroU32) -> Self { + Self { + window, + visual_id: None, + } + } } /// Raw display handle for Wayland. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::WaylandDisplayHandle; -/// let display_handle = WaylandDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct WaylandDisplayHandle { /// A pointer to a `wl_display`. - pub display: *mut c_void, + pub display: NonNull, +} + +impl WaylandDisplayHandle { + /// Create a new display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_void; + /// # use core::ptr::NonNull; + /// # use raw_window_handle::WaylandDisplayHandle; + /// # + /// let display: NonNull; + /// # display = NonNull::from(&()).cast(); + /// let handle = WaylandDisplayHandle::new(display); + /// ``` + pub fn new(display: NonNull) -> Self { + Self { display } + } } /// Raw window handle for Wayland. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::WaylandWindowHandle; -/// let window_handle = WaylandWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct WaylandWindowHandle { /// A pointer to a `wl_surface`. - pub surface: *mut c_void, + pub surface: NonNull, +} + +impl WaylandWindowHandle { + /// Create a new handle to a surface. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_void; + /// # use core::ptr::NonNull; + /// # use raw_window_handle::WaylandWindowHandle; + /// # + /// let surface: NonNull; + /// # surface = NonNull::from(&()).cast(); + /// let handle = WaylandWindowHandle::new(surface); + /// ``` + pub fn new(surface: NonNull) -> Self { + Self { surface } + } } /// Raw display handle for the Linux Kernel Mode Set/Direct Rendering Manager. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::DrmDisplayHandle; -/// let display_handle = DrmDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct DrmDisplayHandle { /// The drm file descriptor. + // TODO: Use `std::os::fd::RawFd`? pub fd: i32, } +impl DrmDisplayHandle { + /// Create a new handle to a file descriptor. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::DrmDisplayHandle; + /// # + /// let fd: i32; + /// # fd = 0; + /// let handle = DrmDisplayHandle::new(fd); + /// ``` + pub fn new(fd: i32) -> Self { + Self { fd } + } +} + /// Raw window handle for the Linux Kernel Mode Set/Direct Rendering Manager. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::DrmWindowHandle; -/// let handle = DrmWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct DrmWindowHandle { @@ -139,112 +241,76 @@ pub struct DrmWindowHandle { pub plane: u32, } +impl DrmWindowHandle { + /// Create a new handle to a plane. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::DrmWindowHandle; + /// # + /// let plane: u32; + /// # plane = 0; + /// let handle = DrmWindowHandle::new(plane); + /// ``` + pub fn new(plane: u32) -> Self { + Self { plane } + } +} + /// Raw display handle for the Linux Generic Buffer Manager. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::GbmDisplayHandle; -/// let display_handle = GbmDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct GbmDisplayHandle { /// The gbm device. - pub gbm_device: *mut c_void, + pub gbm_device: NonNull, +} + +impl GbmDisplayHandle { + /// Create a new handle to a device. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_void; + /// # use core::ptr::NonNull; + /// # use raw_window_handle::GbmDisplayHandle; + /// # + /// let ptr: NonNull; + /// # ptr = NonNull::from(&()).cast(); + /// let handle = GbmDisplayHandle::new(ptr); + /// ``` + pub fn new(gbm_device: NonNull) -> Self { + Self { gbm_device } + } } /// Raw window handle for the Linux Generic Buffer Manager. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::GbmWindowHandle; -/// let handle = GbmWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct GbmWindowHandle { /// The gbm surface. - pub gbm_surface: *mut c_void, -} - -impl XlibDisplayHandle { - pub fn empty() -> Self { - Self { - display: ptr::null_mut(), - screen: 0, - } - } -} - -impl XlibWindowHandle { - pub fn empty() -> Self { - Self { - window: 0, - visual_id: 0, - } - } -} - -impl XcbDisplayHandle { - pub fn empty() -> Self { - Self { - connection: ptr::null_mut(), - screen: 0, - } - } -} - -impl XcbWindowHandle { - pub fn empty() -> Self { - Self { - window: 0, - visual_id: 0, - } - } -} - -impl WaylandDisplayHandle { - pub fn empty() -> Self { - Self { - display: ptr::null_mut(), - } - } -} - -impl WaylandWindowHandle { - pub fn empty() -> Self { - Self { - surface: ptr::null_mut(), - } - } -} - -impl DrmDisplayHandle { - pub fn empty() -> Self { - Self { fd: 0 } - } -} - -impl DrmWindowHandle { - pub fn empty() -> Self { - Self { plane: 0 } - } -} - -impl GbmDisplayHandle { - pub fn empty() -> Self { - Self { - gbm_device: ptr::null_mut(), - } - } + pub gbm_surface: NonNull, } impl GbmWindowHandle { - pub fn empty() -> Self { - Self { - gbm_surface: ptr::null_mut(), - } + /// Create a new handle to a surface. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ffi::c_void; + /// # use core::ptr::NonNull; + /// # use raw_window_handle::GbmWindowHandle; + /// # + /// let ptr: NonNull; + /// # ptr = NonNull::from(&()).cast(); + /// let handle = GbmWindowHandle::new(ptr); + /// ``` + pub fn new(gbm_surface: NonNull) -> Self { + Self { gbm_surface } } } diff --git a/src/web.rs b/src/web.rs index 1e6908f..33d7e87 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,29 +1,24 @@ /// Raw display handle for the Web. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::WebDisplayHandle; -/// let mut display_handle = WebDisplayHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct WebDisplayHandle; +pub struct WebDisplayHandle {} impl WebDisplayHandle { - pub fn empty() -> Self { + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::WebDisplayHandle; + /// let handle = WebDisplayHandle::new(); + /// ``` + pub fn new() -> Self { Self {} } } /// Raw window handle for the Web. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::WebWindowHandle; -/// let mut window_handle = WebWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct WebWindowHandle { @@ -32,14 +27,24 @@ pub struct WebWindowHandle { /// When accessing from JS, the attribute will automatically be called `rawHandle`. /// /// Each canvas created by the windowing system should be assigned their own unique ID. - /// 0 should be reserved for invalid / null IDs. /// /// [data attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-* pub id: u32, } impl WebWindowHandle { - pub fn empty() -> Self { - Self { id: 0 } + /// Create a new handle to a canvas element. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::WebWindowHandle; + /// # + /// let id: u32 = 0; // canvas.rawHandle; + /// let handle = WebWindowHandle::new(id); + /// ``` + pub fn new(id: u32) -> Self { + Self { id } } } diff --git a/src/windows.rs b/src/windows.rs index 32b1a88..9751dbf 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,71 +1,91 @@ use core::ffi::c_void; -use core::ptr; +use core::num::NonZeroIsize; +use core::ptr::NonNull; /// Raw display handle for Windows. /// -/// It could be used regardless of Windows window backend. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::WindowsDisplayHandle; -/// let mut display_handle = WindowsDisplayHandle::empty(); -/// /* set fields */ -/// ``` +/// It can be used regardless of Windows window backend. #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct WindowsDisplayHandle; +pub struct WindowsDisplayHandle {} impl WindowsDisplayHandle { - pub fn empty() -> Self { - Self + /// Create a new empty display handle. + /// + /// + /// # Example + /// + /// ``` + /// # use raw_window_handle::WindowsDisplayHandle; + /// let handle = WindowsDisplayHandle::new(); + /// ``` + pub fn new() -> Self { + Self {} } } /// Raw window handle for Win32. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::Win32WindowHandle; -/// let mut window_handle = Win32WindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Win32WindowHandle { /// A Win32 `HWND` handle. - pub hwnd: *mut c_void, - /// The `HINSTANCE` associated with this type's `HWND`. - pub hinstance: *mut c_void, + pub hwnd: NonZeroIsize, + /// The `GWLP_HINSTANCE` associated with this type's `HWND`. + pub hinstance: Option, } impl Win32WindowHandle { - pub fn empty() -> Self { + /// Create a new handle to a window. + /// + /// + /// # Example + /// + /// ``` + /// # use core::num::NonZeroIsize; + /// # use raw_window_handle::Win32WindowHandle; + /// # struct HWND(isize); + /// # + /// let window: HWND; + /// # window = HWND(1); + /// let mut handle = Win32WindowHandle::new(NonZeroIsize::new(window.0).unwrap()); + /// // Optionally set the GWLP_HINSTANCE. + /// # #[cfg(only_for_showcase)] + /// let hinstance = NonZeroIsize::new(unsafe { GetWindowLongPtrW(window, GWLP_HINSTANCE) }).unwrap(); + /// # let hinstance = None; + /// handle.hinstance = hinstance; + /// ``` + pub fn new(hwnd: NonZeroIsize) -> Self { Self { - hwnd: ptr::null_mut(), - hinstance: ptr::null_mut(), + hwnd, + hinstance: None, } } } /// Raw window handle for WinRT. -/// -/// ## Construction -/// ``` -/// # use raw_window_handle::WinRtWindowHandle; -/// let mut window_handle = WinRtWindowHandle::empty(); -/// /* set fields */ -/// ``` #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct WinRtWindowHandle { /// A WinRT `CoreWindow` handle. - pub core_window: *mut c_void, + pub core_window: NonNull, } impl WinRtWindowHandle { - pub fn empty() -> Self { - Self { - core_window: ptr::null_mut(), - } + /// Create a new handle to a window. + /// + /// + /// # Example + /// + /// ``` + /// # use core::ptr::NonNull; + /// # use raw_window_handle::WinRtWindowHandle; + /// # type CoreWindow = (); + /// # + /// let window: NonNull; + /// # window = NonNull::from(&()); + /// let handle = WinRtWindowHandle::new(window.cast()); + /// ``` + pub fn new(core_window: NonNull) -> Self { + Self { core_window } } }