From 6631771e8b0143f0adba028579bd06e14246e8af Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 9 Jul 2023 14:53:47 -0700 Subject: [PATCH 01/12] Port to use raw-window-handle v0.6 --- Cargo.toml | 3 ++- examples/child_window.rs | 2 +- src/event_loop.rs | 10 +++++----- src/platform_impl/android/mod.rs | 12 ++++++++---- src/platform_impl/ios/window.rs | 8 +++++--- src/platform_impl/linux/mod.rs | 6 +++--- src/platform_impl/macos/window.rs | 6 +++--- src/platform_impl/orbital/window.rs | 6 +++--- src/platform_impl/windows/window.rs | 6 +++--- src/window.rs | 11 ++++++----- 10 files changed, 39 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7f5a8ae0d9..9d37a0428e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,8 @@ 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"] } +raw_window_handle = { package = "raw-window-handle", git = "https://github.com/rust-windowing/raw-window-handle.git", features = ["std"] } +raw_window_handle_05 = { package = "raw-window-handle", version = "0.5" } serde = { version = "1", optional = true, features = ["serde_derive"] } smol_str = "0.2.0" diff --git a/examples/child_window.rs b/examples/child_window.rs index 65135b79e0..da402fa057 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -19,7 +19,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)) diff --git a/src/event_loop.rs b/src/event_loop.rs index f497c9338b..3bb4fab4d2 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -12,7 +12,7 @@ use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::{error, fmt}; -use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; +use raw_window_handle::{HandleError, HasRawDisplayHandle, RawDisplayHandle}; #[cfg(not(wasm_platform))] use std::time::{Duration, Instant}; #[cfg(wasm_platform)] @@ -329,8 +329,8 @@ impl EventLoop { unsafe impl 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) -> Result { + Ok(self.event_loop.window_target().p.raw_display_handle()) } } @@ -385,8 +385,8 @@ impl EventLoopWindowTarget { unsafe impl 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) -> Result { + Ok(self.p.raw_display_handle()) } } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index e610dd260f..161e22ac12 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -16,7 +16,7 @@ use android_activity::{ }; use once_cell::sync::Lazy; use raw_window_handle::{ - AndroidDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + AndroidDisplayHandle, AndroidNdkWindowHandle, HandleError, RawDisplayHandle, RawWindowHandle, }; use crate::{ @@ -942,11 +942,15 @@ impl Window { )) } - pub fn raw_window_handle(&self) -> RawWindowHandle { + pub fn raw_window_handle(&self) -> Result { if let Some(native_window) = self.app.native_window().as_ref() { - native_window.raw_window_handle() + // TODO: Port the ndk-rs crate to rwh v0.6 + let mut handle = AndroidNdkWindowHandle::empty(); + handle.a_native_window = native_window.ptr().as_ptr().cast(); + Ok(handle.into()) } 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."); + 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(HandleError::Unavailable) } } diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 71875be61a..fa80eed213 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -10,7 +10,9 @@ use icrate::Foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadMarker}; use objc2::rc::Id; use objc2::runtime::Object; use objc2::{class, msg_send}; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle, UiKitDisplayHandle, UiKitWindowHandle}; +use raw_window_handle::{ + HandleError, RawDisplayHandle, RawWindowHandle, UiKitDisplayHandle, UiKitWindowHandle, +}; use super::uikit::{UIApplication, UIScreen, UIScreenOverscanCompensation}; use super::view::{WinitUIWindow, WinitView, WinitViewController}; @@ -337,12 +339,12 @@ impl Inner { self.window.id() } - pub fn raw_window_handle(&self) -> RawWindowHandle { + pub fn raw_window_handle(&self) -> Result { let mut window_handle = 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 _; - RawWindowHandle::UiKit(window_handle) + Ok(RawWindowHandle::UiKit(window_handle)) } pub fn raw_display_handle(&self) -> RawDisplayHandle { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 4c2a43c7c5..d70b5c8008 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -17,7 +17,7 @@ use std::{ #[cfg(x11_platform)] use once_cell::sync::Lazy; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; +use raw_window_handle::{HandleError, RawDisplayHandle, RawWindowHandle}; use smol_str::SmolStr; use std::time::Duration; @@ -616,8 +616,8 @@ impl Window { } #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { - x11_or_wayland!(match self; Window(window) => window.raw_window_handle()) + pub fn raw_window_handle(&self) -> Result { + Ok(x11_or_wayland!(match self; Window(window) => window.raw_window_handle())) } #[inline] diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index f174753a84..fc236a535e 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -8,7 +8,7 @@ use std::ptr::NonNull; use std::sync::{Mutex, MutexGuard}; use raw_window_handle::{ - AppKitDisplayHandle, AppKitWindowHandle, RawDisplayHandle, RawWindowHandle, + AppKitDisplayHandle, AppKitWindowHandle, HandleError, RawDisplayHandle, RawWindowHandle, }; use crate::{ @@ -1245,11 +1245,11 @@ impl WinitWindow { } #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { + pub fn raw_window_handle(&self) -> Result { let mut window_handle = AppKitWindowHandle::empty(); window_handle.ns_window = self.ns_window(); window_handle.ns_view = self.ns_view(); - RawWindowHandle::AppKit(window_handle) + Ok(RawWindowHandle::AppKit(window_handle)) } #[inline] diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index 11ec6c7ee4..a25c0d6ef7 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -4,7 +4,7 @@ use std::{ }; use raw_window_handle::{ - OrbitalDisplayHandle, OrbitalWindowHandle, RawDisplayHandle, RawWindowHandle, + HandleError, OrbitalDisplayHandle, OrbitalWindowHandle, RawDisplayHandle, RawWindowHandle, }; use crate::{ @@ -384,10 +384,10 @@ impl Window { } #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { + pub fn raw_window_handle(&self) -> Result { let mut handle = OrbitalWindowHandle::empty(); handle.window = self.window_socket.fd as *mut _; - RawWindowHandle::Orbital(handle) + Ok(RawWindowHandle::Orbital(handle)) } #[inline] diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 1a11b2b667..a969fa3ffc 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -1,7 +1,7 @@ #![cfg(windows_platform)] use raw_window_handle::{ - RawDisplayHandle, RawWindowHandle, Win32WindowHandle, WindowsDisplayHandle, + HandleError, RawDisplayHandle, RawWindowHandle, Win32WindowHandle, WindowsDisplayHandle, }; use std::{ cell::Cell, @@ -325,11 +325,11 @@ impl Window { } #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { + pub fn raw_window_handle(&self) -> Result { let mut window_handle = Win32WindowHandle::empty(); window_handle.hwnd = self.window.0 as *mut _; window_handle.hinstance = self.hinstance() as *mut _; - RawWindowHandle::Win32(window_handle) + Ok(RawWindowHandle::Win32(window_handle)) } #[inline] diff --git a/src/window.rs b/src/window.rs index 017501f6b1..958210c6c4 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,7 @@ use std::fmt; use raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + HandleError, HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; use crate::{ @@ -1373,6 +1373,7 @@ impl Window { .map(|inner| MonitorHandle { inner }) } } + unsafe impl HasRawWindowHandle for Window { /// Returns a [`raw_window_handle::RawWindowHandle`] for the Window /// @@ -1389,8 +1390,8 @@ unsafe impl HasRawWindowHandle for Window { /// /// [`Event::Resumed`]: crate::event::Event::Resumed /// [`Event::Suspended`]: crate::event::Event::Suspended - fn raw_window_handle(&self) -> RawWindowHandle { - self.window.raw_window_handle() + fn raw_window_handle(&self) -> Result { + Ok(self.window.raw_window_handle()) } } @@ -1399,8 +1400,8 @@ unsafe impl HasRawDisplayHandle for Window { /// created a window. /// /// [`EventLoop`]: crate::event_loop::EventLoop - fn raw_display_handle(&self) -> RawDisplayHandle { - self.window.raw_display_handle() + fn raw_display_handle(&self) -> Result { + Ok(self.window.raw_display_handle()) } } From d1bd76a9f4cc10e46fe7720f7649713923d73a68 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 9 Jul 2023 15:11:12 -0700 Subject: [PATCH 02/12] Add rwh v0.5 compatibility --- CHANGELOG.md | 1 + src/event_loop.rs | 99 ++++++++++++++++++++++++++++++++++++++ src/window.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 218 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3099b6d91..7de7e90fd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ And please only add new entries to the top of this list, right below the `# Unre - On macOS, add tabbing APIs on `WindowExtMacOS` and `EventLoopWindowTargetExtMacOS`. - **Breaking:** Rename `Window::set_inner_size` to `Window::request_inner_size` and indicate if the size was applied immediately. - On X11, fix false positive flagging of key repeats when pressing different keys with no release between presses. +- Port types to use `raw-window-handle` v0.6. `raw-window-handle` v0.5 is still supported. - Implement `PartialOrd` and `Ord` for `KeyCode` and `NativeKeyCode`. - On Web, implement `WindowEvent::Occluded`. - On Web, fix touch location to be as accurate as mouse position. diff --git a/src/event_loop.rs b/src/event_loop.rs index 3bb4fab4d2..bc03d7b1a3 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -334,6 +334,17 @@ unsafe impl HasRawDisplayHandle for EventLoop { } } +unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoop { + fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { + let result = HasRawDisplayHandle::raw_display_handle(self); + + match result { + Ok(handle) => cvt_rdh_06_to_05(handle), + Err(e) => panic!("Failed to get raw display handle: {:?}", e), + } + } +} + impl Deref for EventLoop { type Target = EventLoopWindowTarget; fn deref(&self) -> &EventLoopWindowTarget { @@ -390,6 +401,17 @@ unsafe impl HasRawDisplayHandle for EventLoopWindowTarget { } } +unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoopWindowTarget { + fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { + let result = HasRawDisplayHandle::raw_display_handle(self); + + match result { + Ok(handle) => cvt_rdh_06_to_05(handle), + Err(e) => panic!("Failed to get raw display handle: {:?}", e), + } + } +} + /// Used to send custom events to [`EventLoop`]. pub struct EventLoopProxy { event_loop_proxy: platform_impl::EventLoopProxy, @@ -474,3 +496,80 @@ impl AsyncRequestSerial { Self { serial } } } + +/// Convert a `raw_window_handle` v0.6 `RawDisplayHandle` to a `raw_window_handle` v0.5 +/// `RawDisplayHandle`. +pub(crate) fn cvt_rdh_06_to_05(handle: RawDisplayHandle) -> raw_window_handle_05::RawDisplayHandle { + use raw_window_handle_05 as v5; + + match handle { + RawDisplayHandle::Android(_handle) => { + let result = v5::AndroidDisplayHandle::empty(); + v5::RawDisplayHandle::Android(result) + } + + RawDisplayHandle::AppKit(_handle) => { + let result = v5::AppKitDisplayHandle::empty(); + v5::RawDisplayHandle::AppKit(result) + } + + RawDisplayHandle::Drm(handle) => { + let mut result = v5::DrmDisplayHandle::empty(); + result.fd = handle.fd; + v5::RawDisplayHandle::Drm(result) + } + + RawDisplayHandle::Gbm(handle) => { + let mut result = v5::GbmDisplayHandle::empty(); + result.gbm_device = handle.gbm_device; + v5::RawDisplayHandle::Gbm(result) + } + + RawDisplayHandle::Haiku(_handle) => { + let result = v5::HaikuDisplayHandle::empty(); + v5::RawDisplayHandle::Haiku(result) + } + + RawDisplayHandle::Orbital(_handle) => { + let result = v5::OrbitalDisplayHandle::empty(); + v5::RawDisplayHandle::Orbital(result) + } + + RawDisplayHandle::UiKit(_handle) => { + let result = v5::UiKitDisplayHandle::empty(); + v5::RawDisplayHandle::UiKit(result) + } + + RawDisplayHandle::Wayland(handle) => { + let mut result = v5::WaylandDisplayHandle::empty(); + result.display = handle.display; + v5::RawDisplayHandle::Wayland(result) + } + + RawDisplayHandle::Web(_handle) => { + let result = v5::WebDisplayHandle::empty(); + v5::RawDisplayHandle::Web(result) + } + + RawDisplayHandle::Windows(_handle) => { + let result = v5::WindowsDisplayHandle::empty(); + v5::RawDisplayHandle::Windows(result) + } + + RawDisplayHandle::Xcb(handle) => { + let mut result = v5::XcbDisplayHandle::empty(); + result.connection = handle.connection; + result.screen = handle.screen; + v5::RawDisplayHandle::Xcb(result) + } + + RawDisplayHandle::Xlib(handle) => { + let mut result = v5::XlibDisplayHandle::empty(); + result.display = handle.display; + result.screen = handle.screen; + v5::RawDisplayHandle::Xlib(result) + } + + handle => panic!("Unsupported raw_display_handle: {:?}", handle), + } +} diff --git a/src/window.rs b/src/window.rs index 958210c6c4..df11deca87 100644 --- a/src/window.rs +++ b/src/window.rs @@ -8,7 +8,7 @@ use raw_window_handle::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError}, - event_loop::EventLoopWindowTarget, + event_loop::{cvt_rdh_06_to_05, EventLoopWindowTarget}, monitor::{MonitorHandle, VideoMode}, platform_impl, }; @@ -1395,6 +1395,17 @@ unsafe impl HasRawWindowHandle for Window { } } +unsafe impl raw_window_handle_05::HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> raw_window_handle_05::RawWindowHandle { + let result = HasRawWindowHandle::raw_window_handle(self); + + match result { + Ok(result) => cvt_rwh_06_to_05(result), + Err(e) => panic!("Error while getting raw window handle: {:?}", e), + } + } +} + unsafe impl HasRawDisplayHandle for Window { /// Returns a [`raw_window_handle::RawDisplayHandle`] used by the [`EventLoop`] that /// created a window. @@ -1405,6 +1416,17 @@ unsafe impl HasRawDisplayHandle for Window { } } +unsafe impl raw_window_handle_05::HasRawDisplayHandle for Window { + fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { + let result = HasRawDisplayHandle::raw_display_handle(self); + + match result { + Ok(result) => cvt_rdh_06_to_05(result), + Err(e) => panic!("Error while getting raw display handle: {:?}", e), + } + } +} + /// The behavior of cursor grabbing. /// /// Use this enum with [`Window::set_cursor_grab`] to grab the cursor. @@ -1580,3 +1602,98 @@ impl ActivationToken { Self { _token } } } + +/// Convert a `raw-window-handle` v0.6 `RawWindowHandle` to a `raw-window-handle` v0.5 +/// `RawWindowHandle`. +fn cvt_rwh_06_to_05(handle: RawWindowHandle) -> raw_window_handle_05::RawWindowHandle { + use raw_window_handle_05 as v5; + + match handle { + RawWindowHandle::AndroidNdk(ndk) => { + let mut handle = v5::AndroidNdkWindowHandle::empty(); + handle.a_native_window = ndk.a_native_window; + v5::RawWindowHandle::AndroidNdk(handle) + } + + RawWindowHandle::AppKit(app_kit) => { + let mut handle = v5::AppKitWindowHandle::empty(); + handle.ns_window = app_kit.ns_window; + handle.ns_view = app_kit.ns_view; + v5::RawWindowHandle::AppKit(handle) + } + + RawWindowHandle::Drm(drm) => { + let mut handle = v5::DrmWindowHandle::empty(); + handle.plane = drm.plane; + v5::RawWindowHandle::Drm(handle) + } + + RawWindowHandle::Gbm(gbm) => { + let mut handle = v5::GbmWindowHandle::empty(); + handle.gbm_surface = gbm.gbm_surface; + v5::RawWindowHandle::Gbm(handle) + } + + RawWindowHandle::Haiku(haiku) => { + let mut handle = v5::HaikuWindowHandle::empty(); + handle.b_direct_window = haiku.b_direct_window; + handle.b_window = haiku.b_window; + v5::RawWindowHandle::Haiku(handle) + } + + RawWindowHandle::Orbital(orbital) => { + let mut handle = v5::OrbitalWindowHandle::empty(); + handle.window = orbital.window; + v5::RawWindowHandle::Orbital(handle) + } + + RawWindowHandle::UiKit(ui_kit) => { + let mut handle = v5::UiKitWindowHandle::empty(); + handle.ui_window = ui_kit.ui_window; + handle.ui_view = ui_kit.ui_view; + handle.ui_view_controller = ui_kit.ui_view_controller; + v5::RawWindowHandle::UiKit(handle) + } + + RawWindowHandle::Wayland(wayland) => { + let mut handle = v5::WaylandWindowHandle::empty(); + handle.surface = wayland.surface; + v5::RawWindowHandle::Wayland(handle) + } + + RawWindowHandle::Web(web) => { + let mut handle = v5::WebWindowHandle::empty(); + handle.id = web.id; + v5::RawWindowHandle::Web(handle) + } + + RawWindowHandle::Win32(win32) => { + let mut handle = v5::Win32WindowHandle::empty(); + handle.hinstance = win32.hinstance; + handle.hwnd = win32.hwnd; + v5::RawWindowHandle::Win32(handle) + } + + RawWindowHandle::WinRt(winrt) => { + let mut handle = v5::WinRtWindowHandle::empty(); + handle.core_window = winrt.core_window; + v5::RawWindowHandle::WinRt(handle) + } + + RawWindowHandle::Xcb(xcb) => { + let mut handle = v5::XcbWindowHandle::empty(); + handle.window = xcb.window; + handle.visual_id = xcb.visual_id; + v5::RawWindowHandle::Xcb(handle) + } + + RawWindowHandle::Xlib(xlib) => { + let mut handle = v5::XlibWindowHandle::empty(); + handle.window = xlib.window; + handle.visual_id = xlib.visual_id; + v5::RawWindowHandle::Xlib(handle) + } + + handle => panic!("Unsupported raw window handle type: {:?}", handle), + } +} From 0b095b32b98add546f014add59d9fd948ce4c7e7 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 9 Jul 2023 15:17:03 -0700 Subject: [PATCH 03/12] Oopsie --- deny.toml | 1 + src/window.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index db4f119fbc..9c532135ad 100644 --- a/deny.toml +++ b/deny.toml @@ -40,6 +40,7 @@ skip = [ { name = "num_enum"}, # See above ^, waiting for release { name = "num_enum_derive"},# See above ^, waiting for release { name = "miniz_oxide"}, # https://github.com/rust-lang/flate2-rs/issues/340 + { name = "raw-window-handle" }, # https://github.com/rust-windowing/raw-window-handle/issues/125, slow transition { name = "redox_syscall" }, # https://gitlab.redox-os.org/redox-os/orbclient/-/issues/46 ] skip-tree = [] diff --git a/src/window.rs b/src/window.rs index df11deca87..6255fcc7f2 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1391,7 +1391,7 @@ unsafe impl HasRawWindowHandle for Window { /// [`Event::Resumed`]: crate::event::Event::Resumed /// [`Event::Suspended`]: crate::event::Event::Suspended fn raw_window_handle(&self) -> Result { - Ok(self.window.raw_window_handle()) + self.window.raw_window_handle() } } From e27a659d619a2064319b9b843fb4a3570f415498 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 9 Jul 2023 20:38:46 -0700 Subject: [PATCH 04/12] Implement borrowed display traits --- src/event_loop.rs | 12 +++++++++++- src/window.rs | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/event_loop.rs b/src/event_loop.rs index bc03d7b1a3..309c1e89c1 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -12,7 +12,9 @@ use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::{error, fmt}; -use raw_window_handle::{HandleError, HasRawDisplayHandle, RawDisplayHandle}; +use raw_window_handle::{ + DisplayHandle, HandleError, HasDisplayHandle, HasRawDisplayHandle, RawDisplayHandle, +}; #[cfg(not(wasm_platform))] use std::time::{Duration, Instant}; #[cfg(wasm_platform)] @@ -334,6 +336,14 @@ unsafe impl HasRawDisplayHandle for EventLoop { } } +impl HasDisplayHandle for EventLoop { + fn display_handle(&self) -> Result, HandleError> { + // SAFETY: The returned display handle is always valid for this lifetime. + self.raw_display_handle() + .map(|handle| unsafe { DisplayHandle::borrow_raw(handle) }) + } +} + unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoop { fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { let result = HasRawDisplayHandle::raw_display_handle(self); diff --git a/src/window.rs b/src/window.rs index 6255fcc7f2..7f611e93c4 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,8 @@ use std::fmt; use raw_window_handle::{ - HandleError, HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + DisplayHandle, HandleError, HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, + HasWindowHandle, RawDisplayHandle, RawWindowHandle, WindowHandle, }; use crate::{ @@ -1395,6 +1396,13 @@ unsafe impl HasRawWindowHandle for Window { } } +impl HasWindowHandle for Window { + fn window_handle(&self) -> Result, HandleError> { + self.raw_window_handle() + .map(|window| unsafe { WindowHandle::borrow_raw(window) }) + } +} + unsafe impl raw_window_handle_05::HasRawWindowHandle for Window { fn raw_window_handle(&self) -> raw_window_handle_05::RawWindowHandle { let result = HasRawWindowHandle::raw_window_handle(self); @@ -1416,6 +1424,13 @@ unsafe impl HasRawDisplayHandle for Window { } } +impl HasDisplayHandle for Window { + fn display_handle(&self) -> Result, HandleError> { + self.raw_display_handle() + .map(|display| unsafe { DisplayHandle::borrow_raw(display) }) + } +} + unsafe impl raw_window_handle_05::HasRawDisplayHandle for Window { fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { let result = HasRawDisplayHandle::raw_display_handle(self); From 52600f494154cf51e3cbf9192c48813e8cbf9698 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 9 Jul 2023 20:41:06 -0700 Subject: [PATCH 05/12] Missed one --- src/event_loop.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/event_loop.rs b/src/event_loop.rs index 309c1e89c1..4d25406e14 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -411,6 +411,14 @@ unsafe impl HasRawDisplayHandle for EventLoopWindowTarget { } } +impl HasDisplayHandle for EventLoopWindowTarget { + fn display_handle(&self) -> Result, HandleError> { + // SAFETY: The returned display handle is always valid for this lifetime. + self.raw_display_handle() + .map(|handle| unsafe { DisplayHandle::borrow_raw(handle) }) + } +} + unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoopWindowTarget { fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { let result = HasRawDisplayHandle::raw_display_handle(self); From 58e1b9d3e6303edd235ccc162179c71c8b09e60c Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 10 Jul 2023 18:08:35 +0200 Subject: [PATCH 06/12] Fix Web backend --- src/platform_impl/web/window.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index c267f8d6ff..8200dc9184 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -6,7 +6,9 @@ use crate::window::{ WindowAttributes, WindowButtons, WindowId as RootWI, WindowLevel, }; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WebDisplayHandle, WebWindowHandle}; +use raw_window_handle::{ + HandleError, RawDisplayHandle, RawWindowHandle, WebDisplayHandle, WebWindowHandle, +}; use web_sys::{Document, HtmlCanvasElement}; use super::r#async::Dispatcher; @@ -399,10 +401,10 @@ impl Window { } #[inline] - pub fn raw_window_handle(&self) -> RawWindowHandle { + pub fn raw_window_handle(&self) -> Result { let mut window_handle = WebWindowHandle::empty(); window_handle.id = self.id.0; - RawWindowHandle::Web(window_handle) + Ok(RawWindowHandle::Web(window_handle)) } #[inline] From 75e5104cdc61c7fdd905edaa47220dc2bf11cab3 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Mon, 10 Jul 2023 16:19:43 -0700 Subject: [PATCH 07/12] Port examples to use the new softbuffer --- Cargo.toml | 2 +- examples/child_window.rs | 19 ++++++++------ examples/control_flow.rs | 13 +++++++--- examples/cursor.rs | 3 ++- examples/cursor_grab.rs | 11 ++++++--- examples/custom_events.rs | 11 ++++++--- examples/drag_window.rs | 5 ++-- examples/fullscreen.rs | 11 ++++++--- examples/handling_close.rs | 11 ++++++--- examples/ime.rs | 11 ++++++--- examples/key_binding.rs | 12 ++++++--- examples/mouse_wheel.rs | 11 ++++++--- examples/multithreaded.rs | 17 +++++++++---- examples/multiwindow.rs | 5 ++-- examples/request_redraw.rs | 11 ++++++--- examples/resizable.rs | 19 ++++++++------ examples/theme.rs | 13 ++++++---- examples/timer.rs | 12 ++++++--- examples/touchpad_gestures.rs | 11 ++++++--- examples/transparent.rs | 13 ++++++---- examples/util/fill.rs | 37 +++++++++++++++++++--------- examples/web.rs | 17 +++++++------ examples/web_aspect_ratio.rs | 19 ++++++++------ examples/window.rs | 13 ++++++---- examples/window_buttons.rs | 13 ++++++---- examples/window_debug.rs | 13 ++++++---- examples/window_drag_resize.rs | 15 ++++++----- examples/window_icon.rs | 17 +++++++------ examples/window_option_as_alt.rs | 15 +++++++---- examples/window_pump_events.rs | 13 ++++++---- examples/window_resize_increments.rs | 15 ++++++----- 31 files changed, 257 insertions(+), 151 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9d37a0428e..2130294e85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ image = { version = "0.24.0", default-features = false, features = ["png"] } simple_logger = { version = "2.1.0", default_features = false } [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dev-dependencies] -softbuffer = "0.3.0" +softbuffer = { git = "https://github.com/rust-windowing/softbuffer.git", branch = "notgull/rwh-v0.6" } [target.'cfg(target_os = "android")'.dependencies] # Coordinate the next winit release with android-ndk-rs: https://github.com/rust-windowing/winit/issues/1995 diff --git a/examples/child_window.rs b/examples/child_window.rs index da402fa057..b557d4f2b9 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -5,6 +5,7 @@ mod fill; #[cfg(any(x11_platform, macos_platform, windows_platform))] fn main() -> Result<(), impl std::error::Error> { use std::collections::HashMap; + use std::rc::Rc; use raw_window_handle::HasRawWindowHandle; use winit::{ @@ -17,7 +18,7 @@ fn main() -> Result<(), impl std::error::Error> { fn spawn_child_window( parent: &Window, event_loop: &EventLoopWindowTarget<()>, - windows: &mut HashMap, + windows: &mut HashMap>, ) { let parent = parent.raw_window_handle().unwrap(); let mut builder = WindowBuilder::new() @@ -27,7 +28,7 @@ fn main() -> Result<(), impl std::error::Error> { .with_visible(true); // `with_parent_window` is unsafe. Parent window must be a valid window. builder = unsafe { builder.with_parent_window(Some(parent)) }; - let child_window = builder.build(event_loop).unwrap(); + let child_window = Rc::new(builder.build(event_loop).unwrap()); let id = child_window.id(); windows.insert(id, child_window); @@ -37,12 +38,14 @@ fn main() -> Result<(), impl std::error::Error> { let mut windows = HashMap::new(); let event_loop: EventLoop<()> = EventLoop::new(); - let parent_window = WindowBuilder::new() - .with_title("parent window") - .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) - .with_inner_size(LogicalSize::new(640.0f32, 480.0f32)) - .build(&event_loop) - .unwrap(); + let parent_window = Rc::new( + WindowBuilder::new() + .with_title("parent window") + .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) + .with_inner_size(LogicalSize::new(640.0f32, 480.0f32)) + .build(&event_loop) + .unwrap(), + ); println!("parent window: {parent_window:?})"); diff --git a/examples/control_flow.rs b/examples/control_flow.rs index cde5626593..f44665de05 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -1,5 +1,6 @@ #![allow(clippy::single_match)] +use std::rc::Rc; use std::thread; #[cfg(not(wasm_platform))] use std::time; @@ -37,10 +38,14 @@ fn main() -> Result<(), impl std::error::Error> { println!("Press 'Esc' to close the window."); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title( + "Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.", + ) + .build(&event_loop) + .unwrap(), + ); let mut mode = Mode::Wait; let mut request_redraw = false; diff --git a/examples/cursor.rs b/examples/cursor.rs index e7d3b9d52c..bb24425913 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, @@ -14,7 +15,7 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new().build(&event_loop).unwrap(); + let window = Rc::new(WindowBuilder::new().build(&event_loop).unwrap()); window.set_title("A fantastic window!"); let mut cursor_idx = 0; diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index b69ab47c16..f3e93b1872 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, @@ -15,10 +16,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("Super Cursor Grab'n'Hide Simulator 9000") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("Super Cursor Grab'n'Hide Simulator 9000") + .build(&event_loop) + .unwrap(), + ); let mut modifiers = ModifiersState::default(); diff --git a/examples/custom_events.rs b/examples/custom_events.rs index 2e8f5472f3..9e0f38622e 100644 --- a/examples/custom_events.rs +++ b/examples/custom_events.rs @@ -3,6 +3,7 @@ #[cfg(not(wasm_platform))] fn main() -> Result<(), impl std::error::Error> { use simple_logger::SimpleLogger; + use std::rc::Rc; use winit::{ event::{Event, WindowEvent}, event_loop::EventLoopBuilder, @@ -20,10 +21,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoopBuilder::::with_user_event().build(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .build(&event_loop) + .unwrap(), + ); // `EventLoopProxy` allows you to dispatch custom events to the main Winit event // loop from any thread. diff --git a/examples/drag_window.rs b/examples/drag_window.rs index 55056001f7..ae80313c0b 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent}, event_loop::EventLoop, @@ -15,8 +16,8 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window_1 = WindowBuilder::new().build(&event_loop).unwrap(); - let window_2 = WindowBuilder::new().build(&event_loop).unwrap(); + let window_1 = Rc::new(WindowBuilder::new().build(&event_loop).unwrap()); + let window_2 = Rc::new(WindowBuilder::new().build(&event_loop).unwrap()); let mut switched = false; let mut entered_id = window_2.id(); diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 675ad8ff99..42992c89f7 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::dpi::PhysicalSize; use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; use winit::event_loop::EventLoop; @@ -22,10 +23,12 @@ fn main() -> Result<(), impl std::error::Error> { let mut with_min_size = false; let mut with_max_size = false; - let window = WindowBuilder::new() - .with_title("Hello world!") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("Hello world!") + .build(&event_loop) + .unwrap(), + ); let mut monitor_index = 0; let mut monitor = event_loop diff --git a/examples/handling_close.rs b/examples/handling_close.rs index 5fa90283bd..a3d3b39322 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, @@ -15,10 +16,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("Your faithful window") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("Your faithful window") + .build(&event_loop) + .unwrap(), + ); let mut close_requested = false; diff --git a/examples/ime.rs b/examples/ime.rs index 319e06158a..82c9a54dfa 100644 --- a/examples/ime.rs +++ b/examples/ime.rs @@ -2,6 +2,7 @@ use log::LevelFilter; use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ dpi::{PhysicalPosition, PhysicalSize}, event::{ElementState, Event, Ime, WindowEvent}, @@ -26,10 +27,12 @@ fn main() -> Result<(), impl std::error::Error> { let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_inner_size(winit::dpi::LogicalSize::new(256f64, 128f64)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_inner_size(winit::dpi::LogicalSize::new(256f64, 128f64)) + .build(&event_loop) + .unwrap(), + ); let mut ime_purpose = ImePurpose::Normal; let mut ime_allowed = true; diff --git a/examples/key_binding.rs b/examples/key_binding.rs index ef5d531931..4e9884975f 100644 --- a/examples/key_binding.rs +++ b/examples/key_binding.rs @@ -18,16 +18,20 @@ fn main() { #[cfg(any(target_os = "macos", target_os = "windows", target_os = "linux"))] fn main() -> Result<(), impl std::error::Error> { + use std::rc::Rc; + #[path = "util/fill.rs"] mod fill; simple_logger::SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_inner_size(LogicalSize::new(400.0, 200.0)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_inner_size(LogicalSize::new(400.0, 200.0)) + .build(&event_loop) + .unwrap(), + ); let mut modifiers = ModifiersState::default(); diff --git a/examples/mouse_wheel.rs b/examples/mouse_wheel.rs index 38d06aff4d..8527983e34 100644 --- a/examples/mouse_wheel.rs +++ b/examples/mouse_wheel.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{Event, WindowEvent}, event_loop::EventLoop, @@ -14,10 +15,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("Mouse Wheel events") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("Mouse Wheel events") + .build(&event_loop) + .unwrap(), + ); println!( r" diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index bd9f9004dd..20d8334462 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -2,7 +2,12 @@ #[cfg(not(wasm_platform))] fn main() -> Result<(), impl std::error::Error> { - use std::{collections::HashMap, sync::mpsc, thread, time::Duration}; + use std::{ + collections::HashMap, + sync::{mpsc, Arc}, + thread, + time::Duration, + }; use simple_logger::SimpleLogger; use winit::{ @@ -20,10 +25,12 @@ fn main() -> Result<(), impl std::error::Error> { let event_loop = EventLoop::new(); let mut window_senders = HashMap::with_capacity(WINDOW_COUNT); for _ in 0..WINDOW_COUNT { - let window = WindowBuilder::new() - .with_inner_size(WINDOW_SIZE) - .build(&event_loop) - .unwrap(); + let window = Arc::new( + WindowBuilder::new() + .with_inner_size(WINDOW_SIZE) + .build(&event_loop) + .unwrap(), + ); let mut video_modes: Vec<_> = window.current_monitor().unwrap().video_modes().collect(); let mut video_mode_id = 0usize; diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 7fcb724b2d..5581685d7f 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use std::collections::HashMap; +use std::rc::Rc; use simple_logger::SimpleLogger; use winit::{ @@ -19,7 +20,7 @@ fn main() -> Result<(), impl std::error::Error> { let mut windows = HashMap::new(); for _ in 0..3 { - let window = Window::new(&event_loop).unwrap(); + let window = Rc::new(Window::new(&event_loop).unwrap()); println!("Opened a new window: {:?}", window.id()); windows.insert(window.id(), window); } @@ -52,7 +53,7 @@ fn main() -> Result<(), impl std::error::Error> { is_synthetic: false, .. } if matches!(c.as_ref(), "n" | "N") => { - let window = Window::new(event_loop).unwrap(); + let window = Rc::new(Window::new(event_loop).unwrap()); println!("Opened a new window: {:?}", window.id()); windows.insert(window.id(), window); } diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index a064cd39bb..323a4351ba 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{ElementState, Event, WindowEvent}, event_loop::EventLoop, @@ -14,10 +15,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .build(&event_loop) + .unwrap(), + ); event_loop.run(move |event, _, control_flow| { println!("{event:?}"); diff --git a/examples/resizable.rs b/examples/resizable.rs index ecec14b228..b7c8a802e6 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ dpi::LogicalSize, event::{ElementState, Event, KeyEvent, WindowEvent}, @@ -18,14 +19,16 @@ fn main() -> Result<(), impl std::error::Error> { let mut resizable = false; - let window = WindowBuilder::new() - .with_title("Hit space to toggle resizability.") - .with_inner_size(LogicalSize::new(600.0, 300.0)) - .with_min_inner_size(LogicalSize::new(400.0, 200.0)) - .with_max_inner_size(LogicalSize::new(800.0, 400.0)) - .with_resizable(resizable) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("Hit space to toggle resizability.") + .with_inner_size(LogicalSize::new(600.0, 300.0)) + .with_min_inner_size(LogicalSize::new(400.0, 200.0)) + .with_max_inner_size(LogicalSize::new(800.0, 400.0)) + .with_resizable(resizable) + .build(&event_loop) + .unwrap(), + ); event_loop.run(move |event, _, control_flow| { control_flow.set_wait(); diff --git a/examples/theme.rs b/examples/theme.rs index b3dac443ed..9237b984fc 100644 --- a/examples/theme.rs +++ b/examples/theme.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, @@ -15,11 +16,13 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .with_theme(Some(Theme::Dark)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .with_theme(Some(Theme::Dark)) + .build(&event_loop) + .unwrap(), + ); println!("Initial theme: {:?}", window.theme()); println!("debugging keys:"); diff --git a/examples/timer.rs b/examples/timer.rs index 13fceb51b8..46afacd53b 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -1,6 +1,8 @@ #![allow(clippy::single_match)] +use std::rc::Rc; use std::time::Duration; + #[cfg(not(wasm_platform))] use std::time::Instant; #[cfg(wasm_platform)] @@ -20,10 +22,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .build(&event_loop) + .unwrap(), + ); let timer_length = Duration::new(1, 0); diff --git a/examples/touchpad_gestures.rs b/examples/touchpad_gestures.rs index 0cca2c2cfd..7f903af736 100644 --- a/examples/touchpad_gestures.rs +++ b/examples/touchpad_gestures.rs @@ -1,4 +1,5 @@ use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, @@ -12,10 +13,12 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("Touchpad gestures") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("Touchpad gestures") + .build(&event_loop) + .unwrap(), + ); println!("Only supported on macOS at the moment."); diff --git a/examples/transparent.rs b/examples/transparent.rs index b093867d9d..7b56688f68 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{Event, WindowEvent}, event_loop::EventLoop, @@ -14,11 +15,13 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_decorations(false) - .with_transparent(true) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_decorations(false) + .with_transparent(true) + .build(&event_loop) + .unwrap(), + ); window.set_title("A fantastic window!"); diff --git a/examples/util/fill.rs b/examples/util/fill.rs index 7f1f1b1f63..2dcef9a36d 100644 --- a/examples/util/fill.rs +++ b/examples/util/fill.rs @@ -7,38 +7,53 @@ //! The `softbuffer` crate is used, largely because of its ease of use. `glutin` or `wgpu` could //! also be used to fill the window buffer, but they are more complicated to use. +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use winit::window::Window; +// Abstract over Rc and Arc +pub(super) trait FullHandleTy: + AsRef + HasDisplayHandle + HasWindowHandle + 'static +{ +} +impl + HasDisplayHandle + HasWindowHandle + 'static> FullHandleTy for T {} + #[cfg(not(any(target_os = "android", target_os = "ios")))] -pub(super) fn fill_window(window: &Window) { +pub(super) fn fill_window(window: &(impl FullHandleTy + Clone)) { use softbuffer::{Context, Surface}; use std::cell::RefCell; use std::collections::HashMap; use std::mem::ManuallyDrop; use std::num::NonZeroU32; + use std::rc::Rc; use winit::window::WindowId; + type FullHandle = Rc; + /// The graphics context used to draw to a window. struct GraphicsContext { /// The global softbuffer context. - context: Context, + context: Context, /// The hash map of window IDs to surfaces. - surfaces: HashMap, + surfaces: HashMap>, } impl GraphicsContext { - fn new(w: &Window) -> Self { + fn new(w: &(impl FullHandleTy + Clone)) -> Self { + let x: FullHandle = Rc::new(w.clone()); Self { - context: unsafe { Context::new(w) }.expect("Failed to create a softbuffer context"), + context: Context::new(x).expect("Failed to create a softbuffer context"), surfaces: HashMap::new(), } } - fn surface(&mut self, w: &Window) -> &mut Surface { - self.surfaces.entry(w.id()).or_insert_with(|| { - unsafe { Surface::new(&self.context, w) } - .expect("Failed to create a softbuffer surface") + fn surface( + &mut self, + w: &(impl FullHandleTy + Clone), + ) -> &mut Surface { + self.surfaces.entry(w.as_ref().id()).or_insert_with(|| { + let x: FullHandle = Rc::new(w.clone()); + Surface::new(&self.context, x).expect("Failed to create a softbuffer surface") }) } } @@ -61,7 +76,7 @@ pub(super) fn fill_window(window: &Window) { // Fill a buffer with a solid color. const DARK_GRAY: u32 = 0xFF181818; - let size = window.inner_size(); + let size = window.as_ref().inner_size(); surface .resize( @@ -81,6 +96,6 @@ pub(super) fn fill_window(window: &Window) { } #[cfg(any(target_os = "android", target_os = "ios"))] -pub(super) fn fill_window(_window: &Window) { +pub(super) fn fill_window(_window: &impl FullHandleTy) { // No-op on mobile platforms. } diff --git a/examples/web.rs b/examples/web.rs index f8237a7bba..926a13ba13 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -1,5 +1,6 @@ #![allow(clippy::disallowed_methods, clippy::single_match)] +use std::rc::Rc; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, @@ -10,13 +11,15 @@ use winit::{ pub fn main() -> Result<(), impl std::error::Error> { let event_loop = EventLoop::new(); - let builder = WindowBuilder::new().with_title("A fantastic window!"); - #[cfg(wasm_platform)] - let builder = { - use winit::platform::web::WindowBuilderExtWebSys; - builder.with_append(true) - }; - let window = builder.build(&event_loop).unwrap(); + let window = Rc::new({ + let builder = WindowBuilder::new().with_title("A fantastic window!"); + #[cfg(wasm_platform)] + let builder = { + use winit::platform::web::WindowBuilderExtWebSys; + builder.with_append(true) + }; + builder.build(&event_loop).unwrap() + }); #[cfg(wasm_platform)] let log_list = wasm::insert_canvas_and_create_log_list(&window); diff --git a/examples/web_aspect_ratio.rs b/examples/web_aspect_ratio.rs index e0f5ba161f..8e276a70bb 100644 --- a/examples/web_aspect_ratio.rs +++ b/examples/web_aspect_ratio.rs @@ -6,6 +6,7 @@ pub fn main() { #[cfg(wasm_platform)] mod wasm { + use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use web_sys::HtmlCanvasElement; @@ -33,14 +34,16 @@ This example demonstrates the desired future functionality which will possibly b console_log::init_with_level(log::Level::Debug).expect("error initializing logger"); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - // When running in a non-wasm environment this would set the window size to 100x100. - // However in this example it just sets a default initial size of 100x100 that is immediately overwritten due to the layout + styling of the page. - .with_inner_size(PhysicalSize::new(100, 100)) - .with_append(true) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + // When running in a non-wasm environment this would set the window size to 100x100. + // However in this example it just sets a default initial size of 100x100 that is immediately overwritten due to the layout + styling of the page. + .with_inner_size(PhysicalSize::new(100, 100)) + .with_append(true) + .build(&event_loop) + .unwrap(), + ); let canvas = create_canvas(&window); diff --git a/examples/window.rs b/examples/window.rs index fdfd39fa23..d511f5feab 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{Event, WindowEvent}, event_loop::EventLoop, @@ -14,11 +15,13 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) + .build(&event_loop) + .unwrap(), + ); event_loop.run(move |event, _, control_flow| { control_flow.set_wait(); diff --git a/examples/window_buttons.rs b/examples/window_buttons.rs index b531531ced..9e1ad6dc52 100644 --- a/examples/window_buttons.rs +++ b/examples/window_buttons.rs @@ -3,6 +3,7 @@ // This example is used by developers to test various window functions. use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ dpi::LogicalSize, event::{ElementState, Event, KeyEvent, WindowEvent}, @@ -18,11 +19,13 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .with_inner_size(LogicalSize::new(300.0, 300.0)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .with_inner_size(LogicalSize::new(300.0, 300.0)) + .build(&event_loop) + .unwrap(), + ); eprintln!("Window Button keys:"); eprintln!(" (F) Toggle close button"); diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 5c7f232671..12367445e5 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -3,6 +3,7 @@ // This example is used by developers to test various window functions. use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ dpi::{LogicalSize, PhysicalSize}, event::{DeviceEvent, ElementState, Event, KeyEvent, RawKeyEvent, WindowEvent}, @@ -18,11 +19,13 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .with_inner_size(LogicalSize::new(100.0, 100.0)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .with_inner_size(LogicalSize::new(100.0, 100.0)) + .build(&event_loop) + .unwrap(), + ); eprintln!("debugging keys:"); eprintln!(" (E) Enter exclusive fullscreen"); diff --git a/examples/window_drag_resize.rs b/examples/window_drag_resize.rs index 3232c4c807..40b9238279 100644 --- a/examples/window_drag_resize.rs +++ b/examples/window_drag_resize.rs @@ -1,6 +1,7 @@ //! Demonstrates capability to create in-app draggable regions for client-side decoration support. use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent}, event_loop::{ControlFlow, EventLoop}, @@ -17,12 +18,14 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_inner_size(winit::dpi::LogicalSize::new(600.0, 400.0)) - .with_min_inner_size(winit::dpi::LogicalSize::new(400.0, 200.0)) - .with_decorations(false) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_inner_size(winit::dpi::LogicalSize::new(600.0, 400.0)) + .with_min_inner_size(winit::dpi::LogicalSize::new(400.0, 200.0)) + .with_decorations(false) + .build(&event_loop) + .unwrap(), + ); let mut border = false; let mut cursor_location = None; diff --git a/examples/window_icon.rs b/examples/window_icon.rs index 6e65f34881..8bf4d50fe5 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -1,6 +1,7 @@ #![allow(clippy::single_match)] use std::path::Path; +use std::rc::Rc; use simple_logger::SimpleLogger; use winit::{ @@ -25,13 +26,15 @@ fn main() -> Result<(), impl std::error::Error> { let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("An iconic window!") - // At present, this only does anything on Windows and X11, so if you want to save load - // time, you can put icon loading behind a function that returns `None` on other platforms. - .with_window_icon(Some(icon)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("An iconic window!") + // At present, this only does anything on Windows and X11, so if you want to save load + // time, you can put icon loading behind a function that returns `None` on other platforms. + .with_window_icon(Some(icon)) + .build(&event_loop) + .unwrap(), + ); event_loop.run(move |event, _, control_flow| { control_flow.set_wait(); diff --git a/examples/window_option_as_alt.rs b/examples/window_option_as_alt.rs index 60c6fce3e0..1319bda42c 100644 --- a/examples/window_option_as_alt.rs +++ b/examples/window_option_as_alt.rs @@ -1,5 +1,8 @@ #![allow(clippy::single_match)] +#[cfg(target_os = "macos")] +use std::rc::Rc; + #[cfg(target_os = "macos")] use winit::platform::macos::{OptionAsAlt, WindowExtMacOS}; @@ -21,11 +24,13 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) + .build(&event_loop) + .unwrap(), + ); window.set_ime_allowed(true); diff --git a/examples/window_pump_events.rs b/examples/window_pump_events.rs index 2de01bc88e..b6404cd4fe 100644 --- a/examples/window_pump_events.rs +++ b/examples/window_pump_events.rs @@ -8,8 +8,9 @@ wayland_platform, android_platform, ))] + fn main() -> std::process::ExitCode { - use std::{process::ExitCode, thread::sleep, time::Duration}; + use std::{process::ExitCode, thread::sleep, time::Duration, rc::Rc}; use simple_logger::SimpleLogger; use winit::{ @@ -25,10 +26,12 @@ fn main() -> std::process::ExitCode { let mut event_loop = EventLoop::new(); SimpleLogger::new().init().unwrap(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .build(&event_loop) + .unwrap(), + ); 'main: loop { let timeout = Some(Duration::ZERO); diff --git a/examples/window_resize_increments.rs b/examples/window_resize_increments.rs index 0fcf4b9c5c..f5a449dea7 100644 --- a/examples/window_resize_increments.rs +++ b/examples/window_resize_increments.rs @@ -1,5 +1,6 @@ use log::debug; use simple_logger::SimpleLogger; +use std::rc::Rc; use winit::{ dpi::LogicalSize, event::{ElementState, Event, KeyEvent, WindowEvent}, @@ -15,12 +16,14 @@ fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_title("A fantastic window!") - .with_inner_size(LogicalSize::new(128.0, 128.0)) - .with_resize_increments(LogicalSize::new(25.0, 25.0)) - .build(&event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_title("A fantastic window!") + .with_inner_size(LogicalSize::new(128.0, 128.0)) + .with_resize_increments(LogicalSize::new(25.0, 25.0)) + .build(&event_loop) + .unwrap(), + ); let mut has_increments = true; From c4967885a3cc8ff01a2be4239c34964ecb910f6a Mon Sep 17 00:00:00 2001 From: John Nunley Date: Fri, 14 Jul 2023 20:40:34 -0700 Subject: [PATCH 08/12] Use notgull/next branch --- Cargo.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2130294e85..9584360fe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ 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", git = "https://github.com/rust-windowing/raw-window-handle.git", features = ["std"] } +raw_window_handle = { package = "raw-window-handle", version = "0.6", features = ["std"] } raw_window_handle_05 = { package = "raw-window-handle", version = "0.5" } serde = { version = "1", optional = true, features = ["serde_derive"] } smol_str = "0.2.0" @@ -65,7 +65,7 @@ image = { version = "0.24.0", default-features = false, features = ["png"] } simple_logger = { version = "2.1.0", default_features = false } [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dev-dependencies] -softbuffer = { git = "https://github.com/rust-windowing/softbuffer.git", branch = "notgull/rwh-v0.6" } +softbuffer = "0.3.0" [target.'cfg(target_os = "android")'.dependencies] # Coordinate the next winit release with android-ndk-rs: https://github.com/rust-windowing/winit/issues/1995 @@ -207,3 +207,7 @@ web-sys = { version = "0.3.22", features = ['CanvasRenderingContext2d'] } members = [ "run-wasm", ] + +[patch.crates-io] +softbuffer = { git = "https://github.com/rust-windowing/softbuffer.git", branch = "notgull/rwh-v0.6" } +raw_window_handle = { package = "raw-window-handle", git = "https://github.com/rust-windowing/raw-window-handle.git", branch = "notgull/next" } From 167e730c20fb9aa977d7c5d62e74f8a37a7b3f1b Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 15 Jul 2023 12:40:25 -0700 Subject: [PATCH 09/12] Add an OwnedDisplayHandle type This makes glutin integration much easier. --- src/event_loop.rs | 51 +++++++++++++++++++ src/platform_impl/android/mod.rs | 13 +++++ src/platform_impl/ios/event_loop.rs | 13 +++++ src/platform_impl/ios/mod.rs | 3 +- src/platform_impl/linux/mod.rs | 43 ++++++++++++++++ .../linux/wayland/event_loop/mod.rs | 4 ++ src/platform_impl/macos/event_loop.rs | 14 +++++ src/platform_impl/macos/mod.rs | 3 +- src/platform_impl/orbital/event_loop.rs | 13 +++++ src/platform_impl/web/event_loop/mod.rs | 2 +- .../web/event_loop/window_target.rs | 13 +++++ src/platform_impl/web/mod.rs | 3 +- src/platform_impl/windows/event_loop.rs | 13 +++++ src/platform_impl/windows/mod.rs | 3 +- 14 files changed, 186 insertions(+), 5 deletions(-) diff --git a/src/event_loop.rs b/src/event_loop.rs index 4d25406e14..734228a7b9 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -402,6 +402,16 @@ impl EventLoopWindowTarget { #[cfg(any(x11_platform, wasm_platform, wayland_platform, windows))] self.p.listen_device_events(_allowed); } + + /// Get an [`OwnedDisplayHandle`] that keeps the underlying display handle alive. + /// + /// This is necessary to use the display handle outside of the event loop, for example for + /// OpenGL setup. + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle { + p: self.p.owned_display_handle(), + } + } } unsafe impl HasRawDisplayHandle for EventLoopWindowTarget { @@ -430,6 +440,47 @@ unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoopWindowTarg } } +/// An owned handle used to represent the underlying display. +/// +/// It is sometimes necessary to pass a display handle to a function without involving any +/// windows. This comes in play, for example, for OpenGL setup. However, it is impossible to hold +/// a reliable reference to the [`EventLoop`] or an [`EventLoopWindowTarget`] while the event loop +/// is running. This type aims to fill that gap by being a generic-free, cheaply clonable handle +/// representing the display server. +/// +/// If you already have a [`Window`], you can get a display handle from it instead of this. +/// +/// [`Window`]: crate::window::Window +#[derive(Clone)] +pub struct OwnedDisplayHandle { + p: platform_impl::OwnedDisplayHandle, +} + +unsafe impl HasRawDisplayHandle for OwnedDisplayHandle { + fn raw_display_handle(&self) -> Result { + Ok(self.p.raw_display_handle()) + } +} + +impl HasDisplayHandle for OwnedDisplayHandle { + fn display_handle(&self) -> Result, HandleError> { + // SAFETY: The returned display handle is always valid for this lifetime. + self.raw_display_handle() + .map(|handle| unsafe { DisplayHandle::borrow_raw(handle) }) + } +} + +unsafe impl raw_window_handle_05::HasRawDisplayHandle for OwnedDisplayHandle { + fn raw_display_handle(&self) -> raw_window_handle_05::RawDisplayHandle { + let result = HasRawDisplayHandle::raw_display_handle(self); + + match result { + Ok(handle) => cvt_rdh_06_to_05(handle), + Err(e) => panic!("Failed to get raw display handle: {:?}", e), + } + } +} + /// Used to send custom events to [`EventLoop`]. pub struct EventLoopProxy { event_loop_proxy: platform_impl::EventLoopProxy, diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 161e22ac12..4fdbe5a914 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -729,6 +729,19 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { RawDisplayHandle::Android(AndroidDisplayHandle::empty()) } + + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle + } +} + +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + RawDisplayHandle::Android(AndroidDisplayHandle::empty()) + } } #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index f2e77e1a27..29c3dde74f 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -65,12 +65,25 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) } + + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle + } } pub struct EventLoop { window_target: RootEventLoopWindowTarget, } +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) + } +} + #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub(crate) struct PlatformSpecificEventLoopAttributes {} diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index d70bce56b0..28dfd32f52 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -81,7 +81,8 @@ use std::fmt; pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoMode}, window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index d70b5c8008..9bc1c8713b 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -730,6 +730,14 @@ pub enum EventLoop { X(x11::EventLoop), } +#[derive(Clone)] +pub(crate) enum OwnedDisplayHandle { + #[cfg(wayland_platform)] + Wayland(wayland_client::Connection), + #[cfg(x11_platform)] + X(Arc), +} + pub enum EventLoopProxy { #[cfg(x11_platform)] X(x11::EventLoopProxy), @@ -925,6 +933,41 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle()) } + + pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { + match self { + #[cfg(wayland_platform)] + EventLoopWindowTarget::Wayland(ref evlp) => { + OwnedDisplayHandle::Wayland(evlp.display().clone()) + } + + #[cfg(x11_platform)] + EventLoopWindowTarget::X(ref evlp) => { + OwnedDisplayHandle::X(evlp.x_connection().clone()) + } + } + } +} + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { + match self { + #[cfg(wayland_platform)] + OwnedDisplayHandle::Wayland(ref conn) => { + use wayland_client::Proxy; + + let mut handle = raw_window_handle::WaylandDisplayHandle::empty(); + handle.display = conn.display().id().as_ptr().cast(); + handle.into() + } + #[cfg(x11_platform)] + OwnedDisplayHandle::X(ref conn) => { + let mut handle = raw_window_handle::XlibDisplayHandle::empty(); + handle.display = conn.display as *mut _; + handle.into() + } + } + } } fn sticky_exit_callback( diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index a311133309..1c7683838f 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -607,6 +607,10 @@ impl EventLoopWindowTarget { display_handle.display = self.connection.display().id().as_ptr() as *mut _; RawDisplayHandle::Wayland(display_handle) } + + pub fn display(&self) -> &Connection { + &self.connection + } } // The default routine does floor, but we need round on Wayland. diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 8726cf7626..7bb33cbc3f 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -93,6 +93,11 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) } + + #[inline] + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle + } } impl EventLoopWindowTarget { @@ -113,6 +118,15 @@ impl EventLoopWindowTarget { } } +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) + } +} + pub struct EventLoop { /// The delegate is only weakly referenced by NSApplication, so we keep /// it around here as well. diff --git a/src/platform_impl/macos/mod.rs b/src/platform_impl/macos/mod.rs index c12f728107..5bdb3f7cbc 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -24,7 +24,8 @@ use self::window_delegate::WinitWindowDelegate; pub(crate) use self::{ event::KeyEventExtra, event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoMode}, window::{PlatformSpecificWindowBuilderAttributes, WindowId}, diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 3adda04fc4..9be7b6278f 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -754,4 +754,17 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty()) } + + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle + } +} + +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty()) + } } diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 1dcee87840..62b489ab51 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -4,7 +4,7 @@ mod state; mod window_target; pub use self::proxy::EventLoopProxy; -pub use self::window_target::EventLoopWindowTarget; +pub use self::window_target::{EventLoopWindowTarget, OwnedDisplayHandle}; use super::{backend, device, window}; use crate::event::Event; diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 72893f067a..28e88743c3 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -753,4 +753,17 @@ impl EventLoopWindowTarget { pub fn listen_device_events(&self, allowed: DeviceEvents) { self.runner.listen_device_events(allowed) } + + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle + } +} + +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub(crate) fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { + raw_window_handle::WebDisplayHandle::empty().into() + } } diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index dc178179b4..fe995e90e2 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -31,7 +31,8 @@ mod backend; pub use self::device::DeviceId; pub use self::error::OsError; pub(crate) use self::event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + PlatformSpecificEventLoopAttributes, }; pub use self::monitor::{MonitorHandle, VideoMode}; pub use self::window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}; diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index f222450265..add24dc806 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -197,6 +197,9 @@ pub struct EventLoopWindowTarget { pub(crate) runner_shared: EventLoopRunnerShared, } +#[derive(Clone)] +pub struct OwnedDisplayHandle; + impl EventLoop { pub(crate) fn new(attributes: &mut PlatformSpecificEventLoopAttributes) -> Self { let thread_id = unsafe { GetCurrentThreadId() }; @@ -542,6 +545,16 @@ impl EventLoopWindowTarget { pub fn listen_device_events(&self, allowed: DeviceEvents) { raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed); } + + pub fn owned_display_handle(&self) -> OwnedDisplayHandle { + OwnedDisplayHandle + } +} + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { + raw_window_handle::WindowsDisplayHandle::empty().into() + } } /// Returns the id of the main thread. diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 3d5c02a7b1..bb57541110 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -8,7 +8,8 @@ use windows_sys::Win32::{ pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + PlatformSpecificEventLoopAttributes, }, icon::WinIcon, monitor::{MonitorHandle, VideoMode}, From 7650324d4f8fe4f6799a24720d3c9e3978c6712a Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 15 Jul 2023 13:05:18 -0700 Subject: [PATCH 10/12] Remove the ManuallyDrop workaround --- examples/util/fill.rs | 7 +------ examples/window_tabbing.rs | 14 ++++++++------ src/platform_impl/orbital/mod.rs | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/examples/util/fill.rs b/examples/util/fill.rs index 2dcef9a36d..4b931c5312 100644 --- a/examples/util/fill.rs +++ b/examples/util/fill.rs @@ -22,7 +22,6 @@ pub(super) fn fill_window(window: &(impl FullHandleTy + Clone)) { use softbuffer::{Context, Surface}; use std::cell::RefCell; use std::collections::HashMap; - use std::mem::ManuallyDrop; use std::num::NonZeroU32; use std::rc::Rc; use winit::window::WindowId; @@ -59,12 +58,8 @@ pub(super) fn fill_window(window: &(impl FullHandleTy + Clone)) { } thread_local! { - // NOTE: You should never do things like that, create context and drop it before - // you drop the event loop. We do this for brevity to not blow up examples. We use - // ManuallyDrop to prevent destructors from running. - // // A static, thread-local map of graphics contexts to open windows. - static GC: ManuallyDrop>> = ManuallyDrop::new(RefCell::new(None)); + static GC: RefCell> = RefCell::new(None); } GC.with(|gc| { diff --git a/examples/window_tabbing.rs b/examples/window_tabbing.rs index 1989a8f365..7cbe410781 100644 --- a/examples/window_tabbing.rs +++ b/examples/window_tabbing.rs @@ -1,7 +1,7 @@ #![allow(clippy::single_match)] #[cfg(target_os = "macos")] -use std::{collections::HashMap, num::NonZeroUsize}; +use std::{collections::HashMap, num::NonZeroUsize, rc::Rc}; #[cfg(target_os = "macos")] use simple_logger::SimpleLogger; @@ -24,7 +24,7 @@ fn main() -> Result<(), impl std::error::Error> { let event_loop = EventLoop::new(); let mut windows = HashMap::new(); - let window = Window::new(&event_loop).unwrap(); + let window = Rc::new(Window::new(&event_loop).unwrap()); println!("Opened a new window: {:?}", window.id()); windows.insert(window.id(), window); @@ -63,10 +63,12 @@ fn main() -> Result<(), impl std::error::Error> { } => match logical_key.as_ref() { Key::Character("t") => { let tabbing_id = windows.get(&window_id).unwrap().tabbing_identifier(); - let window = WindowBuilder::new() - .with_tabbing_identifier(&tabbing_id) - .build(event_loop) - .unwrap(); + let window = Rc::new( + WindowBuilder::new() + .with_tabbing_identifier(&tabbing_id) + .build(event_loop) + .unwrap(), + ); println!("Added a new tab: {:?}", window.id()); windows.insert(window.id(), window); } diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index 961f6c4e31..cc70a370fe 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -4,7 +4,7 @@ use std::str; use crate::dpi::{PhysicalPosition, PhysicalSize}; -pub use self::event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}; +pub use self::event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle}; mod event_loop; pub use self::window::Window; From d285ce661060aa2b8bf70a01060555d7a5c65c00 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 29 Jul 2023 12:04:03 -0700 Subject: [PATCH 11/12] Mollycoddle the madsmtm --- examples/util/fill.rs | 81 ++++++++++++++++++++++------------ examples/window_ondemand.rs | 9 ++-- examples/window_pump_events.rs | 2 +- src/event_loop.rs | 6 +-- src/window.rs | 2 +- 5 files changed, 62 insertions(+), 38 deletions(-) diff --git a/examples/util/fill.rs b/examples/util/fill.rs index 4b931c5312..b18cf26877 100644 --- a/examples/util/fill.rs +++ b/examples/util/fill.rs @@ -18,7 +18,8 @@ pub(super) trait FullHandleTy: impl + HasDisplayHandle + HasWindowHandle + 'static> FullHandleTy for T {} #[cfg(not(any(target_os = "android", target_os = "ios")))] -pub(super) fn fill_window(window: &(impl FullHandleTy + Clone)) { +mod fill { + use super::FullHandleTy; use softbuffer::{Context, Surface}; use std::cell::RefCell; use std::collections::HashMap; @@ -62,35 +63,57 @@ pub(super) fn fill_window(window: &(impl FullHandleTy + Clone)) { static GC: RefCell> = RefCell::new(None); } - GC.with(|gc| { - // Either get the last context used or create a new one. - let mut gc = gc.borrow_mut(); - let surface = gc - .get_or_insert_with(|| GraphicsContext::new(window)) - .surface(window); - - // Fill a buffer with a solid color. - const DARK_GRAY: u32 = 0xFF181818; - let size = window.as_ref().inner_size(); - - surface - .resize( - NonZeroU32::new(size.width).expect("Width must be greater than zero"), - NonZeroU32::new(size.height).expect("Height must be greater than zero"), - ) - .expect("Failed to resize the softbuffer surface"); - - let mut buffer = surface - .buffer_mut() - .expect("Failed to get the softbuffer buffer"); - buffer.fill(DARK_GRAY); - buffer - .present() - .expect("Failed to present the softbuffer buffer"); - }) + pub(crate) fn fill_window(window: &(impl FullHandleTy + Clone)) { + GC.with(|gc| { + // Either get the last context used or create a new one. + let mut gc = gc.borrow_mut(); + let surface = gc + .get_or_insert_with(|| GraphicsContext::new(window)) + .surface(window); + + // Fill a buffer with a solid color. + const DARK_GRAY: u32 = 0xFF181818; + let size = window.as_ref().inner_size(); + + surface + .resize( + NonZeroU32::new(size.width).expect("Width must be greater than zero"), + NonZeroU32::new(size.height).expect("Height must be greater than zero"), + ) + .expect("Failed to resize the softbuffer surface"); + + let mut buffer = surface + .buffer_mut() + .expect("Failed to get the softbuffer buffer"); + buffer.fill(DARK_GRAY); + buffer + .present() + .expect("Failed to present the softbuffer buffer"); + }) + } + + pub(crate) fn discard_window(window: &WindowId) { + GC.with(|gc| { + let mut gc = gc.borrow_mut(); + if let Some(gc) = &mut *gc { + gc.surfaces.remove(window); + } + }) + } } #[cfg(any(target_os = "android", target_os = "ios"))] -pub(super) fn fill_window(_window: &impl FullHandleTy) { - // No-op on mobile platforms. +mod fill { + use super::FullHandleTy; + use winit::window::WindowId; + + pub(crate) fn fill_window(_window: &impl FullHandleTy) { + // No-op on mobile platforms. + } + + pub(crate) fn discard_window(_window: &WindowId) { + // No-op on mobile platforms. + } } + +pub(super) use fill::{discard_window, fill_window}; diff --git a/examples/window_ondemand.rs b/examples/window_ondemand.rs index 0a59f4fc99..8ff8b1d27a 100644 --- a/examples/window_ondemand.rs +++ b/examples/window_ondemand.rs @@ -3,7 +3,7 @@ // Limit this example to only compatible platforms. #[cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform,))] fn main() -> Result<(), impl std::error::Error> { - use std::time::Duration; + use std::{rc::Rc, time::Duration}; use simple_logger::SimpleLogger; @@ -21,7 +21,7 @@ fn main() -> Result<(), impl std::error::Error> { #[derive(Default)] struct App { window_id: Option, - window: Option, + window: Option>, } SimpleLogger::new().init().unwrap(); @@ -56,8 +56,9 @@ fn main() -> Result<(), impl std::error::Error> { window_id, } if id == window_id => { println!("--------------------------------------------------------- Window {idx} Destroyed"); - app.window_id = None; + let wid = app.window_id.take().unwrap(); control_flow.set_exit(); + fill::discard_window(&wid); } _ => (), } @@ -68,7 +69,7 @@ fn main() -> Result<(), impl std::error::Error> { .build(event_loop) .unwrap(); app.window_id = Some(window.id()); - app.window = Some(window); + app.window = Some(Rc::new(window)); } }) } diff --git a/examples/window_pump_events.rs b/examples/window_pump_events.rs index b6404cd4fe..fe8e2acf0b 100644 --- a/examples/window_pump_events.rs +++ b/examples/window_pump_events.rs @@ -10,7 +10,7 @@ ))] fn main() -> std::process::ExitCode { - use std::{process::ExitCode, thread::sleep, time::Duration, rc::Rc}; + use std::{process::ExitCode, rc::Rc, thread::sleep, time::Duration}; use simple_logger::SimpleLogger; use winit::{ diff --git a/src/event_loop.rs b/src/event_loop.rs index 734228a7b9..6c68aff185 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -350,7 +350,7 @@ unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoop { match result { Ok(handle) => cvt_rdh_06_to_05(handle), - Err(e) => panic!("Failed to get raw display handle: {:?}", e), + Err(e) => panic!("failed to get raw display handle: {:?}", e), } } } @@ -435,7 +435,7 @@ unsafe impl raw_window_handle_05::HasRawDisplayHandle for EventLoopWindowTarg match result { Ok(handle) => cvt_rdh_06_to_05(handle), - Err(e) => panic!("Failed to get raw display handle: {:?}", e), + Err(e) => panic!("failed to get raw display handle: {:?}", e), } } } @@ -476,7 +476,7 @@ unsafe impl raw_window_handle_05::HasRawDisplayHandle for OwnedDisplayHandle { match result { Ok(handle) => cvt_rdh_06_to_05(handle), - Err(e) => panic!("Failed to get raw display handle: {:?}", e), + Err(e) => panic!("failed to get raw display handle: {:?}", e), } } } diff --git a/src/window.rs b/src/window.rs index 7f611e93c4..93edb7bc88 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1709,6 +1709,6 @@ fn cvt_rwh_06_to_05(handle: RawWindowHandle) -> raw_window_handle_05::RawWindowH v5::RawWindowHandle::Xlib(handle) } - handle => panic!("Unsupported raw window handle type: {:?}", handle), + handle => panic!("unsupported raw window handle type: {:?}", handle), } } From 500123120a0adc97f9ba72a05b5ff84b1a3d3e5f Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 29 Jul 2023 12:10:05 -0700 Subject: [PATCH 12/12] Silence the unused warning --- examples/util/fill.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/util/fill.rs b/examples/util/fill.rs index b18cf26877..498fd3a2e7 100644 --- a/examples/util/fill.rs +++ b/examples/util/fill.rs @@ -116,4 +116,5 @@ mod fill { } } +#[allow(dead_code, unused_imports)] pub(super) use fill::{discard_window, fill_window};