From e940fe89a34da65eeb9b624b286ee13d70b5c86f Mon Sep 17 00:00:00 2001 From: Matti Virkkunen Date: Fri, 3 Mar 2023 19:58:33 +0200 Subject: [PATCH 1/3] Expose raw window and display handles in eframe --- crates/eframe/CHANGELOG.md | 2 +- crates/eframe/src/epi/mod.rs | 52 +++++++++++++++++++++ crates/eframe/src/native/epi_integration.rs | 4 ++ crates/eframe/src/native/run.rs | 6 ++- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/crates/eframe/CHANGELOG.md b/crates/eframe/CHANGELOG.md index 7a507d22e5f8..37eb3b985ece 100644 --- a/crates/eframe/CHANGELOG.md +++ b/crates/eframe/CHANGELOG.md @@ -5,7 +5,7 @@ NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/C ## Unreleased - +* Expose raw window and display handles in `CreationContext` and `Frame` ## 0.22.0 - 2023-05-23 * Fix: `request_repaint_after` works even when called from background thread [#2939](https://github.com/emilk/egui/pull/2939) diff --git a/crates/eframe/src/epi/mod.rs b/crates/eframe/src/epi/mod.rs index f1707883d49c..5e1e389fb0af 100644 --- a/crates/eframe/src/epi/mod.rs +++ b/crates/eframe/src/epi/mod.rs @@ -19,6 +19,10 @@ use std::any::Any; #[cfg(any(feature = "glow", feature = "wgpu"))] pub use crate::native::run::UserEvent; +use raw_window_handle::{ + HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, +}; + #[cfg(not(target_arch = "wasm32"))] #[cfg(any(feature = "glow", feature = "wgpu"))] pub use winit::event_loop::EventLoopBuilder; @@ -64,6 +68,30 @@ pub struct CreationContext<'s> { /// Can be used to manage GPU resources for custom rendering with WGPU using [`egui::PaintCallback`]s. #[cfg(feature = "wgpu")] pub wgpu_render_state: Option, + + /// Raw platform window handle + #[cfg(not(target_arch = "wasm32"))] + pub(crate) raw_window_handle: RawWindowHandle, + + /// Raw platform display handle for window + #[cfg(not(target_arch = "wasm32"))] + pub(crate) raw_display_handle: RawDisplayHandle, +} + +#[allow(unsafe_code)] +#[cfg(not(target_arch = "wasm32"))] +unsafe impl HasRawWindowHandle for CreationContext<'_> { + fn raw_window_handle(&self) -> RawWindowHandle { + self.raw_window_handle + } +} + +#[allow(unsafe_code)] +#[cfg(not(target_arch = "wasm32"))] +unsafe impl HasRawDisplayHandle for CreationContext<'_> { + fn raw_display_handle(&self) -> RawDisplayHandle { + self.raw_display_handle + } } // ---------------------------------------------------------------------------- @@ -695,6 +723,30 @@ pub struct Frame { /// such that it can be retrieved during [`App::post_rendering`] with [`Frame::screenshot`] #[cfg(not(target_arch = "wasm32"))] pub(crate) screenshot: std::cell::Cell>, + + /// Raw platform window handle + #[cfg(not(target_arch = "wasm32"))] + pub(crate) raw_window_handle: raw_window_handle::RawWindowHandle, + + /// Raw platform display handle for window + #[cfg(not(target_arch = "wasm32"))] + pub(crate) raw_display_handle: raw_window_handle::RawDisplayHandle, +} + +#[allow(unsafe_code)] +#[cfg(not(target_arch = "wasm32"))] +unsafe impl raw_window_handle::HasRawWindowHandle for Frame { + fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle { + self.raw_window_handle + } +} + +#[allow(unsafe_code)] +#[cfg(not(target_arch = "wasm32"))] +unsafe impl raw_window_handle::HasRawDisplayHandle for Frame { + fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { + self.raw_display_handle + } } impl Frame { diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 9053d745d26c..4409c1298bd4 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -3,6 +3,8 @@ use winit::event_loop::EventLoopWindowTarget; #[cfg(target_os = "macos")] use winit::platform::macos::WindowBuilderExtMacOS as _; +use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; + #[cfg(feature = "accesskit")] use egui::accesskit; use egui::NumExt as _; @@ -380,6 +382,8 @@ impl EpiIntegration { #[cfg(feature = "wgpu")] wgpu_render_state, screenshot: std::cell::Cell::new(None), + raw_display_handle: window.raw_display_handle(), + raw_window_handle: window.raw_window_handle(), }; let mut egui_winit = egui_winit::State::new(event_loop); diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 2f3daceb4e55..0ee7e5a3cbdf 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -3,6 +3,7 @@ use std::time::Instant; +use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _}; use winit::event_loop::{ ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget, }; @@ -345,7 +346,6 @@ mod glow_integration { prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext}, surface::GlSurface, }; - use raw_window_handle::HasRawWindowHandle; use super::*; @@ -756,6 +756,8 @@ mod glow_integration { gl: Some(gl.clone()), #[cfg(feature = "wgpu")] wgpu_render_state: None, + raw_display_handle: gl_window.window().raw_display_handle(), + raw_window_handle: gl_window.window().raw_window_handle(), }); if app.warm_up_enabled() { @@ -1215,6 +1217,8 @@ mod wgpu_integration { #[cfg(feature = "glow")] gl: None, wgpu_render_state, + raw_display_handle: window.raw_display_handle(), + raw_window_handle: window.raw_window_handle(), }); if app.warm_up_enabled() { From 6b90d6d9d50c9d2cfa2ebae36937c8ea262b3863 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Sun, 11 Jun 2023 17:49:42 +0200 Subject: [PATCH 2/3] Ensure that no one implements `Clone` in the future --- Cargo.lock | 1 + crates/eframe/Cargo.toml | 1 + crates/eframe/src/epi/mod.rs | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0f24c11e0fd4..e7f11111224a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1164,6 +1164,7 @@ dependencies = [ "raw-window-handle", "ron", "serde", + "static_assertions", "thiserror", "tts", "wasm-bindgen", diff --git a/crates/eframe/Cargo.toml b/crates/eframe/Cargo.toml index 13e8ccd2db4b..9f5a492579d2 100644 --- a/crates/eframe/Cargo.toml +++ b/crates/eframe/Cargo.toml @@ -96,6 +96,7 @@ egui_glow = { version = "0.22.0", path = "../egui_glow", optional = true, defaul glow = { version = "0.12", optional = true } ron = { version = "0.8", optional = true, features = ["integer128"] } serde = { version = "1", optional = true, features = ["derive"] } +static_assertions = "1.1.0" # ------------------------------------------- # native: diff --git a/crates/eframe/src/epi/mod.rs b/crates/eframe/src/epi/mod.rs index 5e1e389fb0af..5132f98cf012 100644 --- a/crates/eframe/src/epi/mod.rs +++ b/crates/eframe/src/epi/mod.rs @@ -22,6 +22,7 @@ pub use crate::native::run::UserEvent; use raw_window_handle::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; +use static_assertions::assert_not_impl_any; #[cfg(not(target_arch = "wasm32"))] #[cfg(any(feature = "glow", feature = "wgpu"))] @@ -78,6 +79,9 @@ pub struct CreationContext<'s> { pub(crate) raw_display_handle: RawDisplayHandle, } +// Implementing `Clone` would violate the guarantees of `HasRawWindowHandle` and `HasRawDisplayHandle`. +assert_not_impl_any!(CreationContext<'_>: Clone); + #[allow(unsafe_code)] #[cfg(not(target_arch = "wasm32"))] unsafe impl HasRawWindowHandle for CreationContext<'_> { @@ -733,6 +737,9 @@ pub struct Frame { pub(crate) raw_display_handle: raw_window_handle::RawDisplayHandle, } +// Implementing `Clone` would violate the guarantees of `HasRawWindowHandle` and `HasRawDisplayHandle`. +assert_not_impl_any!(Frame: Clone); + #[allow(unsafe_code)] #[cfg(not(target_arch = "wasm32"))] unsafe impl raw_window_handle::HasRawWindowHandle for Frame { From e3764acb80b4666b9727e466c68530c42f70aac9 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister <4602612+bash@users.noreply.github.com> Date: Sun, 11 Jun 2023 17:52:52 +0200 Subject: [PATCH 3/3] Cleanup --- crates/eframe/src/epi/mod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/eframe/src/epi/mod.rs b/crates/eframe/src/epi/mod.rs index 5132f98cf012..75380cd159e9 100644 --- a/crates/eframe/src/epi/mod.rs +++ b/crates/eframe/src/epi/mod.rs @@ -19,9 +19,11 @@ use std::any::Any; #[cfg(any(feature = "glow", feature = "wgpu"))] pub use crate::native::run::UserEvent; +#[cfg(not(target_arch = "wasm32"))] use raw_window_handle::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; +#[cfg(not(target_arch = "wasm32"))] use static_assertions::assert_not_impl_any; #[cfg(not(target_arch = "wasm32"))] @@ -80,6 +82,7 @@ pub struct CreationContext<'s> { } // Implementing `Clone` would violate the guarantees of `HasRawWindowHandle` and `HasRawDisplayHandle`. +#[cfg(not(target_arch = "wasm32"))] assert_not_impl_any!(CreationContext<'_>: Clone); #[allow(unsafe_code)] @@ -730,28 +733,29 @@ pub struct Frame { /// Raw platform window handle #[cfg(not(target_arch = "wasm32"))] - pub(crate) raw_window_handle: raw_window_handle::RawWindowHandle, + pub(crate) raw_window_handle: RawWindowHandle, /// Raw platform display handle for window #[cfg(not(target_arch = "wasm32"))] - pub(crate) raw_display_handle: raw_window_handle::RawDisplayHandle, + pub(crate) raw_display_handle: RawDisplayHandle, } // Implementing `Clone` would violate the guarantees of `HasRawWindowHandle` and `HasRawDisplayHandle`. +#[cfg(not(target_arch = "wasm32"))] assert_not_impl_any!(Frame: Clone); #[allow(unsafe_code)] #[cfg(not(target_arch = "wasm32"))] -unsafe impl raw_window_handle::HasRawWindowHandle for Frame { - fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle { +unsafe impl HasRawWindowHandle for Frame { + fn raw_window_handle(&self) -> RawWindowHandle { self.raw_window_handle } } #[allow(unsafe_code)] #[cfg(not(target_arch = "wasm32"))] -unsafe impl raw_window_handle::HasRawDisplayHandle for Frame { - fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { +unsafe impl HasRawDisplayHandle for Frame { + fn raw_display_handle(&self) -> RawDisplayHandle { self.raw_display_handle } }