# 機能設計書 123-WPFターミナルコントロール

## 概要

本ドキュメントは、WPFアプリケーションに組み込み可能なターミナルコントロール（Microsoft.Terminal.Wpf）の設計を記述する。本コントロールは、WPFのHwndHostを活用してネイティブターミナルHWNDをホストし、VT100シーケンスの受信・表示およびキーボード・マウス入力の処理を提供する。

### 本機能の処理概要

WPFターミナルコントロールは、WPFアプリケーション内にターミナルエミュレータを埋め込むためのコントロールライブラリである。TerminalControl（UserControl）とTerminalContainer（HwndHost）の2層構造で構成され、ネイティブDLL（Microsoft.Terminal.Control.dll）を通じてターミナルの描画・入力処理を行う。

**業務上の目的・背景**：サードパーティのWPFアプリケーションや社内ツールにターミナル機能を組み込むニーズに応えるためのコンポーネントである。Windows Terminal本体のUWP/WinUIベースのコントロールとは別に、WPFアプリケーション向けに特化したラッパーを提供することで、.NET Framework/WPFエコシステムへのターミナル機能の統合を可能にする。

**機能の利用シーン**：WPFアプリケーション開発者がアプリケーション内にターミナルエミュレータを組み込む場合に使用する。ITerminalConnectionインターフェースを実装したバックエンドと接続することで、シェルプロセスやリモート接続の入出力を表示・操作できる。

**主要な処理内容**：
1. ネイティブターミナルHWNDの作成と管理（HwndHost経由）
2. ITerminalConnectionによるバックエンドとの接続管理
3. キーボード入力（WM_KEYDOWN/WM_KEYUP/WM_CHAR）のターミナルへの転送
4. VTシーケンスの受信と描画
5. テーマ設定（色、フォント、カーソルスタイル）
6. リサイズ処理（自動リサイズ/手動リサイズ）
7. スクロールバーとスクロール制御
8. テキスト選択
9. DPIスケーリング対応
10. UIオートメーション対応

**関連システム・外部連携**：Microsoft.Terminal.Control.dll（ネイティブDLL）とP/Invoke経由で連携する。ITerminalConnectionインターフェースを通じて任意のターミナルバックエンドと接続可能である。

**権限による制御**：特定の権限制御は存在しない。ホストアプリケーションの権限に従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| なし | （WPFホストアプリケーション内） | 主画面 | WPFアプリケーションに組み込まれて使用される |

## 機能種別

UIコンポーネント / ターミナルエミュレーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Connection | ITerminalConnection | Yes | ターミナルバックエンドへの接続 | null設定時はカーソルを非表示にしリセットシーケンスを送信 |
| Theme | TerminalTheme | No | ターミナルの色テーマ（前景色、背景色、選択色、カーソルスタイル、16色カラーテーブル） | - |
| FontFamily | string | No | フォントファミリ名 | - |
| FontSize | short | No | フォントサイズ | - |
| AutoResize | bool | No | 自動リサイズの有効/無効（デフォルト: true） | - |

### 入力データソース

- ITerminalConnection.TerminalOutputイベント：バックエンドからのVTシーケンス出力
- Windowsメッセージ：WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_MOUSEWHEEL等

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Rows | int | 現在のターミナルの行数 |
| Columns | int | 現在のターミナルの列数 |
| TerminalRendererSize | Size | ターミナルレンダラーのピクセルサイズ |
| GetSelectedText() | string | 選択中のテキスト（選択なしの場合は空文字列） |

### 出力先

- ITerminalConnection.WriteInput：ユーザー入力をバックエンドに送信
- ITerminalConnection.Resize：サイズ変更をバックエンドに通知
- TerminalScrolledイベント：スクロール位置の変更通知
- UserScrolledイベント：ユーザースクロール操作の通知

## 処理フロー

### 処理シーケンス

```
1. TerminalControl（UserControl）のインスタンス化
   └─ TerminalContainer（HwndHost）の初期化
2. BuildWindowCore でネイティブターミナルHWNDを作成
   └─ NativeMethods.CreateTerminal でDLLのターミナル生成
   └─ スクロール・書き込みコールバックの登録
3. ITerminalConnectionを設定
   └─ 既存接続の切断、リセットシーケンス送信
   └─ TerminalOutputイベントの購読開始
   └─ Connection.Start() でバックエンドを開始
4. TerminalOutputイベント受信
   └─ NativeMethods.TerminalSendOutput でネイティブ描画
5. キーボード入力のメッセージフック処理
   └─ WM_KEYDOWN/WM_KEYUP → TerminalSendKeyEvent
   └─ WM_CHAR → TerminalSendCharEvent
6. 書き込みコールバック（OnWrite）
   └─ Connection.WriteInput でバックエンドに送信
7. リサイズ処理
   └─ TerminalTriggerResize → Connection.Resize
```

