# 機能設計書 102-Headless

## 概要

本ドキュメントは、Avalonia UIフレームワークにおけるヘッドレスモード機能の機能設計書である。UIなしでのテスト実行環境を提供する。

### 本機能の処理概要

Headlessプラットフォームは、実際のディスプレイやウィンドウシステムを必要とせずにAvalonia UIアプリケーションを実行するための仮想プラットフォームを提供する。主に自動テストやCI/CD環境でのUIテスト実行に使用される。

**業務上の目的・背景**：UIアプリケーションの自動テストは、CIパイプラインでの品質保証に不可欠である。従来、GUIテストは実際のディスプレイ環境を必要としたが、Headlessモードによりサーバー環境やDockerコンテナでもUIテストが可能になる。これにより、テストの自動化・並列化が促進され、開発サイクルが短縮される。

**機能の利用シーン**：
- CIサーバー（GitHub Actions、Azure DevOps等）でのUIテスト実行
- Dockerコンテナ内でのAvaloniaアプリケーションテスト
- ユニットテストフレームワーク（xUnit、NUnit）との統合テスト
- スクリーンショットベースのリグレッションテスト
- パフォーマンステストやメモリリークテスト

**主要な処理内容**：
1. 仮想ウィンドウ（HeadlessWindowImpl）の作成と管理
2. フレームバッファへのオフスクリーンレンダリング
3. 入力イベント（キーボード、マウス）のシミュレーション
4. レンダリング結果のビットマップキャプチャ
5. Dispatcherベースの同期処理
6. 仮想クリップボードとスクリーン情報の提供

**関連システム・外部連携**：
- xUnitテストフレームワーク（Avalonia.Headless.XUnit）
- NUnitテストフレームワーク（Avalonia.Headless.NUnit）
- VNCサーバー（Avalonia.Headless.Vnc）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | HeadlessWindowImpl | 仮想画面 | 仮想ウィンドウとしてレンダリングターゲットを提供 |

## 機能種別

テスト支援 / プラットフォーム統合 / オフスクリーンレンダリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| UseHeadlessDrawing | bool | No | ヘッドレス描画の使用有無 | デフォルトtrue |
| FrameBufferFormat | PixelFormat | No | フレームバッファのピクセルフォーマット | デフォルトRgba8888 |

### 入力データソース

- テストコードからのプログラマティックな入力イベント
- HeadlessWindowExtensionsを通じた入力シミュレーション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| LastRenderedFrame | WriteableBitmap | 最後にレンダリングされたフレームのビットマップ |
| WindowState | WindowState | ウィンドウの状態 |
| ClientSize | Size | クライアント領域のサイズ |

### 出力先

- メモリ上のフレームバッファ
- テストアサーション用のビットマップデータ

## 処理フロー

### 処理シーケンス

```
1. UseHeadless拡張メソッド呼び出し
   └─ AvaloniaHeadlessPlatformOptionsの設定
2. AvaloniaHeadlessPlatform.Initialize実行
   └─ ManagedDispatcherImplの登録
   └─ HeadlessWindowingPlatformの登録
   └─ 仮想デバイス（クリップボード、キーボード等）の登録
3. HeadlessWindowImpl作成
   └─ フレームバッファサーフェスの作成
   └─ マウス/キーボードデバイスの初期化
4. テスト実行
   └─ 入力イベントシミュレーション
   └─ レンダリング処理
   └─ フレームキャプチャ
```

### フローチャート

