mac.rs

  1//! Macos screen have a y axis that goings up from the bottom of the screen and
  2//! an origin at the bottom left of the main display.
  3mod dispatcher;
  4mod display;
  5mod display_link;
  6mod events;
  7mod screen_capture;
  8
  9#[cfg(not(feature = "macos-blade"))]
 10mod metal_atlas;
 11#[cfg(not(feature = "macos-blade"))]
 12pub mod metal_renderer;
 13
 14use core_video::image_buffer::CVImageBuffer;
 15#[cfg(not(feature = "macos-blade"))]
 16use metal_renderer as renderer;
 17
 18#[cfg(feature = "macos-blade")]
 19use crate::platform::blade as renderer;
 20
 21mod attributed_string;
 22
 23#[cfg(feature = "font-kit")]
 24mod open_type;
 25
 26#[cfg(feature = "font-kit")]
 27mod text_system;
 28
 29mod platform;
 30mod window;
 31mod window_appearance;
 32
 33use crate::{DevicePixels, Pixels, Size, px, size};
 34use cocoa::{
 35    base::{id, nil},
 36    foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger},
 37};
 38
 39use objc::runtime::{BOOL, NO, YES};
 40use std::{
 41    ffi::{CStr, c_char},
 42    ops::Range,
 43};
 44
 45pub(crate) use dispatcher::*;
 46pub(crate) use display::*;
 47pub(crate) use display_link::*;
 48pub(crate) use platform::*;
 49pub(crate) use window::*;
 50
 51#[cfg(feature = "font-kit")]
 52pub(crate) use text_system::*;
 53
 54/// A frame of video captured from a screen.
 55pub(crate) type PlatformScreenCaptureFrame = CVImageBuffer;
 56
 57trait BoolExt {
 58    fn to_objc(self) -> BOOL;
 59}
 60
 61impl BoolExt for bool {
 62    fn to_objc(self) -> BOOL {
 63        if self { YES } else { NO }
 64    }
 65}
 66
 67trait NSStringExt {
 68    unsafe fn to_str(&self) -> &str;
 69}
 70
 71impl NSStringExt for id {
 72    unsafe fn to_str(&self) -> &str {
 73        unsafe {
 74            let cstr = self.UTF8String();
 75            if cstr.is_null() {
 76                ""
 77            } else {
 78                CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
 79            }
 80        }
 81    }
 82}
 83
 84#[repr(C)]
 85#[derive(Copy, Clone, Debug)]
 86struct NSRange {
 87    pub location: NSUInteger,
 88    pub length: NSUInteger,
 89}
 90
 91impl NSRange {
 92    fn invalid() -> Self {
 93        Self {
 94            location: NSNotFound as NSUInteger,
 95            length: 0,
 96        }
 97    }
 98
 99    fn is_valid(&self) -> bool {
100        self.location != NSNotFound as NSUInteger
101    }
102
103    fn to_range(self) -> Option<Range<usize>> {
104        if self.is_valid() {
105            let start = self.location as usize;
106            let end = start + self.length as usize;
107            Some(start..end)
108        } else {
109            None
110        }
111    }
112}
113
114impl From<Range<usize>> for NSRange {
115    fn from(range: Range<usize>) -> Self {
116        NSRange {
117            location: range.start as NSUInteger,
118            length: range.len() as NSUInteger,
119        }
120    }
121}
122
123unsafe impl objc::Encode for NSRange {
124    fn encode() -> objc::Encoding {
125        let encoding = format!(
126            "{{NSRange={}{}}}",
127            NSUInteger::encode().as_str(),
128            NSUInteger::encode().as_str()
129        );
130        unsafe { objc::Encoding::from_str(&encoding) }
131    }
132}
133
134unsafe fn ns_string(string: &str) -> id {
135    unsafe { NSString::alloc(nil).init_str(string).autorelease() }
136}
137
138impl From<NSSize> for Size<Pixels> {
139    fn from(value: NSSize) -> Self {
140        Size {
141            width: px(value.width as f32),
142            height: px(value.height as f32),
143        }
144    }
145}
146
147impl From<NSRect> for Size<Pixels> {
148    fn from(rect: NSRect) -> Self {
149        let NSSize { width, height } = rect.size;
150        size(width.into(), height.into())
151    }
152}
153
154impl From<NSRect> for Size<DevicePixels> {
155    fn from(rect: NSRect) -> Self {
156        let NSSize { width, height } = rect.size;
157        size(DevicePixels(width as i32), DevicePixels(height as i32))
158    }
159}