use objc2::MainThreadMarker;
use objc2::rc::Retained;
use objc2_app_kit::{NSToolbar, NSView, NSWindow, NSWindowButton, NSWindowToolbarStyle};
use winit::window::Window;
use crate::{Rect, Titlebar};
const ASSUMED: Rect = Rect {
x: 0.0,
y: 0.0,
w: 78.0,
h: 28.0,
};
pub fn native_controls(window: &Window) -> Rect {
measure(window).unwrap_or(ASSUMED)
}
pub fn set_titlebar(window: &Window, titlebar: Titlebar) {
let style = match titlebar {
Titlebar::Standard => return,
Titlebar::Medium => NSWindowToolbarStyle::UnifiedCompact,
Titlebar::Tall => NSWindowToolbarStyle::Unified,
};
let Some(ns_window) = ns_window(window) else {
return;
};
let Some(mtm) = MainThreadMarker::new() else {
return;
};
let toolbar = NSToolbar::new(mtm);
ns_window.setToolbar(Some(&toolbar));
ns_window.setToolbarStyle(style);
}
fn ns_window(window: &Window) -> Option<Retained<NSWindow>> {
use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle};
let RawWindowHandle::AppKit(h) = window.window_handle().ok()?.as_raw() else {
return None;
};
let view = unsafe { Retained::retain(h.ns_view.as_ptr().cast::<NSView>()) }?;
view.window()
}
fn measure(window: &Window) -> Option<Rect> {
let ns_window = ns_window(window)?;
let frame = ns_window.frame();
let titlebar = frame.size.height - ns_window.contentLayoutRect().size.height;
if titlebar <= 0.0 {
return None;
}
let in_window = |b: NSWindowButton| {
let button = ns_window.standardWindowButton(b)?;
let superview = unsafe { button.superview() }?;
Some(superview.convertRect_toView(button.frame(), None))
};
let close = in_window(NSWindowButton::CloseButton)?;
let zoom = in_window(NSWindowButton::ZoomButton)?;
let leading = close.origin.x;
let trailing = zoom.origin.x + zoom.size.width;
if leading < 0.0 || trailing <= leading {
return None;
}
let centre = frame.size.height - (close.origin.y + close.size.height / 2.0);
let h = (2.0 * centre).min(titlebar);
if h <= 0.0 {
return None;
}
Some(Rect::new(0.0, 0.0, (trailing + leading) as f32, h as f32))
}