# 通知設計書 56-DispatchCommandRequested

## 概要

本ドキュメントは、Windows Terminal における DispatchCommandRequested イベント通知の設計仕様を記述する。コマンドパレット、サジェスションコントロール、スニペットペインからコマンドのディスパッチが要求された際に発火し、TerminalPage でアクションを実行するためのアクション通知である。

### 本通知の処理概要

DispatchCommandRequested は、ユーザーがコマンドパレット、サジェスション（補完候補）コントロール、またはスニペットペインからコマンドを選択した際に発火するイベントである。選択されたコマンド（Command オブジェクト）を TerminalPage に伝搬し、ActionDispatch を通じてアクションを実行する。

**業務上の目的・背景**：Windows Terminal では多数のコマンドやアクションが利用可能であり、コマンドパレットやサジェスション、スニペットなど複数のUIコンポーネントからコマンドを発行できる。DispatchCommandRequested はこれらの異なるUIコンポーネントからのコマンド発行を統一的に処理するための仕組みである。コマンドの実行ロジックを TerminalPage に集約することで、一貫した動作を保証する。

**通知の送信タイミング**：ユーザーがコマンドパレットでコマンドを選択した時、サジェスションコントロールで補完候補を選択した時、またはスニペットペインでスニペットを実行した時に発火する。

**通知の受信者**：TerminalPage が全ての送信元（CommandPalette、SuggestionsControl、SnippetsPaneContent）からの DispatchCommandRequested イベントを _OnDispatchCommandRequested ハンドラで受信する。

**通知内容の概要**：sender オブジェクトと Command オブジェクトが渡される。Command には ActionAndArgs プロパティがあり、実行すべきアクションとその引数が格納されている。

**期待されるアクション**：TerminalPage は Command の ActionAndArgs を取得し、_actionDispatch->DoAction(sender, actionAndArgs) を呼び出してアクションを実行する。

## 通知種別

アプリ内イベント通知（WinRT TypedEventHandler）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無 |

### 送信先決定ロジック

TerminalPage が各UIコンポーネントの生成時にハンドラを登録する。CommandPalette（L2163）、SuggestionsControl（L2196）、SnippetsPaneContent（L3685）の各コンポーネントに対して _OnDispatchCommandRequested が設定される。

## 通知テンプレート

### イベント引数

| 項目 | 内容 |
|-----|------|
| イベント型（BasicPaneEvents） | `TypedEventHandler<IInspectable, Command>` |
| イベント型（SnippetsPaneContent） | `TypedEventHandler<Object, Command>` |
| イベント型（CommandPalette/SuggestionsControl） | 独自定義 |
| 定義元 | `BasicPaneEvents.h` L19, `TerminalPaneContent.idl` L35, `CommandPalette.idl`, `SuggestionsControl.idl` |
| プロパティ | sender, Command |

### イベントデータ構造

