# 機能設計書 1-新しいタブの作成

## 概要

本ドキュメントは、Windows Terminal における「新しいタブの作成」機能の設計を記述する。ユーザーが新しいターミナルタブを作成し、指定されたプロファイルまたはデフォルトプロファイルでセッションを開始する機能の詳細を定義する。

### 本機能の処理概要

**業務上の目的・背景**：ターミナルアプリケーションにおいて、複数のシェルセッションを同時に管理する必要がある。新しいタブの作成機能は、ユーザーが複数の作業を並行して行えるようにするための基盤機能であり、異なるプロファイル（PowerShell、CMD、WSL等）を使い分けながら効率的に作業を進めることを可能にする。

**機能の利用シーン**：ユーザーが新しいシェルセッションを開始したい場合に利用される。具体的には、タブバーの「+」ボタンのクリック、キーボードショートカット（Ctrl+Shift+T等）、コマンドパレットからの実行、またはコマンドライン引数（`wt new-tab`）による起動時に使用される。ドロップダウンメニューから特定のプロファイルを選択して新しいタブを作成することもできる。

**主要な処理内容**：
1. NewTabアクションの受信とアクション引数（NewTabArgs）の解析
2. プロファイルの解決（指定プロファイルまたはデフォルトプロファイル）
3. ターミナル設定（TerminalSettings）の生成
4. 自動昇格（auto-elevation）の判定と処理
5. ペイン（Pane）の作成とConPTY接続の確立
6. タブオブジェクトの初期化とタブバーへの挿入
7. イベントハンドラの登録とフォーカスの設定

**関連システム・外部連携**：ConPTY（Pseudo Console）を介したシェルプロセスとの接続、プロファイル設定（settings.json）からのプロファイル情報取得、自動昇格時のWindowsのUAC連携がある。

**権限による制御**：プロファイルにelevate設定が含まれる場合、管理者権限への自動昇格が試行される。現在のプロセスが昇格済みの場合は通常どおりタブを作成し、未昇格の場合はUACプロンプトを表示して新しい昇格済みウィンドウでタブを開く。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | TerminalPage（メイン画面） | 主画面 | 新規タブ作成アクション（_HandleNewTab）を処理し、指定プロファイルでタブを開く |
| 2 | TabRowControl（タブ行） | 補助画面 | NewTabButtonのClick（OnNewTabButtonClick）により新しいタブを作成 |

## 機能種別

CRUD操作（タブの作成） / プロセス管理（シェルプロセスの起動）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ContentArgs | INewContentArgs (NewTerminalArgs) | No | 新しいタブの作成パラメータ。プロファイルインデックス、プロファイル名、コマンドライン、開始ディレクトリ等を含む | プロファイルインデックスが有効範囲内であること。無効な場合はS_FALSEを返す |

### 入力データソース

- settings.json: プロファイル設定、デフォルトプロファイル設定
- アクション引数: NewTabArgs経由のContentArgs（プロファイル指定、コマンドライン指定等）
- UIイベント: タブバーの「+」ボタンクリック、キーボードショートカット

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 新規タブ | TerminalApp::Tab | 作成されたタブオブジェクト |
| タブViewItem | MUX::Controls::TabViewItem | タブバーに表示されるUIエレメント |
| TerminalControl | TermControl | ターミナル表示コントロール |

### 出力先

- タブバー（TabView）への新規タブアイテムの追加
- タブ管理リスト（_tabs, _mruTabs）への登録

## 処理フロー

### 処理シーケンス

```
1. _HandleNewTab がアクションイベントを受信
   └─ ActionEventArgs から NewTabArgs を取得
2. 引数の検証
   └─ args が null の場合はデフォルトプロファイルで _OpenNewTab(nullptr) を呼び出し
   └─ args がある場合は _shouldBailForInvalidProfileIndex で有効性チェック
3. _OpenNewTab の実行
   └─ NewTerminalArgs からプロファイルを解決（_settings.GetProfileForArgs）
   └─ プロファイルが null の場合は S_FALSE を返却
4. TerminalSettings の生成
   └─ Settings::TerminalSettings::CreateWithNewTerminalArgs でプロファイル設定を構築
5. 自動昇格の判定
   └─ _maybeElevate で管理者権限が必要か確認
   └─ 昇格が必要な場合は別ウィンドウで開き、S_OK を返却
6. ペインの作成
   └─ _MakePane でペインオブジェクトを作成（ConPTY接続を含む）
7. タブの初期化
   └─ _CreateNewTabFromPane でタブオブジェクトを作成
   └─ _InitializeTab でイベントハンドラ登録、タブバー挿入、フォーカス設定
8. タブ挿入位置の決定
   └─ NewTabPosition 設定に基づき、末尾または現在のタブの後に挿入
```

### フローチャート