```mermaid
flowchart TD
    A[UseHeadless] --> B[AvaloniaHeadlessPlatform.Initialize]
    B --> C[サービス登録]
    C --> D[Compositor作成]
    D --> E{テスト実行}
    E --> F[HeadlessWindowImpl.Show]
    F --> G[入力シミュレーション]
    G --> H[ForceRenderTimerTick]
    H --> I[フレームバッファ描画]
    I --> J[GetLastRenderedFrame]
    J --> K[アサーション]
    K --> E
    K --> L[テスト完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-102-1 | フレームレート | デフォルト60FPSでレンダータイマーを動作 | 常時 |
| BR-102-2 | 同期レンダリング | ForceRenderTimerTickで同期的にフレーム更新可能 | テスト時 |
| BR-102-3 | Zオーダー管理 | ウィンドウ表示順序を内部カウンタで管理 | 複数ウィンドウ時 |

### 計算ロジック

特になし。

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EMBED_NOT_SUPPORTED | PlatformNotSupportedException | EmbeddableWindow作成試行 | 通常のCreateWindowを使用 |
| INIT_REQUIRED | InvalidOperationException | 初期化前のサービス使用 | UseHeadless呼び出し確認 |

### リトライ仕様

リトライなし。

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

トランザクションなし。

## パフォーマンス要件

- レンダータイマーはバックグラウンドスレッドで実行しない（RunsInBackground = false）
- フレームバッファは必要時のみ割り当て
- 前回フレームの再利用による効率化

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

- クリップボードはスタブ実装のため実際のシステムクリップボードと分離
- テスト環境の隔離を保証

## 備考

- VNC連携はAvalonia.Headless.Vnc拡張パッケージで提供
- xUnit/NUnit統合は専用パッケージで提供

---

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

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

### 推奨読解順序

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

プラットフォームオプションとインターフェースの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AvaloniaHeadlessPlatform.cs | `src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs` | AvaloniaHeadlessPlatformOptions（110-114行目）でフレームバッファ設定を定義 |
| 1-2 | IHeadlessWindow.cs | `src/Headless/Avalonia.Headless/IHeadlessWindow.cs` | IHeadlessWindowインターフェースで入力シミュレーションメソッドを定義 |

**読解のコツ**: UseHeadlessDrawing=trueでヘッドレス描画サブシステムを使用。FrameBufferFormatでピクセル形式を指定。

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

処理の起点となるプラットフォーム初期化を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AvaloniaHeadlessPlatform.cs | `src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs` | Initialize（76-94行目）でサービス登録、UseHeadless（118-125行目）がAppBuilder拡張 |

**主要処理フロー**:
1. **78-79行目**: クリップボード実装の作成
2. **81-92行目**: AvaloniaLocatorへのサービス登録（Dispatcher、Clipboard、Cursor等）
3. **93行目**: Compositorの作成
4. **89-90行目**: RenderTimerとWindowingPlatformの登録

#### Step 3: ウィンドウ実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | HeadlessWindowImpl.cs | `src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs` | IWindowImpl、IPopupImpl、IFramebufferPlatformSurface、IHeadlessWindowを実装 |

**主要処理フロー**:
- **30-40行目**: コンストラクタでデバイス初期化、デフォルトサイズ1024x768
- **179-219行目**: FramebufferProxyとLockメソッドでフレームバッファ管理
- **223-236行目**: GetLastRenderedFrameで最後の描画結果取得
- **279-357行目**: 入力シミュレーションメソッド群（KeyPress, MouseDown等）

#### Step 4: レンダータイマーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AvaloniaHeadlessPlatform.cs | `src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs` | RenderTimerクラス（19-51行目）でDispatcherTimerベースのレンダリング制御 |

**主要処理フロー**:
- **43-46行目**: コンストラクタでFPS設定
- **48行目**: RunsInBackground = falseでメインスレッド実行
- **50行目**: ForceTick()で強制的なフレーム更新

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

```
UseHeadless (AvaloniaHeadlessPlatformExtensions)
    │
    ├─ UseRenderingSubsystem (HeadlessDrawing時)
    │      └─ HeadlessPlatformRenderInterface.Initialize
    │
    └─ UseWindowingSubsystem
           └─ AvaloniaHeadlessPlatform.Initialize
                  │
                  ├─ ManagedDispatcherImpl登録
                  ├─ HeadlessClipboardImplStub登録
                  ├─ HeadlessCursorFactoryStub登録
                  ├─ KeyboardDevice登録
                  ├─ RenderTimer登録
                  ├─ HeadlessWindowingPlatform登録
                  └─ Compositor作成

HeadlessWindowingPlatform.CreateWindow
    └─ HeadlessWindowImpl (constructor)
           │
           ├─ KeyboardDevice取得
           ├─ HeadlessScreensStub作成
           ├─ MouseDevice作成
           └─ フレームバッファ初期化
```

### データフロー図

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

テストコード ────────────▶ IHeadlessWindow ─────────▶ RawInputEventArgs
(MouseDown等)             (入力シミュレーション)
                                │
                                ▼
ForceRenderTimerTick ────▶ RenderTimer.ForceTick ────▶ レンダリング実行
                                │
                                ▼
                          HeadlessWindowImpl.Lock ────▶ WriteableBitmap
                                │
                                ▼
GetLastRenderedFrame ────▶ フレームバッファ読取 ────▶ テスト検証用画像
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AvaloniaHeadlessPlatform.cs | `src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs` | ソース | プラットフォーム初期化とサービス登録 |
| HeadlessWindowImpl.cs | `src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs` | ソース | 仮想ウィンドウ実装 |
| IHeadlessWindow.cs | `src/Headless/Avalonia.Headless/IHeadlessWindow.cs` | ソース | 入力シミュレーションインターフェース |
| HeadlessPlatformStubs.cs | `src/Headless/Avalonia.Headless/HeadlessPlatformStubs.cs` | ソース | スタブ実装（Clipboard、Cursor、Screen等） |
| HeadlessPlatformRenderInterface.cs | `src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs` | ソース | レンダリングインターフェース |
| HeadlessWindowExtensions.cs | `src/Headless/Avalonia.Headless/HeadlessWindowExtensions.cs` | ソース | ウィンドウ拡張メソッド |
| HeadlessUnitTestSession.cs | `src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs` | ソース | ユニットテストセッション管理 |
| AvaloniaTestApplicationAttribute.cs | `src/Headless/Avalonia.Headless/AvaloniaTestApplicationAttribute.cs` | ソース | テストアプリケーション属性 |
