From 11d4a301e48166ae9fcf9042cd29ce8108b35d26 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 11 Aug 2022 15:33:02 +0100 Subject: [PATCH] Implement version 0.4 of the HasRawWindowHandle trait This makes Winit 0.27 compatible with crates like Wgpu 0.13 that are using the raw_window_handle v0.4 crate and aren't able to upgrade to 0.5 until they do a new release (since it requires a semver change). The change is intended to be self-contained (instead of pushing the details into all the platform_impl backends) since this is only intended to be a temporary trait implementation for backwards compatibility that will likely be removed before the next Winit release. Fixes #2415. --- CHANGELOG.md | 1 + Cargo.toml | 3 +- src/window.rs | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd90848..4f8b10e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ And please only add new entries to the top of this list, right below the `# Unre - On X11, fix min, max and resize increment hints not persisting for resizable windows (e.g. on DPI change). - On Windows, respect min/max inner sizes when creating the window. - **Breaking:** On Windows, device events are now ignored for unfocused windows by default, use `EventLoopWindowTarget::set_device_event_filter` to set the filter level. +- For backwards compatibility, `Window` now (additionally) implements the old version (`0.4`) of the `HasRawWindowHandle` trait # 0.27.1 (2022-07-30) diff --git a/Cargo.toml b/Cargo.toml index 53654422..c2761a0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,8 @@ instant = { version = "0.1", features = ["wasm-bindgen"] } once_cell = "1.12" log = "0.4" serde = { version = "1", optional = true, features = ["serde_derive"] } -raw-window-handle = "0.5.0" +raw_window_handle = { package = "raw-window-handle", version = "0.5" } +raw_window_handle_04 = { package = "raw-window-handle", version = "0.4" } bitflags = "1" mint = { version = "0.5.6", optional = true } diff --git a/src/window.rs b/src/window.rs index 4e1cb18b..dba514f9 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1066,6 +1066,109 @@ unsafe impl HasRawDisplayHandle for Window { self.window.raw_display_handle() } } +unsafe impl raw_window_handle_04::HasRawWindowHandle for Window { + /// Returns a [`raw_window_handle_04::RawWindowHandle`] for the Window + /// + /// This provides backwards compatibility for downstream crates that have not yet + /// upgraded to `raw_window_handle` version 0.5, such as Wgpu version 0.13. + /// + /// ## 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) -> raw_window_handle_04::RawWindowHandle { + use raw_window_handle_04::{ + AndroidNdkHandle, AppKitHandle, HaikuHandle, OrbitalHandle, UiKitHandle, WaylandHandle, + WebHandle, Win32Handle, WinRtHandle, XcbHandle, XlibHandle, + }; + + // XXX: Ideally this would be encapsulated either through a + // compatibility API from raw_window_handle_05 or else within the + // backends but since this is only to provide short-term backwards + // compatibility, we just handle the full mapping inline here. + // + // The intention is to remove this trait implementation before Winit + // 0.28, once crates have had time to upgrade to raw_window_handle 0.5 + + match (self.window.raw_window_handle(), self.window.raw_display_handle()) { + (RawWindowHandle::UiKit(window_handle), _) => { + let mut handle = UiKitHandle::empty(); + handle.ui_view = window_handle.ui_view; + handle.ui_window = window_handle.ui_window; + handle.ui_view_controller = window_handle.ui_view_controller; + raw_window_handle_04::RawWindowHandle::UiKit(handle) + }, + (RawWindowHandle::AppKit(window_handle), _) => { + let mut handle = AppKitHandle::empty(); + handle.ns_window = window_handle.ns_window; + handle.ns_view = window_handle.ns_view; + raw_window_handle_04::RawWindowHandle::AppKit(handle) + }, + (RawWindowHandle::Orbital(window_handle), _) => { + let mut handle = OrbitalHandle::empty(); + handle.window = window_handle.window; + raw_window_handle_04::RawWindowHandle::Orbital(handle) + }, + (RawWindowHandle::Xlib(window_handle), RawDisplayHandle::Xlib(display_handle)) => { + let mut handle = XlibHandle::empty(); + handle.display = display_handle.display; + handle.window = window_handle.window; + handle.visual_id = window_handle.visual_id; + raw_window_handle_04::RawWindowHandle::Xlib(handle) + }, + (RawWindowHandle::Xcb(window_handle), RawDisplayHandle::Xcb(display_handle)) => { + let mut handle = XcbHandle::empty(); + handle.connection = display_handle.connection; + handle.window = window_handle.window; + handle.visual_id = window_handle.visual_id; + raw_window_handle_04::RawWindowHandle::Xcb(handle) + }, + (RawWindowHandle::Wayland(window_handle), RawDisplayHandle::Wayland(display_handle)) => { + let mut handle = WaylandHandle::empty(); + handle.display = display_handle.display; + handle.surface = window_handle.surface; + raw_window_handle_04::RawWindowHandle::Wayland(handle) + }, + (RawWindowHandle::Win32(window_handle), _) => { + let mut handle = Win32Handle::empty(); + handle.hwnd = window_handle.hwnd; + handle.hinstance = window_handle.hinstance; + raw_window_handle_04::RawWindowHandle::Win32(handle) + }, + (RawWindowHandle::WinRt(window_handle), _) => { + let mut handle = WinRtHandle::empty(); + handle.core_window = window_handle.core_window; + raw_window_handle_04::RawWindowHandle::WinRt(handle) + }, + (RawWindowHandle::Web(window_handle), _) => { + let mut handle = WebHandle::empty(); + handle.id = window_handle.id; + raw_window_handle_04::RawWindowHandle::Web(handle) + }, + (RawWindowHandle::AndroidNdk(window_handle), _) => { + let mut handle = AndroidNdkHandle::empty(); + handle.a_native_window = window_handle.a_native_window; + raw_window_handle_04::RawWindowHandle::AndroidNdk(handle) + }, + (RawWindowHandle::Haiku(window_handle), _) => { + let mut handle = HaikuHandle::empty(); + handle.b_window = window_handle.b_window; + handle.b_direct_window = window_handle.b_direct_window; + raw_window_handle_04::RawWindowHandle::Haiku(handle) + }, + _ => panic!("No HasRawWindowHandle version 0.4 backwards compatibility for new Winit window type"), + } + } +} /// The behavior of cursor grabbing. ///