use anyhow::Result;
use core_graphics::geometry::CGRect;
use gpui::{px, size, Bounds, DisplayId, Pixels, PlatformDisplay};
use objc::{class, msg_send, sel, sel_impl};
use uuid::Uuid;
#[derive(Debug)]
pub(crate) struct IosDisplay {
screen: *mut objc::runtime::Object,
}
unsafe impl Send for IosDisplay {}
unsafe impl Sync for IosDisplay {}
impl IosDisplay {
pub fn main() -> Self {
unsafe {
let screen: *mut objc::runtime::Object = msg_send![class!(UIScreen), mainScreen];
Self { screen }
}
}
pub fn all() -> impl Iterator<Item = Self> {
unsafe {
let screens: *mut objc::runtime::Object = msg_send![class!(UIScreen), screens];
let count: usize = msg_send![screens, count];
(0..count).map(move |i| {
let screen: *mut objc::runtime::Object = msg_send![screens, objectAtIndex: i];
Self { screen }
})
}
}
fn bounds_in_points(&self) -> CGRect {
unsafe { msg_send![self.screen, bounds] }
}
pub fn native_scale(&self) -> f32 {
unsafe {
let scale: f64 = msg_send![self.screen, nativeScale];
scale as f32
}
}
pub fn scale(&self) -> f32 {
unsafe {
let scale: f64 = msg_send![self.screen, scale];
scale as f32
}
}
}
impl PlatformDisplay for IosDisplay {
fn id(&self) -> DisplayId {
DisplayId::new(self.screen as u32)
}
fn uuid(&self) -> Result<Uuid> {
let bounds = self.bounds_in_points();
let scale = self.native_scale();
let bytes = format!(
"ios-screen-{}-{}-{}",
bounds.size.width as u32,
bounds.size.height as u32,
(scale * 100.0) as u32
);
Ok(Uuid::new_v5(&Uuid::NAMESPACE_OID, bytes.as_bytes()))
}
fn bounds(&self) -> Bounds<Pixels> {
let bounds = self.bounds_in_points();
Bounds {
origin: Default::default(),
size: size(px(bounds.size.width as f32), px(bounds.size.height as f32)),
}
}
}