diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index c37dc1cf62cf..974b94113d74 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -41,6 +41,14 @@ pub type EventLoopBuilderHook = Box) #[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))] pub type WindowBuilderHook = Box egui::ViewportBuilder>; +/// Hook into the building of the winit native window. +/// +/// You can configure any platform specific details required on top of the default configuration +/// done by `eframe`. +#[cfg(not(target_arch = "wasm32"))] +pub type WinitWindowAttributeBuilderHook = + Box winit::window::WindowAttributes>; + type DynError = Box; /// This is how your app is created. @@ -380,6 +388,14 @@ pub struct NativeOptions { #[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))] pub window_builder: Option, + /// Hook into the building of the winit native window. + /// + /// Specify a callback here in case you need to make platform specific changes to the + /// native window before it is created. + /// + /// Note: A [`NativeOptions`] clone will not include any `native_window_builder` hook. + pub winit_window_attribute_builder: Option, + #[cfg(feature = "glow")] /// Needed for cross compiling for VirtualBox VMSVGA driver with OpenGL ES 2.0 and OpenGL 2.1 which doesn't support SRGB texture. /// See . @@ -438,6 +454,8 @@ impl Clone for NativeOptions { #[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))] window_builder: None, // Skip any builder callbacks if cloning + winit_window_attribute_builder: None, // Skip any builder callbacks if cloning + #[cfg(feature = "wgpu_no_default_features")] wgpu_options: self.wgpu_options.clone(), @@ -474,6 +492,8 @@ impl Default for NativeOptions { #[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))] window_builder: None, + winit_window_attribute_builder: None, + #[cfg(feature = "glow")] shader_version: None, diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 96a52db88e5a..474eeddc8e0c 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -99,6 +99,19 @@ pub fn apply_window_settings( } } +pub fn create_winit_window_attributes( + egui_ctx: &egui::Context, + viewport_builder: ViewportBuilder, + native_options: &mut epi::NativeOptions, +) -> winit::window::WindowAttributes { + let window_attributes = egui_winit::create_winit_window_attributes(egui_ctx, viewport_builder); + + match std::mem::take(&mut native_options.winit_window_attribute_builder) { + Some(hook) => hook(window_attributes), + None => window_attributes, + } +} + #[cfg(not(target_os = "ios"))] fn largest_monitor_point_size(egui_zoom_factor: f32, event_loop: &ActiveEventLoop) -> egui::Vec2 { profiling::function_scope!(); diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 1cd49449f152..67efc93d63d1 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -106,6 +106,7 @@ struct Viewport { ids: ViewportIdPair, class: ViewportClass, builder: ViewportBuilder, + window_attributes: Option, deferred_commands: Vec, info: ViewportInfo, actions_requested: Vec, @@ -915,7 +916,7 @@ impl GlutinWindowContext { unsafe fn new( egui_ctx: &egui::Context, viewport_builder: ViewportBuilder, - native_options: &NativeOptions, + native_options: &mut NativeOptions, event_loop: &ActiveEventLoop, ) -> Result { profiling::function_scope!(); @@ -961,16 +962,19 @@ impl GlutinWindowContext { log::debug!("trying to create glutin Display with config: {config_template_builder:?}"); + let root_window_attributes = epi_integration::create_winit_window_attributes( + egui_ctx, + viewport_builder.clone(), + native_options, + ); + // Create GL display. This may probably create a window too on most platforms. Definitely on `MS windows`. Never on Android. let display_builder = glutin_winit::DisplayBuilder::new() // we might want to expose this option to users in the future. maybe using an env var or using native_options. // // The justification for FallbackEgl over PreferEgl is at https://github.com/emilk/egui/pull/2526#issuecomment-1400229576 . .with_preference(glutin_winit::ApiPreference::FallbackEgl) - .with_window_attributes(Some(egui_winit::create_winit_window_attributes( - egui_ctx, - viewport_builder.clone(), - ))); + .with_window_attributes(Some(root_window_attributes.clone())); let (window, gl_config) = { profiling::scope!("DisplayBuilder::build"); @@ -1068,6 +1072,7 @@ impl GlutinWindowContext { ids: ViewportIdPair::ROOT, class: ViewportClass::Root, builder: viewport_builder, + window_attributes: Some(root_window_attributes), deferred_commands: vec![], info: viewport_info, actions_requested: Default::default(), @@ -1134,10 +1139,9 @@ impl GlutinWindowContext { window } else { log::debug!("Creating a window for viewport {viewport_id:?}"); - let window_attributes = egui_winit::create_winit_window_attributes( - &self.egui_ctx, - viewport.builder.clone(), - ); + let window_attributes = viewport.window_attributes.take().unwrap_or_else(|| { + egui_winit::create_winit_window_attributes(&self.egui_ctx, viewport.builder.clone()) + }); if window_attributes.transparent() && self.gl_config.supports_transparency() == Some(false) { @@ -1384,6 +1388,7 @@ fn initialize_or_update_viewport( ids, class, builder, + window_attributes: None, deferred_commands: vec![], info: Default::default(), actions_requested: Default::default(), diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index cb634200a223..b02722f9e5ca 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -960,7 +960,13 @@ fn create_window( ) .with_visible(false); // Start hidden until we render the first frame to fix white flash on startup (https://github.com/emilk/egui/pull/3631) - let window = egui_winit::create_window(egui_ctx, event_loop, &viewport_builder)?; + let window_attributes = epi_integration::create_winit_window_attributes( + egui_ctx, + viewport_builder.clone(), + native_options, + ); + let window = event_loop.create_window(window_attributes)?; + egui_winit::apply_viewport_builder_to_window(egui_ctx, &window, &viewport_builder); epi_integration::apply_window_settings(&window, window_settings); Ok((window, viewport_builder)) }