nifty_macos/
context_menu.rs1use objc2::rc::Retained;
6use objc2::{DefinedClass, MainThreadMarker, MainThreadOnly, define_class, msg_send};
7use objc2_app_kit::{NSEvent, NSMenu, NSView};
8
9use nifty_runtime::{MenuEntry, MenuHandler};
10
11use crate::areas;
12use crate::classes::MenuTarget;
13use crate::menus;
14
15#[derive(Debug)]
16pub(crate) struct MenuAreaIvars {
17 menu: Retained<NSMenu>,
18 _target: Retained<MenuTarget>,
20}
21
22define_class!(
23 #[unsafe(super = NSView)]
25 #[thread_kind = MainThreadOnly]
26 #[name = "NiftyMenuArea"]
27 #[ivars = MenuAreaIvars]
28 #[derive(Debug)]
29 pub(crate) struct MenuArea;
30);
31
32impl MenuArea {
33 pub(crate) fn new(
35 mtm: MainThreadMarker,
36 entries: &[MenuEntry<usize>],
37 on_select: MenuHandler,
38 ) -> Retained<Self> {
39 let target = MenuTarget::new(mtm, on_select);
40 let menu = menus::context_menu(mtm, entries, &target);
41 let this = Self::alloc(mtm).set_ivars(MenuAreaIvars {
42 menu,
43 _target: target,
44 });
45 areas::hidden(unsafe { msg_send![super(this), init] })
47 }
48}
49
50pub(crate) fn menu_at(host: &NSView, event: &NSEvent) -> Option<Retained<NSMenu>> {
52 let point = host.convertPoint_fromView(event.locationInWindow(), None);
53 areas::innermost::<MenuArea>(host, point).map(|area| area.ivars().menu.clone())
54}