From 660d2f3cb64e36bbd3a609f22b614dfda8b03f81 Mon Sep 17 00:00:00 2001 From: Wind-Explorer Date: Thu, 27 Aug 2026 00:38:03 +0800 Subject: [PATCH] open control panel from tray --- src-tauri/Cargo.toml | 2 +- src-tauri/src/ui/control_panel/mod.rs | 20 ++++++++---- src-tauri/src/ui/mod.rs | 2 ++ src-tauri/src/ui/tray.rs | 45 +++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 src-tauri/src/ui/tray.rs diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6237fec..8ee386b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] tauri-build = { version = "2", features = [] } [dependencies] -tauri = { version = "2", features = ["macos-private-api", "unstable"] } +tauri = { version = "2", features = ["macos-private-api", "tray-icon", "unstable"] } tauri-plugin-dialog = "2" tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } diff --git a/src-tauri/src/ui/control_panel/mod.rs b/src-tauri/src/ui/control_panel/mod.rs index 6cfdb9e..63e2b26 100644 --- a/src-tauri/src/ui/control_panel/mod.rs +++ b/src-tauri/src/ui/control_panel/mod.rs @@ -5,11 +5,7 @@ const ACTION_WINDOW_PREFIX: &str = "control-panel-action-"; pub fn init(handle: &AppHandle) { if let Some(window) = handle.get_webview_window(WINDOW_LABEL) { - if !window.is_visible().unwrap() { - window.center().unwrap(); - window.show().unwrap(); - }; - window.set_focus().unwrap(); + window.hide().unwrap(); return; }; @@ -23,9 +19,11 @@ pub fn init(handle: &AppHandle) { .min_inner_size(400.0, 600.0) .resizable(false) .maximizable(false) - .visible(true); + .center() + .visible(false); let window = builder.build().unwrap(); + window.hide().unwrap(); let window_c = window.clone(); window.on_window_event(move |event: &tauri::WindowEvent| { if let tauri::WindowEvent::CloseRequested { api, .. } = event { @@ -35,6 +33,16 @@ pub fn init(handle: &AppHandle) { }); } +pub fn show(handle: &AppHandle) -> Result<(), String> { + let window = handle + .get_webview_window(WINDOW_LABEL) + .ok_or_else(|| "Control panel window was not created during startup.".to_string())?; + + window.unminimize().map_err(|error| error.to_string())?; + window.show().map_err(|error| error.to_string())?; + window.set_focus().map_err(|error| error.to_string()) +} + #[tauri::command] #[specta::specta] pub fn open_action_window( diff --git a/src-tauri/src/ui/mod.rs b/src-tauri/src/ui/mod.rs index 7c5c18f..8ca25ad 100644 --- a/src-tauri/src/ui/mod.rs +++ b/src-tauri/src/ui/mod.rs @@ -4,10 +4,12 @@ pub mod control_panel; #[cfg(debug_assertions)] mod debug; pub mod scene; +mod tray; pub fn init(app_handle: &AppHandle) { #[cfg(debug_assertions)] debug::init(app_handle); scene::init(app_handle); control_panel::init(app_handle); + tray::init(app_handle); } diff --git a/src-tauri/src/ui/tray.rs b/src-tauri/src/ui/tray.rs new file mode 100644 index 0000000..6985c48 --- /dev/null +++ b/src-tauri/src/ui/tray.rs @@ -0,0 +1,45 @@ +use tauri::{ + AppHandle, + menu::{Menu, MenuItem}, + tray::TrayIconBuilder, +}; + +use super::control_panel; + +const OPEN_CONTROL_PANEL_ID: &str = "open-control-panel"; +const QUIT_ID: &str = "quit"; + +pub fn init(handle: &AppHandle) { + let open_control_panel = MenuItem::with_id( + handle, + OPEN_CONTROL_PANEL_ID, + "Open Control Panel", + true, + None::<&str>, + ) + .expect("Open Control Panel tray menu item should be created"); + let quit = MenuItem::with_id(handle, QUIT_ID, "Quit", true, None::<&str>) + .expect("Quit tray menu item should be created"); + let menu = Menu::with_items(handle, &[&open_control_panel, &quit]) + .expect("Tray menu should be created"); + + let mut builder = TrayIconBuilder::new() + .tooltip("Wyd") + .menu(&menu) + .show_menu_on_left_click(true) + .on_menu_event(|app, event| match event.id().as_ref() { + OPEN_CONTROL_PANEL_ID => { + if let Err(error) = control_panel::show(app) { + eprintln!("Failed to show control panel: {error}"); + } + } + QUIT_ID => app.exit(0), + _ => {} + }); + + if let Some(icon) = handle.default_window_icon() { + builder = builder.icon(icon.clone()); + } + + builder.build(handle).expect("Tray icon should be created"); +}