### フローチャート

```mermaid
flowchart TD
    A[TerminalControl生成] --> B[TerminalContainer生成]
    B --> C[BuildWindowCore: ネイティブHWND作成]
    C --> D[コールバック登録]
    D --> E{Connection設定?}
    E -->|Yes| F[既存接続切断・リセット]
    F --> G[TerminalOutput購読開始]
    G --> H[Connection.Start]
    E -->|No| I[カーソル非表示]

    H --> J[TerminalOutput受信]
    J --> K[TerminalSendOutput: 描画]
    K --> L[OnScroll: スクロール通知]

    M[キー入力] --> N{メッセージ種別}
    N -->|WM_KEYDOWN/UP| O[TerminalSendKeyEvent]
    N -->|WM_CHAR| P[TerminalSendCharEvent]

    O --> Q[OnWrite: 入力をバックエンドへ]
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-123-01 | 接続リセット | 新しい接続設定時に、既存接続を切断しリセットシーケンス（\x001bc\x1b]104\x1b\\）を送信する | Connection setter実行時 |
| BR-123-02 | カーソル制御 | 接続がnullの場合はカーソルを非表示（\x1b[?25l）、初回接続時はカーソルを表示（\x1b[?25h） | Connection setter実行時 |
| BR-123-03 | 自動リサイズ | AutoResize=trueの場合、WM_WINDOWPOSCHANGEDでターミナルを自動リサイズする | ウィンドウサイズ変更時 |
| BR-123-04 | リサイズ検証 | リサイズ時に幅・高さ・行数・列数が0の場合はArgumentExceptionをスローする | Resize呼び出し時 |
| BR-123-05 | DPI対応 | DPI変更時にTerminalDpiChangedをネイティブに通知する | OnDpiChanged発火時 |
| BR-123-06 | マージン計算 | AutoResize=falseの場合、レンダラーサイズとコントロールサイズの差分をマージンとして表示する | OnRenderSizeChanged時 |
| BR-123-07 | TSF回避 | TSFのTF_TMAE_CONSOLEフラグがWPFと互換性がないため、AvoidBuggyTSFConsoleFlagsを初期化時に呼び出す | コンストラクタ実行時 |

### 計算ロジック

**マージン計算（CalculateMargins）**：
- width = controlSize.Width - (TerminalRendererSize.Width / DpiScaleX) - scrollbar.ActualWidth
- height = controlSize.Height - (TerminalRendererSize.Height / DpiScaleY)
- 負の値は0にクリップ

**スクロール量計算（TermControl_UserScrolled）**：
- lineDelta = 120 / SystemParameters.WheelScrollLines
- accumulatedDeltaにdeltaを加算し、lineDelta以上の蓄積で行単位スクロール

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

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

データベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ArgumentException | 引数エラー | Resize時に幅・高さが0 | 例外をスロー |
| ArgumentException | 引数エラー | Resize時に行数が0 | 例外をスロー |
| ArgumentException | 引数エラー | Resize時に列数が0 | 例外をスロー |

### リトライ仕様

リトライが必要な処理は存在しない。

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

トランザクション処理は存在しない。

## パフォーマンス要件

- ネイティブDLLによるDirectXベースの描画を使用するため、高いレンダリングパフォーマンスを維持する
- スクロール処理はDispatcher.InvokeAsyncで非同期的にUI更新を行い、UIスレッドのブロッキングを防止する
- DPI変更時は即座にネイティブに通知してレンダリングを更新する

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

- P/Invoke経由でネイティブDLL（Microsoft.Terminal.Control.dll）を呼び出すため、DLLの信頼性が前提となる
- ITerminalConnectionの実装によりバックエンドの入出力が制御されるため、接続先の信頼性はホストアプリケーションの責任範囲である

## 備考

- WPFのHwndHostを使用してネイティブHWNDをホストする設計のため、WPFのレンダリングパイプラインとは独立して描画される
- UIオートメーションはWPFの標準AutomationPeerを無効化し、ネイティブHwndTerminalのUiaProviderに委譲している
- TerminalControlは内部でTermControlAutomationPeerを返し、IsContentElement/IsControlElementをfalseに設定することでUIA木から除外している
- スクロールバーはWPFのScrollBarコントロールで実装されている

---

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

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

### 推奨読解順序

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

まず、ターミナルの接続インターフェース・テーマ定義・イベント引数の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ITerminalConnection.cs | `src/cascadia/WpfTerminalControl/ITerminalConnection.cs` | バックエンド接続インターフェース。Start/WriteInput/Resize/Close/TerminalOutputイベント |
| 1-2 | TerminalTheme.cs | `src/cascadia/WpfTerminalControl/TerminalTheme.cs` | テーマ構造体。DefaultBackground/Foreground/SelectionBackground、CursorStyle列挙型、16色ColorTable |
| 1-3 | TerminalOutputEventArgs.cs | `src/cascadia/WpfTerminalControl/TerminalOutputEventArgs.cs` | バックエンド出力イベント引数。Dataプロパティ |
| 1-4 | NativeMethods.cs | `src/cascadia/WpfTerminalControl/NativeMethods.cs` | P/Invoke宣言。CreateTerminal/TerminalSendOutput/TerminalSendKeyEvent等のネイティブ関数、WindowMessage列挙型、TilSize/WINDOWPOS構造体 |

**読解のコツ**: `TerminalTheme`はStructLayoutAttribute(LayoutKind.Sequential)でマーシャリングされ、ネイティブコードと直接やり取りされる。ColorTableは[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]で16要素固定配列。色はWin32 COLORREF形式（BGR順）である点に注意。

#### Step 2: XAMLレイアウトを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TerminalControl.xaml | `src/cascadia/WpfTerminalControl/TerminalControl.xaml` | 2列Grid構成。TerminalContainer + ScrollBar |

**主要処理フロー**:
- **12-22行目**: Gridレイアウト。左列にTerminalContainer（termContainer）、右列にScrollBar（scrollbar）
- **17行目**: TerminalContainerの宣言（local:TerminalContainer）
- **18-21行目**: ScrollBarの宣言。Scroll="Scrollbar_Scroll"、SmallChange="1"

#### Step 3: HwndHostコンテナを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TerminalContainer.cs | `src/cascadia/WpfTerminalControl/TerminalContainer.cs` | HwndHostを継承したネイティブターミナルホスト。ライフサイクル管理、入力処理、リサイズ |

**主要処理フロー**:
- **32-42行目**: コンストラクタ。AvoidBuggyTSFConsoleFlags呼び出し、MessageHook/GotFocusイベント登録
- **89-121行目**: Connection setter。既存接続の切断、リセットシーケンス送信、新規接続のTerminalOutput購読とStart()呼び出し
- **138-150行目**: SetTheme。ネイティブにテーマ設定を送信し、サイズが有効なら再リサイズ
- **170-188行目**: Resize(Size)。TerminalTriggerResizeでネイティブリサイズ、行列数更新、Connection.Resize呼び出し
- **259-268行目**: WndProc。WM_GETOBJECTをhandled=falseにしてネイティブのUiaProviderに委譲
- **286-304行目**: BuildWindowCore。CreateTerminal、スクロール/書き込みコールバック登録、DPIの初期設定
- **307-311行目**: DestroyWindowCore。DestroyTerminalでクリーンアップ
- **333-414行目**: MessageHook。WM_SETFOCUS/KILLFOCUS/MOUSEACTIVATE/KEYDOWN/KEYUP/CHAR/WINDOWPOSCHANGED/MOUSEWHEEL の処理

#### Step 4: UserControlレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TerminalControl.xaml.cs | `src/cascadia/WpfTerminalControl/TerminalControl.xaml.cs` | UserControlレベルのAPI。テーマ設定、リサイズ、スクロール制御、マージン計算 |

**主要処理フロー**:
- **27-36行目**: コンストラクタ。TerminalScrolled/UserScrolledイベント購読、ScrollBarマウスホイール対応、GotFocusイベント登録
- **81-103行目**: SetTheme。termContainerにテーマ設定を委譲、COLORREF→RGBの変換、外部背景色の設定
- **121-130行目**: ResizeAsync。行・列指定でリサイズしマージン再計算（非同期）
- **137-151行目**: TriggerResize。DPIスケーリングを適用してtermContainerのResizeを呼び出し
- **154-165行目**: OnCreateAutomationPeer。TermControlAutomationPeerを返し、UIA木から自身を除外
- **168-195行目**: OnRenderSizeChanged。DPIスケーリングを適用しtermContainerのサイズを更新、AutoResize=falseならマージン計算
- **202-235行目**: CalculateMargins。TerminalRendererSizeとcontrolSizeの差分からマージンを算出
- **248-266行目**: TermControl_UserScrolled。スクロール量を蓄積し行単位で変換、Dispatcher.InvokeAsyncでUI更新
- **268-277行目**: TermControl_TerminalScrolled。ScrollBarのMinimum/Maximum/Value/ViewportSizeを更新

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

```
TerminalControl (UserControl) [TerminalControl.xaml.cs]
    |
    +-- TerminalContainer (HwndHost) [TerminalContainer.cs]
    |       |
    |       +-- NativeMethods (P/Invoke) [NativeMethods.cs]
    |       |       |
    |       |       +-- Microsoft.Terminal.Control.dll (ネイティブDLL)
    |       |               |
    |       |               +-- CreateTerminal / DestroyTerminal
    |       |               +-- TerminalSendOutput
    |       |               +-- TerminalSendKeyEvent / TerminalSendCharEvent
    |       |               +-- TerminalTriggerResize / TerminalCalculateResize
    |       |               +-- TerminalSetTheme / TerminalSetFocused / TerminalDpiChanged
    |       |               +-- TerminalGetSelection / TerminalIsSelectionActive
    |       |               +-- TerminalUserScroll
    |       |               +-- TerminalRegisterScrollCallback / TerminalRegisterWriteCallback
    |       |
    |       +-- ITerminalConnection (接続インターフェース) [ITerminalConnection.cs]
    |               |
    |               +-- Start / WriteInput / Resize / Close
    |               +-- TerminalOutput イベント
    |
    +-- ScrollBar (WPF標準コントロール)
