//! Macos screen have a y axis that goings up from the bottom of the screen and //! an origin at the bottom left of the main display. mod dispatcher; mod display; mod display_link; mod events; mod keyboard; #[cfg(feature = "screen-capture")] mod screen_capture; #[cfg(not(feature = "macos-blade"))] mod metal_atlas; #[cfg(not(feature = "macos-blade"))] pub mod metal_renderer; use core_video::image_buffer::CVImageBuffer; #[cfg(not(feature = "macos-blade"))] use metal_renderer as renderer; #[cfg(feature = "macos-blade")] use crate::platform::blade as renderer; mod attributed_string; #[cfg(feature = "font-kit")] mod open_type; #[cfg(feature = "font-kit")] mod text_system; mod platform; mod window; mod window_appearance; use crate::{DevicePixels, Pixels, Size, px, size}; use cocoa::{ base::{id, nil}, foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger}, }; use objc::runtime::{BOOL, NO, YES}; use std::{ ffi::{CStr, c_char}, ops::Range, }; pub(crate) use dispatcher::*; pub(crate) use display::*; pub(crate) use display_link::*; pub(crate) use keyboard::*; pub(crate) use platform::*; pub(crate) use window::*; #[cfg(feature = "font-kit")] pub(crate) use text_system::*; /// A frame of video captured from a screen. pub(crate) type PlatformScreenCaptureFrame = CVImageBuffer; trait BoolExt { fn to_objc(self) -> BOOL; } impl BoolExt for bool { fn to_objc(self) -> BOOL { if self { YES } else { NO } } } trait NSStringExt { unsafe fn to_str(&self) -> &str; } impl NSStringExt for id { unsafe fn to_str(&self) -> &str { unsafe { let cstr = self.UTF8String(); if cstr.is_null() { "" } else { CStr::from_ptr(cstr as *mut c_char).to_str().unwrap() } } } } #[repr(C)] #[derive(Copy, Clone, Debug)] struct NSRange { pub location: NSUInteger, pub length: NSUInteger, } impl NSRange { fn invalid() -> Self { Self { location: NSNotFound as NSUInteger, length: 0, } } fn is_valid(&self) -> bool { self.location != NSNotFound as NSUInteger } fn to_range(self) -> Option> { if self.is_valid() { let start = self.location as usize; let end = start + self.length as usize; Some(start..end) } else { None } } } impl From> for NSRange { fn from(range: Range) -> Self { NSRange { location: range.start as NSUInteger, length: range.len() as NSUInteger, } } } unsafe impl objc::Encode for NSRange { fn encode() -> objc::Encoding { let encoding = format!( "{{NSRange={}{}}}", NSUInteger::encode().as_str(), NSUInteger::encode().as_str() ); unsafe { objc::Encoding::from_str(&encoding) } } } unsafe fn ns_string(string: &str) -> id { unsafe { NSString::alloc(nil).init_str(string).autorelease() } } impl From for Size { fn from(value: NSSize) -> Self { Size { width: px(value.width as f32), height: px(value.height as f32), } } } impl From for Size { fn from(rect: NSRect) -> Self { let NSSize { width, height } = rect.size; size(width.into(), height.into()) } } impl From for Size { fn from(rect: NSRect) -> Self { let NSSize { width, height } = rect.size; size(DevicePixels(width as i32), DevicePixels(height as i32)) } }