```cpp
// BasicPaneEvents.h
til::typed_event<winrt::Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::Command> DispatchCommandRequested;

// SnippetsPaneContent (TerminalPaneContent.idl)
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Command | 実行すべきコマンドオブジェクト | CommandPalette/SuggestionsControl/SnippetsPaneContent の選択項目 | Yes |
| sender | コマンド発行元のコントロール | 各UIコンポーネント（SnippetsPaneContent の場合は最後にアクティブだった TermControl） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| UI操作 | コマンドパレットでのコマンド選択 | ToggleCommandPalette 以外のアクション | CommandPalette.cpp L798: コマンド選択後にディスパッチ |
| UI操作 | サジェスションでの候補選択 | 常に発火 | SuggestionsControl.cpp L733: 候補選択後にディスパッチ |
| UI操作 | スニペットペインでの実行 | lastActiveControl が有効 | SnippetsPaneContent.cpp L142: スニペット実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ToggleCommandPalette アクション | CommandPalette ではこのアクションのディスパッチを抑制する（L796-797）。パレット自身がトグルされることを防止 |
| lastActiveControl が null | SnippetsPaneContent で _control.get() が null の場合はディスパッチしない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A{コマンド選択元} -->|コマンドパレット| B[CommandPalette]
    A -->|サジェスション| C[SuggestionsControl]
    A -->|スニペット| D[SnippetsPaneContent]
    B --> E{ToggleCommandPalette?}
    E -->|Yes| F[ディスパッチ抑制]
    E -->|No| G[DispatchCommandRequested.raise]
    C --> G
    D --> H{lastActiveControl 有効?}
    H -->|有効| I[Focus + DispatchCommandRequested.raise]
    H -->|無効| J[処理なし]
    G --> K[TerminalPage::_OnDispatchCommandRequested]
    I --> K
    K --> L[_actionDispatch->DoAction]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| コマンド実行失敗 | DoAction で例外発生 | ActionDispatch 内で例外処理 |
| lastActiveControl 無効 | SnippetsPaneContent でターミナルが既に閉じられている | _control.get() の null チェックでスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

## セキュリティ考慮事項

- SnippetsPaneContent ではコマンド実行前に lastActiveControl にフォーカスを設定するため、コマンドの実行コンテキストが適切に設定される
- CommandPalette では ToggleCommandPalette アクションのディスパッチを抑制し、無限ループを防止している
- SuggestionsControl では winget コマンドの実行に関するテレメトリトラッキングが行われている

## 備考

- 3つの異なるUIコンポーネントが同じ DispatchCommandRequested イベントパターンを使用しているが、それぞれ独自にイベントを定義している
- SnippetsPaneContent は sender として lastActiveControl（TermControl）を渡す。これにより、アクションディスパッチ側がコマンドの送信元を適切に識別できる
- CommandPalette と SuggestionsControl はそれぞれ TraceLogging でテレメトリを記録している

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

DispatchCommandRequested は Command オブジェクトを引数に取る。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | BasicPaneEvents.h | `src/cascadia/TerminalApp/BasicPaneEvents.h` | L19: til::typed_event<IInspectable, Command> の定義 |
| 1-2 | TerminalPaneContent.idl | `src/cascadia/TerminalApp/TerminalPaneContent.idl` | L35: SnippetsPaneContent での DispatchCommandRequested 宣言 |
| 1-3 | CommandPalette.idl | `src/cascadia/TerminalApp/CommandPalette.idl` | DispatchCommandRequested 宣言 |
| 1-4 | SuggestionsControl.idl | `src/cascadia/TerminalApp/SuggestionsControl.idl` | DispatchCommandRequested 宣言 |

**読解のコツ**: Command オブジェクトは Microsoft.Terminal.Settings.Model 名前空間に属し、ActionAndArgs プロパティで実行すべきアクションとその引数を保持する。

#### Step 2: 送信元を理解する（3箇所）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CommandPalette.cpp | `src/cascadia/TerminalApp/CommandPalette.cpp` | L793-798: コマンド選択後の DispatchCommandRequested.raise。ToggleCommandPalette アクション除外ロジック |
| 2-2 | SuggestionsControl.cpp | `src/cascadia/TerminalApp/SuggestionsControl.cpp` | L733: 候補選択後のディスパッチ |
| 2-3 | SnippetsPaneContent.cpp | `src/cascadia/TerminalApp/SnippetsPaneContent.cpp` | L134-143: _runCommand メソッド。lastActiveControl にフォーカスを設定し、sender として渡す |

**主要処理フロー（SnippetsPaneContent）**:
1. **L136**: `_control.get()` で lastActiveControl の有効性チェック
2. **L141**: `strongControl.Focus(FocusState::Programmatic)` でフォーカス設定
3. **L142**: `DispatchCommandRequested.raise(strongControl, command)` でディスパッチ

#### Step 3: 受信・実行層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | L2163, L2196, L3685: 各UIコンポーネントからの DispatchCommandRequested ハンドラ登録 |
| 3-2 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | L623-627: _OnDispatchCommandRequested の実装。ActionAndArgs を取得して DoAction を呼び出す |

**主要処理フロー**:
- **L625**: `command.ActionAndArgs()` でアクションと引数を取得
- **L626**: `_actionDispatch->DoAction(sender, actionAndArgs)` でアクション実行

### プログラム呼び出し階層図

```
CommandPalette (コマンド選択)
    +-- DispatchCommandRequested.raise(*this, command)
    |
SuggestionsControl (候補選択)
    +-- DispatchCommandRequested.raise(*this, command)
    |
SnippetsPaneContent::_runCommand
    +-- strongControl.Focus(FocusState::Programmatic)
    +-- DispatchCommandRequested.raise(strongControl, command)
    |
    +----- 全て -----> TerminalPage::_OnDispatchCommandRequested
                            |
                            +-- command.ActionAndArgs()
                            +-- _actionDispatch->DoAction(sender, actionAndArgs)
```

### データフロー図

```
[入力]                    [処理]                          [出力]

コマンド選択 ---------> CommandPalette /              アクション実行
(UI操作)               SuggestionsControl /          (DoAction)
                       SnippetsPaneContent
                              |
                              v
                         Command オブジェクト
                         (ActionAndArgs)
                              |
                              v
                         TerminalPage
                         ::_OnDispatchCommandRequested
                              |
                              v
                         _actionDispatch->DoAction
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| BasicPaneEvents.h | `src/cascadia/TerminalApp/BasicPaneEvents.h` | ヘッダ | DispatchCommandRequested イベントのC++定義 |
| CommandPalette.idl | `src/cascadia/TerminalApp/CommandPalette.idl` | IDL定義 | CommandPalette でのイベント宣言 |
| CommandPalette.cpp | `src/cascadia/TerminalApp/CommandPalette.cpp` | ソース | コマンド選択時のイベント発火 |
| CommandPalette.h | `src/cascadia/TerminalApp/CommandPalette.h` | ヘッダ | CommandPalette クラス宣言 |
| SuggestionsControl.idl | `src/cascadia/TerminalApp/SuggestionsControl.idl` | IDL定義 | SuggestionsControl でのイベント宣言 |
| SuggestionsControl.cpp | `src/cascadia/TerminalApp/SuggestionsControl.cpp` | ソース | 候補選択時のイベント発火 |
| SuggestionsControl.h | `src/cascadia/TerminalApp/SuggestionsControl.h` | ヘッダ | SuggestionsControl クラス宣言 |
| TerminalPaneContent.idl | `src/cascadia/TerminalApp/TerminalPaneContent.idl` | IDL定義 | SnippetsPaneContent でのイベント宣言 |
| SnippetsPaneContent.cpp | `src/cascadia/TerminalApp/SnippetsPaneContent.cpp` | ソース | スニペット実行時のイベント発火 |
| TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | ソース | イベント受信・アクション実行 |
| TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | ヘッダ | ハンドラ宣言 |
