グローバルショートカットを登録する

Recipe ID: win-031

アプリがフォーカスを持っていなくても(バックグラウンドにいても)反応する、システム全体のショートカットキーを登録する方法を紹介します。

例えば「Ctrl + Shift + P を押すとウィンドウを表示/非表示にする」といった機能を実装する場合に使用します。

前提条件

この機能は tauri-plugin-global-shortcut プラグインを使用します。

プラグインのインストール

npm run tauri add global-shortcut

Permissions (権限) の設定

src-tauri/capabilities/default.json に以下の権限を追加します。

{
  "permissions": [
    ...,
    "global-shortcut:allow-register",
    "global-shortcut:allow-unregister",
    "global-shortcut:allow-is-registered"
  ]
}

※ 各操作(登録、解除、確認)にはそれぞれ明示的な権限許可が必要です。

1. フロントエンドから変更する (TypeScript)

フロントエンドからショートカットを登録する場合、Tauri の API を使用します。

ハンドラ関数に渡される event オブジェクトの state プロパティを確認することで、キーが「押された時 (Pressed)」か「離された時 (Released)」かを判定できます。

import { register, unregister, isRegistered } from '@tauri-apps/plugin-global-shortcut';

const shortcut = 'CommandOrControl+Shift+P';

// 既に登録されているか確認
const isRegisteredResult = await isRegistered(shortcut);

if (isRegisteredResult) {
  console.log(`${shortcut} は既に登録されています`);
} else {
  // ショートカットを登録する
  await register(shortcut, (event) => {
    if (event.state === 'Pressed') {
      console.log('Ctrl+Shift+P が押されました');
      // ウィンドウの表示切り替えなどの処理
    }
  });
}

// 複数のショートカットを登録
await register(['CommandOrControl+Shift+Q', 'Shift+Space'], (event) => {
  if (event.state === 'Pressed') {
    console.log(`ショートカット ${event.shortcut} が押されました`);
  }
});

// ショートカットの登録解除(クリーンアップ時など)
// await unregister('CommandOrControl+Shift+P');

2. バックエンドから変更する (Rust)

Rust側でショートカットを管理する場合、イベントループ内で処理を行うか、プラグインの機能を利用します。

tauri-plugin-global-shortcut プラグインをインストールすると、lib.rs.plugin(tauri_plugin_global_shortcut::Builder::new().build()) が追記されます。以下のサンプルを使う際には、追加された行を削除して、tauri_plugin_global_shortcut が重複しないようにしてください。

use tauri::Manager;
use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            #[cfg(desktop)]
            {
                // Ctrl + Shift + P
                let shortcut = Shortcut::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyP);

                app.handle().plugin(
                    tauri_plugin_global_shortcut::Builder::new()
                        .with_handler(move |app_handle, sc, event| {
                            if sc == &shortcut {
                                match event.state() {
                                    ShortcutState::Pressed => {
                                        println!("Ctrl+Shift+P が押されました (Pressed)");
                                        if let Some(window) = app_handle.get_webview_window("main") {
                                             let _ = window.set_focus();
                                        }
                                    }
                                    ShortcutState::Released => {
                                        println!("Ctrl+Shift+P が離されました (Released)");
                                    }
                                }
                            }
                        })
                        .build(),
                )?;

                // ショートカットを登録
                app.global_shortcut().register(shortcut)?;
            }
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

注意事項

  • キーの競合: Ctrl+CCtrl+V など、OSや他のアプリで頻繁に使われるショートカットを登録すると、本来の機能が動作しなくなる場合があります。
  • プラットフォームの違い: mac の Command と Windows の Control を区別するために、CommandOrControl を使用することをお勧めします。