# 機能設計書 59-不透明度の調整

## 概要

本ドキュメントは、Windows Terminal における「不透明度の調整」機能の設計を記述する。AdjustOpacity アクションにより、ウィンドウの透明度を調整する機能である。

### 本機能の処理概要

**業務上の目的・背景**：ターミナルウィンドウの透明度（不透明度）をリアルタイムで調整できるようにする。背景のデスクトップやドキュメントを参照しながらターミナル作業を行いたい場合や、視覚的な好みに合わせた透明度設定を可能にする。アクリル効果（Acrylic/Mica）との連携も行う。

**機能の利用シーン**：ユーザーがターミナルウィンドウの背景透過度を変更したい場合に利用する。キーバインドまたはコマンドパレットから AdjustOpacity アクションを実行し、相対値または絶対値で不透明度を指定する。コマンドパレットでのプレビュー機能にも対応。

**主要な処理内容**：
1. ユーザーが AdjustOpacity アクションを実行
2. ActionArgs から AdjustOpacityArgs を取得（Opacity 値と Relative フラグ）
3. ControlCore::AdjustOpacity で相対/絶対モードに応じた不透明度計算
4. _setOpacity で新しい不透明度を設定（0.0f～1.0f にクランプ）
5. アクリル効果の自動制御と TransparencyChanged イベントの発火
6. レンダリングエンジンの透過背景設定を更新

**関連システム・外部連携**：Windows のアクリル/Mica 効果、DirectX レンダリングエンジンの透過背景レンダリング機構と連携する。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | TerminalPage（メイン画面） | 主画面 | _HandleAdjustOpacityによりウィンドウ透明度を調整 |
| 6 | TermControl（ターミナル表示） | 主画面 | AdjustOpacityにより透明度を調整 |

## 機能種別

外観設定操作 / ランタイム設定変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Opacity | Int32 | Yes | 不透明度の値。相対モード時はパーセント増減量、絶対モード時はパーセント値 | 結果が 0.0f～1.0f にクランプ |
| Relative | Boolean | No | true: 現在値に対する相対変更、false: 絶対値での設定 | デフォルト: true |

### 入力データソース

キーバインド設定またはコマンドパレットからの AdjustOpacity アクション。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Handled | bool | 処理結果（_ApplyToActiveControls の戻り値） |
| TransparencyChangedEventArgs | イベント引数 | 新しい不透明度値を含む透明度変更イベント |

### 出力先

ウィンドウの透明度設定が更新される。TransparencyChanged イベントが発火し、ウィンドウコンテナがアクリル/背景設定を更新する。

## 処理フロー

### 処理シーケンス

```
1. TerminalPage::_HandleAdjustOpacity がアクションイベントを受信
   └─ ActionArgs から AdjustOpacityArgs を取得（Opacity, Relative）
2. _ApplyToActiveControls で control.AdjustOpacity(opacity/100.0f, relative) を呼び出し
3. ControlCore::AdjustOpacity(opacityAdjust, relative) が実行される
   ├─ relative=true の場合: AdjustOpacity(opacityAdjust) で相対値として処理
   └─ relative=false の場合: _setOpacity(opacityAdjust) で絶対値として処理
4. 相対値処理: AdjustOpacity(adjustment)
   ├─ adjustment == 0 の場合: 即座に return
   └─ _setOpacity(Opacity() + adjustment) で加算
5. _setOpacity(opacity, focused=true) が実行される
   ├─ clamp(opacity, 0.0f, 1.0f) で範囲制限
   ├─ _runtimeFocusedOpacity に保存
   ├─ _runtimeUseAcrylic の自動判定（透明度 < 1.0f かつ UseAcrylic 設定有効時）
   ├─ _renderEngine->EnableTransparentBackground() で透過設定更新
   ├─ _renderer->NotifyPaintFrame() で再描画通知
   └─ TransparencyChanged イベントを発火
```

### フローチャート

