# 通知設計書 27-CM_SET_WINDOW_SIZE

## 概要

本ドキュメントは、Windows Terminalのコンソールホスト（conhost）におけるCM_SET_WINDOW_SIZEウィンドウメッセージ通知の設計を記述する。スクリーンバッファやビューポートのサイズ変更に伴い、ウィンドウの物理サイズを調整する必要がある際に、メインGUIスレッドでのウィンドウサイズ変更を要求するカスタムWindowsメッセージである。

### 本通知の処理概要

CM_SET_WINDOW_SIZEは、コンソールのスクリーンバッファサイズやビューポートサイズが変更された際に、PostMessageWを使用してウィンドウメッセージキューに投入されるカスタムメッセージである。受信側のウィンドウプロシージャが実際のウィンドウサイズ変更処理を行う。

**業務上の目的・背景**：ターミナルアプリケーションがバッファサイズやビューポートサイズを変更した場合（例: コンソールAPIのSetConsoleWindowInfo呼び出し等）、ウィンドウの物理的なピクセルサイズも対応して変更する必要がある。ウィンドウサイズの変更（SetWindowPos等）はメインGUIスレッドで行う必要があるため、PostMessageWでメッセージキューに要求を投入する。重複送信を防ぐフラグ（CONSOLE_SETTING_WINDOW_SIZE）が設けられている。

**通知の送信タイミング**：SCREEN_INFORMATIONのPostUpdateWindowSizeメソッド内でWindow::PostUpdateWindowSizeが呼び出され、PostMessageWで送信される。ビューポート変更、フォントサイズ変更、Alt Screen Buffer切替等の複数の場面で呼び出される。

**通知の受信者**：コンソールウィンドウのウィンドウプロシージャ（Window::ConsoleWindowProc）。

**通知内容の概要**：ウィンドウサイズ更新要求のシグナルのみ。wParamにはSCREEN_INFORMATIONへのポインタが含まれる。

**期待されるアクション**：ウィンドウプロシージャが_InternalSetWindowSizeを呼び出し、現在のビューポートサイズとフォントサイズに基づいてウィンドウの物理サイズを再計算・適用する。

## 通知種別

ウィンドウメッセージ通知（カスタムWindowsメッセージ: WM_USER + 2）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（PostMessageW） |
| 優先度 | 中 |
| リトライ | 無 |

### 送信先決定ロジック

コンソールウィンドウハンドルに対して直接PostMessageWで送信する。

## 通知テンプレート

### メッセージパラメータ

| 項目 | 内容 |
|-----|------|
| メッセージID | CM_SET_WINDOW_SIZE (WM_USER + 2) |
| wParam | SCREEN_INFORMATIONへのポインタ |
| lParam | 0 |

### 本文テンプレート

