Add RawInput::safe_area and handle safe area on iOS in eframe#4915
Add RawInput::safe_area and handle safe area on iOS in eframe#4915frederik-uni wants to merge 10 commits intoemilk:mainfrom
RawInput::safe_area and handle safe area on iOS in eframe#4915Conversation
|
I think this should be part of |
|
@emilk so, I move the safe area insets function to eframe, but what about the safe area widget. I think it would be better to use something like this instead of a widget: fn safe_area<R>(ui: &mut Ui, inner: impl FnOnce(&mut Ui) -> R) -> R {
let insets = get_ios_safe_area_insets();
if let Some(insets) = insets {
let cursor = ui.cursor().min;
/*
let x = insets.left - cursor.x as f64;
if x > 0. {
let (id, rect) = ui.allocate_space(vec2(x as f32, ui.available_height()));
ui.interact(rect, id, Sense::hover());
}
*/
let y = insets.top - cursor.y as f64;
if y > 0. {
let (id, rect) = ui.allocate_space(vec2(ui.available_width(), y as f32));
ui.interact(rect, id, Sense::hover());
}
let max_height = ui.available_height() - insets.bottom as f32;
if max_height > 0.0 {
ui.set_max_height(max_height);
}
let max_width = ui.available_width() - insets.right as f32;
if max_width > 0.0 {
ui.set_max_width(max_width);
}
}
inner(ui)
}where should I put it? should this be part of egui/egui_extras. should this & the safe area insets function be hidden behind a feature or should it be enabled for every iOS build? its kinda essential and probably needed in every iOS build anyway. And this example above will not work when the inset is != 0 on the left. do you have any ideas how I could get this to work properly? Something like this would be great |
|
One approach would be to modify |
|
Seems like winit will soon have a safe area api: rust-windowing/winit#3890 |
|
Preview available at https://egui-pr-preview.github.io/pr/4915-iOS-safe-area-widget |
|
Im not quite sure when which events fires in winit. I guessed. theoretically WindowEvent::Resized(_) & ScaleFactorChanged should be enough, but im not sure if the events fire when the app is minimized or repopend in split screen or if the device was flipped while the screen was of so included Focused(true) & Occluded(false). Im not quite sure when the safe area gets merged into winit as it had no updates the last 3 weeks. Migrating from my implementation to the winit implementation should be quite easy anyway( |
I don't know how that got here
|
The winit PR was approved and is added to the 0.31 milestone so I think it makes sense to just wait for that and then update your PR with the winit implementation |
|
@emilk the code was merged so once the version bump is in crates.io & this project is updated, this can be merged without change |
|
Cool, Can this be merged now? |
|
Sorry, I didn't expect the winit 0.31 release to take so long. I'm fine with merging the objc approach. Will look into it next week. |
# Conflicts: # Cargo.lock # crates/egui/src/pass_state.rs
This reverts commit 2bd0785.
|
I've merged master and reverted the commit relying on winit's safe area implementation, and tested it with my egui ios demo, works well! ScreenRecording_04-22-2025.14-17-35_1.movOnly thing I noticed is that windows and popups can extend past the safe area, which I don't think it should. It could mean e.g. a combobox popup is partially hidden behind the bottom bar thingy. It'd also be nice if the keyboard opening would affect the safe area so that the ui could adjust accordingly. |
…t `Area`s being able to move outside the safe area.
RawInput::safe_area and handle safe area on iOS in eframe
ScreenRecording_04-22-2025.17-32-43_1.MP4Works really well now! I've updated the way safe area is handled, it now maches screen_rect in that it's only updated if it's |
| /// Safe area insets of the screen. I.e., area not covered by the status bar, navigation bar, etc. | ||
| #[derive(Debug, PartialEq, Copy, Clone, Default)] | ||
| #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] | ||
| pub struct SafeArea { | ||
| pub top: f32, | ||
| pub right: f32, | ||
| pub bottom: f32, | ||
| pub left: f32, |
There was a problem hiding this comment.
This needs better docstring.
Does the struct describe the bounds of the safe area? If so, why isn't it a Rect?
Or is this describing the outer margins by which you need to shrink in order to make the screen rect safe? If so, SafeArea is a VERY confusing name (since it is really describing the unsafe margins). ScreenMargins would be a better name. And it can be (or wrap) a MarginF32
There was a problem hiding this comment.
| pub fn screen_rect(&self) -> Rect { | ||
| self.screen_rect - self.safe_area | ||
| } |
There was a problem hiding this comment.
That self.screen_rect != self.screen_rect() is too confusing. Use different words for different things please
There was a problem hiding this comment.
I think there are three options but none are great:
-
keep
screen_rectand have it return the "safe area rect"- needs some new name for the rect that includes the "unsafe area"
- which is hard because the screen is the most outer rect of a computer. Maybe
outer_screen_rect? 😕
- which is hard because the screen is the most outer rect of a computer. Maybe
- no breaking changes for egui apps, since you'd want to use
screen_rectin most places
- needs some new name for the rect that includes the "unsafe area"
-
deprecate
screen_rectand introduce two new terms- e.g.
outer_rectandinner_rectorviewport_rectandcontent_rect
- e.g.
-
keep
screen_rect, having it return the "unsafe outer rect"- inner rect could be
content_rectorinner_rect - naming would make sense
- no breaking changes but most existing code using
screen_rectwould probably be wrong without any warning, since it should be using the screen_rect when it should be usingcontent_rect
- inner rect could be
I think I prefer option 2 since it seems like the most "correct" thing to do
…4915) This is a squashed version of emilk#4915
…4915) This is a squashed version of the PR, rebased on to a more recent upstream.
…4915) This is a squashed version of the PR started by @frederik-uni and continued by @lucasmerlin, rebased on to a more recent upstream. emilk#4915
|
@lucasmerlin I've gone ahead and tried to address the open points of feedback on a branch here: https://github.com/irh/egui/tree/ios-safe-area. It would be great if we could get this landed, should I open a new PR or would you prefer to pull my changes into this one? |
|
@irh Nice! You should create a new one, I don't think you can update this one |
…4915) Co-authored-by: lucasmerlin <[email protected]> This is a squashed version of the PR started by @frederik-uni and continued by @lucasmerlin, rebased on to a more recent `master`. emilk#4915
@lucasmerlin Ok great, new PR here: #7578. |
…4915) Co-authored-by: lucasmerlin <[email protected]> This is a squashed version of the PR started by @frederik-uni and continued by @lucasmerlin, rebased on to a more recent `master`. emilk#4915
This PR is a continuation of #4915 by @frederik-uni and @lucasmerlin that introduces support for keeping egui content within the 'safe area' on iOS (avoiding the notch / dynamic island / menu bar etc.), with the following changes: - `SafeArea` now wraps `MarginF32` and has been renamed to `SafeAreaInsets` to clarify its purpose. - `InputState::screen_rect` is now marked as deprecated in favour of either `viewport_rect` (which contains the entire screen), or `content_rect` (which is the viewport rect with the safe area insets removed). - I added some comments to the safe area insets logic pointing out the [safe area API coming in winit v0.31](rust-windowing/winit#3910). --------- Co-authored-by: frederik-uni <[email protected]> Co-authored-by: Lucas Meurer <[email protected]> Co-authored-by: Emil Ernerfeldt <[email protected]>
This PR is a continuation of emilk#4915 by @frederik-uni and @lucasmerlin that introduces support for keeping egui content within the 'safe area' on iOS (avoiding the notch / dynamic island / menu bar etc.), with the following changes: - `SafeArea` now wraps `MarginF32` and has been renamed to `SafeAreaInsets` to clarify its purpose. - `InputState::screen_rect` is now marked as deprecated in favour of either `viewport_rect` (which contains the entire screen), or `content_rect` (which is the viewport rect with the safe area insets removed). - I added some comments to the safe area insets logic pointing out the [safe area API coming in winit v0.31](rust-windowing/winit#3910). --------- Co-authored-by: frederik-uni <[email protected]> Co-authored-by: Lucas Meurer <[email protected]> Co-authored-by: Emil Ernerfeldt <[email protected]>
Before:


After: