From 073f49682da20828dbd118f1d97e14a2b3879631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CF=84?= <4602612+bash@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:18:28 +0200 Subject: [PATCH] Expose Raw Window and Display Handles (#3073) * Expose raw window and display handles in eframe * Ensure that no one implements `Clone` in the future * Cleanup --------- Co-authored-by: Matti Virkkunen --- Cargo.lock | 1 + crates/eframe/CHANGELOG.md | 2 +- crates/eframe/Cargo.toml | 1 + crates/eframe/src/epi/mod.rs | 63 +++++++++++++++++++++ crates/eframe/src/native/epi_integration.rs | 4 ++ crates/eframe/src/native/run.rs | 6 +- 6 files changed, 75 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f24c11e0..e7f111112 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/CHANGELOG.md b/crates/eframe/CHANGELOG.md index 7a507d22e..37eb3b985 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/Cargo.toml b/crates/eframe/Cargo.toml index 13e8ccd2d..9f5a49257 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 f1707883d..75380cd15 100644 --- a/crates/eframe/src/epi/mod.rs +++ b/crates/eframe/src/epi/mod.rs @@ -19,6 +19,13 @@ 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"))] #[cfg(any(feature = "glow", feature = "wgpu"))] pub use winit::event_loop::EventLoopBuilder; @@ -64,6 +71,34 @@ 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, +} + +// Implementing `Clone` would violate the guarantees of `HasRawWindowHandle` and `HasRawDisplayHandle`. +#[cfg(not(target_arch = "wasm32"))] +assert_not_impl_any!(CreationContext<'_>: Clone); + +#[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 +730,34 @@ 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: RawWindowHandle, + + /// Raw platform display handle for window + #[cfg(not(target_arch = "wasm32"))] + 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 HasRawWindowHandle for Frame { + fn raw_window_handle(&self) -> RawWindowHandle { + self.raw_window_handle + } +} + +#[allow(unsafe_code)] +#[cfg(not(target_arch = "wasm32"))] +unsafe impl HasRawDisplayHandle for Frame { + fn raw_display_handle(&self) -> 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 9053d745d..4409c1298 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 2f3daceb4..0ee7e5a3c 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() {