1#[cfg(target_os = "ios")]
2pub use ios::get_safe_area_insets;
3
4#[cfg(target_os = "ios")]
5mod ios {
6    use egui::{SafeAreaInsets, epaint::MarginF32};
7    use objc2::{ClassType, rc::Retained};
8    use objc2_foundation::{MainThreadMarker, NSObjectProtocol};
9    use objc2_ui_kit::{UIApplication, UISceneActivationState, UIWindowScene};
10
11    pub fn get_safe_area_insets() -> SafeAreaInsets {
21        let Some(main_thread_marker) = MainThreadMarker::new() else {
22            log::error!("Getting safe area insets needs to be performed on the main thread");
23            return SafeAreaInsets::default();
24        };
25
26        let app = UIApplication::sharedApplication(main_thread_marker);
27
28        #[allow(unsafe_code)]
29        unsafe {
30            for scene in app.connectedScenes() {
32                if scene.isKindOfClass(UIWindowScene::class())
33                    && matches!(
34                        scene.activationState(),
35                        UISceneActivationState::ForegroundActive
36                            | UISceneActivationState::ForegroundInactive
37                    )
38                {
39                    let window_scene = Retained::cast::<UIWindowScene>(scene.clone());
41                    if let Some(window) = window_scene.keyWindow() {
42                        let insets = window.safeAreaInsets();
43                        return SafeAreaInsets(MarginF32 {
44                            top: insets.top as f32,
45                            left: insets.left as f32,
46                            right: insets.right as f32,
47                            bottom: insets.bottom as f32,
48                        });
49                    }
50                }
51            }
52        }
53
54        SafeAreaInsets::default()
55    }
56}