トレイアイコンがクリックされた時の処理を書く

Recipe ID: menu-012

トレイアイコンがクリックされたとき(左クリック、右クリック、ダブルクリックなど)のイベントをハンドリングする方法を解説します。

Tauri v2 の JavaScript API では、TrayIcon.newaction オプションでコールバック関数を指定することで、簡単にイベントを取得できます。

前提条件

※ アイコン画像のロード形式に合わせて image-pngimage-ico が必要になる場合があります。

Cargo.toml の設定

Tauri v2 ではトレイ機能は Core (本体) に統合されているため、追加のプラグイン(tauri-plugin-tray など)のインストールは不要です。
ただし、src-tauri/Cargo.tomltray-icon 機能を有効にする必要があります。

[dependencies]
tauri = { version = "2", features = ["tray-icon", "image-png"] }

Permissions (権限) の設定

src-tauri/capabilities/default.jsoncore:tray:default を追加します。

{
  "permissions": [
    ...,
    "core:tray:default",
    "core:menu:default", // メニューを表示する場合
    "core:app:allow-default-window-icon", // defaultWindowIcon を使用する場合
    "core:window:allow-hide",
    "core:window:allow-show",
    "core:window:allow-set-focus",
    "core:window:allow-is-visible"
  ]
}

1. フロントエンドで処理する (TypeScript)

action コールバックにはイベントオブジェクトが渡されます。

import { TrayIcon } from '@tauri-apps/api/tray';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { defaultWindowIcon } from '@tauri-apps/api/app';

const icon = await defaultWindowIcon();
if (icon) {
    const tray = await TrayIcon.new({
      icon: icon,
      tooltip: 'Click me!',
      action: async (event) => {
        console.log('Tray Event:', event);

        // Click, DoubleClick, etc.
        if (event.type === 'Click' && event.button === 'Left') {
              console.log('左クリックされました');
              const win = getCurrentWindow();
              const isVisible = await win.isVisible();
              if (isVisible) {
                await win.hide();
              } else {
                await win.show();
                await win.setFocus();
              }
        }
      }
    });
}

2. バックエンドで処理する (Rust)

Rust 側では on_tray_icon_event を使用してハンドリングします。

use tauri::tray::{TrayIconBuilder, TrayIconEvent, MouseButton};
use tauri::Manager;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            let _tray = TrayIconBuilder::with_id("main-tray")
                .icon(app.default_window_icon().unwrap().clone())
                .on_tray_icon_event(|tray, event| {
                    match event {
                        TrayIconEvent::Click { button: MouseButton::Left, .. } => {
                             println!("左クリックされました");
                             let app = tray.app_handle();
                             if let Some(window) = app.get_webview_window("main") {
                                 let _ = window.show();
                                 let _ = window.set_focus();
                             }
                        }
                        TrayIconEvent::DoubleClick { .. } => {
                             println!("ダブルクリックされました");
                        }
                        _ => {}
                    }
                })
                .build(app)?;
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

補足

* macOS の挙動: トレイにメニューが設定されている場合、左クリックでもメニューが表示され、Click イベントが発火しないことがあります(OSの仕様)。
* イベント情報の取得: イベントオブジェクトからはクリック位置 (position) や矩形情報 (rect) も取得可能です。