use bevy_app::prelude::*;
use bevy_ecs::{prelude::*, system::SystemParam};
#[derive(Resource, Clone, Debug, Default)]
pub struct IosSafeAreaResource {
pub top: f32,
pub bottom: f32,
pub left: f32,
pub right: f32,
}
#[derive(SystemParam)]
pub struct IosSafeArea<'w> {
resource: Option<Res<'w, IosSafeAreaResource>>,
}
impl IosSafeArea<'_> {
pub fn top(&self) -> f32 {
self.resource.as_ref().map(|r| r.top).unwrap_or(0.)
}
pub fn bottom(&self) -> f32 {
self.resource.as_ref().map(|r| r.bottom).unwrap_or(0.)
}
pub fn left(&self) -> f32 {
self.resource.as_ref().map(|r| r.left).unwrap_or(0.)
}
pub fn right(&self) -> f32 {
self.resource.as_ref().map(|r| r.right).unwrap_or(0.)
}
}
#[derive(Default)]
pub struct IosSafeAreaPlugin;
impl Plugin for IosSafeAreaPlugin {
#[cfg_attr(not(target_os = "ios"), allow(unused_variables))]
fn build(&self, app: &mut App) {
#[cfg(target_os = "ios")]
app.add_systems(Startup, init);
}
}
#[cfg(target_os = "ios")]
fn init(
_non_send_marker: bevy_ecs::system::NonSendMarker,
window: Single<Entity, With<bevy_window::PrimaryWindow>>,
mut commands: Commands,
) {
use bevy_log::tracing;
use winit::raw_window_handle::HasWindowHandle;
tracing::debug!("safe area updating");
bevy_winit::WINIT_WINDOWS.with_borrow(|windows| {
let raw_window = windows.get_window(*window).expect("invalid window handle");
if let Ok(handle) = raw_window.window_handle() {
if let winit::raw_window_handle::RawWindowHandle::UiKit(handle) = handle.as_raw() {
let ui_view: *mut std::ffi::c_void = handle.ui_view.as_ptr();
let (top, bottom, left, right) = unsafe {
(
crate::native::swift_safearea_top(ui_view),
crate::native::swift_safearea_bottom(ui_view),
crate::native::swift_safearea_left(ui_view),
crate::native::swift_safearea_right(ui_view),
)
};
let safe_area = IosSafeAreaResource {
top,
bottom,
left,
right,
};
tracing::debug!("safe area updated: {:?}", safe_area);
commands.insert_resource(safe_area);
}
}
});
}