# 機能設計書 68-ウィンドウ名変更UIを開く

## 概要

本ドキュメントは、Windows Terminalにおけるウィンドウ名変更UIを開く機能（OpenWindowRenamer）の設計を記述する。

### 本機能の処理概要

ウィンドウのインライン名前変更ダイアログ（TeachingTip）を表示する機能である。ユーザーはテキストボックスに新しいウィンドウ名を入力し、Enter/Okで確定、Escapeでキャンセルできる。

**業務上の目的・背景**：No.67（RenameWindow）はプログラム的に名前を設定するが、本機能はユーザーがインタラクティブにウィンドウ名を入力・編集するためのUIを提供する。GUIベースでの操作を好むユーザー向けの機能である。

**機能の利用シーン**：ユーザーがコマンドパレットやキーバインドからウィンドウ名変更UIを開き、テキストボックスにウィンドウ名を入力する場面で利用される。

**主要な処理内容**：
1. `_HandleOpenWindowRenamer`ハンドラがTeachingTip（WindowRenamer）を遅延ロードする
2. テーマの更新を行い、LayoutUpdatedイベントを設定してテキストボックスへのフォーカス移動を準備する
3. TeachingTipを開く（`IsOpen(true)`）
4. ユーザーがEnterキーを押すかOkボタンをクリックすると、`_WindowRenamerActionClick`が呼ばれ、`_RequestWindowRename`を実行する
5. Escapeキーで変更をキャンセルし、元の名前に戻す

**関連システム・外部連携**：XAML TeachingTipコントロール（MUX::Controls::TeachingTip）を使用。XAML Islandsでの制限事項あり。

**権限による制御**：特別な権限制御は行わない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | TerminalPage（メイン画面） | 主画面 | _HandleOpenWindowRenamerによりWindowRenamer TeachingTipを表示 |

## 機能種別

UI表示操作 / データ入力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | パラメータなし | - |

ユーザー入力:

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| テキストボックス入力 | winrt::hstring | No | 新しいウィンドウ名 | - |

### 入力データソース

キーバインドアクション（ShortcutAction::OpenWindowRenamer）またはコマンドパレットからのアクション呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| WindowRenamer TeachingTip | UI要素 | ウィンドウ名入力ダイアログ |
| RenameWindowRequested イベント | イベント | ウィンドウ名変更要求（確定時） |

### 出力先

画面上にTeachingTipとして表示。確定時は No.67（ウィンドウ名の変更）と同じパスでウィンドウ名が更新される。

## 処理フロー

### 処理シーケンス

```
1. ユーザーがOpenWindowRenamerアクションを実行
   └─ ActionDispatcherがイベントを発火
2. _HandleOpenWindowRenamer が呼び出される
   └─ WindowRenamer TeachingTip が null なら遅延ロード
3. テーマの更新
   └─ _UpdateTeachingTipTheme()
4. LayoutUpdatedイベントハンドラを設定
   └─ テキストボックスへのフォーカス移動を準備
   └─ 初回は2回目のLayoutUpdated、2回目以降は1回目のLayoutUpdatedでフォーカス
5. WindowRenamer.IsOpen(true) でTeachingTipを開く
6a. [Enter押下時] _WindowRenamerKeyDown/_WindowRenamerKeyUp → _WindowRenamerActionClick
   └─ _RequestWindowRename(newName) で名前変更要求
7a. [Escape押下時] _WindowRenamerKeyUp → 元の名前に戻す
   └─ WindowRenamer.IsOpen(false) で閉じる
```

### フローチャート

