メニューにショートカットキーを割り当てる

Recipe ID: menu-004

メニュー項目にショートカットキー(アクセラレータ)を割り当てる方法を解説します。

OS ごと(Windows/Mac/Linux)のキーの違いを吸収するために、Tauri では CmdOrCtrl という便利な修飾子が用意されています。

ここで解説する「メニューのアクセラレータ」は、メニュー項目にショートカットキーを表示するだけであり、ショートカットキーが機能するわけではありません。ショートカットキーの動作については「グローバルショートカット」を参照してください。

前提条件

Permissions (権限) の設定

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

{
  "permissions": [
    ...,
    "core:menu:default"
  ]
}

1. フロントエンドから作成する (TypeScript)

シンプルな記法(オブジェクト形式)

accelerator プロパティに文字列で指定します。

import { Menu } from '@tauri-apps/api/menu';

const menu = await Menu.new({
  items: [
    {
      text: 'ファイル',
      items: [
        {
          id: 'new',
          text: '新規作成',
          accelerator: 'CmdOrCtrl+N',
          action: () => console.log('New File')
        },
        {
          id: 'save',
          text: '保存',
          accelerator: 'CmdOrCtrl+S',
          action: () => console.log('Save')
        },
        {
          item: 'Separator'  // セパレーター
        },
        {
          id: 'quit',
          text: '終了',
          accelerator: 'CmdOrCtrl+Q',
          action: () => console.log('Quit')
        }
      ]
    }
  ]
});

await menu.setAsAppMenu();

MenuItem クラスを使用した記法

import { Menu, MenuItem, Submenu } from '@tauri-apps/api/menu';

// 新規作成: Cmd+N (Mac) / Ctrl+N (Win)
const newItem = await MenuItem.new({
  id: 'new',
  text: '新規作成',
  accelerator: 'CmdOrCtrl+N',
  action: () => console.log('New File')
});

// 保存: Cmd+S / Ctrl+S
const saveItem = await MenuItem.new({
  id: 'save',
  text: '保存',
  accelerator: 'CmdOrCtrl+S',
  action: () => console.log('Save')
});

// 終了: Cmd+Q / Ctrl+Q
const quitItem = await MenuItem.new({
  id: 'quit',
  text: '終了',
  accelerator: 'CmdOrCtrl+Q',
  action: () => console.log('Quit')
});

const fileMenu = await Submenu.new({
  text: 'ファイル',
  items: [newItem, saveItem, quitItem]
});

const menu = await Menu.new({
  items: [fileMenu]
});
await menu.setAsAppMenu();

参考: MenuItemOptions API リファレンス

指定可能なキーの例

修飾キー説明
CmdOrCtrlMac では Command、Windows/Linux では Ctrl
ShiftShift キー
Alt または OptionAlt キー(Mac では Option)
SuperWindows キー / Mac の Command キー
特殊キー説明
Enter, Space, Backspace, Delete, Tab各種入力キー
F1 ... F12ファンクションキー
Up, Down, Left, Right矢印キー
Home, End, PageUp, PageDown移動キー

組み合わせ例:
* CmdOrCtrl+Shift+Z (やり直し)
* CmdOrCtrl+Alt+S (別名で保存)
* F11 (全画面表示)

2. バックエンドから作成する (Rust)

MenuBuilder を使用した記法(推奨)

use tauri::menu::{MenuBuilder, MenuItemBuilder, SubmenuBuilder};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            let file_menu = SubmenuBuilder::new(app, "ファイル")
                .item(
                    &MenuItemBuilder::with_id("new", "新規作成")
                        .accelerator("CmdOrCtrl+N")
                        .build(app)?,
                )
                .item(
                    &MenuItemBuilder::with_id("save", "保存")
                        .accelerator("CmdOrCtrl+S")
                        .build(app)?,
                )
                .separator()
                .item(
                    &MenuItemBuilder::with_id("quit", "終了")
                        .accelerator("CmdOrCtrl+Q")
                        .build(app)?,
                )
                .build()?;

            let menu = MenuBuilder::new(app)
                .item(&file_menu)
                .build()?;

            app.set_menu(menu)?;

            Ok(())
        })
        .on_menu_event(|app, event| {
            match event.id().0.as_str() {
                "new" => println!("New File"),
                "save" => println!("Save"),
                "quit" => {
                    println!("Quit");
                    app.exit(0);
                }
                _ => {}
            }
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

MenuItem を個別に作成する記法

MenuItem::with_id の最後の引数(Option<&str>)でアクセラレータを指定します。

use tauri::menu::{Menu, MenuItem, Submenu};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            let handle = app.handle();

            let new_item = MenuItem::with_id(
                handle, 
                "new", 
                "新規作成", 
                true, 
                Some("CmdOrCtrl+N")  // アクセラレータを指定
            )?;
            
            let save_item = MenuItem::with_id(
                handle, 
                "save", 
                "保存", 
                true, 
                Some("CmdOrCtrl+S")
            )?;

            let quit_item = MenuItem::with_id(
                handle, 
                "quit", 
                "終了", 
                true, 
                Some("CmdOrCtrl+Q")
            )?;

            let file_menu = Submenu::with_items(
                handle, 
                "ファイル", 
                true, 
                &[&new_item, &save_item, &quit_item]
            )?;

            let menu = Menu::with_items(handle, &[&file_menu])?;
            app.set_menu(menu)?;

            Ok(())
        })
        .on_menu_event(|app, event| {
            match event.id().0.as_str() {
                "new" => println!("New File"),
                "save" => println!("Save"),
                "quit" => {
                    println!("Quit");
                    app.exit(0);
                }
                _ => {}
            }
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

補足

* アクセラレータの表示: 設定したアクセラレータはメニュー項目の右側に表示されます。
* グローバルショートカット: メニューが表示されていない状態でもショートカットを有効にしたい場合は、別途グローバルショートカットの設定が必要です。
* 競合の回避: OSやブラウザが予約しているショートカットとの競合に注意してください(例:Ctrl+W はブラウザのタブを閉じる操作)。