# 機能設計書 30-ブロードキャスト入力切替

## 概要

本ドキュメントは、Windows Terminal における「ブロードキャスト入力切替（ToggleBroadcastInput）」機能の設計を記述する。タブ内のすべてのペインに入力をブロードキャスト（同時送信）するモードのオン/オフを切り替える機能である。

### 本機能の処理概要

**業務上の目的・背景**：複数のサーバーに同じコマンドを同時に実行する場合や、複数の環境で同じ操作を並行して行う場合に、1つのペインへの入力を他の全ペインにも同時に送信できることが作業効率を大幅に向上させる。サーバー管理やインフラ運用において頻繁に利用される機能である。

**機能の利用シーン**：ユーザーが複数のSSHセッションを別々のペインで開いており、全サーバーに同じコマンド（apt update, systemctl restart など）を同時に実行したい場合に利用する。ブロードキャスト有効時は全ペインのカーソルが強調表示され、タブヘッダーにブロードキャストアイコンが表示される。

**主要な処理内容**：
1. ToggleBroadcastInputアクションが発火する
2. アクティブタブのブロードキャスト状態を反転する
3. タブステータスのIsInputBroadcastActiveを更新する
4. ルートペインの全リーフペインに対してブロードキャストを有効/無効化する
5. 有効化時: 各TerminalControlのKeySent/CharSent/StringSentイベントにブロードキャストハンドラを登録する
6. 無効化時: ブロードキャストハンドラの登録を解除する
7. ブロードキャスト中は、1つのペインへの入力が他の全ペインにも送信される

**関連システム・外部連携**：TerminalControl のイベント（KeySent, CharSent, StringSent）を介してペイン間の入力伝播を実現する。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | TerminalPage（メイン画面） | 主画面 | _HandleToggleBroadcastInputによりブロードキャスト入力を切替 |
| 3 | TabHeaderControl（タブヘッダー） | 補助画面 | HeaderBroadcastIconによりブロードキャスト状態を表示 |

## 機能種別

UI操作（ペイン入力ブロードキャスト）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| （なし） | - | - | 引数なしのトグル操作 | - |

### 入力データソース

キーバインド設定。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Handled | bool | 常にtrue |

### 出力先

タブの入力ブロードキャスト状態の変更。各ペインのカーソル表示状態の更新。タブヘッダーのブロードキャストアイコン更新。

## 処理フロー

### 処理シーケンス

```
1. _HandleToggleBroadcastInput が ActionEventArgs を受信
   └─ _senderOrFocusedTab でアクティブタブを取得
2. Tab::ToggleBroadcastInput() を呼び出し
3. ブロードキャスト状態を反転
   └─ newIsBroadcasting = !_tabStatus.IsInputBroadcastActive()
   └─ _tabStatus.IsInputBroadcastActive(newIsBroadcasting) で更新
4. _rootPane->EnableBroadcast(newIsBroadcasting) を呼び出し
   └─ 各リーフペインの _broadcastEnabled を設定
   └─ カーソル表示状態を更新（有効時: Shown, 無効時: Default）
   └─ ビジュアルを更新 (UpdateVisuals)
5. WalkTree でイベントハンドラを管理
   └─ 有効化時: _addBroadcastHandlers で KeySent/CharSent/StringSent にハンドラ登録
   └─ 無効化時: 既存ハンドラの revoke（解除）
6. Handled = true
```

### フローチャート