```mermaid
flowchart TD
    A[AdjustOpacity アクション受信] --> B[AdjustOpacityArgs から Opacity/Relative 取得]
    B --> C[Opacity を 100 で除算]
    C --> D[_ApplyToActiveControls]
    D --> E{Relative?}
    E -->|true| F[AdjustOpacity で相対変更]
    E -->|false| G[_setOpacity で絶対設定]
    F --> H{adjustment == 0?}
    H -->|Yes| I[処理スキップ]
    H -->|No| J[_setOpacity: 現在値 + adjustment]
    G --> K[_setOpacity: opacityAdjust]
    J --> L[clamp 0.0f - 1.0f]
    K --> L
    L --> M[_runtimeFocusedOpacity 更新]
    M --> N{透明度 < 1.0 かつ UseAcrylic?}
    N -->|Yes| O[_runtimeUseAcrylic = true]
    N -->|No| P[_runtimeUseAcrylic = false]
    O --> Q[EnableTransparentBackground]
    P --> Q
    Q --> R[NotifyPaintFrame で再描画]
    R --> S[TransparencyChanged イベント発火]
    S --> T[終了]
    I --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-1 | 範囲制限 | 不透明度は 0.0f（完全透明）から 1.0f（完全不透明）にクランプされる | 常時 |
| BR-59-2 | パーセント変換 | ActionArgs の Opacity 値は百分率で指定し、内部では 100 で除算して使用 | 常時 |
| BR-59-3 | 相対/絶対モード | Relative=true で現在値に加算、false で絶対値として設定 | 常時 |
| BR-59-4 | アクリル自動制御 | 不透明度が 1.0 未満かつ UseAcrylic 設定有効時にアクリル効果を有効化 | 透明度変更時 |
| BR-59-5 | ゼロ変更スキップ | 相対モードで adjustment=0 の場合は処理をスキップ | 相対モード時 |
| BR-59-6 | ClearType 制御 | 透過背景時は ClearType から Grayscale アンチエイリアスにフォールバック | 透過背景有効時 |

### 計算ロジック

- 相対モード: `newOpacity = clamp(currentOpacity + (Opacity / 100.0f), 0.0f, 1.0f)`
- 絶対モード: `newOpacity = clamp(Opacity / 100.0f, 0.0f, 1.0f)`
- アクリル判定: `_runtimeUseAcrylic = (newOpacity < 1.0f) && _settings.UseAcrylic()`

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

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | ActionArgs 取得失敗 | AdjustOpacityArgs へのキャストが失敗 | 処理をスキップ |
| なし | レンダーエンジン未初期化 | _renderEngine が null の場合 | 透過設定更新をスキップ |

### リトライ仕様

リトライ処理は不要。

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

_setOpacity 内でレンダリングエンジン操作時に LockForWriting を取得。

## パフォーマンス要件

不透明度変更自体は即座に完了。NotifyPaintFrame による再描画フレーム通知が発生する。

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

特になし。

## 備考

- プレビュー機能は ActionPreviewHandlers.cpp の _PreviewAdjustOpacity で実装されている
- _runtimeFocusedOpacity はフォーカス時の不透明度を保持し、フォーカス状態の遷移時にスムーズな透明度変更に使用される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ActionArgs.idl | `src/cascadia/TerminalSettingsModel/ActionArgs.idl` | AdjustOpacityArgs の定義（Opacity: Int32, Relative: Boolean） |
| 1-2 | EventArgs.h | `src/cascadia/TerminalControl/EventArgs.h` | TransparencyChangedEventArgs の定義 |
| 1-3 | ControlCore.h | `src/cascadia/TerminalControl/ControlCore.h` | _runtimeFocusedOpacity, _runtimeUseAcrylic の宣言 |

**読解のコツ**: AdjustOpacityArgs の Opacity は Int32（パーセント値）だが、内部処理では 100 で除算して 0.0f-1.0f の float として扱う。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | _HandleAdjustOpacity メソッド（1256-1269行目） |

**主要処理フロー**:
1. **1256-1269行目**: AdjustOpacityArgs から Opacity と Relative を取得し、control.AdjustOpacity(opacity/100.0f, relative) を呼び出す

#### Step 3: ControlCore の不透明度調整を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | AdjustOpacity(float, bool) メソッド（2434-2444行目）: 相対/絶対の振り分け |
| 3-2 | ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | AdjustOpacity(float) メソッド（744-752行目）: 相対値加算 |
| 3-3 | ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | _setOpacity メソッド（761-791行目）: 実際の不透明度設定 |

**主要処理フロー**:
- **2434-2444行目**: relative フラグで AdjustOpacity(float) / _setOpacity を呼び分け
- **744-752行目**: adjustment が 0 でないことを確認し、_setOpacity に現在値+adjustment を渡す
- **761-791行目**: clamp、_runtimeFocusedOpacity 更新、_runtimeUseAcrylic 判定、EnableTransparentBackground、TransparencyChanged イベント

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

```
TerminalPage::_HandleAdjustOpacity (AppActionHandlers.cpp:1256)
    │
    ├─ ActionArgs.try_as<AdjustOpacityArgs>() → Opacity, Relative 取得
    │
    └─ _ApplyToActiveControls
           │
           └─ ControlCore::AdjustOpacity(float, bool) (ControlCore.cpp:2434)
                  │
                  ├─ [relative=true] AdjustOpacity(float) (ControlCore.cpp:744)
                  │      │
                  │      └─ _setOpacity(currentOpacity + adjustment)
                  │
                  └─ [relative=false] _setOpacity(opacityAdjust)
                         │
                         ├─ clamp(0.0f, 1.0f)
                         ├─ _runtimeFocusedOpacity 更新
                         ├─ _runtimeUseAcrylic 判定
                         ├─ EnableTransparentBackground()
                         ├─ NotifyPaintFrame()
                         └─ TransparencyChanged.raise()
