# 機能設計書 29-ペインへのフォーカス

## 概要

本ドキュメントは、Windows Terminal における「ペインへのフォーカス（FocusPane）」機能の設計を記述する。ペインIDを指定して直接そのペインにフォーカスを移動する機能である。

### 本機能の処理概要

**業務上の目的・背景**：No.21のMoveFocus（方向ベースのフォーカス移動）とは異なり、ペインのIDを直接指定してフォーカスを移動できる機能が必要である。タブの状態復元（BuildStartupActions）や、スクリプトから特定のペインを正確に指定してフォーカスする場合に使用される。

**機能の利用シーン**：タブ状態の復元時に、保存されたフォーカス状態を再現するために使用される。また、設定ファイルのアクション定義で特定のペインIDを指定してフォーカスを設定する場合に利用する。コマンドラインの `wt focus-pane` サブコマンドからも呼び出し可能。

**主要な処理内容**：
1. FocusPaneアクション引数からペインID（UInt32）を取得する
2. ズーム状態の場合は事前にアンズームする
3. フォーカスされたタブ内でIDに一致するペインを検索する
4. 一致するペインが見つかった場合、そのペインにフォーカスを移動する
5. 見つからなかった場合はHandled=falseを返す

**関連システム・外部連携**：特になし。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | TerminalPage（メイン画面） | 主画面 | _HandleFocusPaneによりID指定でペインにフォーカス移動 |

## 機能種別

UI操作（ペインフォーカス制御）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Id | UInt32 | Yes | フォーカスを設定するペインのID | 有効なペインID |

### 入力データソース

キーバインド設定、コマンドライン（`wt focus-pane --target <id>`）、またはタブ状態復元処理（BuildStartupActions）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Handled | bool | 指定IDのペインが見つかり、フォーカスが移動されたかどうか |

### 出力先

UIフォーカス状態の更新（指定ペインへのフォーカス移動）。

## 処理フロー

### 処理シーケンス

```
1. _HandleFocusPane が ActionEventArgs を受信
   └─ FocusPaneArgs にキャストして Id を取得
2. _GetFocusedTabImpl() でフォーカスされたタブを取得
3. _UnZoomIfNeeded() でズームを解除
4. activeTab->FocusPane(paneId) を呼び出し
   └─ Tab::FocusPane が _rootPane->FocusPane(id) に委譲
5. Pane::FocusPane(id) で WalkTree を実行
   └─ 各ペインの _parentChildPath をリセット
   └─ _id == id のペインが見つかったら _FocusFirstChild() でフォーカス設定
6. 結果を Handled に設定
```

### フローチャート

