システムトレイアイコンをクリックした際に表示されるメニュー(コンテキストメニュー)を作成する方法を解説します。
Tauri v2 では、tauri::tray モジュールを使用してメニューをトレイに関連付けます。
前提条件
※ アイコン画像のロード形式に合わせて image-png や image-ico が必要になる場合があります。
Cargo.toml の設定
Tauri v2 ではトレイ機能は Core (本体) に統合されているため、追加のプラグイン(tauri-plugin-tray など)のインストールは不要です。
ただし、src-tauri/Cargo.toml で tray-icon 機能を有効にする必要があります。
[dependencies]
tauri = { version = "2", features = ["tray-icon", "image-png"] }
Permissions (権限) の設定
src-tauri/capabilities/default.json に core:tray:default を追加します。
{
"permissions": [
...,
"core:tray:default",
"core:menu:default", // メニューを表示する場合
"core:app:allow-default-window-icon" // defaultWindowIcon を使用する場合
]
}
1. バックエンドから作成する (Rust) - 推奨
Rust 側で TrayIconBuilder を使用します。
use tauri::menu::{MenuBuilder, MenuItem};
use tauri::tray::TrayIconBuilder;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app| {
// メニューの作成
let menu = MenuBuilder::new(app)
.text("show", "表示")
.text("hide", "隠す")
.separator()
.text("quit", "終了")
.build()?;
// トレイアイコンの作成とメニューの紐付け
let _tray = TrayIconBuilder::with_id("tray")
.icon(app.default_window_icon().unwrap().clone())
.menu(&menu)
.show_menu_on_left_click(false) // Windows等で左クリックでメニューを出すか
.build(app)?;
Ok(())
})
.on_menu_event(|app, event| {
match event.id().0.as_str() {
"show" => { /* ウィンドウを表示 */ }
"hide" => { /* ウィンドウを隠す */ }
"quit" => app.exit(0),
_ => {}
}
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
2. フロントエンドから作成する (TypeScript)
TrayIcon.new の menu オプションに Menu インスタンスを渡します。
import { TrayIcon } from '@tauri-apps/api/tray';
import { Menu } from '@tauri-apps/api/menu';
import { defaultWindowIcon } from '@tauri-apps/api/app';
// 1. メニューの作成
const menu = await Menu.new({
items: [
{
id: 'show',
text: 'ウィンドウを表示',
action: async () => { /* ... */ }
},
{ item: 'Separator' },
{
id: 'quit',
text: '終了',
action: () => { /* ... */ }
}
]
});
// 2. トレイアイコンの作成
const icon = await defaultWindowIcon();
if (icon) {
const tray = await TrayIcon.new({
id: 'tray',
icon: icon,
tooltip: 'My App',
menu: menu
});
}