From 461328f54dd5e588f019d82cab87964a3a132bdc Mon Sep 17 00:00:00 2001 From: lucasmerlin Date: Tue, 22 Aug 2023 14:35:18 +0200 Subject: [PATCH 1/3] Fix iOS support in `eframe` (#3241) * Fix the app only taking up half the screen size on iPad * Fix request_repaint not working on iOS * Always use run_and_exit on iOS since run_and_return is not supported by winit on iOS right now. * Fix typo * Fix eframe glow on ios * Handle more cases --- crates/eframe/src/native/epi_integration.rs | 4 ++++ crates/eframe/src/native/run.rs | 22 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 725522eb0..65c5ccbe4 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -138,6 +138,9 @@ pub fn window_builder( window_builder = window_builder_drag_and_drop(window_builder, *drag_and_drop_support); + // Always use the default window size / position on iOS. Trying to restore the previous position + // causes the window to be shown too small. + #[cfg(not(target_os = "ios"))] let inner_size_points = if let Some(mut window_settings) = window_settings { // Restore pos/size from previous session @@ -163,6 +166,7 @@ pub fn window_builder( *initial_window_size }; + #[cfg(not(target_os = "ios"))] if *centered { if let Some(monitor) = event_loop.available_monitors().next() { let monitor_size = monitor.size().to_logical::(monitor.scale_factor()); diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index bd084a501..4a508db9b 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -119,6 +119,7 @@ fn with_event_loop( }) } +#[cfg(not(target_os = "ios"))] fn run_and_return( event_loop: &mut EventLoop, mut winit_app: impl WinitApp, @@ -332,6 +333,11 @@ fn run_and_exit(event_loop: EventLoop, mut winit_app: impl WinitApp + next_repaint_time = extremely_far_future(); ControlFlow::Poll } else { + // WaitUntil seems to not work on iOS + #[cfg(target_os = "ios")] + if let Some(window) = winit_app.window() { + window.request_redraw(); + } ControlFlow::WaitUntil(next_repaint_time) }; }) @@ -1052,6 +1058,7 @@ mod glow_integration { mut native_options: epi::NativeOptions, app_creator: epi::AppCreator, ) -> Result<()> { + #[cfg(not(target_os = "ios"))] if native_options.run_and_return { with_event_loop(native_options, |event_loop, native_options| { let glow_eframe = @@ -1063,6 +1070,13 @@ mod glow_integration { let glow_eframe = GlowWinitApp::new(&event_loop, app_name, native_options, app_creator); run_and_exit(event_loop, glow_eframe); } + + #[cfg(target_os = "ios")] + { + let event_loop = create_event_loop_builder(&mut native_options).build(); + let glow_eframe = GlowWinitApp::new(&event_loop, app_name, native_options, app_creator); + run_and_exit(event_loop, glow_eframe); + } } } @@ -1490,6 +1504,7 @@ mod wgpu_integration { mut native_options: epi::NativeOptions, app_creator: epi::AppCreator, ) -> Result<()> { + #[cfg(not(target_os = "ios"))] if native_options.run_and_return { with_event_loop(native_options, |event_loop, native_options| { let wgpu_eframe = @@ -1501,6 +1516,13 @@ mod wgpu_integration { let wgpu_eframe = WgpuWinitApp::new(&event_loop, app_name, native_options, app_creator); run_and_exit(event_loop, wgpu_eframe); } + + #[cfg(target_os = "ios")] + { + let event_loop = create_event_loop_builder(&mut native_options).build(); + let wgpu_eframe = WgpuWinitApp::new(&event_loop, app_name, native_options, app_creator); + run_and_exit(event_loop, wgpu_eframe); + } } } From 32a63da5800fc1af0400e2d018c79cb09eec673f Mon Sep 17 00:00:00 2001 From: "David M. Lary" Date: Tue, 22 Aug 2023 08:35:15 -0500 Subject: [PATCH 2/3] Added Context::is_context_menu_open() (#3267) I encountered a case where I needed to know if an egui context menu was open, even if the mouse cursor was not in an egui area (full details in discord). I found that every resource I needed to detect that the menu was open was either private, or pub(crate). While it is possible to wrap the `Response::context_menu()` in code to do state-tracking, it becomes necessary to duplicate that code in every place you use a context menu. In this commit, I add `Context::is_context_menu_open()`. Named similarly to `Context::is_pointer_over_area()`, this method will return true if any context menu is open. This is possible because the context menu uses a temp var with a fixed Id to store its state. This method just fetches the state, and interrogates it to see if there is a menu present. One helper method, `BarState::has_root()`, was added as all the fields needed to perform the check were private to the `menu` module. I've also updated the Context Menu demo to show the result of `is_context_menu_open()` to verify the code functions as expected. --- crates/egui/src/context.rs | 8 ++++++++ crates/egui/src/menu.rs | 8 +++++++- crates/egui_demo_lib/src/demo/context_menu.rs | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index d8d5a0f5a..c79e2683f 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -1389,6 +1389,14 @@ impl Context { pub fn highlight_widget(&self, id: Id) { self.frame_state_mut(|fs| fs.highlight_next_frame.insert(id)); } + + /// Is an egui context menu open? + pub fn is_context_menu_open(&self) -> bool { + self.data(|d| { + d.get_temp::(menu::CONTEXT_MENU_ID_STR.into()) + .map_or(false, |state| state.has_root()) + }) + } } // Ergonomic methods to forward some calls often used in 'if let' without holding the borrow diff --git a/crates/egui/src/menu.rs b/crates/egui/src/menu.rs index 5e27e9536..0364cf468 100644 --- a/crates/egui/src/menu.rs +++ b/crates/egui/src/menu.rs @@ -48,6 +48,10 @@ impl BarState { MenuRoot::stationary_click_interaction(response, &mut self.open_menu, response.id); self.open_menu.show(response, add_contents) } + + pub(crate) fn has_root(&self) -> bool { + self.open_menu.inner.is_some() + } } impl std::ops::Deref for BarState { @@ -212,12 +216,14 @@ fn stationary_menu_image_impl<'c, R>( InnerResponse::new(inner.map(|r| r.inner), button_response) } +pub(crate) const CONTEXT_MENU_ID_STR: &str = "__egui::context_menu"; + /// Response to secondary clicks (right-clicks) by showing the given menu. pub(crate) fn context_menu( response: &Response, add_contents: impl FnOnce(&mut Ui), ) -> Option> { - let menu_id = Id::new("__egui::context_menu"); + let menu_id = Id::new(CONTEXT_MENU_ID_STR); let mut bar_state = BarState::load(&response.ctx, menu_id); MenuRoot::context_click_interaction(response, &mut bar_state, response.id); diff --git a/crates/egui_demo_lib/src/demo/context_menu.rs b/crates/egui_demo_lib/src/demo/context_menu.rs index f8b6bc58a..1e1487ceb 100644 --- a/crates/egui_demo_lib/src/demo/context_menu.rs +++ b/crates/egui_demo_lib/src/demo/context_menu.rs @@ -66,6 +66,11 @@ impl super::View for ContextMenus { ui.menu_button("Click for menu", Self::nested_menus); ui.button("Right-click for menu") .context_menu(Self::nested_menus); + if ui.ctx().is_context_menu_open() { + ui.label("Context menu is open"); + } else { + ui.label("Context menu is closed"); + } }); ui.separator(); From ec506c0a4343c220c9ecda9b07b1dfea8d675934 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 22 Aug 2023 15:35:27 +0200 Subject: [PATCH 3/3] Use the minus character instead of "dash" (#3271) * Use the minus character instead of "dash" See https://github.com/rerun-io/rerun/issues/3053 * docstring * fix --- crates/egui/src/data/input.rs | 2 +- crates/egui/src/lib.rs | 5 ++++- crates/egui/src/widgets/drag_value.rs | 8 ++++---- crates/egui/src/widgets/slider.rs | 8 ++++---- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index ed61aa216..bf28a8b00 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -788,7 +788,7 @@ impl Key { Key::ArrowLeft => "⏴", Key::ArrowRight => "⏵", Key::ArrowUp => "⏶", - Key::Minus => "-", + Key::Minus => crate::MINUS_CHAR_STR, Key::PlusEquals => "+", _ => self.name(), } diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index aab9049b6..924724aa8 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -25,7 +25,7 @@ //! fn ui_counter(ui: &mut egui::Ui, counter: &mut i32) { //! // Put the buttons and label on the same row: //! ui.horizontal(|ui| { -//! if ui.button("-").clicked() { +//! if ui.button("−").clicked() { //! *counter -= 1; //! } //! ui.label(counter.to_string()); @@ -467,6 +467,9 @@ macro_rules! egui_assert { // ---------------------------------------------------------------------------- +/// The minus character: +pub(crate) const MINUS_CHAR_STR: &str = "−"; + /// The default egui fonts supports around 1216 emojis in total. /// Here are some of the most useful: /// ∞⊗⎗⎘⎙⏏⏴⏵⏶⏷ diff --git a/crates/egui/src/widgets/drag_value.rs b/crates/egui/src/widgets/drag_value.rs index 0e1b54605..5cd01ef06 100644 --- a/crates/egui/src/widgets/drag_value.rs +++ b/crates/egui/src/widgets/drag_value.rs @@ -271,7 +271,7 @@ impl<'a> DragValue<'a> { self.custom_formatter(move |n, _| format!("{:0>min_width$b}", n as i64)) } else { self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$b}", n.abs() as i64) }) } @@ -306,7 +306,7 @@ impl<'a> DragValue<'a> { self.custom_formatter(move |n, _| format!("{:0>min_width$o}", n as i64)) } else { self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$o}", n.abs() as i64) }) } @@ -345,11 +345,11 @@ impl<'a> DragValue<'a> { self.custom_formatter(move |n, _| format!("{:0>min_width$x}", n as i64)) } (false, true) => self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$X}", n.abs() as i64) }), (false, false) => self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$x}", n.abs() as i64) }), } diff --git a/crates/egui/src/widgets/slider.rs b/crates/egui/src/widgets/slider.rs index f793d86e7..4314498c5 100644 --- a/crates/egui/src/widgets/slider.rs +++ b/crates/egui/src/widgets/slider.rs @@ -395,7 +395,7 @@ impl<'a> Slider<'a> { self.custom_formatter(move |n, _| format!("{:0>min_width$b}", n as i64)) } else { self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$b}", n.abs() as i64) }) } @@ -430,7 +430,7 @@ impl<'a> Slider<'a> { self.custom_formatter(move |n, _| format!("{:0>min_width$o}", n as i64)) } else { self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$o}", n.abs() as i64) }) } @@ -469,11 +469,11 @@ impl<'a> Slider<'a> { self.custom_formatter(move |n, _| format!("{:0>min_width$x}", n as i64)) } (false, true) => self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$X}", n.abs() as i64) }), (false, false) => self.custom_formatter(move |n, _| { - let sign = if n < 0.0 { "-" } else { "" }; + let sign = if n < 0.0 { MINUS_CHAR_STR } else { "" }; format!("{sign}{:0>min_width$x}", n.abs() as i64) }), }