```mermaid
flowchart TD
    A[FocusPane アクション発火] --> B[FocusPaneArgs から Id 取得]
    B --> C[アクティブタブ取得]
    C --> D[_UnZoomIfNeeded]
    D --> E[Tab::FocusPane paneId]
    E --> F[Pane::FocusPane id - WalkTree]
    F --> G{ペインID が一致?}
    G -->|Yes| H[_FocusFirstChild でフォーカス設定]
    H --> I[Handled = true]
    G -->|No: 全ペイン走査完了| J[Handled = false]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-29-01 | ID不一致時の無操作 | 指定IDに一致するペインが存在しない場合はHandled=false | ID不一致 |
| BR-29-02 | ズーム事前解除 | フォーカス移動前にズームを解除する | ズーム中 |
| BR-29-03 | 親子パスのリセット | フォーカス設定時に全ペインの_parentChildPathをリセットする | 常時 |
| BR-29-04 | フォーカスされたタブのみが対象 | 現在のフォーカスされたタブ内のペインのみが検索対象 | 常時 |

### 計算ロジック

WalkTree で全ペインを走査し、`_id == id` のマッチングを行う。最初にマッチしたペインで走査を終了する。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無操作 | args が null | 何もしない |
| - | 無操作 | アクティブタブが存在しない | 何もしない |
| - | フォーカス失敗 | 指定IDのペインが存在しない | Handled=false |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

WalkTree はO(n)で走査。通常のペイン数では即座に完了する。

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

特になし。

## 備考

- 本アクションは `_senderOrFocusedTab` ではなく `_GetFocusedTabImpl` を使用する。非アクティブタブからのfocusPaneコマンド送信は現在サポートされていない。
- タブ状態の保存と復元において、フォーカス状態の再現に使用される（BuildStartupActions で FocusPaneArgs として保存）。
- コマンドラインの `wt focus-pane` サブコマンドからも呼び出し可能。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ActionArgs.idl | `src/cascadia/TerminalSettingsModel/ActionArgs.idl` | **437-441行目**: FocusPaneArgs クラスの定義。Id (UInt32) プロパティを持つ |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | **1166-1191行目**: `_HandleFocusPane` メソッド。FocusPaneArgsからIdを取得し、アンズーム後にFocusPaneを呼び出す |

**主要処理フロー**:
1. **1171行目**: `FocusPaneArgs` にキャスト
2. **1173行目**: `realArgs.Id()` でペインIDを取得
3. **1186行目**: `_UnZoomIfNeeded()` でズーム解除
4. **1187行目**: `activeTab->FocusPane(paneId)` でフォーカス設定

**読解のコツ**: このハンドラは `_senderOrFocusedTab` ではなく `_GetFocusedTabImpl` を使用している点に注意。コメント（1175-1182行目）でその理由が説明されている。

#### Step 3: Tab層の処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Tab.cpp | `src/cascadia/TerminalApp/Tab.cpp` | **922-934行目**: `FocusPane(id)` メソッド。_changingActivePaneフラグを設定し、ルートペインに委譲 |

**主要処理フロー**:
- **930行目**: `_changingActivePane = true` でフラグ設定
- **931行目**: `_rootPane->FocusPane(id)` に委譲
- **932行目**: `_changingActivePane = false` でフラグ解除

#### Step 4: Pane層のフォーカス設定

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Pane.cpp | `src/cascadia/TerminalApp/Pane.cpp` | **2446-2460行目**: `FocusPane(id)` メソッド。WalkTreeで全ペインを走査し、IDマッチしたペインにフォーカス設定 |

**主要処理フロー**:
- **2449行目**: WalkTree で全ペインの `_parentChildPath` をリセット
- **2451行目**: `_id == id` のマッチングチェック
- **2455行目**: `_FocusFirstChild()` でフォーカスを設定

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

```
TerminalPage::_HandleFocusPane (AppActionHandlers.cpp:1166)
    |
    +-- TerminalPage::_UnZoomIfNeeded
    |
    +-- Tab::FocusPane(id) (Tab.cpp:922)
            |
            +-- Pane::FocusPane(id) (Pane.cpp:2446)
                    |
                    +-- Pane::WalkTree
                    |       +-- _parentChildPath.reset() (全ペイン)
                    |       +-- _id == id チェック
                    |
                    +-- Pane::_FocusFirstChild (マッチしたペイン)
```

### データフロー図

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

FocusPaneArgs ──> Id (UInt32) ──> _HandleFocusPane
                                       |
                               _UnZoomIfNeeded
                                       |
                              Tab::FocusPane(id)
                                       |
                       Pane::FocusPane(id) - WalkTree
                                       |
                            _id == id マッチング
                                       |
                          _FocusFirstChild ──> UI フォーカス更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | _HandleFocusPane アクションハンドラ |
| Tab.cpp | `src/cascadia/TerminalApp/Tab.cpp` | ソース | FocusPane(id) メソッド / BuildStartupActions でのフォーカス保存 |
| Pane.cpp | `src/cascadia/TerminalApp/Pane.cpp` | ソース | FocusPane(id), WalkTree, _FocusFirstChild |
| Pane.h | `src/cascadia/TerminalApp/Pane.h` | ヘッダー | FocusPane 宣言, _id メンバ |
| ActionArgs.idl | `src/cascadia/TerminalSettingsModel/ActionArgs.idl` | IDL | FocusPaneArgs の型定義 |
| ActionArgs.cpp | `src/cascadia/TerminalSettingsModel/ActionArgs.cpp` | ソース | FocusPaneArgs::GenerateName の実装 |
| AppCommandlineArgs.cpp | `src/cascadia/TerminalApp/AppCommandlineArgs.cpp` | ソース | focus-pane コマンドラインサブコマンドの解析 |
