From 4cdf1dec78a5dc5512ded7eab7c7a1e7d7ac0a9b Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 10 Aug 2022 17:34:55 +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. Addresses: #2415 --- CHANGELOG.md | 1 + Cargo.toml | 3 +- src/event_loop.rs | 2 +- src/platform_impl/windows/event_loop.rs | 2 +- src/platform_impl/windows/window.rs | 2 +- src/window.rs | 118 +++++++++++++++++++++++- 6 files changed, 122 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5633f7b23d8..b856cb3d5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,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. +- 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 5365442273c..d0acd196362 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_05 = { 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/event_loop.rs b/src/event_loop.rs index b96c80c9bc5..588ed3b0dfb 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -13,7 +13,7 @@ use std::{error, fmt}; use instant::Instant; use once_cell::sync::OnceCell; -use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; +use raw_window_handle_05::{HasRawDisplayHandle, RawDisplayHandle}; use crate::{event::Event, monitor::MonitorHandle, platform_impl}; diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 632fc854f9c..1c83d68129a 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -19,7 +19,7 @@ use std::{ use once_cell::sync::Lazy; use parking_lot::Mutex; -use raw_window_handle::{RawDisplayHandle, WindowsDisplayHandle}; +use raw_window_handle_05::{RawDisplayHandle, WindowsDisplayHandle}; use windows_sys::Win32::{ Devices::HumanInterfaceDevice::MOUSE_MOVE_RELATIVE, diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index e63075a833d..d553de58aba 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -1,7 +1,7 @@ #![cfg(target_os = "windows")] use parking_lot::Mutex; -use raw_window_handle::{ +use raw_window_handle_05::{ RawDisplayHandle, RawWindowHandle, Win32WindowHandle, WindowsDisplayHandle, }; use std::{ diff --git a/src/window.rs b/src/window.rs index 4e1cb18b7ef..ce84739706f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,7 +1,7 @@ //! The [`Window`] struct and associated types. use std::fmt; -use raw_window_handle::{ +use raw_window_handle_05::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; @@ -1056,7 +1056,6 @@ unsafe impl HasRawWindowHandle for Window { self.window.raw_window_handle() } } - unsafe impl HasRawDisplayHandle for Window { /// Returns a [`raw_window_handle::RawDisplayHandle`] used by the [`EventLoop`] that /// created a window. @@ -1066,6 +1065,121 @@ 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() { + 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) => { + if let RawDisplayHandle::Xlib(display_handle) = self.window.raw_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) + } else { + panic!("Unsupported display handle associated with Xlib window"); + } + }, + RawWindowHandle::Xcb(window_handle) => { + if let RawDisplayHandle::Xcb(display_handle) = self.window.raw_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) + } else { + panic!("Unsupported display handle associated with Xcb window"); + } + }, + RawWindowHandle::Wayland(window_handle) => { + if let RawDisplayHandle::Wayland(display_handle) = self.window.raw_display_handle() { + let mut handle = WaylandHandle::empty(); + handle.display = display_handle.display; + handle.surface = window_handle.surface; + raw_window_handle_04::RawWindowHandle::Wayland(handle) + } else { + panic!("Unsupported display handle associated with Xcb window"); + } + }, + 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. ///