콘텐츠로 이동

Menu

Electron Menu.setApplicationMenuMenu.popup에 대응하는 메뉴 API. macOS는 NSMenu 기반 애플리케이션 메뉴와 popup을 제공하고, Linux는 GTK 기반 menu.popup을 제공한다. Frontend JS + Zig/Rust/Go/Node 백엔드 SDK 모두 노출된다.

Suji는 macOS App 메뉴(About/Hide/Quit)는 유지하고, caller가 전달한 top-level 메뉴를 그 뒤에 붙인다. 기본 File/Edit/View/Window/Help 메뉴로 되돌리려면 resetApplicationMenu()를 호출한다.

APImacOSLinuxWindows
menu.setApplicationMenu✅ NSMenustub (false)stub
menu.resetApplicationMenu✅ 기본 메뉴 복원stub (false)stub
menu.popup✅ NSMenu popup✅ GTK popupstub
Click eventmenu:clickmenu:click for popup items

Linux는 native 애플리케이션 메뉴바를 만들지 않고 menu.popup만 지원한다. Windows는 native menu 구현 전까지 graceful false 응답.

항목필드
일반 item{ label, click, enabled? }
checkbox{ type: "checkbox", label, click, checked?, enabled? }
separator{ type: "separator" }
submenu{ type?: "submenu", label, enabled?, submenu: MenuItem[] }

setApplicationMenu의 top-level 항목은 메뉴바에 붙는 메뉴이므로 submenu 형태를 사용한다. menu.popup은 top-level item/checkbox/separator/submenu를 모두 받을 수 있다. 중첩 submenu는 지원된다.

checkbox는 클릭 시 native menu item의 checked state를 즉시 토글하고, 동일하게 menu:click {click} 이벤트를 발화한다.

import { menu, on } from '@suji/api';
await menu.setApplicationMenu([
{
label: 'Tools',
submenu: [
{ label: 'Run Task', click: 'run-task' },
{ type: 'checkbox', label: 'Enable Feature', click: 'toggle-feature', checked: true },
{ type: 'separator' },
{
label: 'Nested',
submenu: [{ label: 'Open Panel', click: 'open-panel' }],
},
],
},
]);
on('menu:click', ({ click }) => {
if (click === 'run-task') {
// run action
}
});
await menu.resetApplicationMenu();
// Programmatic context menu. x/y 생략 시 현재 커서 위치.
await menu.popup([
{ label: 'Refresh', click: 'refresh' },
{ type: 'separator' },
{ label: 'Inspect', click: 'inspect' },
], { x: 320, y: 240 });
_ = suji.menu.setApplicationMenuRaw(
"\"items\":[{\"type\":\"submenu\",\"label\":\"Tools\",\"submenu\":[{\"label\":\"Run\",\"click\":\"run\"},{\"type\":\"checkbox\",\"label\":\"Flag\",\"click\":\"flag\",\"checked\":true}]}]",
);
_ = suji.menu.resetApplicationMenu();
use suji::menu::{self, MenuItem};
let _ = menu::set_application_menu(&[
MenuItem::Submenu {
label: "Tools",
enabled: true,
submenu: vec![
MenuItem::Item { label: "Run", click: "run", enabled: true },
MenuItem::Checkbox { label: "Flag", click: "flag", checked: true, enabled: true },
MenuItem::Separator,
],
},
]);
let _ = menu::reset_application_menu();
import "github.com/ohah/suji-go/menu"
menu.SetApplicationMenu([]menu.MenuItem{
menu.Submenu("Tools", []menu.MenuItem{
menu.Item("Run", "run"),
menu.Checkbox("Flag", "flag", true),
menu.Separator(),
}),
})
menu.ResetApplicationMenu()
import { menu, on } from '@suji/node';
await menu.setApplicationMenu([
{ label: 'Tools', submenu: [{ label: 'Run', click: 'run' }] },
]);
on('menu:click', ({ click }) => {
// click === 'run'
});
  • macOS는 NSMenu / NSMenuItem을 구성하고 NSApplication.setMainMenu:로 교체한다.
  • checkbox item은 클릭 시 native state를 즉시 토글하고 menu:click 이벤트를 발화한다.
  • menu.popupx/y를 둘 다 지정하면 해당 화면 좌표에 표시하고, 생략하면 현재 커서 위치에 표시한다.
  • macOS popup은 native 동기 modal이라 dismiss/선택 전까지 호출 thread를 점유한다.
  • Linux는 GTK GtkMenu를 만들어 같은 menu:click 이벤트로 발화한다.