```mermaid
flowchart TD
    A[_HandleNewTab 受信] --> B{args が null?}
    B -->|Yes| C[_OpenNewTab nullptr]
    B -->|No| D[NewTabArgs を取得]
    D --> E{プロファイルインデックス有効?}
    E -->|No| F[Handled=false で終了]
    E -->|Yes| C2[_OpenNewTab ContentArgs]
    C --> G[プロファイル解決]
    C2 --> G
    G --> H{プロファイル取得成功?}
    H -->|No| I[S_FALSE 返却]
    H -->|Yes| J[TerminalSettings 生成]
    J --> K{自動昇格が必要?}
    K -->|Yes| L[昇格済みウィンドウで開く]
    K -->|No| M[_MakePane でペイン作成]
    M --> N[_CreateNewTabFromPane]
    N --> O[_InitializeTab]
    O --> P[タブバーに挿入・フォーカス設定]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトプロファイル適用 | 引数が指定されない場合はデフォルトプロファイルで新しいタブを作成する | NewTabArgs が null または ContentArgs が未指定の場合 |
| BR-02 | 無効プロファイルの拒否 | プロファイルインデックスが有効範囲外の場合、タブ作成を行わない | プロファイルインデックスがプロファイル数以上の場合 |
| BR-03 | タブ挿入位置 | NewTabPosition 設定が AfterCurrentTab の場合、現在のフォーカスタブの直後に挿入する。それ以外の場合は末尾に挿入する | 常時 |
| BR-04 | 自動昇格 | プロファイルの elevate 設定が true の場合、管理者権限で新しいウィンドウを開く | elevate が設定されており、現在のプロセスが未昇格の場合 |
| BR-05 | MRUリスト追加 | 新しいタブは常に MRU（Most Recently Used）リストの末尾に追加される | 常時 |

### 計算ロジック

タブ挿入位置の算出：
- `NewTabPosition == AfterCurrentTab` の場合: `insertPosition = currentFocusedTabIndex + 1`
- それ以外の場合: `insertPosition = _tabs.Size()`（末尾）

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

### 操作別データベース影響一覧

本機能はデータベースを使用しない。設定データは settings.json ファイルから読み込まれる。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| S_FALSE | プロファイル未発見 | GetProfileForArgs が null を返した場合 | タブを作成せず S_FALSE を返却 |
| Handled=false | 無効なプロファイルインデックス | _shouldBailForInvalidProfileIndex が true を返した場合 | アクションを未処理として返却 |
| CATCH_RETURN | 例外発生 | _OpenNewTab 内で例外が発生した場合 | HRESULT エラーコードを返却し、ログに記録 |

### リトライ仕様

リトライは行わない。エラー発生時はタブ作成をスキップする。

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

トランザクション管理は不要。タブの作成はメモリ上のオブジェクト操作であり、失敗時は部分的に作成されたオブジェクトが破棄される。

## パフォーマンス要件

タブの作成はユーザー操作に応じた同期処理であり、ConPTY接続の確立を含めて体感上即座に完了する必要がある。プロファイル解決と設定生成は軽量な処理であり、主要なコストはシェルプロセスの起動にある。

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

- 自動昇格（elevate）機能により、UAC プロンプトを経て管理者権限でシェルプロセスを起動可能
- 昇格済みプロセスから非昇格プロセスへの降格はセキュリティ上の制約によりサポートされない（Centennial パッケージの制約）
- プロファイルのコマンドライン設定は信頼された設定ファイル（settings.json）からのみ読み込まれる

## 備考

- NewTab アクションは `ShortcutAction::NewTab` としてアクションマップに登録される
- タブ作成時に TabView::SelectionChanged イベントが発火し、ターミナルコントロールの XAML ツリーへのアタッチが行われる
- タブの初期化（_InitializeTab）では、タブのクローズ要求、アイコン更新、ビジュアルベル等の多数のイベントハンドラが登録される

---

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

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

### 推奨読解順序

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

まず、アクション引数の型定義を把握することで、タブ作成時に渡されるパラメータを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ActionArgs.idl | `src/cascadia/TerminalSettingsModel/ActionArgs.idl` | NewTabArgs の定義。ContentArgs プロパティ（INewContentArgs型）がタブ作成パラメータを保持する |
| 1-2 | ActionArgs.h | `src/cascadia/TerminalSettingsModel/ActionArgs.h` | NewTabArgs の C++ 実装。ContentArgs() メソッドの実装を確認 |

**読解のコツ**: WinRT IDL ファイルは COM ベースのインターフェース定義であり、`runtimeclass` がクラス定義、`{ get; }` がプロパティのゲッターを意味する。`INewContentArgs` はタブ・ペイン作成で共有されるインターフェースである。

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

アクションハンドラが処理の起点となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | _HandleNewTab メソッド（459-478行目）がエントリーポイント |

**主要処理フロー**:
1. **459-461行目**: _HandleNewTab メソッドの定義。IInspectable sender と ActionEventArgs args を受け取る
2. **462-466行目**: args が null の場合、デフォルトプロファイルで _OpenNewTab(nullptr) を呼び出す
3. **467-477行目**: NewTabArgs が存在する場合、プロファイルインデックスの有効性を検証し、_OpenNewTab(realArgs.ContentArgs()) を呼び出す
4. **469-473行目**: _shouldBailForInvalidProfileIndex による無効プロファイルインデックスのチェック

#### Step 3: タブ作成処理を理解する

TabManagement.cpp が実際のタブ作成ロジックを担当する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TabManagement.cpp | `src/cascadia/TerminalApp/TabManagement.cpp` | _OpenNewTab（64-93行目）、_InitializeTab（100-195行目）、_CreateNewTabFromPane（202-211行目） |

**主要処理フロー**:
- **64-93行目**: _OpenNewTab - プロファイル解決、TerminalSettings生成、自動昇格判定、ペイン作成、タブ作成
- **69行目**: `_settings.GetProfileForArgs(newTerminalArgs)` でプロファイルを解決
- **76行目**: `Settings::TerminalSettings::CreateWithNewTerminalArgs` で設定を生成
- **79行目**: `_maybeElevate` で自動昇格の必要性を判定
- **90行目**: `_MakePane` でペインを作成し、`_CreateNewTabFromPane` でタブを作成
- **100-195行目**: _InitializeTab - タブの挿入位置計算、イベントハンドラ登録、TabView への追加
- **105-116行目**: 挿入位置の計算。NewTabPosition::AfterCurrentTab の場合は現在のタブの次に挿入
- **119行目**: `_tabs.InsertAt(insertPosition, *newTabImpl)` でタブリストに挿入
- **120行目**: `_mruTabs.Append(*newTabImpl)` で MRU リストに追加

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

```
_HandleNewTab (AppActionHandlers.cpp:459)
    |
    +-- _OpenNewTab (TabManagement.cpp:64)
    |       |
    |       +-- _settings.GetProfileForArgs() -- プロファイル解決
    |       |
    |       +-- TerminalSettings::CreateWithNewTerminalArgs() -- 設定生成
    |       |
    |       +-- _maybeElevate() -- 自動昇格判定
    |       |
    |       +-- _MakePane() -- ペイン作成（ConPTY接続含む）
    |       |
    |       +-- _CreateNewTabFromPane (TabManagement.cpp:202)
    |               |
    |               +-- winrt::make_self<Tab>(pane) -- タブオブジェクト作成
    |               |
    |               +-- _InitializeTab (TabManagement.cpp:100)
    |                       |
    |                       +-- _GetFocusedTabIndex() -- 挿入位置算出
    |                       +-- _tabs.InsertAt() -- タブリスト挿入
    |                       +-- _mruTabs.Append() -- MRUリスト追加
    |                       +-- _RegisterTabEvents() -- イベント登録
    |                       +-- _tabView.TabItems().InsertAt() -- UI挿入
    |                       +-- _tabView.SelectedItem() -- フォーカス設定