```mermaid
flowchart TD
    A[OpenWindowRenamerアクション受信] --> B[_HandleOpenWindowRenamer]
    B --> C{WindowRenamer == null?}
    C -->|Yes| D[FindName で遅延ロード]
    C -->|No| E[テーマ更新]
    D --> E
    E --> F[LayoutUpdatedハンドラ設定]
    F --> G[WindowRenamer.IsOpen=true]
    G --> H[テキストボックスにフォーカス]
    H --> I{ユーザー操作}
    I -->|Enter| J[_WindowRenamerActionClick]
    J --> K[_RequestWindowRename]
    K --> L[RenameWindowRequested.raise]
    I -->|Escape| M[元の名前に戻す]
    M --> N[WindowRenamer.IsOpen=false]
    L --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | 遅延ロード | WindowRenamer TeachingTipは初回使用時にFindNameで遅延ロードされる | 初回表示時 |
| BR-68-02 | フォーカス管理 | 初回は2回目のLayoutUpdated、2回目以降は1回目のLayoutUpdatedでテキストボックスにフォーカスを移動 | TeachingTip開封時 |
| BR-68-03 | Enter/Escapeハンドリング | EnterでKeyDown→KeyUpの両方を追跡して確定、Escapeで変更をキャンセル | キー操作時 |
| BR-68-04 | ContentDialog不使用 | XAML IslandsでContentDialog内のTextBoxがキー入力を受け付けないため、TeachingTipを使用 | 常に適用 |
| BR-68-05 | 閉じた後のフォーカス | TeachingTipが閉じられた後、_FocusActiveControlでターミナルにフォーカスを戻す | TeachingTip閉じ時 |

### 計算ロジック

特別な計算ロジックはない。

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

データベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | - | 名前変更が失敗した場合 | RenameFailed コールバックで通知（No.67と同じ） |

### リトライ仕様

リトライ処理は不要。ユーザーが再度UIを開いて再試行可能。

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

トランザクション管理は不要。

## パフォーマンス要件

TeachingTipの遅延ロードにより初回表示時に若干の遅延が発生する可能性がある。

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

特別なセキュリティ考慮事項はない。

## 備考

- GH#12021: TeachingTipにはOpenedイベントがないため（microsoft/microsoft-ui-xaml#1607）、LayoutUpdatedイベントを使用してフォーカス管理を行う回避策が実装されている。
- `_renamerLayoutCount`変数でLayoutUpdatedの呼び出し回数を追跡し、初回と2回目以降でフォーカスタイミングを調整している。
- `_renamerPressedEnter`フラグにより、コマンドパレットからのEnter keyupが誤ってリネームを確定させることを防止している。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | `_renamerLayoutCount`、`_renamerPressedEnter`などのUI状態管理変数を確認 |

**読解のコツ**: TeachingTipのフォーカス管理は複雑な回避策となっている。コメントにGitHub Issueの参照があるので、背景を理解するのに参照すると良い。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | `_HandleOpenWindowRenamer`（1022-1085行目）のハンドラ実装 |

**主要処理フロー**:
1. **1025-1031行目**: TeachingTipの遅延ロード。`FindName(L"WindowRenamer")`でXAMLからロード
2. **1034行目**: テーマ更新
3. **1060-1078行目**: LayoutUpdatedイベントハンドラの設定。`_renamerLayoutCount`でフォーカスタイミングを制御
4. **1081行目**: `_renamerPressedEnter = false`の初期化
5. **1082行目**: `WindowRenamer().IsOpen(true)`でTeachingTipを開く

#### Step 3: キー入力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_WindowRenamerKeyDown`（4612-4620行目）、`_WindowRenamerKeyUp`（4629-4644行目）のキーイベント処理 |

**主要処理フロー**:
- **4616-4618行目**: `_WindowRenamerKeyDown` - Enter押下時に`_renamerPressedEnter = true`
- **4633-4636行目**: `_WindowRenamerKeyUp` - Enter keyup + `_renamerPressedEnter`で`_WindowRenamerActionClick`呼び出し
- **4638-4643行目**: Escape keyupで元の名前に戻し、TeachingTipを閉じる

#### Step 4: 確定処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_WindowRenamerActionClick`（4576-4581行目）と`_RequestWindowRename`（4583-4600行目） |

**主要処理フロー**:
- **4579-4580行目**: テキストボックスの内容を取得し、`_RequestWindowRename`に渡す
- **4585行目**: `RenameWindowRequestedArgs`を作成
- **4590行目**: `WindowRenamer().IsOpen(false)`でTeachingTipを閉じる
- **4592行目**: `RenameWindowRequested.raise()`でイベント発火

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

```
ActionDispatcher (ShortcutAction::OpenWindowRenamer)
    |
    +-- TerminalPage::_HandleOpenWindowRenamer()     [AppActionHandlers.cpp:1022]
            |
            +-- FindName("WindowRenamer")            (遅延ロード - 初回のみ)
            +-- WindowRenamer().IsOpen(true)          (TeachingTip表示)
            +-- LayoutUpdatedハンドラ
                    |
                    +-- WindowRenamerTextBox().Focus() (フォーカス移動)

ユーザー操作:
    Enter → _WindowRenamerKeyDown() → _WindowRenamerKeyUp()
                                            |
                                            +-- _WindowRenamerActionClick()    [TerminalPage.cpp:4576]
                                                    |
                                                    +-- _RequestWindowRename() [TerminalPage.cpp:4583]
                                                            |
                                                            +-- RenameWindowRequested.raise()
    Escape → _WindowRenamerKeyUp()
                    |
                    +-- WindowRenamer().IsOpen(false)
```

### データフロー図

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

OpenWindowRenamerアクション -> TeachingTip表示 ---------->  WindowRenamer UI

テキストボックス入力       -> _WindowRenamerActionClick -> RenameWindowRequested
(Enter確定)                   _RequestWindowRename()       ウィンドウ名更新

Escape                     -> 元の名前復元 ------------->  TeachingTip閉じ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | _HandleOpenWindowRenamerハンドラ |
| TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | ヘッダー | UI状態管理変数、RenameWindowRequestedイベント |
| TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | ソース | _WindowRenamerActionClick、_WindowRenamerKeyDown/Up、_RequestWindowRename |
| TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | XAML | WindowRenamer TeachingTipとWindowRenamerTextBoxの定義 |