```
PostMessageW(GetWindowHandle(), CM_SET_WINDOW_SIZE, (WPARAM)&ScreenInfo, 0)
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| ScreenInfo | 対象スクリーンバッファ | GetScreenInfo() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | SetConsoleWindowInfo等 | CONSOLE_SETTING_WINDOW_SIZEフラグが未設定 | コンソールAPIによるウィンドウサイズ変更 |
| 内部処理 | ビューポート変更（window.cpp） | 同上 | スクロールバー操作等によるビューポート変更 |
| 内部処理 | フォントサイズ変更 | 同上 | フォント変更に伴うウィンドウリサイズ |
| 内部処理 | Alt Screen Buffer切替 | 同上 | Alt Bufferの有効化/無効化 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| CONSOLE_SETTING_WINDOW_SIZE設定済み | 既にウィンドウサイズ変更要求が送信済みの場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[サイズ変更要求] --> B[PostUpdateWindowSize呼び出し]
    B --> C{CONSOLE_SETTING_WINDOW_SIZEフラグ設定済み?}
    C -->|Yes| D[FALSE返却、処理スキップ]
    C -->|No| E[CONSOLE_SETTING_WINDOW_SIZEフラグ設定]
    E --> F[PostMessageW CM_SET_WINDOW_SIZE]
    F --> G[ウィンドウプロシージャで受信]
    G --> H[_InternalSetWindowSize呼び出し]
    H --> I[CONSOLE_SETTING_WINDOW_SIZEフラグクリア]
    I --> J[ウィンドウサイズ計算・適用]
    J --> K[終了]
    D --> K
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| PostMessageW失敗 | ウィンドウが既に破棄されている等 | FALSEを返却 |
| サイズ計算エラー | 無効なスクリーン情報 | _InternalSetWindowSize内でNTSTATUSエラーを返却 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

CONSOLE_SETTING_WINDOW_SIZEフラグにより、前の要求が処理されるまで新しい要求は抑止される。これにより事実上のレート制限が実現される。

### 配信時間帯

制限なし

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

- wParamにSCREEN_INFORMATIONへのポインタが含まれるが、同一プロセス内のウィンドウメッセージであるため外部からのアクセスリスクはない
- ウィンドウサイズ変更は画面表示のみに影響し、データセキュリティへの影響はない

## 備考

- CONSOLE_SETTING_WINDOW_SIZEフラグは重複送信防止のための排他制御メカニズムである
- _InternalSetWindowSizeはフルスクリーンモードまたは最大化モードの場合、ウィンドウサイズ変更をスキップする
- wParamにポインタを渡しているが、受信側の_InternalSetWindowSizeではこのポインタは使用せず、GetScreenInfo()で改めてスクリーン情報を取得する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CustomWindowMessages.h | `src/interactivity/win32/CustomWindowMessages.h` | CM_SET_WINDOW_SIZEの定義（行9: WM_USER + 2） |

#### Step 2: 送信側を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | windowproc.cpp | `src/interactivity/win32/windowproc.cpp` | Window::PostUpdateWindowSize関数（行983-995） |

**主要処理フロー**:
1. **行988**: CONSOLE_SETTING_WINDOW_SIZEフラグのチェック
2. **行993**: フラグを設定
3. **行994**: `PostMessageW(GetWindowHandle(), CM_SET_WINDOW_SIZE, (WPARAM)&ScreenInfo, 0)` で送信

#### Step 3: 受信側を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | windowproc.cpp | `src/interactivity/win32/windowproc.cpp` | CM_SET_WINDOW_SIZEハンドラ（行694-698） |
| 3-2 | window.cpp | `src/interactivity/win32/window.cpp` | _InternalSetWindowSize関数（行570-） |

**主要処理フロー**:
- **windowproc.cpp 行696**: `_InternalSetWindowSize()` を呼び出し
- **window.cpp 行575**: CONSOLE_SETTING_WINDOW_SIZEフラグをクリア
- **window.cpp 行577**: フルスクリーン/最大化モードでないかチェック
- **window.cpp 行583-602**: ビューポートサイズとフォントサイズからウィンドウサイズを計算

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

```
SCREEN_INFORMATION::PostUpdateWindowSize (screenInfo.cpp:736)
    |
    +-- Window::PostUpdateWindowSize (windowproc.cpp:983)
           |
           +-- PostMessageW(CM_SET_WINDOW_SIZE)
                  |
                  +-- Window::ConsoleWindowProc (windowproc.cpp:694)
                         |
                         +-- Window::_InternalSetWindowSize (window.cpp:570)
                                |
                                +-- SetWindowPos() / AdjustWindowRectEx()
```

### データフロー図

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

ビューポート/バッファ     PostUpdateWindowSize           ウィンドウサイズ変更
サイズ変更要求    -----> PostMessageW               ---> SetWindowPos()
                         CM_SET_WINDOW_SIZE               ウィンドウが
                              |                           リサイズされる
                              v
                         _InternalSetWindowSize
                         (フォントサイズ x ビューポートサイズ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CustomWindowMessages.h | `src/interactivity/win32/CustomWindowMessages.h` | ソース（ヘッダ） | CM_SET_WINDOW_SIZEメッセージID定義 |
| windowproc.cpp | `src/interactivity/win32/windowproc.cpp` | ソース（実装） | メッセージ送信（PostUpdateWindowSize）と受信処理 |
| window.cpp | `src/interactivity/win32/window.cpp` | ソース（実装） | _InternalSetWindowSize（実際のリサイズ処理） |
| screenInfo.cpp | `src/host/screenInfo.cpp` | ソース（実装） | PostUpdateWindowSizeの呼び出し元 |
| screenInfo.hpp | `src/host/screenInfo.hpp` | ソース（ヘッダ） | SCREEN_INFORMATIONクラス定義 |
| getset.cpp | `src/host/getset.cpp` | ソース（実装） | コンソールAPI経由のPostUpdateWindowSize呼び出し |
| output.cpp | `src/host/output.cpp` | ソース（実装） | フォント変更等に伴うPostUpdateWindowSize呼び出し |
