Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS safe area #4915

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft

Conversation

frederik-uni
Copy link
Contributor

Before:
Screenshot 2024-08-04 at 23 24 07
After:
Screenshot 2024-08-04 at 23 22 51

@emilk
Copy link
Owner

emilk commented Aug 5, 2024

I think this should be part of eframe, i.e. so you can call eframe::safe_area_top(ctx) to get how many ui points from the top it is safe to put widgets.

@frederik-uni
Copy link
Contributor Author

frederik-uni commented Aug 5, 2024

@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 ui.within(rect, |ui| {});

@emilk
Copy link
Owner

emilk commented Aug 26, 2024

One approach would be to modify FrameState::available_rect so that is is the safe area. That would mean egui::CentralPanel (and other panels) would start within that smaller rect. However, one should still paint some sort of background color outside that.

@emilk emilk added the iOS label Aug 26, 2024
@lucasmerlin
Copy link
Collaborator

lucasmerlin commented Sep 16, 2024

Seems like winit will soon have a safe area api: rust-windowing/winit#3890
Maybe we can use that one instead? Then other platforms will also be supported once support is added to winit (rust-windowing/winit#3910)

@frederik-uni frederik-uni marked this pull request as draft September 16, 2024 12:06
Copy link

github-actions bot commented Oct 2, 2024

Preview available at https://egui-pr-preview.github.io/pr/4915-iOS-safe-area-widget
Note that it might take a couple seconds for the update to show up after the preview_build workflow has completed.

@frederik-uni frederik-uni marked this pull request as ready for review October 2, 2024 16:50
@frederik-uni
Copy link
Contributor Author

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(self.egui_input_mut().safe_area = Some(egui::SafeArea::from(safe_area::get_ios_safe_area_insets())); would need to be changed to self.egui_input_mut().safe_area = Some(egui::SafeArea::from(window.get_safe_area()))

I don't know how that got here
@lucasmerlin
Copy link
Collaborator

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 emilk marked this pull request as draft October 29, 2024 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants