コピー・貼り付けなどの標準メニューを入れる

PredefinedMenuItem(Rust はビルダーの copy() など)で、処理を書かずに切り取り・コピー・貼り付けや終了を入れる。OS ごとに使えない項目と、Linux で必要な linux-libxdo も示す。

メニュー・トレイ 対象: Tauri 2.x 更新日: 読了目安: 約8分 menu-007
目次
  1. 前提条件
  2. 1. フロントエンドから実装する (TypeScript)
  3. 標準項目で「編集」メニューを組む
  4. 既定のメニューを土台にする
  5. 2. バックエンドから実装する (Rust)
  6. 動作確認
  7. よくあるエラーと対処法
  8. OS ごとの違いと注意点
  9. 関連レシピ

「編集」メニューの切り取り・コピー・貼り付け・すべて選択や、「最小化」「終了」「このアプリについて」のように、動作があらかじめ用意されている項目は標準項目(PredefinedMenuItem)で入れます。クリック時の処理を書かなくても、フォーカスのある入力欄に対するコピーなど決まった動作をします。注意点は、自前のメニューを設定すると既定のメニューが丸ごと置き換わることと、OS ごとに使えない項目があることです。メニューの組み立て方は アプリケーションのメニューバーを作る を参照してください。

前提条件

プラグインは不要です。標準項目の作成や Menu.default()(core:menu:allow-create-default)に使う権限は core:menu:default にあり、core:default に含まれるので追加は要りません。

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default"
  ]
}

Linux で切り取り・コピー・貼り付け・すべて選択を動かすには、src-tauri/Cargo.toml で tauri に linux-libxdo feature を足します(既存の features があればそこに追加)。必要な libxdo-dev(Fedora は libxdo-devel)は Tauri の前提パッケージに含まれています。

[dependencies]
tauri = { version = "2", features = ["linux-libxdo"] }

使える標準項目と、非対応の OS は次のとおりです(JS の item の値 / Rust のビルダーのメソッド)。

JS / Rust内容非対応
Cut Copy Paste SelectAll / .cut() .copy() .paste() .select_all()切り取り・コピー・貼り付け・すべて選択なし(Linux は linux-libxdo が必要)
Undo Redo / .undo() .redo()元に戻す・やり直しWindows・Linux
Minimize Maximize CloseWindow / .minimize() .maximize() .close_window()最小化・最大化・ウィンドウを閉じるLinux
Quit / .quit()アプリを終了Linux
Hide HideOthers / .hide() .hide_others()アプリを隠す・ほかを隠すLinux
Fullscreen ShowAll Services BringAllToFront / .fullscreen() などフルスクリーン・すべてを表示など macOS 向けWindows・Linux
{ About: {...} } / .about()このアプリについてなし
Separator / .separator()区切り線なし

1. フロントエンドから実装する (TypeScript)

標準項目で「編集」メニューを組む

オブジェクト形式で item に種類を書くと標準項目になり、text で表記を変えられます。macOS では最初のサブメニューがアプリ名のメニューになるので、「このアプリについて」と「終了」を入れたサブメニューを先頭に置きます。

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

const appMenu = await Submenu.new({
  text: 'アプリ',
  items: [
    { item: { About: { name: 'My Editor', version: '1.0.0', copyright: '© 2026 Example' } }, text: 'My Editor について' },
    { item: 'Separator' },
    { item: 'Quit', text: '終了' },
  ],
});

const editMenu = await Submenu.new({
  text: '編集',
  items: [
    { item: 'Undo', text: '元に戻す' }, // Windows・Linux では非対応
    { item: 'Redo', text: 'やり直し' },
    { item: 'Separator' },
    { item: 'Cut', text: '切り取り' },
    { item: 'Copy', text: 'コピー' },
    { item: 'Paste', text: '貼り付け' },
    { item: 'SelectAll', text: 'すべて選択' },
  ],
});

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

既定のメニューを土台にする

Menu.default() は、Tauri が macOS で自動的に付けているのと同じ既定のメニュー(編集・ウィンドウ・ヘルプなど)を作ります。自分のサブメニューを append() で足せば、標準項目を 1 つずつ書かずに済みます。ただしサブメニュー名は「Edit」「Window」「Help」などの英語で固定です。

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

const menu = await Menu.default();
await menu.append(
  await Submenu.new({
    text: 'ツール',
    items: [{ id: 'tools-format', text: '整形', action: () => console.log('format') }],
  }),
);
await menu.setAsAppMenu();

2. バックエンドから実装する (Rust)

MenuBuilder と SubmenuBuilder には標準項目ごとのメソッドがあり、.copy() は既定の表記、.copy_with_text("コピー") は指定した表記で追加します。OS で項目を変えるときは cfg!() で分岐すると、どの OS でも両方の分岐がコンパイルされるので書き間違いに気付けます。

use tauri::menu::{AboutMetadata, Menu, MenuBuilder, SubmenuBuilder};
use tauri::{AppHandle, Wry};

fn build_menu(app: &AppHandle) -> tauri::Result<Menu<Wry>> {
    let info = app.package_info();
    let about = AboutMetadata {
        name: Some(info.name.clone()),
        version: Some(info.version.to_string()),
        copyright: Some("© 2026 Example".into()),
        ..Default::default()
    };
    // macOS は最初のサブメニューがアプリ名のメニューになるので、置く項目を分ける
    let first = if cfg!(target_os = "macos") {
        SubmenuBuilder::new(app, &info.name)
            .about_with_text(format!("{} について", info.name), Some(about))
            .separator()
            .services_with_text("サービス")
            .separator()
            .hide_with_text("隠す")
            .hide_others_with_text("ほかを隠す")
            .separator()
            .quit_with_text("終了")
            .build()?
    } else {
        SubmenuBuilder::new(app, "ファイル")
            .about_with_text("バージョン情報", Some(about))
            .separator()
            .close_window_with_text("閉じる") // この 2 つは Linux では非対応
            .quit_with_text("終了")
            .build()?
    };
    let edit = SubmenuBuilder::new(app, "編集")
        .undo_with_text("元に戻す")
        .redo_with_text("やり直し")
        .separator()
        .cut_with_text("切り取り")
        .copy_with_text("コピー")
        .paste_with_text("貼り付け")
        .select_all_with_text("すべて選択")
        .build()?;
    MenuBuilder::new(app).item(&first).item(&edit).build()
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .menu(build_menu) // アプリ全体のメニューとして設定する
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

標準項目には action を指定できません。自前の項目(「整形」など)の処理は メニューがクリックされた時の処理を書く を参照してください。

動作確認

ページに <textarea> を置いて npm run tauri dev で起動します。文字を選択して「編集」→「コピー」、別の場所で「編集」→「貼り付け」を選ぶと貼り付けられます。Windows で「元に戻す」「やり直し」が機能しないのは非対応のためです。About の項目を選ぶと、名前・バージョン・著作権表示が表示されます。

よくあるエラーと対処法

  • 自前のメニューに変えたら、macOS でコピー・貼り付けのショートカットが効かなくなった: 既定のメニューが置き換わり、編集メニューの項目ごとショートカットがなくなっています。「編集」サブメニューに Cut・Copy・Paste・SelectAll(必要なら Undo・Redo)を入れます。
  • Linux でメニューの「コピー」などを選んでも何も起きない: linux-libxdo feature を足していません。Cargo.toml に追加して再ビルドします。
  • 標準項目を無効にしたい、クリックを拾いたい: 標準項目で変えられるのは文言だけで、action も setEnabled() もありません。自前の MenuItem にして、実行中にメニュー項目を変更する(無効化・文言の書き換え) の方法で切り替えます。
  • macOS で先頭に置いた「編集」がアプリ名のメニューになる: 最初のサブメニューは名前に関係なくアプリ名のメニューの位置に置かれます。アプリ用のサブメニューを先頭に置きます(Windows と macOS でメニューを出し分ける)。
  • 「menu.create_default not allowed. Permissions associated with this command: core:menu:allow-create-default, core:menu:default」: capability に core:default が無いときのデバッグビルドのエラーです(リリースビルドでは「Command plugin:menu|create_default not allowed by ACL」)。core:menu:default を足します。

OS ごとの違いと注意点

  • macOS: メニューを何も設定しなければ、Tauri が既定のメニュー(Menu.default() と同じもの)を自動で付けます。不要なら Builder::enable_macos_default_menu(false) で止めます。About の authors・comments・license・website は表示されません。
  • Windows: Linux と同じく、メニューを設定しなければメニューバーは付きません。Undo・Redo・Fullscreen などは非対応です。About の icon と credits は使われません。
  • Linux: 非対応の項目が最も多く、Quit も使えません。終了は自前の項目を作ってクリック時に app.exit(0) を呼ぶと、どの OS でも同じに動きます。credits も使われません。
  • 共通: 同じ標準項目は 右クリックメニュー にも入れられます。

関連レシピ

参考リンク(公式ドキュメント)

Web Ninja

この記事を書いた人

Web Ninja ウェブエンジニア (Web Engineer)

会社員ネットワークエンジニアから独立してかれこれ 25 年以上 Web エンジニアとして活動中。普段は JavaScript と Node.js を自在に操り、時には C++ や Perl といった古流の技も嗜みます。近年は Tauri × Rust という新たな武器を手に、デスクトップアプリ開発の最前線を駆け抜けています。「作りたい」を「作れる」に変えるための、実践的な「技」をお届けします。

お問い合わせ: tauri.ninja@gmail.com

内容の誤り・動かないコードを報告する