```

### データフロー図

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

AdjustOpacityArgs     ───▶ TerminalPage                   ───▶ 透明度更新
(Opacity: int,              ::_HandleAdjustOpacity               + アクリル制御
 Relative: bool)                 │                               + 再描画
                                 ├─ Opacity / 100.0f
                                 ▼
                            ControlCore::AdjustOpacity
                                 │
                                 ▼
                            _setOpacity
                                 │
                                 ├─ clamp → 新不透明度
                                 ├─ UseAcrylic 判定 ◀── プロファイル設定
                                 ├─ EnableTransparentBackground ──▶ レンダラー
                                 └─ TransparencyChanged ──────────▶ ウィンドウ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | _HandleAdjustOpacity アクションハンドラー |
| ActionPreviewHandlers.cpp | `src/cascadia/TerminalApp/ActionPreviewHandlers.cpp` | ソース | _PreviewAdjustOpacity プレビュー機能 |
| ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | ソース | AdjustOpacity, _setOpacity の実装 |
| ControlCore.h | `src/cascadia/TerminalControl/ControlCore.h` | ヘッダー | AdjustOpacity メソッド宣言、ランタイム変数 |
| ControlCore.idl | `src/cascadia/TerminalControl/ControlCore.idl` | IDL | AdjustOpacity の IDL 定義 |
| EventArgs.h | `src/cascadia/TerminalControl/EventArgs.h` | ヘッダー | TransparencyChangedEventArgs 定義 |
| ActionArgs.idl | `src/cascadia/TerminalSettingsModel/ActionArgs.idl` | IDL | AdjustOpacityArgs 定義 |
| AllShortcutActions.h | `src/cascadia/TerminalSettingsModel/AllShortcutActions.h` | ヘッダー | AdjustOpacity アクション登録 |
| TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | ソース | TermControl の AdjustOpacity ラッパー |
| ControlInteractivity.cpp | `src/cascadia/TerminalControl/ControlInteractivity.cpp` | ソース | マウスホイールからの AdjustOpacity 呼び出し |
