From e41fac825c22e123061e3e2082e19429213679cc Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 14 Oct 2023 19:07:39 -0700 Subject: [PATCH] Update to new raw-window-handle strategy Signed-off-by: John Nunley Co-authored-by: TornaxO7 --- Cargo.toml | 8 +- deny.toml | 1 + examples/child_window.rs | 22 +++-- examples/util/fill.rs | 4 +- src/event_loop.rs | 31 ++++-- src/lib.rs | 3 + src/platform/ios.rs | 26 ++--- src/platform/macos.rs | 48 +++++---- src/platform/windows.rs | 33 ++++--- src/platform_impl/android/mod.rs | 60 ++++++++++-- src/platform_impl/ios/event_loop.rs | 17 +++- src/platform_impl/ios/window.rs | 42 ++++++-- src/platform_impl/linux/mod.rs | 45 +++++++-- .../linux/wayland/event_loop/mod.rs | 28 ++++-- src/platform_impl/linux/wayland/window/mod.rs | 50 ++++++++-- src/platform_impl/linux/x11/mod.rs | 23 ++++- src/platform_impl/linux/x11/window.rs | 63 +++++++++--- src/platform_impl/macos/event_loop.rs | 16 ++- src/platform_impl/macos/window.rs | 77 +++++++++------ src/platform_impl/orbital/event_loop.rs | 17 +++- src/platform_impl/orbital/window.rs | 44 +++++++-- .../web/event_loop/window_target.rs | 18 +++- src/platform_impl/web/window.rs | 38 ++++++-- src/platform_impl/windows/event_loop.rs | 15 ++- src/platform_impl/windows/window.rs | 78 +++++++++++---- src/window.rs | 97 ++++++++++++------- 26 files changed, 662 insertions(+), 242 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1e189755a2..752a8576b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ categories = ["gui"] rust-version = "1.65.0" [package.metadata.docs.rs] -features = ["serde"] +features = ["rwh_04", "rwh_05", "rwh_06", "serde"] default-target = "x86_64-unknown-linux-gnu" # These are all tested in CI targets = [ @@ -35,7 +35,7 @@ targets = [ rustdoc-args = ["--cfg", "docsrs"] [features] -default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"] +default = ["rwh_06", "x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"] x11 = ["x11-dl", "bytemuck", "percent-encoding", "xkbcommon-dl/x11", "x11rb"] wayland = ["wayland-client", "wayland-backend", "wayland-protocols", "wayland-protocols-plasma", "sctk", "fnv", "memmap2"] wayland-dlopen = ["wayland-backend/dlopen"] @@ -55,7 +55,9 @@ cursor-icon = "1.0.0" log = "0.4" mint = { version = "0.5.6", optional = true } once_cell = "1.12" -raw_window_handle = { package = "raw-window-handle", version = "0.5", features = ["std"] } +rwh_04 = { package = "raw-window-handle", version = "0.4", optional = true } +rwh_05 = { package = "raw-window-handle", version = "0.5", features = ["std"], optional = true } +rwh_06 = { package = "raw-window-handle", version = "0.6", features = ["std"], optional = true } serde = { version = "1", optional = true, features = ["serde_derive"] } smol_str = "0.2.0" diff --git a/deny.toml b/deny.toml index eb551db8e7..982c4149e2 100644 --- a/deny.toml +++ b/deny.toml @@ -31,6 +31,7 @@ multiple-versions = "deny" wildcards = "allow" # at least until https://github.com/EmbarkStudios/cargo-deny/issues/241 is fixed deny = [] skip = [ + { name = "raw-window-handle" }, # we intentionally have multiple versions of this { name = "bitflags" }, # the ecosystem is in the process of migrating. { name = "nix" }, # differing version - as of 2023-03-02 whis can be solved with `cargo update && cargo update -p calloop --precise 0.10.2` { name = "memoffset"}, # due to different nix versions. diff --git a/examples/child_window.rs b/examples/child_window.rs index df036075c6..9234d9e4e6 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -1,8 +1,15 @@ -#[cfg(any(x11_platform, macos_platform, windows_platform))] +#[cfg(all( + feature = "rwh_06", + any(x11_platform, macos_platform, windows_platform) +))] #[path = "util/fill.rs"] mod fill; -#[cfg(any(x11_platform, macos_platform, windows_platform))] +#[cfg(all( + feature = "rwh_06", + any(x11_platform, macos_platform, windows_platform) +))] +#[allow(deprecated)] fn main() -> Result<(), impl std::error::Error> { use std::collections::HashMap; @@ -10,7 +17,7 @@ fn main() -> Result<(), impl std::error::Error> { dpi::{LogicalPosition, LogicalSize, Position}, event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::{EventLoop, EventLoopWindowTarget}, - window::raw_window_handle::HasRawWindowHandle, + raw_window_handle::HasRawWindowHandle, window::{Window, WindowBuilder, WindowId}, }; @@ -19,7 +26,7 @@ fn main() -> Result<(), impl std::error::Error> { event_loop: &EventLoopWindowTarget<()>, windows: &mut HashMap, ) { - let parent = parent.raw_window_handle(); + let parent = parent.raw_window_handle().unwrap(); let mut builder = WindowBuilder::new() .with_title("child window") .with_inner_size(LogicalSize::new(200.0f32, 200.0f32)) @@ -81,7 +88,10 @@ fn main() -> Result<(), impl std::error::Error> { }) } -#[cfg(not(any(x11_platform, macos_platform, windows_platform)))] +#[cfg(not(all( + feature = "rwh_06", + any(x11_platform, macos_platform, windows_platform) +)))] fn main() { - panic!("This example is supported only on x11, macOS, and Windows."); + panic!("This example is supported only on x11, macOS, and Windows, with the `rwh_06` feature enabled."); } diff --git a/examples/util/fill.rs b/examples/util/fill.rs index 7f1f1b1f63..a47ce95a04 100644 --- a/examples/util/fill.rs +++ b/examples/util/fill.rs @@ -9,7 +9,7 @@ use winit::window::Window; -#[cfg(not(any(target_os = "android", target_os = "ios")))] +#[cfg(all(feature = "rwh_05", not(any(target_os = "android", target_os = "ios"))))] pub(super) fn fill_window(window: &Window) { use softbuffer::{Context, Surface}; use std::cell::RefCell; @@ -80,7 +80,7 @@ pub(super) fn fill_window(window: &Window) { }) } -#[cfg(any(target_os = "android", target_os = "ios"))] +#[cfg(not(all(feature = "rwh_05", not(any(target_os = "android", target_os = "ios")))))] pub(super) fn fill_window(_window: &Window) { // No-op on mobile platforms. } diff --git a/src/event_loop.rs b/src/event_loop.rs index 1b9d688831..503bb79e5f 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -12,7 +12,6 @@ use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::{error, fmt}; -use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; #[cfg(not(wasm_platform))] use std::time::{Duration, Instant}; #[cfg(wasm_platform)] @@ -248,10 +247,18 @@ impl EventLoop { } } -unsafe impl HasRawDisplayHandle for EventLoop { +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for EventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + rwh_06::HasDisplayHandle::display_handle(&**self) + } +} + +#[cfg(feature = "rwh_05")] +unsafe impl rwh_05::HasRawDisplayHandle for EventLoop { /// Returns a [`raw_window_handle::RawDisplayHandle`] for the event loop. - fn raw_display_handle(&self) -> RawDisplayHandle { - self.event_loop.window_target().p.raw_display_handle() + fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { + rwh_05::HasRawDisplayHandle::raw_display_handle(&**self) } } @@ -327,10 +334,20 @@ impl EventLoopWindowTarget { } } -unsafe impl HasRawDisplayHandle for EventLoopWindowTarget { +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for EventLoopWindowTarget { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = self.p.raw_display_handle_rwh_06()?; + // SAFETY: The display will never be deallocated while the event loop is alive. + Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) }) + } +} + +#[cfg(feature = "rwh_05")] +unsafe impl rwh_05::HasRawDisplayHandle for EventLoopWindowTarget { /// Returns a [`raw_window_handle::RawDisplayHandle`] for the event loop. - fn raw_display_handle(&self) -> RawDisplayHandle { - self.p.raw_display_handle() + fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { + self.p.raw_display_handle_rwh_05() } } diff --git a/src/lib.rs b/src/lib.rs index 651681d7a1..b505961f30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,6 +139,9 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![allow(clippy::missing_safety_doc)] +#[cfg(feature = "rwh_06")] +pub use rwh_06 as raw_window_handle; + #[allow(unused_imports)] #[macro_use] extern crate log; diff --git a/src/platform/ios.rs b/src/platform/ios.rs index e1a6fa86cd..2097453917 100644 --- a/src/platform/ios.rs +++ b/src/platform/ios.rs @@ -118,7 +118,7 @@ pub trait WindowBuilderExtIOS { /// /// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc /// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc - fn with_scale_factor(self, scale_factor: f64) -> WindowBuilder; + fn with_scale_factor(self, scale_factor: f64) -> Self; /// Sets the valid orientations for the [`Window`]. /// @@ -126,7 +126,7 @@ pub trait WindowBuilderExtIOS { /// /// This sets the initial value returned by /// [`-[UIViewController supportedInterfaceOrientations]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621435-supportedinterfaceorientations?language=objc). - fn with_valid_orientations(self, valid_orientations: ValidOrientations) -> WindowBuilder; + fn with_valid_orientations(self, valid_orientations: ValidOrientations) -> Self; /// Sets whether the [`Window`] prefers the home indicator hidden. /// @@ -136,7 +136,7 @@ pub trait WindowBuilderExtIOS { /// [`-[UIViewController prefersHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden?language=objc). /// /// This only has an effect on iOS 11.0+. - fn with_prefers_home_indicator_hidden(self, hidden: bool) -> WindowBuilder; + fn with_prefers_home_indicator_hidden(self, hidden: bool) -> Self; /// Sets the screen edges for which the system gestures will take a lower priority than the /// application's touch handling. @@ -145,10 +145,7 @@ pub trait WindowBuilderExtIOS { /// [`-[UIViewController preferredScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys?language=objc). /// /// This only has an effect on iOS 11.0+. - fn with_preferred_screen_edges_deferring_system_gestures( - self, - edges: ScreenEdge, - ) -> WindowBuilder; + fn with_preferred_screen_edges_deferring_system_gestures(self, edges: ScreenEdge) -> Self; /// Sets whether the [`Window`] prefers the status bar hidden. /// @@ -156,40 +153,37 @@ pub trait WindowBuilderExtIOS { /// /// This sets the initial value returned by /// [`-[UIViewController prefersStatusBarHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621440-prefersstatusbarhidden?language=objc). - fn with_prefers_status_bar_hidden(self, hidden: bool) -> WindowBuilder; + fn with_prefers_status_bar_hidden(self, hidden: bool) -> Self; } impl WindowBuilderExtIOS for WindowBuilder { #[inline] - fn with_scale_factor(mut self, scale_factor: f64) -> WindowBuilder { + fn with_scale_factor(mut self, scale_factor: f64) -> Self { self.platform_specific.scale_factor = Some(scale_factor); self } #[inline] - fn with_valid_orientations(mut self, valid_orientations: ValidOrientations) -> WindowBuilder { + fn with_valid_orientations(mut self, valid_orientations: ValidOrientations) -> Self { self.platform_specific.valid_orientations = valid_orientations; self } #[inline] - fn with_prefers_home_indicator_hidden(mut self, hidden: bool) -> WindowBuilder { + fn with_prefers_home_indicator_hidden(mut self, hidden: bool) -> Self { self.platform_specific.prefers_home_indicator_hidden = hidden; self } #[inline] - fn with_preferred_screen_edges_deferring_system_gestures( - mut self, - edges: ScreenEdge, - ) -> WindowBuilder { + fn with_preferred_screen_edges_deferring_system_gestures(mut self, edges: ScreenEdge) -> Self { self.platform_specific .preferred_screen_edges_deferring_system_gestures = edges; self } #[inline] - fn with_prefers_status_bar_hidden(mut self, hidden: bool) -> WindowBuilder { + fn with_prefers_status_bar_hidden(mut self, hidden: bool) -> Self { self.platform_specific.prefers_status_bar_hidden = hidden; self } diff --git a/src/platform/macos.rs b/src/platform/macos.rs index d3fedeb116..d543c299d8 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -183,92 +183,88 @@ pub enum ActivationPolicy { /// - `with_fullsize_content_view` pub trait WindowBuilderExtMacOS { /// Enables click-and-drag behavior for the entire window, not just the titlebar. - fn with_movable_by_window_background(self, movable_by_window_background: bool) - -> WindowBuilder; + fn with_movable_by_window_background(self, movable_by_window_background: bool) -> Self; /// Makes the titlebar transparent and allows the content to appear behind it. - fn with_titlebar_transparent(self, titlebar_transparent: bool) -> WindowBuilder; + fn with_titlebar_transparent(self, titlebar_transparent: bool) -> Self; /// Hides the window title. - fn with_title_hidden(self, title_hidden: bool) -> WindowBuilder; + fn with_title_hidden(self, title_hidden: bool) -> Self; /// Hides the window titlebar. - fn with_titlebar_hidden(self, titlebar_hidden: bool) -> WindowBuilder; + fn with_titlebar_hidden(self, titlebar_hidden: bool) -> Self; /// Hides the window titlebar buttons. - fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> WindowBuilder; + fn with_titlebar_buttons_hidden(self, titlebar_buttons_hidden: bool) -> Self; /// Makes the window content appear behind the titlebar. - fn with_fullsize_content_view(self, fullsize_content_view: bool) -> WindowBuilder; - fn with_disallow_hidpi(self, disallow_hidpi: bool) -> WindowBuilder; - fn with_has_shadow(self, has_shadow: bool) -> WindowBuilder; + fn with_fullsize_content_view(self, fullsize_content_view: bool) -> Self; + fn with_disallow_hidpi(self, disallow_hidpi: bool) -> Self; + fn with_has_shadow(self, has_shadow: bool) -> Self; /// Window accepts click-through mouse events. - fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> WindowBuilder; + fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> Self; /// Defines the window tabbing identifier. /// /// - fn with_tabbing_identifier(self, identifier: &str) -> WindowBuilder; + fn with_tabbing_identifier(self, identifier: &str) -> Self; /// Set how the Option keys are interpreted. /// /// See [`WindowExtMacOS::set_option_as_alt`] for details on what this means if set. - fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> WindowBuilder; + fn with_option_as_alt(self, option_as_alt: OptionAsAlt) -> Self; } impl WindowBuilderExtMacOS for WindowBuilder { #[inline] - fn with_movable_by_window_background( - mut self, - movable_by_window_background: bool, - ) -> WindowBuilder { + fn with_movable_by_window_background(mut self, movable_by_window_background: bool) -> Self { self.platform_specific.movable_by_window_background = movable_by_window_background; self } #[inline] - fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> WindowBuilder { + fn with_titlebar_transparent(mut self, titlebar_transparent: bool) -> Self { self.platform_specific.titlebar_transparent = titlebar_transparent; self } #[inline] - fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> WindowBuilder { + fn with_titlebar_hidden(mut self, titlebar_hidden: bool) -> Self { self.platform_specific.titlebar_hidden = titlebar_hidden; self } #[inline] - fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> WindowBuilder { + fn with_titlebar_buttons_hidden(mut self, titlebar_buttons_hidden: bool) -> Self { self.platform_specific.titlebar_buttons_hidden = titlebar_buttons_hidden; self } #[inline] - fn with_title_hidden(mut self, title_hidden: bool) -> WindowBuilder { + fn with_title_hidden(mut self, title_hidden: bool) -> Self { self.platform_specific.title_hidden = title_hidden; self } #[inline] - fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> WindowBuilder { + fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self { self.platform_specific.fullsize_content_view = fullsize_content_view; self } #[inline] - fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> WindowBuilder { + fn with_disallow_hidpi(mut self, disallow_hidpi: bool) -> Self { self.platform_specific.disallow_hidpi = disallow_hidpi; self } #[inline] - fn with_has_shadow(mut self, has_shadow: bool) -> WindowBuilder { + fn with_has_shadow(mut self, has_shadow: bool) -> Self { self.platform_specific.has_shadow = has_shadow; self } #[inline] - fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> WindowBuilder { + fn with_accepts_first_mouse(mut self, accepts_first_mouse: bool) -> Self { self.platform_specific.accepts_first_mouse = accepts_first_mouse; self } #[inline] - fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> WindowBuilder { + fn with_tabbing_identifier(mut self, tabbing_identifier: &str) -> Self { self.platform_specific .tabbing_identifier .replace(tabbing_identifier.to_string()); @@ -276,7 +272,7 @@ impl WindowBuilderExtMacOS for WindowBuilder { } #[inline] - fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> WindowBuilder { + fn with_option_as_alt(mut self, option_as_alt: OptionAsAlt) -> Self { self.platform_specific.option_as_alt = option_as_alt; self } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 0da33468a0..8e10157944 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -161,6 +161,7 @@ impl WindowExtWindows for Window { } /// Additional methods on `WindowBuilder` that are specific to Windows. +#[allow(rustdoc::broken_intra_doc_links)] pub trait WindowBuilderExtWindows { /// Set an owner to the window to be created. Can be used to create a dialog box, for example. /// This only works when [`WindowBuilder::with_parent_window`] isn't called or set to `None`. @@ -173,7 +174,7 @@ pub trait WindowBuilderExtWindows { /// - An owned window is hidden when its owner is minimized. /// /// For more information, see - fn with_owner_window(self, parent: HWND) -> WindowBuilder; + fn with_owner_window(self, parent: HWND) -> Self; /// Sets a menu on the window to be created. /// @@ -185,13 +186,13 @@ pub trait WindowBuilderExtWindows { /// If you use this, it is recommended that you combine it with `with_theme(Some(Theme::Light))` to avoid a jarring effect. /// /// [`CreateMenu`]: windows_sys::Win32::UI::WindowsAndMessaging::CreateMenu - fn with_menu(self, menu: HMENU) -> WindowBuilder; + fn with_menu(self, menu: HMENU) -> Self; /// This sets `ICON_BIG`. A good ceiling here is 256x256. - fn with_taskbar_icon(self, taskbar_icon: Option) -> WindowBuilder; + fn with_taskbar_icon(self, taskbar_icon: Option) -> Self; /// This sets `WS_EX_NOREDIRECTIONBITMAP`. - fn with_no_redirection_bitmap(self, flag: bool) -> WindowBuilder; + fn with_no_redirection_bitmap(self, flag: bool) -> Self; /// Enables or disables drag and drop support (enabled by default). Will interfere with other crates /// that use multi-threaded COM API (`CoInitializeEx` with `COINIT_MULTITHREADED` instead of @@ -199,66 +200,66 @@ pub trait WindowBuilderExtWindows { /// COM API regardless of this option. Currently only fullscreen mode does that, but there may be more in the future. /// If you need COM API with `COINIT_MULTITHREADED` you must initialize it before calling any winit functions. /// See for more information. - fn with_drag_and_drop(self, flag: bool) -> WindowBuilder; + fn with_drag_and_drop(self, flag: bool) -> Self; /// Whether show or hide the window icon in the taskbar. - fn with_skip_taskbar(self, skip: bool) -> WindowBuilder; + fn with_skip_taskbar(self, skip: bool) -> Self; /// Customize the window class name. - fn with_class_name>(self, class_name: S) -> WindowBuilder; + fn with_class_name>(self, class_name: S) -> Self; /// Shows or hides the background drop shadow for undecorated windows. /// /// The shadow is hidden by default. /// Enabling the shadow causes a thin 1px line to appear on the top of the window. - fn with_undecorated_shadow(self, shadow: bool) -> WindowBuilder; + fn with_undecorated_shadow(self, shadow: bool) -> Self; } impl WindowBuilderExtWindows for WindowBuilder { #[inline] - fn with_owner_window(mut self, parent: HWND) -> WindowBuilder { + fn with_owner_window(mut self, parent: HWND) -> Self { self.platform_specific.owner = Some(parent); self } #[inline] - fn with_menu(mut self, menu: HMENU) -> WindowBuilder { + fn with_menu(mut self, menu: HMENU) -> Self { self.platform_specific.menu = Some(menu); self } #[inline] - fn with_taskbar_icon(mut self, taskbar_icon: Option) -> WindowBuilder { + fn with_taskbar_icon(mut self, taskbar_icon: Option) -> Self { self.platform_specific.taskbar_icon = taskbar_icon; self } #[inline] - fn with_no_redirection_bitmap(mut self, flag: bool) -> WindowBuilder { + fn with_no_redirection_bitmap(mut self, flag: bool) -> Self { self.platform_specific.no_redirection_bitmap = flag; self } #[inline] - fn with_drag_and_drop(mut self, flag: bool) -> WindowBuilder { + fn with_drag_and_drop(mut self, flag: bool) -> Self { self.platform_specific.drag_and_drop = flag; self } #[inline] - fn with_skip_taskbar(mut self, skip: bool) -> WindowBuilder { + fn with_skip_taskbar(mut self, skip: bool) -> Self { self.platform_specific.skip_taskbar = skip; self } #[inline] - fn with_class_name>(mut self, class_name: S) -> WindowBuilder { + fn with_class_name>(mut self, class_name: S) -> Self { self.platform_specific.class_name = class_name.into(); self } #[inline] - fn with_undecorated_shadow(mut self, shadow: bool) -> WindowBuilder { + fn with_undecorated_shadow(mut self, shadow: bool) -> Self { self.platform_specific.decoration_shadow = shadow; self } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 10d431c21a..2c6ef65c38 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -16,9 +16,6 @@ use android_activity::{ AndroidApp, AndroidAppWaker, ConfigurationRef, InputStatus, MainEvent, Rect, }; use once_cell::sync::Lazy; -use raw_window_handle::{ - AndroidDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, -}; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -688,8 +685,20 @@ impl EventLoopWindowTarget { #[inline] pub fn listen_device_events(&self, _allowed: DeviceEvents) {} - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Android(AndroidDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Android(rwh_05::AndroidDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Android( + rwh_06::AndroidDisplayHandle::new(), + )) } pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { @@ -935,7 +944,21 @@ impl Window { )) } - pub fn raw_window_handle(&self) -> RawWindowHandle { + #[cfg(feature = "rwh_04")] + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + if let Some(native_window) = self.app.native_window().as_ref() { + let mut handle = rwh_04::AndroidNdkHandle::empty(); + handle.a_native_window = native_window.ptr().as_ptr() as *mut _; + rwh_04::RawWindowHandle::AndroidNdk(handle) + } else { + panic!("Cannot get the native window, it's null and will always be null before Event::Resumed and after Event::Suspended. Make sure you only call this function between those events."); + } + } + + #[cfg(feature = "rwh_05")] + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + use rwh_05::HasRawWindowHandle; + if let Some(native_window) = self.app.native_window().as_ref() { native_window.raw_window_handle() } else { @@ -943,8 +966,29 @@ impl Window { } } - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Android(AndroidDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Android(rwh_05::AndroidDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + pub fn raw_window_handle_rwh_06(&self) -> Result { + if let Some(native_window) = self.app.native_window().as_ref() { + let handle = rwh_06::AndroidNdkWindowHandle::new(native_window.ptr().cast()); + Ok(rwh_06::RawWindowHandle::AndroidNdk(handle)) + } else { + log::error!("Cannot get the native window, it's null and will always be null before Event::Resumed and after Event::Suspended. Make sure you only call this function between those events."); + Err(rwh_06::HandleError::Unavailable) + } + } + + #[cfg(feature = "rwh_06")] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Android( + rwh_06::AndroidDisplayHandle::new(), + )) } pub fn config(&self) -> ConfigurationRef { diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index 883acfc8a4..dab69606ee 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -16,7 +16,6 @@ use core_foundation::runloop::{ }; use icrate::Foundation::{MainThreadMarker, NSString}; use objc2::ClassType; -use raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle}; use crate::{ error::EventLoopError, @@ -52,8 +51,20 @@ impl EventLoopWindowTarget { #[inline] pub fn listen_device_events(&self, _allowed: DeviceEvents) {} - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::UiKit(rwh_05::UiKitDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::UiKit( + rwh_06::UiKitDisplayHandle::new(), + )) } pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 46eb6435eb..8864c58b3a 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -6,7 +6,6 @@ use icrate::Foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, Main use objc2::rc::Id; use objc2::runtime::AnyObject; use objc2::{class, msg_send}; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle, UiKitDisplayHandle, UiKitWindowHandle}; use super::app_state::EventWrapper; use super::uikit::{UIApplication, UIScreen, UIScreenOverscanCompensation}; @@ -332,16 +331,47 @@ impl Inner { self.window.id() } - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut window_handle = UiKitWindowHandle::empty(); + #[cfg(feature = "rwh_04")] + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut window_handle = rwh_04::UiKitHandle::empty(); window_handle.ui_window = Id::as_ptr(&self.window) as _; window_handle.ui_view = Id::as_ptr(&self.view) as _; window_handle.ui_view_controller = Id::as_ptr(&self.view_controller) as _; - RawWindowHandle::UiKit(window_handle) + rwh_04::RawWindowHandle::UiKit(window_handle) } - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut window_handle = rwh_05::UiKitWindowHandle::empty(); + window_handle.ui_window = Id::as_ptr(&self.window) as _; + window_handle.ui_view = Id::as_ptr(&self.view) as _; + window_handle.ui_view_controller = Id::as_ptr(&self.view_controller) as _; + rwh_05::RawWindowHandle::UiKit(window_handle) + } + + #[cfg(feature = "rwh_05")] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::UiKit(rwh_05::UiKitDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + pub fn raw_window_handle_rwh_06(&self) -> Result { + let mut window_handle = rwh_06::UiKitWindowHandle::new({ + let ui_view = Id::as_ptr(&self.view) as _; + std::ptr::NonNull::new(ui_view).expect("Id should never be null") + }); + window_handle.ui_view_controller = + std::ptr::NonNull::new(Id::as_ptr(&self.view_controller) as _); + Ok(rwh_06::RawWindowHandle::UiKit(window_handle)) + } + + #[cfg(feature = "rwh_06")] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::UiKit( + rwh_06::UiKitDisplayHandle::new(), + )) } pub fn theme(&self) -> Option { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 8fb148564a..e7d8be5b75 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -11,7 +11,6 @@ use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Mutex}; #[cfg(x11_platform)] use once_cell::sync::Lazy; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use smol_str::SmolStr; #[cfg(x11_platform)] @@ -578,14 +577,36 @@ impl Window { Some(x11_or_wayland!(match self; Window(w) => w.primary_monitor()?; as MonitorHandle)) } + #[cfg(feature = "rwh_04")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - x11_or_wayland!(match self; Window(window) => window.raw_window_handle()) + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + x11_or_wayland!(match self; Window(window) => window.raw_window_handle_rwh_04()) } + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - x11_or_wayland!(match self; Window(window) => window.raw_display_handle()) + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + x11_or_wayland!(match self; Window(window) => window.raw_window_handle_rwh_05()) + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + x11_or_wayland!(match self; Window(window) => window.raw_display_handle_rwh_05()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_window_handle_rwh_06(&self) -> Result { + x11_or_wayland!(match self; Window(window) => window.raw_window_handle_rwh_06()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + x11_or_wayland!(match self; Window(window) => window.raw_display_handle_rwh_06()) } #[inline] @@ -855,8 +876,18 @@ impl EventLoopWindowTarget { x11_or_wayland!(match self; Self(evlp) => evlp.listen_device_events(allowed)) } - pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { - x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle()) + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle_rwh_05()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle_rwh_06()) } pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index c0baead6a1..1b84b65fc4 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -9,12 +9,10 @@ use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; -use raw_window_handle::{RawDisplayHandle, WaylandDisplayHandle}; - use sctk::reexports::calloop; use sctk::reexports::calloop::Error as CalloopError; use sctk::reexports::client::globals; -use sctk::reexports::client::{Connection, Proxy, QueueHandle, WaylandSource}; +use sctk::reexports::client::{Connection, QueueHandle, WaylandSource}; use crate::dpi::{LogicalSize, PhysicalSize}; use crate::error::{EventLoopError, OsError as RootOsError}; @@ -653,10 +651,28 @@ impl EventLoopWindowTarget { #[inline] pub fn listen_device_events(&self, _allowed: DeviceEvents) {} - pub fn raw_display_handle(&self) -> RawDisplayHandle { - let mut display_handle = WaylandDisplayHandle::empty(); + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + use sctk::reexports::client::Proxy; + + let mut display_handle = rwh_05::WaylandDisplayHandle::empty(); display_handle.display = self.connection.display().id().as_ptr() as *mut _; - RawDisplayHandle::Wayland(display_handle) + rwh_05::RawDisplayHandle::Wayland(display_handle) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + use sctk::reexports::client::Proxy; + + Ok(rwh_06::WaylandDisplayHandle::new({ + let ptr = self.connection.display().id().as_ptr(); + std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null") + }) + .into()) } } diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index d7b5bbe396..2f79918f48 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -3,10 +3,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -use raw_window_handle::{ - RawDisplayHandle, RawWindowHandle, WaylandDisplayHandle, WaylandWindowHandle, -}; - use sctk::reexports::calloop; use sctk::reexports::client::protocol::wl_display::WlDisplay; use sctk::reexports::client::protocol::wl_surface::WlSurface; @@ -57,6 +53,7 @@ pub struct Window { compositor: Arc, /// The wayland display used solely for raw window handle. + #[allow(dead_code)] display: WlDisplay, /// Xdg activation to request user attention. @@ -650,18 +647,51 @@ impl Window { None } + #[cfg(feature = "rwh_04")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut window_handle = WaylandWindowHandle::empty(); + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut window_handle = rwh_04::WaylandHandle::empty(); window_handle.surface = self.window.wl_surface().id().as_ptr() as *mut _; - RawWindowHandle::Wayland(window_handle) + window_handle.display = self.display.id().as_ptr() as *mut _; + rwh_04::RawWindowHandle::Wayland(window_handle) } + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - let mut display_handle = WaylandDisplayHandle::empty(); + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut window_handle = rwh_05::WaylandWindowHandle::empty(); + window_handle.surface = self.window.wl_surface().id().as_ptr() as *mut _; + rwh_05::RawWindowHandle::Wayland(window_handle) + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + let mut display_handle = rwh_05::WaylandDisplayHandle::empty(); display_handle.display = self.display.id().as_ptr() as *mut _; - RawDisplayHandle::Wayland(display_handle) + rwh_05::RawDisplayHandle::Wayland(display_handle) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_window_handle_rwh_06(&self) -> Result { + Ok(rwh_06::WaylandWindowHandle::new({ + let ptr = self.window.wl_surface().id().as_ptr(); + std::ptr::NonNull::new(ptr as *mut _).expect("wl_surface will never be null") + }) + .into()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::WaylandDisplayHandle::new({ + let ptr = self.display.id().as_ptr(); + std::ptr::NonNull::new(ptr as *mut _).expect("wl_proxy should never be null") + }) + .into()) } #[inline] diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 037426a036..640b5168d3 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -45,7 +45,6 @@ use std::{ use libc::{self, setlocale, LC_CTYPE}; use atoms::*; -use raw_window_handle::{RawDisplayHandle, XlibDisplayHandle}; use x11rb::x11_utils::X11Error as LogicalError; use x11rb::{ @@ -704,11 +703,27 @@ impl EventLoopWindowTarget { .expect_then_ignore_error("Failed to update device event filter"); } - pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { - let mut display_handle = XlibDisplayHandle::empty(); + #[cfg(feature = "rwh_05")] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + let mut display_handle = rwh_05::XlibDisplayHandle::empty(); display_handle.display = self.xconn.display as *mut _; display_handle.screen = self.xconn.default_screen_index() as c_int; - RawDisplayHandle::Xlib(display_handle) + display_handle.into() + } + + #[cfg(feature = "rwh_06")] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + let display_handle = rwh_06::XlibDisplayHandle::new( + // SAFETY: display will never be null + Some( + std::ptr::NonNull::new(self.xconn.display as *mut _) + .expect("X11 display should never be null"), + ), + self.xconn.default_screen_index() as c_int, + ); + Ok(display_handle.into()) } pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index bab2f8c59f..e3ee0e4d77 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -7,7 +7,6 @@ use std::{ sync::{Arc, Mutex, MutexGuard}, }; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XlibDisplayHandle, XlibWindowHandle}; use x11rb::{ connection::Connection, properties::{WmHints, WmHintsState, WmSizeHints, WmSizeHintsSpecification}, @@ -117,9 +116,11 @@ unsafe impl Sync for UnownedWindow {} pub(crate) struct UnownedWindow { pub(crate) xconn: Arc, // never changes xwindow: xproto::Window, // never changes - visual: u32, // never changes + #[allow(dead_code)] + visual: u32, // never changes root: xproto::Window, // never changes - screen_id: i32, // never changes + #[allow(dead_code)] + screen_id: i32, // never changes cursor: Mutex, cursor_grabbed_mode: Mutex, #[allow(clippy::mutex_atomic)] @@ -148,12 +149,15 @@ impl UnownedWindow { ) -> Result { let xconn = &event_loop.xconn; let atoms = xconn.atoms(); + #[cfg(feature = "rwh_06")] let root = match window_attrs.parent_window { - Some(RawWindowHandle::Xlib(handle)) => handle.window as xproto::Window, - Some(RawWindowHandle::Xcb(handle)) => handle.window, + Some(rwh_06::RawWindowHandle::Xlib(handle)) => handle.window as xproto::Window, + Some(rwh_06::RawWindowHandle::Xcb(handle)) => handle.window.get(), Some(raw) => unreachable!("Invalid raw window handle {raw:?} on X11"), None => event_loop.root, }; + #[cfg(not(feature = "rwh_06"))] + let root = event_loop.root; let mut monitors = leap!(xconn.available_monitors()); let guessed_monitor = if monitors.is_empty() { @@ -1464,11 +1468,13 @@ impl UnownedWindow { WindowButtons::all() } + #[allow(dead_code)] #[inline] pub fn xlib_display(&self) -> *mut c_void { self.xconn.display as _ } + #[allow(dead_code)] #[inline] pub fn xlib_window(&self) -> c_ulong { self.xwindow as ffi::Window @@ -1817,20 +1823,55 @@ impl UnownedWindow { // TODO timer } + #[cfg(feature = "rwh_04")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut window_handle = XlibWindowHandle::empty(); + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut window_handle = rwh_04::XlibHandle::empty(); + window_handle.display = self.xlib_display(); window_handle.window = self.xlib_window(); window_handle.visual_id = self.visual as c_ulong; - RawWindowHandle::Xlib(window_handle) + rwh_04::RawWindowHandle::Xlib(window_handle) } + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - let mut display_handle = XlibDisplayHandle::empty(); + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut window_handle = rwh_05::XlibWindowHandle::empty(); + window_handle.window = self.xlib_window(); + window_handle.visual_id = self.visual as c_ulong; + window_handle.into() + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + let mut display_handle = rwh_05::XlibDisplayHandle::empty(); display_handle.display = self.xlib_display(); display_handle.screen = self.screen_id; - RawDisplayHandle::Xlib(display_handle) + display_handle.into() + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_window_handle_rwh_06(&self) -> Result { + let mut window_handle = rwh_06::XlibWindowHandle::new(self.xlib_window()); + window_handle.visual_id = self.visual as c_ulong; + Ok(window_handle.into()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::XlibDisplayHandle::new( + Some( + std::ptr::NonNull::new(self.xlib_display()) + .expect("display pointer should never be null"), + ), + self.screen_id, + ) + .into()) } #[inline] diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 0fca45aded..fc56b11d37 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -21,7 +21,6 @@ use icrate::Foundation::MainThreadMarker; use objc2::rc::{autoreleasepool, Id}; use objc2::runtime::NSObjectProtocol; use objc2::{msg_send_id, ClassType}; -use raw_window_handle::{AppKitDisplayHandle, RawDisplayHandle}; use super::appkit::{NSApp, NSApplication, NSApplicationActivationPolicy, NSEvent, NSWindow}; use crate::{ @@ -89,9 +88,20 @@ impl EventLoopWindowTarget { #[inline] pub fn listen_device_events(&self, _allowed: DeviceEvents) {} + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::AppKit(rwh_05::AppKitDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::AppKit( + rwh_06::AppKitDisplayHandle::new(), + )) } pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 0d58a55f7e..5bb3d04268 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -7,10 +7,6 @@ use std::os::raw::c_void; use std::ptr::NonNull; use std::sync::{Mutex, MutexGuard}; -use raw_window_handle::{ - AppKitDisplayHandle, AppKitWindowHandle, RawDisplayHandle, RawWindowHandle, -}; - use crate::{ dpi::{ LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size, Size::Logical, @@ -452,29 +448,19 @@ impl WinitWindow { }) .ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSWindow`")))?; + #[cfg(feature = "rwh_06")] match attrs.parent_window { - Some(RawWindowHandle::AppKit(handle)) => { + Some(rwh_06::RawWindowHandle::AppKit(handle)) => { // SAFETY: Caller ensures the pointer is valid or NULL - let parent: Id = match unsafe { Id::retain(handle.ns_window.cast()) } { - Some(window) => window, - None => { - // SAFETY: Caller ensures the pointer is valid or NULL - let parent_view: Id = - match unsafe { Id::retain(handle.ns_view.cast()) } { - Some(view) => view, - None => { - return Err(os_error!(OsError::CreationError( - "raw window handle should be non-empty" - ))) - } - }; - parent_view.window().ok_or_else(|| { - os_error!(OsError::CreationError( - "parent view should be installed in a window" - )) - })? - } - }; + // Unwrap is fine, since the pointer comes from `NonNull`. + let parent_view: Id = + unsafe { Id::retain(handle.ns_view.as_ptr().cast()) }.unwrap(); + let parent = parent_view.window().ok_or_else(|| { + os_error!(OsError::CreationError( + "parent view should be installed in a window" + )) + })?; + // SAFETY: We know that there are no parent -> child -> parent cycles since the only place in `winit` // where we allow making a window a child window is right here, just after it's been created. unsafe { parent.addChildWindow(&this, NSWindowOrderingMode::NSWindowAbove) }; @@ -1352,17 +1338,48 @@ impl WinitWindow { Some(monitor) } + #[cfg(feature = "rwh_04")] + #[inline] + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut window_handle = rwh_04::AppKitHandle::empty(); + window_handle.ns_window = self as *const Self as *mut _; + window_handle.ns_view = Id::as_ptr(&self.contentView()) as *mut _; + rwh_04::RawWindowHandle::AppKit(window_handle) + } + + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut window_handle = AppKitWindowHandle::empty(); + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut window_handle = rwh_05::AppKitWindowHandle::empty(); window_handle.ns_window = self as *const Self as *mut _; window_handle.ns_view = Id::as_ptr(&self.contentView()) as *mut _; - RawWindowHandle::AppKit(window_handle) + rwh_05::RawWindowHandle::AppKit(window_handle) } + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::AppKit(rwh_05::AppKitDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_window_handle_rwh_06(&self) -> Result { + let window_handle = rwh_06::AppKitWindowHandle::new({ + let ptr = Id::as_ptr(&self.contentView()) as *mut _; + std::ptr::NonNull::new(ptr).expect("Id should never be null") + }); + Ok(rwh_06::RawWindowHandle::AppKit(window_handle)) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::AppKit( + rwh_06::AppKitDisplayHandle::new(), + )) } fn toggle_style_mask(&self, mask: NSWindowStyleMask, on: bool) { diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index cd64a9228f..954a2142a1 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -11,7 +11,6 @@ use orbclient::{ ButtonEvent, EventOption, FocusEvent, HoverEvent, KeyEvent, MouseEvent, MoveEvent, QuitEvent, ResizeEvent, ScrollEvent, TextInputEvent, }; -use raw_window_handle::{OrbitalDisplayHandle, RawDisplayHandle}; use crate::{ error::EventLoopError, @@ -736,8 +735,20 @@ impl EventLoopWindowTarget { #[inline] pub fn listen_device_events(&self, _allowed: DeviceEvents) {} - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Orbital(rwh_05::OrbitalDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Orbital( + rwh_06::OrbitalDisplayHandle::new(), + )) } pub fn set_control_flow(&self, control_flow: ControlFlow) { diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index f08df9c8d4..26ab72681a 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -3,10 +3,6 @@ use std::{ sync::{Arc, Mutex}, }; -use raw_window_handle::{ - OrbitalDisplayHandle, OrbitalWindowHandle, RawDisplayHandle, RawWindowHandle, -}; - use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, @@ -400,16 +396,46 @@ impl Window { )) } + #[cfg(feature = "rwh_04")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut handle = OrbitalWindowHandle::empty(); + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut handle = rwh_04::OrbitalHandle::empty(); handle.window = self.window_socket.fd as *mut _; - RawWindowHandle::Orbital(handle) + rwh_04::RawWindowHandle::Orbital(handle) + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut handle = rwh_05::OrbitalWindowHandle::empty(); + handle.window = self.window_socket.fd as *mut _; + rwh_05::RawWindowHandle::Orbital(handle) + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Orbital(rwh_05::OrbitalDisplayHandle::empty()) } + #[cfg(feature = "rwh_06")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty()) + pub fn raw_window_handle_rwh_06(&self) -> Result { + let handle = rwh_06::OrbitalWindowHandle::new({ + let window = self.window_socket.fd as *mut _; + std::ptr::NonNull::new(window).expect("orbital fd shoul never be null") + }); + Ok(rwh_06::RawWindowHandle::Orbital(handle)) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Orbital( + rwh_06::OrbitalDisplayHandle::new(), + )) } #[inline] diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index b0bfd4755b..ba1868532d 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -6,8 +6,6 @@ use std::marker::PhantomData; use std::rc::Rc; use std::sync::atomic::Ordering; -use raw_window_handle::{RawDisplayHandle, WebDisplayHandle}; - use super::runner::EventWrapper; use super::{ super::{monitor::MonitorHandle, KeyEventExtra}, @@ -672,8 +670,20 @@ impl EventLoopWindowTarget { None } - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Web(WebDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Web(rwh_05::WebDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Web( + rwh_06::WebDisplayHandle::new(), + )) } pub fn listen_device_events(&self, allowed: DeviceEvents) { diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 2285d9f734..fd6fad4e29 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -6,7 +6,6 @@ use crate::window::{ WindowAttributes, WindowButtons, WindowId as RootWI, WindowLevel, }; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WebDisplayHandle, WebWindowHandle}; use web_sys::HtmlCanvasElement; use super::r#async::Dispatcher; @@ -358,16 +357,43 @@ impl Inner { self.id } + #[cfg(feature = "rwh_04")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut window_handle = WebWindowHandle::empty(); + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut window_handle = rwh_04::WebHandle::empty(); window_handle.id = self.id.0; - RawWindowHandle::Web(window_handle) + rwh_04::RawWindowHandle::Web(window_handle) } + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Web(WebDisplayHandle::empty()) + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut window_handle = rwh_05::WebWindowHandle::empty(); + window_handle.id = self.id.0; + rwh_05::RawWindowHandle::Web(window_handle) + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Web(rwh_05::WebDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_window_handle_rwh_06(&self) -> Result { + let window_handle = rwh_06::WebWindowHandle::new(self.id.0); + Ok(rwh_06::RawWindowHandle::Web(window_handle)) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Web( + rwh_06::WebDisplayHandle::new(), + )) } #[inline] diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index a8ed8f2a08..0abd9b1798 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -18,7 +18,6 @@ use std::{ }; use once_cell::sync::Lazy; -use raw_window_handle::{RawDisplayHandle, WindowsDisplayHandle}; use windows_sys::Win32::{ Devices::HumanInterfaceDevice::MOUSE_MOVE_RELATIVE, @@ -534,8 +533,18 @@ impl EventLoopWindowTarget { Some(monitor) } - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Windows(WindowsDisplayHandle::empty()) + #[cfg(feature = "rwh_05")] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Windows(rwh_05::WindowsDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Windows( + rwh_06::WindowsDisplayHandle::new(), + )) } pub fn listen_device_events(&self, allowed: DeviceEvents) { diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index ebfd3b0e5f..ed539c2059 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -1,8 +1,5 @@ #![cfg(windows_platform)] -use raw_window_handle::{ - RawDisplayHandle, RawWindowHandle, Win32WindowHandle, WindowsDisplayHandle, -}; use std::{ cell::Cell, ffi::c_void, @@ -337,18 +334,53 @@ impl Window { self.window.0 } + #[cfg(feature = "rwh_04")] + #[inline] + pub fn raw_window_handle_rwh_04(&self) -> rwh_04::RawWindowHandle { + let mut window_handle = rwh_04::Win32Handle::empty(); + window_handle.hwnd = self.window.0 as *mut _; + let hinstance = unsafe { super::get_window_long(self.hwnd(), GWLP_HINSTANCE) }; + window_handle.hinstance = hinstance as *mut _; + rwh_04::RawWindowHandle::Win32(window_handle) + } + + #[cfg(feature = "rwh_05")] #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - let mut window_handle = Win32WindowHandle::empty(); + pub fn raw_window_handle_rwh_05(&self) -> rwh_05::RawWindowHandle { + let mut window_handle = rwh_05::Win32WindowHandle::empty(); window_handle.hwnd = self.window.0 as *mut _; let hinstance = unsafe { super::get_window_long(self.hwnd(), GWLP_HINSTANCE) }; window_handle.hinstance = hinstance as *mut _; - RawWindowHandle::Win32(window_handle) + rwh_05::RawWindowHandle::Win32(window_handle) + } + + #[cfg(feature = "rwh_05")] + #[inline] + pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle { + rwh_05::RawDisplayHandle::Windows(rwh_05::WindowsDisplayHandle::empty()) + } + + #[cfg(feature = "rwh_06")] + #[inline] + pub fn raw_window_handle_rwh_06(&self) -> Result { + let mut window_handle = rwh_06::Win32WindowHandle::new(unsafe { + // SAFETY: Handle will never be zero. + let window = self.window.0; + std::num::NonZeroIsize::new_unchecked(window) + }); + let hinstance = unsafe { super::get_window_long(self.hwnd(), GWLP_HINSTANCE) }; + window_handle.hinstance = std::num::NonZeroIsize::new(hinstance); + Ok(rwh_06::RawWindowHandle::Win32(window_handle)) } + #[cfg(feature = "rwh_06")] #[inline] - pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Windows(WindowsDisplayHandle::empty()) + pub fn raw_display_handle_rwh_06( + &self, + ) -> Result { + Ok(rwh_06::RawDisplayHandle::Windows( + rwh_06::WindowsDisplayHandle::new(), + )) } #[inline] @@ -1228,27 +1260,33 @@ where // so the diffing later can work. window_flags.set(WindowFlags::CLOSABLE, true); + let mut fallback_parent = || match pl_attribs.owner { + Some(parent) => { + window_flags.set(WindowFlags::POPUP, true); + Some(parent) + } + None => { + window_flags.set(WindowFlags::ON_TASKBAR, true); + None + } + }; + + #[cfg(feature = "rwh_06")] let parent = match attributes.parent_window { - Some(RawWindowHandle::Win32(handle)) => { + Some(rwh_06::RawWindowHandle::Win32(handle)) => { window_flags.set(WindowFlags::CHILD, true); if pl_attribs.menu.is_some() { warn!("Setting a menu on a child window is unsupported"); } - Some(handle.hwnd as HWND) + Some(handle.hwnd.get() as HWND) } Some(raw) => unreachable!("Invalid raw window handle {raw:?} on Windows"), - None => match pl_attribs.owner { - Some(parent) => { - window_flags.set(WindowFlags::POPUP, true); - Some(parent) - } - None => { - window_flags.set(WindowFlags::ON_TASKBAR, true); - None - } - }, + None => fallback_parent(), }; + #[cfg(not(feature = "rwh_06"))] + let parent = fallback_parent(); + let mut initdata = InitData { event_loop, attributes, diff --git a/src/window.rs b/src/window.rs index a232062ad1..4bf90b8413 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,10 +1,6 @@ //! The [`Window`] struct and associated types. use std::fmt; -use raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, -}; - use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError}, @@ -18,9 +14,6 @@ pub use crate::icon::{BadIcon, Icon}; #[doc(inline)] pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError}; -#[doc(inline)] -pub use raw_window_handle; - /// Represents a window. /// /// @@ -159,7 +152,8 @@ pub struct WindowAttributes { pub resize_increments: Option, pub content_protected: bool, pub window_level: WindowLevel, - pub parent_window: Option, + #[cfg(feature = "rwh_06")] + pub parent_window: Option, pub active: bool, } @@ -185,6 +179,7 @@ impl Default for WindowAttributes { preferred_theme: None, resize_increments: None, content_protected: false, + #[cfg(feature = "rwh_06")] parent_window: None, active: true, } @@ -197,7 +192,9 @@ impl WindowBuilder { pub fn new() -> Self { Default::default() } +} +impl WindowBuilder { /// Get the current window attributes. pub fn window_attributes(&self) -> &WindowAttributes { &self.window @@ -456,7 +453,7 @@ impl WindowBuilder { /// /// [`WindowEvent::Focused`]: crate::event::WindowEvent::Focused. #[inline] - pub fn with_active(mut self, active: bool) -> WindowBuilder { + pub fn with_active(mut self, active: bool) -> Self { self.window.active = active; self } @@ -476,8 +473,12 @@ impl WindowBuilder { /// /// - **X11**: A child window is confined to the client area of its parent window. /// - **Android / iOS / Wayland / Web:** Unsupported. + #[cfg(feature = "rwh_06")] #[inline] - pub unsafe fn with_parent_window(mut self, parent_window: Option) -> Self { + pub unsafe fn with_parent_window( + mut self, + parent_window: Option, + ) -> Self { self.window.parent_window = parent_window; self } @@ -1505,41 +1506,71 @@ impl Window { } } -unsafe impl HasRawWindowHandle for Window { - /// Returns a [`raw_window_handle::RawWindowHandle`] for the Window - /// - /// ## Platform-specific - /// - /// ### Android - /// - /// Only available after receiving [`Event::Resumed`] and before [`Event::Suspended`]. *If you - /// try to get the handle outside of that period, this function will panic*! - /// - /// Make sure to release or destroy any resources created from this `RawWindowHandle` (ie. Vulkan - /// or OpenGL surfaces) before returning from [`Event::Suspended`], at which point Android will - /// release the underlying window/surface: any subsequent interaction is undefined behavior. - /// - /// [`Event::Resumed`]: crate::event::Event::Resumed - /// [`Event::Suspended`]: crate::event::Event::Suspended - fn raw_window_handle(&self) -> RawWindowHandle { - struct Wrapper(RawWindowHandle); +#[cfg(feature = "rwh_06")] +impl rwh_06::HasWindowHandle for Window { + fn window_handle(&self) -> Result, rwh_06::HandleError> { + struct Wrapper(rwh_06::RawWindowHandle); + unsafe impl Send for Wrapper {} + + let raw = self + .window + .maybe_wait_on_main(|w| w.raw_window_handle_rwh_06().map(Wrapper))? + .0; + + // SAFETY: The window handle will never be deallocated while the window is alive. + Ok(unsafe { rwh_06::WindowHandle::borrow_raw(raw) }) + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for Window { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + struct Wrapper(rwh_06::RawDisplayHandle); + unsafe impl Send for Wrapper {} + + let raw = self + .window + .maybe_wait_on_main(|w| w.raw_display_handle_rwh_06().map(Wrapper))? + .0; + + // SAFETY: The window handle will never be deallocated while the window is alive. + Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) }) + } +} + +#[cfg(feature = "rwh_05")] +unsafe impl rwh_05::HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> rwh_05::RawWindowHandle { + struct Wrapper(rwh_05::RawWindowHandle); unsafe impl Send for Wrapper {} self.window - .maybe_wait_on_main(|w| Wrapper(w.raw_window_handle())) + .maybe_wait_on_main(|w| Wrapper(w.raw_window_handle_rwh_05())) .0 } } -unsafe impl HasRawDisplayHandle for Window { +#[cfg(feature = "rwh_05")] +unsafe impl rwh_05::HasRawDisplayHandle for Window { /// Returns a [`raw_window_handle::RawDisplayHandle`] used by the [`EventLoop`] that /// created a window. /// /// [`EventLoop`]: crate::event_loop::EventLoop - fn raw_display_handle(&self) -> RawDisplayHandle { - struct Wrapper(RawDisplayHandle); + fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { + struct Wrapper(rwh_05::RawDisplayHandle); + unsafe impl Send for Wrapper {} + self.window + .maybe_wait_on_main(|w| Wrapper(w.raw_display_handle_rwh_05())) + .0 + } +} + +#[cfg(feature = "rwh_04")] +unsafe impl rwh_04::HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> rwh_04::RawWindowHandle { + struct Wrapper(rwh_04::RawWindowHandle); unsafe impl Send for Wrapper {} self.window - .maybe_wait_on_main(|w| Wrapper(w.raw_display_handle())) + .maybe_wait_on_main(|w| Wrapper(w.raw_window_handle_rwh_04())) .0 } }