```mermaid
flowchart TD
    A[ToggleBroadcastInput アクション発火] --> B[アクティブタブ取得]
    B --> C[Tab::ToggleBroadcastInput]
    C --> D[ブロードキャスト状態反転]
    D --> E[_rootPane->EnableBroadcast]
    E --> F[各リーフペインの _broadcastEnabled 更新]
    F --> G[カーソル表示状態更新]
    G --> H[WalkTree: イベントハンドラ管理]
    H --> I{ブロードキャスト有効?}
    I -->|Yes| J[_addBroadcastHandlers: KeySent/CharSent/StringSent ハンドラ登録]
    I -->|No| K[既存ハンドラ revoke]
    J --> L[Handled = true]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-30-01 | 全ペインへのブロードキャスト | 有効時はタブ内の全リーフペインに入力が送信される | ブロードキャスト有効 |
| BR-30-02 | ソースペインの除外 | 入力元のペインにはブロードキャストされない（二重入力防止） | BroadcastKey/Char/String 実行時 |
| BR-30-03 | カーソル強調表示 | ブロードキャスト有効時はカーソルが CursorDisplayState::Shown に設定される | ブロードキャスト有効 |
| BR-30-04 | イベントハンドラの適切な管理 | 有効化時にハンドラ登録、無効化時にハンドラ解除を行う | 状態変更時 |

### 計算ロジック

入力ブロードキャストは3種類のイベントチャネルで実現される：
1. **KeySent**: キーボードキー入力（VKey, ScanCode, Modifiers, KeyDown）
2. **CharSent**: 文字入力（Character, ScanCode, Modifiers）
3. **StringSent**: 文字列入力（Text）

各イベントハンドラは、ソースコントロール以外の全ペインに対して同じ入力を送信する。

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | スキップ | アクティブタブが存在しない | 何もしない |
| - | スキップ | ペインIDが未設定 | WalkTree内でスキップ |

### リトライ仕様

リトライは不要。

## トランザクション仕様

該当なし。

## パフォーマンス要件

イベントハンドラの登録/解除はO(n)。ブロードキャスト時の入力伝播もO(n)。通常のペイン数では即座に完了する。

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

ブロードキャストされる入力にはパスワード等の機密情報が含まれる可能性がある。ユーザーはブロードキャスト状態を視覚的に確認できる（タブヘッダーアイコン、カーソル表示）。

## 備考

- ブロードキャスト中に新しいペインが追加された場合のハンドラ登録は、WalkTree の再実行によって管理される。
- Pane::BroadcastKey / BroadcastChar / BroadcastString メソッドがWalkTreeで全ペインに入力を配信する。
- ソースコントロールの判定は `sender.try_as<TermControl>()` で行われ、自身への二重送信を防止する。

---

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

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

### 推奨読解順序

#### Step 1: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | **1569-1577行目**: `_HandleToggleBroadcastInput` メソッド。アクティブタブのToggleBroadcastInputを呼び出す |

**主要処理フロー**:
1. **1572行目**: `_senderOrFocusedTab(sender)` でアクティブタブ取得
2. **1574行目**: `activeTab->ToggleBroadcastInput()` 呼び出し
3. **1575行目**: `Handled(true)` 設定

#### Step 2: Tab層のブロードキャスト制御

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Tab.cpp | `src/cascadia/TerminalApp/Tab.cpp` | **2149-2186行目**: `ToggleBroadcastInput` メソッド。状態反転、EnableBroadcast呼び出し、イベントハンドラ管理 |

**主要処理フロー**:
- **2151行目**: `!_tabStatus.IsInputBroadcastActive()` で状態反転
- **2152行目**: `_tabStatus.IsInputBroadcastActive(newIsBroadcasting)` でタブステータス更新
- **2153行目**: `_rootPane->EnableBroadcast(newIsBroadcasting)` でペイン側を更新
- **2161-2185行目**: WalkTree でイベントハンドラの登録/解除

#### Step 3: ブロードキャストハンドラ

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Tab.cpp | `src/cascadia/TerminalApp/Tab.cpp` | **2188-2229行目**: `_addBroadcastHandlers` メソッド。KeySent/CharSent/StringSentイベントにハンドラを登録 |

**主要処理フロー**:
- **2192-2204行目**: KeySent イベントハンドラ（BroadcastKey呼び出し）
- **2206-2217行目**: CharSent イベントハンドラ（BroadcastChar呼び出し）
- **2219-2228行目**: StringSent イベントハンドラ（BroadcastString呼び出し）

#### Step 4: Pane層のブロードキャスト

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Pane.cpp | `src/cascadia/TerminalApp/Pane.cpp` | **2993-3011行目**: `EnableBroadcast` メソッド。各リーフペインの _broadcastEnabled とカーソル状態を更新 |
| 4-2 | Pane.cpp | `src/cascadia/TerminalApp/Pane.cpp` | **3013行目以降**: `BroadcastKey` メソッド。WalkTreeで全ペインにキー入力をブロードキャスト |

**主要処理フロー**:
- **2997行目**: `_broadcastEnabled = enabled` でフラグ設定
- **2998-3002行目**: カーソル表示状態の更新（Shown / Default）
- **3004行目**: `UpdateVisuals()` でビジュアル更新

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

```
TerminalPage::_HandleToggleBroadcastInput (AppActionHandlers.cpp:1569)
    |
    +-- Tab::ToggleBroadcastInput (Tab.cpp:2149)
            |
            +-- _tabStatus.IsInputBroadcastActive() 状態反転
            |
            +-- Pane::EnableBroadcast (Pane.cpp:2993)
            |       |
            |       +-- [リーフ] _broadcastEnabled 設定
            |       +-- [リーフ] カーソル表示状態更新
            |       +-- [リーフ] UpdateVisuals
            |       +-- [非リーフ] 子ペインに再帰
            |
            +-- WalkTree: イベントハンドラ管理
                    |
                    +-- [有効化] _addBroadcastHandlers
                    |       +-- KeySent ──> BroadcastKey
                    |       +-- CharSent ──> BroadcastChar
                    |       +-- StringSent ──> BroadcastString
                    |
                    +-- [無効化] ハンドラ revoke
```

### データフロー図

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

キーバインド ──> _HandleToggleBroadcastInput
                         |
                Tab::ToggleBroadcastInput
                         |
              ┌──────────┴──────────┐
              |                      |
    Pane::EnableBroadcast    WalkTree: ハンドラ管理
              |                      |
    _broadcastEnabled       KeySent/CharSent/StringSent
    カーソル表示状態                    |
              |               [ブロードキャスト中の入力フロー]
              |                      |
              |     TermControl (入力元) ──> BroadcastKey/Char/String
              |                      |
              |     WalkTree: 全ペインに入力配信
              |     (ソースペイン除外)
              |                      |
              └──────> タブヘッダー更新    全ペインで同一入力実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | _HandleToggleBroadcastInput アクションハンドラ |
| Tab.cpp | `src/cascadia/TerminalApp/Tab.cpp` | ソース | ToggleBroadcastInput / _addBroadcastHandlers |
| Tab.h | `src/cascadia/TerminalApp/Tab.h` | ヘッダー | ToggleBroadcastInput 宣言, ContentEventTokens 構造体 |
| Pane.cpp | `src/cascadia/TerminalApp/Pane.cpp` | ソース | EnableBroadcast / BroadcastKey / BroadcastChar / BroadcastString |
| Pane.h | `src/cascadia/TerminalApp/Pane.h` | ヘッダー | EnableBroadcast / BroadcastKey 等の宣言, _broadcastEnabled メンバ |
| ActionAndArgs.cpp | `src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp` | ソース | ToggleBroadcastInput アクションの登録 |
