#![deny(unsafe_op_in_unsafe_fn)]
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use objc2::rc::Retained;
use objc2::runtime::{NSObject, NSObjectProtocol, ProtocolObject};
use objc2::{DefinedClass, MainThreadOnly, define_class, msg_send};
use objc2_app_kit::{NSWindow, NSWindowDelegate, NSWindowStyleMask};
use objc2_foundation::NSNotification;
pub(crate) struct FullscreenIvars {
is_fullscreen: Arc<AtomicBool>,
}
define_class!(
#[unsafe(super(NSObject))]
#[thread_kind = MainThreadOnly]
#[name = "ConcinnityWindowDelegate"]
#[ivars = FullscreenIvars]
pub(crate) struct WindowDelegate;
unsafe impl NSObjectProtocol for WindowDelegate {}
unsafe impl NSWindowDelegate for WindowDelegate {
#[unsafe(method(windowWillEnterFullScreen:))]
fn window_will_enter_full_screen(&self, _notification: &NSNotification) {
self.ivars().is_fullscreen.store(true, Ordering::Relaxed);
}
#[unsafe(method(windowWillExitFullScreen:))]
fn window_will_exit_full_screen(&self, _notification: &NSNotification) {
self.ivars().is_fullscreen.store(false, Ordering::Relaxed);
}
#[unsafe(method(windowDidEnterFullScreen:))]
fn window_did_enter_full_screen(&self, _notification: &NSNotification) {
self.ivars().is_fullscreen.store(true, Ordering::Relaxed);
}
#[unsafe(method(windowDidExitFullScreen:))]
fn window_did_exit_full_screen(&self, _notification: &NSNotification) {
self.ivars().is_fullscreen.store(false, Ordering::Relaxed);
}
}
);
impl WindowDelegate {
fn new(mtm: objc2::MainThreadMarker, is_fullscreen: Arc<AtomicBool>) -> Retained<Self> {
let this = Self::alloc(mtm).set_ivars(FullscreenIvars { is_fullscreen });
unsafe { msg_send![super(this), init] }
}
}
pub(crate) fn attach_fullscreen_delegate(
mtm: objc2::MainThreadMarker,
window: &NSWindow,
) -> (Retained<WindowDelegate>, Arc<AtomicBool>) {
let is_fullscreen = Arc::new(AtomicBool::new(
window.styleMask().contains(NSWindowStyleMask::FullScreen),
));
let delegate = WindowDelegate::new(mtm, Arc::clone(&is_fullscreen));
window.setDelegate(Some(ProtocolObject::from_ref(&*delegate)));
(delegate, is_fullscreen)
}