```

### データフロー図

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

ITerminalConnection     ───>  TerminalContainer           ───>  ネイティブHWND
 .TerminalOutput               .Connection_TerminalOutput        (描画)
                                |
                                +-- TerminalSendOutput

キーボード入力          ───>  TerminalContainer           ───>  ITerminalConnection
(WM_KEYDOWN/CHAR等)            .MessageHook                      .WriteInput
                                |
                                +-- TerminalSendKeyEvent
                                +-- TerminalSendCharEvent
                                    |
                                    +-- OnWrite callback

スクロール操作          ───>  TerminalControl             ───>  ScrollBar更新
(WM_MOUSEWHEEL)                .TermControl_UserScrolled          |
                                |                                  +-- scrollbar.Value
                                +-- TerminalUserScroll

テーマ設定              ───>  TerminalControl             ───>  ネイティブ再描画
(SetTheme呼び出し)             .SetTheme                          |
                                |                                  +-- Resize
                                +-- TerminalSetTheme
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TerminalControl.xaml | `src/cascadia/WpfTerminalControl/TerminalControl.xaml` | XAML | UserControlのレイアウト定義（Grid + ScrollBar） |
| TerminalControl.xaml.cs | `src/cascadia/WpfTerminalControl/TerminalControl.xaml.cs` | ソース | UserControlのコードビハインド。テーマ設定、リサイズ、スクロール制御 |
| TerminalContainer.cs | `src/cascadia/WpfTerminalControl/TerminalContainer.cs` | ソース | HwndHostのサブクラス。ネイティブHWND管理、入力処理、接続管理 |
| ITerminalConnection.cs | `src/cascadia/WpfTerminalControl/ITerminalConnection.cs` | ソース | バックエンド接続インターフェース定義 |
| NativeMethods.cs | `src/cascadia/WpfTerminalControl/NativeMethods.cs` | ソース | P/Invoke宣言（Microsoft.Terminal.Control.dll） |
| TerminalTheme.cs | `src/cascadia/WpfTerminalControl/TerminalTheme.cs` | ソース | テーマ構造体・カーソルスタイル列挙型の定義 |
| TerminalOutputEventArgs.cs | `src/cascadia/WpfTerminalControl/TerminalOutputEventArgs.cs` | ソース | バックエンド出力イベント引数 |
| WpfTerminalControl.csproj | `src/cascadia/WpfTerminalControl/WpfTerminalControl.csproj` | プロジェクト | C#プロジェクトファイル |
| stylecop.json | `src/cascadia/WpfTerminalControl/stylecop.json` | 設定 | StyleCop設定ファイル |
