From bc6a82310383c3e6f6461a204bbc27dcce116ba1 Mon Sep 17 00:00:00 2001 From: Adia Robbie Date: Sat, 17 Sep 2022 16:20:40 +0700 Subject: [PATCH] eframe: Add `center` to `NativeOptions` and `monitor_size` to `WindowInfo` (#2035) Co-authored-by: Emil Ernerfeldt --- crates/eframe/CHANGELOG.md | 4 +- crates/eframe/src/epi.rs | 40 ++++++++++++++++++- crates/eframe/src/native/epi_integration.rs | 14 +++++++ crates/eframe/src/native/run.rs | 43 ++++++++++++++++++++- 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/crates/eframe/CHANGELOG.md b/crates/eframe/CHANGELOG.md index a552dcab..3b10b41a 100644 --- a/crates/eframe/CHANGELOG.md +++ b/crates/eframe/CHANGELOG.md @@ -10,8 +10,8 @@ NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/C * Enabled deferred render state initialization to support Android ([#1952](https://github.com/emilk/egui/pull/1952)). * Allow empty textures with the glow renderer. * Added `shader_version` to `NativeOptions` for cross compiling support on different target OpenGL | ES versions (on native `glow` renderer only) ([#1993](https://github.com/emilk/egui/pull/1993)). -* Fix: app state is now saved when user presses Cmd-Q on Mac ([#1993](https://github.com/emilk/egui/pull/1993)). - +* Fix: app state is now saved when user presses Cmd-Q on Mac ([#2013](https://github.com/emilk/egui/pull/2013)). +* Added `center` to `NativeOptions` and `monitor_size` to `WindowInfo` on desktop ([#2035](https://github.com/emilk/egui/pull/2035)). ## 0.19.0 - 2022-08-20 * MSRV (Minimum Supported Rust Version) is now `1.61.0` ([#1846](https://github.com/emilk/egui/pull/1846)). diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index 0c3d8228..434fe8a6 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -208,7 +208,7 @@ pub enum HardwareAcceleration { /// Only a single native window is currently supported. #[cfg(not(target_arch = "wasm32"))] pub struct NativeOptions { - /// Sets whether or not the window will always be on top of other windows. + /// Sets whether or not the window will always be on top of other windows at initialization. pub always_on_top: bool, /// Show window in maximized mode @@ -347,6 +347,13 @@ pub struct NativeOptions { /// /// For OpenGL ES 2.0: set this to [`egui_glow::ShaderVersion::Es100`] to solve blank texture problem (by using the "fallback shader"). pub shader_version: Option, + + /// On desktop: make the window position to be centered at initialization. + /// + /// Platform specific: + /// + /// Wayland desktop currently not supported. + pub centered: bool, } #[cfg(not(target_arch = "wasm32"))] @@ -389,6 +396,7 @@ impl Default for NativeOptions { event_loop_builder: None, #[cfg(feature = "glow")] shader_version: None, + centered: false, } } } @@ -712,6 +720,29 @@ impl Frame { self.output.visible = Some(visible); } + /// On desktop: Set the window always on top. + /// + /// (Wayland desktop currently not supported) + #[cfg(not(target_arch = "wasm32"))] + pub fn set_always_on_top(&mut self, always_on_top: bool) { + self.output.always_on_top = Some(always_on_top); + } + + /// On desktop: Set the window to be centered. + /// + /// (Wayland desktop currently not supported) + #[cfg(not(target_arch = "wasm32"))] + pub fn set_centered(&mut self) { + if let Some(monitor_size) = self.info.window_info.monitor_size { + let inner_size = self.info.window_info.size; + if monitor_size.x > 1.0 && monitor_size.y > 1.0 { + let x = (monitor_size.x - inner_size.x) / 2.0; + let y = (monitor_size.y - inner_size.y) / 2.0; + self.set_window_pos(egui::Pos2 { x, y }); + } + } + } + /// for integrations only: call once per frame pub(crate) fn take_app_output(&mut self) -> backend::AppOutput { std::mem::take(&mut self.output) @@ -742,6 +773,9 @@ pub struct WindowInfo { /// Window inner size in egui points (logical pixels). pub size: egui::Vec2, + + /// Current monitor size in egui points (logical pixels) + pub monitor_size: Option, } /// Information about the URL. @@ -915,5 +949,9 @@ pub(crate) mod backend { /// Set to some bool to change window visibility. #[cfg(not(target_arch = "wasm32"))] pub visible: Option, + + /// Set to some bool to tell the window always on top. + #[cfg(not(target_arch = "wasm32"))] + pub always_on_top: Option, } } diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index dc6c5964..66c9ab4f 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -21,6 +21,14 @@ pub fn read_window_info(window: &winit::window::Window, pixels_per_point: f32) - .map(|pos| pos.to_logical::(pixels_per_point.into())) .map(|pos| egui::Pos2 { x: pos.x, y: pos.y }); + let monitor = window.current_monitor().is_some(); + let monitor_size = if monitor { + let size = window.current_monitor().unwrap().size(); + Some(egui::vec2(size.width as _, size.height as _)) + } else { + None + }; + let size = window .inner_size() .to_logical::(pixels_per_point.into()); @@ -32,6 +40,7 @@ pub fn read_window_info(window: &winit::window::Window, pixels_per_point: f32) - x: size.width, y: size.height, }, + monitor_size, } } @@ -138,6 +147,7 @@ pub fn handle_app_output( drag_window, window_pos, visible, + always_on_top, } = app_output; if let Some(decorated) = decorated { @@ -176,6 +186,10 @@ pub fn handle_app_output( if let Some(visible) = visible { window.set_visible(visible); } + + if let Some(always_on_top) = always_on_top { + window.set_always_on_top(always_on_top); + } } // ---------------------------------------------------------------------------- diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index edc46376..77c75e2d 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -223,6 +223,27 @@ fn run_and_exit( }) } +fn centere_window_pos( + monitor: Option, + native_options: &mut epi::NativeOptions, +) { + // Get the current_monitor. + if let Some(monitor) = monitor { + let monitor_size = monitor.size(); + let inner_size = native_options + .initial_window_size + .unwrap_or(egui::Vec2 { x: 800.0, y: 600.0 }); + if monitor_size.width > 0 && monitor_size.height > 0 { + let x = (monitor_size.width - inner_size.x as u32) / 2; + let y = (monitor_size.height - inner_size.y as u32) / 2; + native_options.initial_window_pos = Some(egui::Pos2 { + x: x as _, + y: y as _, + }); + } + } +} + // ---------------------------------------------------------------------------- /// Run an egui app #[cfg(feature = "glow")] @@ -588,13 +609,22 @@ mod glow_integration { app_creator: epi::AppCreator, ) { if native_options.run_and_return { - with_event_loop(native_options, |event_loop, native_options| { + with_event_loop(native_options, |event_loop, mut native_options| { + if native_options.centered { + centere_window_pos(event_loop.available_monitors().next(), &mut native_options); + } + let glow_eframe = GlowWinitApp::new(event_loop, app_name, native_options, app_creator); run_and_return(event_loop, glow_eframe); }); } else { let event_loop = create_event_loop_builder(&mut native_options).build(); + + if native_options.centered { + centere_window_pos(event_loop.available_monitors().next(), &mut native_options); + } + let glow_eframe = GlowWinitApp::new(&event_loop, app_name, native_options, app_creator); run_and_exit(event_loop, glow_eframe); } @@ -959,13 +989,22 @@ mod wgpu_integration { app_creator: epi::AppCreator, ) { if native_options.run_and_return { - with_event_loop(native_options, |event_loop, native_options| { + with_event_loop(native_options, |event_loop, mut native_options| { + if native_options.centered { + centere_window_pos(event_loop.available_monitors().next(), &mut native_options); + } + let wgpu_eframe = WgpuWinitApp::new(event_loop, app_name, native_options, app_creator); run_and_return(event_loop, wgpu_eframe); }); } else { let event_loop = create_event_loop_builder(&mut native_options).build(); + + if native_options.centered { + centere_window_pos(event_loop.available_monitors().next(), &mut native_options); + } + let wgpu_eframe = WgpuWinitApp::new(&event_loop, app_name, native_options, app_creator); run_and_exit(event_loop, wgpu_eframe); }