diff --git a/CHANGELOG.md b/CHANGELOG.md index 9711dde3c8..0d1e111968 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased - Bump MSRV from `1.60` to `1.64`. +- Implement the borrowed handle traits from the `raw-window-handle` crate. # 0.28.3 diff --git a/Cargo.toml b/Cargo.toml index c86287cf82..c211532988 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,8 +42,8 @@ wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"] wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"] wayland-csd-adwaita-notitle = ["sctk-adwaita"] -android-native-activity = [ "android-activity/native-activity" ] -android-game-activity = [ "android-activity/game-activity" ] +android-native-activity = ["android-activity/native-activity"] +android-game-activity = ["android-activity/game-activity"] [build-dependencies] cfg_aliases = "0.1.1" @@ -54,7 +54,7 @@ instant = { version = "0.1", features = ["wasm-bindgen"] } log = "0.4" mint = { version = "0.5.6", optional = true } once_cell = "1.12" -raw_window_handle = { package = "raw-window-handle", version = "0.5" } +raw_window_handle = { package = "raw-window-handle", version = "0.5.2", features = ["std"] } serde = { version = "1", optional = true, features = ["serde_derive"] } [dev-dependencies] diff --git a/examples/window.rs b/examples/window.rs index e54a2f661c..abb21486a4 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -1,5 +1,6 @@ #![allow(clippy::single_match)] +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use simple_logger::SimpleLogger; use winit::{ event::{Event, WindowEvent}, @@ -17,10 +18,19 @@ fn main() { .build(&event_loop) .unwrap(); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt, control_flow| { control_flow.set_wait(); println!("{event:?}"); + // Print the display handle. + println!("Display handle: {:?}", elwt.display_handle()); + + // Print the window handle. + match window.window_handle() { + Ok(handle) => println!("Window handle: {:?}", handle), + Err(_) => println!("Window handle: None"), + } + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, diff --git a/src/event_loop.rs b/src/event_loop.rs index 1f00f7d7ac..e5317fa828 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -13,7 +13,9 @@ use std::{error, fmt}; use instant::{Duration, Instant}; use once_cell::sync::OnceCell; -use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; +use raw_window_handle::{ + DisplayHandle, HandleError, HasDisplayHandle, HasRawDisplayHandle, RawDisplayHandle, +}; use crate::{event::Event, monitor::MonitorHandle, platform_impl}; @@ -48,6 +50,73 @@ pub struct EventLoopWindowTarget { pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync } +/// Target that provides a handle to the display powering the event loop. +/// +/// This type allows one to take advantage of the display's capabilities without +/// having to create a window. It implements [`HasDisplayHandle`]. +/// +/// The main reason why this type exists is to act as a persistent display handle +/// in cases where the [`Window`] is not created yet. Let's say that your graphics +/// framework has a type `Display`, where `T` has to implement [`HasDisplayHandle`] +/// so that the graphics framework can query it for data and be sure that the display is +/// still alive. Also assume that `Display` is somewhat expensive to construct, so +/// you cannot just create a new `Display` every time you need to render. +/// Therefore, you need a *persistent* handle to the display to pass in as `T`. This +/// handle cannot be invalidated by the borrow checker during the lifetime of the +/// program; otherwise, you would have to drop the `Display` and recreate it +/// every time you need to render, which would be very expensive. +/// +/// The [`EventLoop`] type is either owned or borrowed mutably during event +/// handling. Therefore, neither [`EventLoop`], `&EventLoop` or a [`DisplayHandle`] +/// referencing an [`EventLoop`] can be used to provide a [`HasDisplayHandle`] +/// implementation. On the other hand, the [`EventLoopWindowTarget`] type disappears +/// between events so it can't be used as a persistent handle either. In certain +/// cases, you can use a [`Window`]; however, for certain graphics APIs (like OpenGL) +/// you need to be able to query the display before creating a window. In this case, +/// you end up with a "chicken and egg" problem; you need a display handle to create +/// a window, but you need a window to access the display handle. +/// +/// The [`OwnedDisplayHandle`] type breaks this cycle by providing a persistent handle +/// to the display. It is not tied to any lifetime constraints, so it can't be +/// invalidated during event handling. It is also cheaply clonable, so you can +/// more easily pass it around to other parts of your program. Therefore, it can +/// be passed in as `T` to your graphics framework's `Display` type without +/// worrying about the borrow checker. +/// +/// To create an [`OwnedDisplayHandle`], use the [`EventLoopWindowTarget::owned_display_handle`] +/// method. +/// +/// ## Safety +/// +/// The [`DisplayHandle`] returned by the [`OwnedDisplayHandle`] type is guaranteed to +/// remain valid as long as the [`OwnedDisplayHandle`] is alive. The internal display +/// handle is not immediately closed by the [`EventLoop`] being dropped as long as +/// the [`OwnedDisplayHandle`] is still alive. On all platforms, the underlying display +/// is either ref-counted or a ZST, so this is safe. +/// +/// [`EventLoop`]: EventLoop +/// [`Window`]: crate::window::Window +/// [`DisplayHandle`]: raw_window_handle::DisplayHandle +/// [`EventLoopWindowTarget`]: EventLoopWindowTarget +/// [`HasDisplayHandle`]: raw_window_handle::HasDisplayHandle +#[derive(Clone)] +pub struct OwnedDisplayHandle { + pub(crate) p: platform_impl::OwnedDisplayHandle, + + /// Make sure that the display handle is !Send and !Sync. + /// + /// ```compile_fail + /// fn foo() {} + /// foo::(); + /// ``` + /// + /// ```compile_fail + /// fn foo() {} + /// foo::(); + /// ``` + pub(crate) _marker: PhantomData<*mut ()>, +} + /// Object that allows building the event loop. /// /// This is used to make specifying options that affect the whole application @@ -320,6 +389,12 @@ unsafe impl HasRawDisplayHandle for EventLoop { } } +impl HasDisplayHandle for EventLoop { + fn display_handle(&self) -> Result, HandleError> { + self.event_loop.window_target().display_handle() + } +} + impl Deref for EventLoop { type Target = EventLoopWindowTarget; fn deref(&self) -> &EventLoopWindowTarget { @@ -367,6 +442,28 @@ impl EventLoopWindowTarget { #[cfg(any(x11_platform, wayland_platform, windows))] self.p.set_device_event_filter(_filter); } + + /// Get an owned handle to the current display. + /// + /// This handle can be cheaply cloned and used, allowing one to fulfill the [`HasDisplayHandle`] + /// trait bound. + /// + /// For more information, see documentation for [`OwnedDisplayHandle`] and the + /// [`HasDisplayHandle`] trait. + /// + /// ## Example + /// + /// ```no_run + /// use winit::event_loop::EventLoop; + /// + /// let event_loop = EventLoop::new(); + /// let display_handle = event_loop.owned_display_handle(); + /// ``` + /// + /// [`HasDisplayHandle`]: raw_window_handle::HasDisplayHandle + pub fn owned_display_handle(&self) -> &OwnedDisplayHandle { + self.p.owned_display_handle() + } } unsafe impl HasRawDisplayHandle for EventLoopWindowTarget { @@ -376,6 +473,27 @@ unsafe impl HasRawDisplayHandle for EventLoopWindowTarget { } } +impl HasDisplayHandle for EventLoopWindowTarget { + fn display_handle(&self) -> Result, HandleError> { + // SAFETY: The display handle is valid for as long as the window target is. + Ok(unsafe { DisplayHandle::borrow_raw(self.raw_display_handle()) }) + } +} + +unsafe impl HasRawDisplayHandle for OwnedDisplayHandle { + /// Returns a [`raw_window_handle::RawDisplayHandle`] for the event loop. + fn raw_display_handle(&self) -> RawDisplayHandle { + self.p.raw_display_handle() + } +} + +impl HasDisplayHandle for OwnedDisplayHandle { + fn display_handle(&self) -> Result, HandleError> { + // SAFETY: The display handle is valid for as long as the window target is. + Ok(unsafe { DisplayHandle::borrow_raw(self.raw_display_handle()) }) + } +} + /// 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 2e1924e27b..e5e4d18a1d 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, + Active, AndroidDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; use crate::platform_impl::Fullscreen; @@ -340,6 +340,7 @@ impl EventLoop { &redraw_flag, android_app.create_waker(), ), + active: Arc::new(Active::new()), _marker: std::marker::PhantomData, }, _marker: std::marker::PhantomData, @@ -378,6 +379,11 @@ impl EventLoop { match event { MainEvent::InitWindow { .. } => { + // SAFETY: The window is now active. + unsafe { + self.window_target.p.active.set_active(); + } + sticky_exit_callback( event::Event::Resumed, self.window_target(), @@ -392,6 +398,8 @@ impl EventLoop { control_flow, callback, ); + + self.window_target.p.active.set_inactive(); } MainEvent::WindowResized { .. } => resized = true, MainEvent::RedrawNeeded { .. } => *pending_redraw = true, @@ -821,6 +829,7 @@ impl EventLoopProxy { pub struct EventLoopWindowTarget { app: AndroidApp, redraw_requester: RedrawRequester, + active: Arc, _marker: std::marker::PhantomData, } @@ -836,7 +845,23 @@ impl EventLoopWindowTarget { } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Android(AndroidDisplayHandle::empty()) + AndroidDisplayHandle::empty().into() + } + + pub fn owned_display_handle(&self) -> &event_loop::OwnedDisplayHandle { + &event_loop::OwnedDisplayHandle { + p: OwnedDisplayHandle, + _marker: std::marker::PhantomData, + } + } +} + +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + AndroidDisplayHandle::empty().into() } } @@ -876,6 +901,7 @@ pub struct PlatformSpecificWindowBuilderAttributes; pub(crate) struct Window { app: AndroidApp, redraw_requester: RedrawRequester, + active: Arc, } impl Window { @@ -889,6 +915,7 @@ impl Window { Ok(Self { app: el.app.clone(), redraw_requester: el.redraw_requester.clone(), + active: el.active.clone(), }) } @@ -1060,7 +1087,7 @@ impl Window { } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Android(AndroidDisplayHandle::empty()) + AndroidDisplayHandle::empty().into() } pub fn config(&self) -> ConfigurationRef { @@ -1084,6 +1111,10 @@ impl Window { pub fn title(&self) -> String { String::new() } + + pub(crate) fn active(&self) -> &Active { + &self.active + } } #[derive(Default, Clone, Debug)] diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index 8649c8c7a8..9895051029 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -63,7 +63,23 @@ impl EventLoopWindowTarget { } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) + UiKitDisplayHandle::empty().into() + } + + pub fn owned_display_handle(&self) -> &crate::event_loop::OwnedDisplayHandle { + &crate::event_loop::OwnedDisplayHandle { + p: OwnedDisplayHandle, + _marker: PhantomData, + } + } +} + +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + UiKitDisplayHandle::empty().into() } } diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index fc52ee9534..0cafebf953 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/ios/window.rs b/src/platform_impl/ios/window.rs index 880bd843ff..69a1f4d039 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -343,11 +343,11 @@ impl Inner { 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) + window_handle.into() } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) + UiKitDisplayHandle::empty().into() } pub fn theme(&self) -> Option { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 0a90d085ee..02476f21aa 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -685,6 +685,14 @@ pub enum EventLoopProxy { Wayland(wayland::EventLoopProxy), } +#[derive(Clone)] +pub enum OwnedDisplayHandle { + #[cfg(x11_platform)] + X(x11::OwnedDisplayHandle), + #[cfg(wayland_platform)] + Wayland(wayland::OwnedDisplayHandle), +} + impl Clone for EventLoopProxy { fn clone(&self) -> Self { x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.clone(); as EventLoopProxy) @@ -866,6 +874,21 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle()) } + + pub fn owned_display_handle(&self) -> &crate::event_loop::OwnedDisplayHandle { + match self { + #[cfg(wayland_platform)] + EventLoopWindowTarget::Wayland(evlp) => evlp.owned_display_handle(), + #[cfg(x11_platform)] + EventLoopWindowTarget::X(evlp) => evlp.owned_display_handle(), + } + } +} + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { + x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle()) + } } 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 84540f6c81..892398d853 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -21,7 +21,10 @@ use sctk::WaylandSource; use crate::dpi::{LogicalSize, PhysicalSize}; use crate::event::{Event, StartCause, WindowEvent}; -use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}; +use crate::event_loop::{ + ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget, + OwnedDisplayHandle as RootOwnedDisplayHandle, +}; use crate::platform_impl::platform::sticky_exit_callback; use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget; @@ -45,6 +48,9 @@ pub struct EventLoopWindowTarget { /// Wayland display. pub display: Display, + /// Display handle. + pub display_handle: RootOwnedDisplayHandle, + /// Environment to handle object creation, etc. pub env: Environment, @@ -79,7 +85,11 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { let mut display_handle = WaylandDisplayHandle::empty(); display_handle.display = self.display.get_display_ptr() as *mut _; - RawDisplayHandle::Wayland(display_handle) + display_handle.into() + } + + pub fn owned_display_handle(&self) -> &RootOwnedDisplayHandle { + &self.display_handle } } @@ -183,6 +193,12 @@ impl EventLoop { // Create event loop window target. let event_loop_window_target = EventLoopWindowTarget { display: display.clone(), + display_handle: RootOwnedDisplayHandle { + p: super::super::OwnedDisplayHandle::Wayland(OwnedDisplayHandle { + display: display.clone(), + }), + _marker: std::marker::PhantomData, + }, env, state: RefCell::new(WinitState { window_map, @@ -601,6 +617,19 @@ impl EventLoop { } } +#[derive(Clone)] +pub struct OwnedDisplayHandle { + display: Display, +} + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + let mut display_handle = WaylandDisplayHandle::empty(); + display_handle.display = self.display.get_display_ptr() as *mut _; + display_handle.into() + } +} + // The default routine does floor, but we need round on Wayland. fn logical_to_physical_rounded(size: LogicalSize, scale_factor: f64) -> PhysicalSize { let width = size.width as f64 * scale_factor; diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs index fce6d8ecdb..ce1b5c49cc 100644 --- a/src/platform_impl/linux/wayland/mod.rs +++ b/src/platform_impl/linux/wayland/mod.rs @@ -3,7 +3,7 @@ use sctk::reexports::client::protocol::wl_surface::WlSurface; pub use crate::platform_impl::platform::WindowId; -pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}; +pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle}; pub use output::{MonitorHandle, VideoMode}; pub use window::Window; diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 14c317889a..7a1b89da51 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -664,14 +664,14 @@ impl Window { pub fn raw_window_handle(&self) -> RawWindowHandle { let mut window_handle = WaylandWindowHandle::empty(); window_handle.surface = self.surface.as_ref().c_ptr() as *mut _; - RawWindowHandle::Wayland(window_handle) + window_handle.into() } #[inline] pub fn raw_display_handle(&self) -> RawDisplayHandle { let mut display_handle = WaylandDisplayHandle::empty(); display_handle.display = self.display.get_display_ptr() as *mut _; - RawDisplayHandle::Wayland(display_handle) + display_handle.into() } #[inline] diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 0ef073d9e4..48eea0af0e 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -49,6 +49,7 @@ use crate::{ event::{Event, StartCause}, event_loop::{ ControlFlow, DeviceEventFilter, EventLoopClosed, EventLoopWindowTarget as RootELW, + OwnedDisplayHandle as RootODH, }, platform_impl::{ platform::{sticky_exit_callback, WindowId}, @@ -99,6 +100,11 @@ impl PeekableReceiver { } } +#[derive(Clone)] +pub struct OwnedDisplayHandle { + xconn: Arc, +} + pub struct EventLoopWindowTarget { xconn: Arc, wm_delete_window: ffi::Atom, @@ -109,6 +115,7 @@ pub struct EventLoopWindowTarget { windows: RefCell>>, redraw_sender: WakeSender, device_event_filter: Cell, + display_handle: RootODH, _marker: ::std::marker::PhantomData, } @@ -238,6 +245,12 @@ impl EventLoop { windows: Default::default(), _marker: ::std::marker::PhantomData, ime_sender, + display_handle: RootODH { + p: super::OwnedDisplayHandle::X(OwnedDisplayHandle { + xconn: xconn.clone(), + }), + _marker: ::std::marker::PhantomData, + }, xconn, wm_delete_window, net_wm_ping, @@ -566,12 +579,26 @@ impl EventLoopWindowTarget { .queue(); } + pub fn raw_display_handle(&self) -> RawDisplayHandle { + let mut display_handle = XlibDisplayHandle::empty(); + display_handle.display = self.xconn.display as *mut _; + display_handle.screen = + unsafe { (self.xconn.xlib.XDefaultScreen)(self.xconn.display as *mut _) }; + display_handle.into() + } + + pub fn owned_display_handle(&self) -> &RootODH { + &self.display_handle + } +} + +impl OwnedDisplayHandle { pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { let mut display_handle = XlibDisplayHandle::empty(); display_handle.display = self.xconn.display as *mut _; display_handle.screen = unsafe { (self.xconn.xlib.XDefaultScreen)(self.xconn.display as *mut _) }; - RawDisplayHandle::Xlib(display_handle) + display_handle.into() } } diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index a600eca069..478fdae435 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1605,7 +1605,7 @@ impl UnownedWindow { pub fn raw_window_handle(&self) -> RawWindowHandle { let mut window_handle = XlibWindowHandle::empty(); window_handle.window = self.xlib_window(); - RawWindowHandle::Xlib(window_handle) + window_handle.into() } #[inline] @@ -1613,7 +1613,7 @@ impl UnownedWindow { let mut display_handle = XlibDisplayHandle::empty(); display_handle.display = self.xlib_display(); display_handle.screen = self.screen_id; - RawDisplayHandle::Xlib(display_handle) + display_handle.into() } #[inline] diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 72434ac478..5d1657c395 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -24,7 +24,10 @@ use raw_window_handle::{AppKitDisplayHandle, RawDisplayHandle}; use super::appkit::{NSApp, NSApplicationActivationPolicy, NSEvent}; use crate::{ event::Event, - event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget}, + event_loop::{ + ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget, + OwnedDisplayHandle as RootDisplayHandle, + }, platform::macos::ActivationPolicy, platform_impl::platform::{ app::WinitApplication, @@ -89,7 +92,15 @@ impl EventLoopWindowTarget { #[inline] pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) + AppKitDisplayHandle::empty().into() + } + + #[inline] + pub fn owned_display_handle(&self) -> &RootDisplayHandle { + &RootDisplayHandle { + p: OwnedDisplayHandle, + _marker: PhantomData, + } } } @@ -103,6 +114,16 @@ impl EventLoopWindowTarget { } } +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + #[inline] + pub fn raw_display_handle(&self) -> RawDisplayHandle { + AppKitDisplayHandle::empty().into() + } +} + 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 80bf89522e..a26c6b72e1 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -23,7 +23,8 @@ use self::window::WinitWindow; use self::window_delegate::WinitWindowDelegate; pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + EventLoop, EventLoopProxy, EventLoopWindowTarget, OwnedDisplayHandle, + PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoMode}, window::{PlatformSpecificWindowBuilderAttributes, WindowId}, diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 6d3e79af96..2d6470cd88 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -1228,12 +1228,12 @@ impl WinitWindow { let mut window_handle = AppKitWindowHandle::empty(); window_handle.ns_window = self.ns_window(); window_handle.ns_view = self.ns_view(); - RawWindowHandle::AppKit(window_handle) + window_handle.into() } #[inline] pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) + AppKitDisplayHandle::empty().into() } fn toggle_style_mask(&self, mask: NSWindowStyleMask, on: bool) { diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index f0ad43d5b3..7107ee2ced 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -704,6 +704,22 @@ impl EventLoopWindowTarget { } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty()) + OrbitalDisplayHandle::empty().into() + } + + pub fn owned_display_handle(&self) -> &crate::event_loop::OwnedDisplayHandle { + &crate::event_loop::OwnedDisplayHandle { + p: OwnedDisplayHandle, + _marker: std::marker::PhantomData, + } + } +} + +#[derive(Clone)] +pub struct OwnedDisplayHandle; + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + OrbitalDisplayHandle::empty().into() } } diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index 97d1dc511a..58cfeac2ba 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; diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index fa30bb10d4..f7f523949a 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -381,12 +381,12 @@ impl Window { pub fn raw_window_handle(&self) -> RawWindowHandle { let mut handle = OrbitalWindowHandle::empty(); handle.window = self.window_socket.fd as *mut _; - RawWindowHandle::Orbital(handle) + handle.into() } #[inline] pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Orbital(OrbitalDisplayHandle::empty()) + OrbitalDisplayHandle::empty().into() } #[inline] diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 6bec70c972..b6441938ad 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 17aafd946d..d7b23c0b5c 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -28,6 +28,9 @@ impl Clone for EventLoopWindowTarget { } } +#[derive(Clone)] +pub struct OwnedDisplayHandle; + impl EventLoopWindowTarget { pub fn new() -> Self { Self { @@ -350,6 +353,19 @@ impl EventLoopWindowTarget { } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Web(WebDisplayHandle::empty()) + WebDisplayHandle::empty().into() + } + + pub fn owned_display_handle(&self) -> &crate::event_loop::OwnedDisplayHandle { + &crate::event_loop::OwnedDisplayHandle { + p: OwnedDisplayHandle, + _marker: std::marker::PhantomData, + } + } +} + +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + WebDisplayHandle::empty().into() } } diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index aab8f43398..5178b07a8a 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -29,7 +29,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/web/window.rs b/src/platform_impl/web/window.rs index a46a0b80c6..65a467eb64 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -396,12 +396,12 @@ impl Window { pub fn raw_window_handle(&self) -> RawWindowHandle { let mut window_handle = WebWindowHandle::empty(); window_handle.id = self.id.0; - RawWindowHandle::Web(window_handle) + window_handle.into() } #[inline] pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Web(WebDisplayHandle::empty()) + WebDisplayHandle::empty().into() } #[inline] diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 6d5f9d44a5..d748fc8d88 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -186,6 +186,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() }; @@ -331,7 +334,14 @@ impl EventLoopWindowTarget { } pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Windows(WindowsDisplayHandle::empty()) + WindowsDisplayHandle::empty().into() + } + + pub fn owned_display_handle(&self) -> &crate::event_loop::OwnedDisplayHandle { + &crate::event_loop::OwnedDisplayHandle { + p: OwnedDisplayHandle, + _marker: PhantomData, + } } pub fn set_device_event_filter(&self, filter: DeviceEventFilter) { @@ -339,6 +349,12 @@ impl EventLoopWindowTarget { } } +impl OwnedDisplayHandle { + pub fn raw_display_handle(&self) -> RawDisplayHandle { + WindowsDisplayHandle::empty().into() + } +} + /// Returns the id of the main thread. /// /// Windows has no real API to check if the current executing thread is the "main thread", unlike diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 9c58d1c4bd..859a78be22 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -7,7 +7,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}, diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 21fa458e9d..8855d11c3d 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -321,12 +321,12 @@ impl Window { 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) + window_handle.into() } #[inline] pub fn raw_display_handle(&self) -> RawDisplayHandle { - RawDisplayHandle::Windows(WindowsDisplayHandle::empty()) + WindowsDisplayHandle::empty().into() } #[inline] diff --git a/src/window.rs b/src/window.rs index 50d8cd2487..1edb19ff85 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,8 @@ use std::fmt; use raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + DisplayHandle, HandleError, HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, + HasWindowHandle, RawDisplayHandle, RawWindowHandle, WindowHandle, }; use crate::{ @@ -1325,6 +1326,7 @@ impl Window { .map(|inner| MonitorHandle { inner }) } } + unsafe impl HasRawWindowHandle for Window { /// Returns a [`raw_window_handle::RawWindowHandle`] for the Window /// @@ -1346,6 +1348,27 @@ unsafe impl HasRawWindowHandle for Window { } } +impl HasWindowHandle for Window { + fn window_handle(&self) -> Result, HandleError> { + // See if we are active or not. + #[cfg(not(any(android_platform, raw_window_handle_force_refcount)))] + let active = Some(raw_window_handle::ActiveHandle::new()); + + #[cfg(any(android_platform, raw_window_handle_force_refcount))] + let active = self.window.active().handle(); + + match active { + Some(active) => { + // SAFETY: The window is active and the window handle is valid for the duration of + // this object's lifetime. + Ok(unsafe { WindowHandle::borrow_raw(self.raw_window_handle(), active) }) + } + + None => Err(HandleError::Inactive), + } + } +} + unsafe impl HasRawDisplayHandle for Window { /// Returns a [`raw_window_handle::RawDisplayHandle`] used by the [`EventLoop`] that /// created a window. @@ -1356,6 +1379,14 @@ unsafe impl HasRawDisplayHandle for Window { } } +impl HasDisplayHandle for Window { + fn display_handle(&self) -> Result, HandleError> { + // SAFETY: The display is active and the display handle is valid for the duration of this + // object's lifetime. + Ok(unsafe { DisplayHandle::borrow_raw(self.raw_display_handle()) }) + } +} + /// The behavior of cursor grabbing. /// /// Use this enum with [`Window::set_cursor_grab`] to grab the cursor.