aboutsummaryrefslogtreecommitdiff
path: root/bundle/src-tauri/src
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 02:46:30 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 02:46:30 +0000
commit77098c720639a421f81ee14e47250d167d7af7bd (patch)
treedcf4d021f7828e34d9f463b8cf5159326617f242 /bundle/src-tauri/src
parent9efee50d405b8ca990d30114fb6ec6a57e2e92f1 (diff)
feat(bundle): add a native menu bar listing the shortcuts
One Tauri menu definition serves the macOS menu bar and the top of each window on Windows. Menu clicks run the same frontend commands as the keyboard shortcuts in the focused window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'bundle/src-tauri/src')
-rw-r--r--bundle/src-tauri/src/main.rs16
-rw-r--r--bundle/src-tauri/src/menu.rs55
2 files changed, 70 insertions, 1 deletions
diff --git a/bundle/src-tauri/src/main.rs b/bundle/src-tauri/src/main.rs
index 80b28c5..9f63fc5 100644
--- a/bundle/src-tauri/src/main.rs
+++ b/bundle/src-tauri/src/main.rs
@@ -1,6 +1,7 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod compiler;
+mod menu;
mod runner;
use compiler::Compiler;
use runner::{OutputEvent, Runner};
@@ -11,7 +12,9 @@ use std::{
Mutex,
},
};
-use tauri::{ipc::Channel, AppHandle, Manager, State, WebviewWindow, WebviewWindowBuilder};
+use tauri::{
+ ipc::Channel, AppHandle, Emitter, Manager, State, WebviewWindow, WebviewWindowBuilder,
+};
// Each window runs its own program, keyed by window label.
#[derive(Default)]
@@ -87,6 +90,17 @@ fn main() {
let compiler = Compiler::load();
tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())
+ .menu(menu::build)
+ // Menu items act on the focused window, like its keyboard shortcuts.
+ .on_menu_event(|app, event| {
+ let focused = app
+ .webview_windows()
+ .into_values()
+ .find(|window| window.is_focused().unwrap_or(false));
+ if let Some(window) = focused {
+ let _ = window.emit_to(window.label(), "menu", event.id().as_ref());
+ }
+ })
.manage(Runners::default())
.manage(compiler)
.invoke_handler(tauri::generate_handler![
diff --git a/bundle/src-tauri/src/menu.rs b/bundle/src-tauri/src/menu.rs
new file mode 100644
index 0000000..83ba7e3
--- /dev/null
+++ b/bundle/src-tauri/src/menu.rs
@@ -0,0 +1,55 @@
+use tauri::{
+ menu::{Menu, MenuBuilder, MenuItem, SubmenuBuilder},
+ AppHandle, Runtime,
+};
+
+// One menu for all platforms: the macOS menu bar, or the top of each window elsewhere.
+// Custom item ids name the frontend commands that the same shortcuts run.
+pub fn build<R: Runtime>(app: &AppHandle<R>) -> tauri::Result<Menu<R>> {
+ let item = |id: &str, text: &str, accelerator: &str| {
+ MenuItem::with_id(app, id, text, true, Some(accelerator))
+ };
+ let file = SubmenuBuilder::new(app, "File")
+ .item(&item("new", "New", "CmdOrCtrl+N")?)
+ .item(&item("new_window", "New Window", "CmdOrCtrl+Shift+N")?)
+ .item(&item("open", "Open…", "CmdOrCtrl+O")?)
+ .item(&item("save", "Save", "CmdOrCtrl+S")?)
+ .separator()
+ .close_window()
+ .build()?;
+ // macOS needs the predefined edit items for clipboard and undo keys in the webview.
+ let edit = SubmenuBuilder::new(app, "Edit")
+ .undo()
+ .redo()
+ .separator()
+ .cut()
+ .copy()
+ .paste()
+ .select_all()
+ .separator()
+ .item(&item("find", "Find", "CmdOrCtrl+F")?)
+ .item(&item("comment", "Toggle Line Comment", "CmdOrCtrl+/")?)
+ .build()?;
+ let window = SubmenuBuilder::new(app, "Window")
+ .minimize()
+ .maximize()
+ .build()?;
+ let menu = MenuBuilder::new(app);
+ // macOS shows the first submenu as the application menu. Quit skips unsaved-changes
+ // prompts, so other platforms close windows instead.
+ #[cfg(target_os = "macos")]
+ let menu = menu.item(
+ &SubmenuBuilder::new(app, "CPSC Bundle")
+ .about(None)
+ .separator()
+ .services()
+ .separator()
+ .hide()
+ .hide_others()
+ .show_all()
+ .separator()
+ .quit()
+ .build()?,
+ );
+ menu.items(&[&file, &edit, &window]).build()
+}