```

### データフロー図

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

ActionEventArgs ---------> _HandleNewTab
  NewTabArgs                 |
    ContentArgs -----------> _OpenNewTab
                              |
settings.json ------------> GetProfileForArgs
  (プロファイル設定)          |
                           CreateWithNewTerminalArgs
                              |
                           _MakePane ---------> Pane
                              |                  |
                           _CreateNewTabFromPane |
                              |                  |
                           _InitializeTab -----> Tab -----> _tabs (タブリスト)
                                                    |-----> _mruTabs (MRUリスト)
                                                    |-----> TabView (UI)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | アクションハンドラ。_HandleNewTab のエントリーポイント |
| TabManagement.cpp | `src/cascadia/TerminalApp/TabManagement.cpp` | ソース | タブ管理ロジック。_OpenNewTab, _InitializeTab, _CreateNewTabFromPane |
| TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | ヘッダー | TerminalPage クラス定義。メソッド宣言とメンバー変数 |
| TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | ソース | TerminalPage の実装。_MakePane 等のユーティリティ |
| ActionArgs.idl | `src/cascadia/TerminalSettingsModel/ActionArgs.idl` | IDL | NewTabArgs の WinRT インターフェース定義 |
| ActionArgs.h | `src/cascadia/TerminalSettingsModel/ActionArgs.h` | ヘッダー | NewTabArgs の C++ 実装 |
| TabRowControl.h | `src/cascadia/TerminalApp/TabRowControl.h` | ヘッダー | タブ行コントロール。「+」ボタンの UI 定義 |
