# 通知設計書 33-CharSentEventArgs

## 概要

本ドキュメントは、Windows Terminal における文字入力通知（CharSentEventArgs）の設計仕様を記述する。CharSentEventArgs は、ユーザーが文字を入力した際に TermControl から発火されるイベントであり、入力された文字、スキャンコード、修飾キー状態の情報をブロードキャストする。

### 本通知の処理概要

CharSentEventArgs は、ターミナルコントロールへの文字入力をリスナーにブロードキャストするための通知機構である。KeySentEventArgs がキーの押下/解放を通知するのに対し、CharSentEventArgs は変換済みの文字入力を通知する。

**業務上の目的・背景**：Windows Terminal のブロードキャスト入力機能において、キーイベント（KeySent）だけでなく文字入力イベントも転送する必要がある。Windows のテキスト入力処理では、キー押下とは別に WM_CHAR に相当する文字入力イベントが発生するため、CharSentEventArgs はこの文字入力をブロードキャストする役割を担う。IME（Input Method Editor）を含む多言語入力にも対応する。

**通知の送信タイミング**：TermControl の `_CharacterHandler` メソッド内で、CharacterReceivedRoutedEventArgs を受け取った際に発火する。CharSent イベントにリスナーが登録されている場合のみ、CharSentEventArgs オブジェクトが生成されイベントが発火する。

**通知の受信者**：CharSent イベントをサブスクライブしているリスナー。主にブロードキャスト入力機能を利用するアプリケーション層のコンポーネントが受信する。

**通知内容の概要**：入力文字（Character, wchar_t型）、スキャンコード（ScanCode, WORD型）、修飾キー状態（Modifiers, ControlKeyStates型）の3つの情報を含む。KeySentEventArgs と異なり、KeyDown フラグは含まれない（文字入力は常に「入力」を意味するため）。

**期待されるアクション**：受信側は、受け取った文字入力情報を自身のターミナル接続に転送（RawWriteChar 経由）することで、ブロードキャスト入力を実現する。

## 通知種別

アプリ内通知（WinRT イベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（イベント raise は呼び出し元スレッド上で即時実行） |
| 優先度 | 高（ユーザー入力のリアルタイム処理） |
| リトライ | なし |

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

CharSent イベントにリスナーが登録されているかどうかを `if (CharSent)` で確認し、リスナーがある場合のみ CharSentEventArgs を生成してイベントを発火する。

## 通知テンプレート

### メール通知の場合

該当なし（アプリ内イベント通知）

### 本文テンプレート

該当なし（構造化データとしてイベント引数を伝達）

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Character | 入力された文字（wchar_t） | CharacterReceivedRoutedEventArgs.Character() | Yes |
| ScanCode | ハードウェアスキャンコード（WORD） | KeyStatus.ScanCode | Yes |
| Modifiers | 修飾キー状態（ControlKeyStates） | _GetPressedModifierKeys() + EnhancedKey フラグ | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 文字入力 | _CharacterHandler メソッド呼び出し | CharSent イベントにリスナーが存在する場合 | 文字入力時にブロードキャスト |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| リスナー未登録 | CharSent イベントにリスナーがない場合、オブジェクト生成とイベント発火をスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ユーザーが文字を入力] --> B[_CharacterHandler 呼び出し]
    B --> C[文字、スキャンコード、修飾キー情報を取得]
    C --> D[EnhancedKey フラグ確認・設定]
    D --> E{CharSent リスナー存在?}
    E -->|Yes| F[CharSentEventArgs 生成<br/>Character, ScanCode, Modifiers]
    E -->|No| G[スキップ]
    F --> H[CharSent.raise イベント発火]
    H --> I[RawWriteChar でターミナルに送信]
    G --> I
    I --> J[e.Handled 設定]
```

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

### 参照テーブル一覧

該当なし（インメモリイベント処理のみ）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 特になし | CharSentEventArgs の生成は単純なデータコピーであり失敗しない | - |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（文字入力頻度に依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（文字入力発生時に即座に通知）

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

- 文字入力情報にはパスワード等の機密情報が含まれる可能性があるが、プロセス内のイベント通知であり外部送信は行わない
- ブロードキャスト入力はユーザーが明示的に有効化する機能である

## 備考

- CharSentEventArgs は KeySentEventArgs と対になるイベントであり、キー入力と文字入力の両方をカバーすることでブロードキャスト入力の完全性を確保する
- EnhancedKey フラグは KeyStatus.IsExtendedKey から取得され、拡張キー（矢印キー等）を示す
- _CharacterHandler は XAML の CharacterReceived イベントに対応するハンドラーである

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EventArgs.idl | `src/cascadia/TerminalControl/EventArgs.idl` | CharSentEventArgs の IDL 定義（行139-144）。Character, ScanCode, Modifiers の3プロパティ |
| 1-2 | EventArgs.h | `src/cascadia/TerminalControl/EventArgs.h` | CharSentEventArgs の C++ 実装（行222-233）。コンストラクタで wchar_t, WORD, ControlKeyStates を受け取る |

**読解のコツ**: CharSentEventArgs は KeySentEventArgs と類似構造だが、KeyDown プロパティがない点が異なる。Character は wchar_t 型で Unicode 文字を格納する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | _CharacterHandler メソッド（行1489-1513）。CharacterReceivedRoutedEventArgs から文字とスキャンコードを取得し、CharSent イベントを発火 |

**主要処理フロー**:
1. **行1492**: `e.Character()` で入力文字を取得
2. **行1494**: `keyStatus.ScanCode` でスキャンコードを取得
3. **行1495**: `_GetPressedModifierKeys()` で修飾キー状態を取得
4. **行1497-1499**: `keyStatus.IsExtendedKey` で EnhancedKey フラグを追加
5. **行1504**: `if (CharSent)` でリスナー存在チェック
6. **行1506-1507**: CharSentEventArgs 生成とイベント発火
7. **行1510**: `RawWriteChar` でターミナル接続に入力を送信

#### Step 3: イベント宣言

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TermControl.idl | `src/cascadia/TerminalControl/TermControl.idl` | CharSent イベント宣言（行81）|
| 3-2 | TermControl.h | `src/cascadia/TerminalControl/TermControl.h` | til::typed_event 宣言（行216）|

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

```
XAML CharacterReceived イベント
    |
    +-- TermControl::_CharacterHandler(sender, e)
           |
           +-- e.Character() / keyStatus.ScanCode / _GetPressedModifierKeys()
           |
           +-- [if CharSent リスナー存在]
           |       CharSentEventArgs 生成
           |       CharSent.raise(*this, args)
           |           |
           |           +-- [リスナー側] ブロードキャスト先の RawWriteChar
           |
           +-- RawWriteChar(ch, scanCode, modifiers)
                  |
                  +-- ControlCore::SendCharEvent
```

### データフロー図

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

CharacterReceived            TermControl                     リスナー / ターミナル接続
(character, scanCode,  -->  _CharacterHandler() -------->  CharSent イベント発火
 modifiers)                  CharSentEventArgs生成           -> ブロードキャスト先へ転送
                             RawWriteChar                    -> ControlCore -> Terminal
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EventArgs.idl | `src/cascadia/TerminalControl/EventArgs.idl` | IDL定義 | CharSentEventArgs の WinRT インターフェース定義 |
| EventArgs.h | `src/cascadia/TerminalControl/EventArgs.h` | ソース | CharSentEventArgs の C++ 実装 |
| EventArgs.cpp | `src/cascadia/TerminalControl/EventArgs.cpp` | ソース | WinRT 生成コードのインクルード |
| TermControl.idl | `src/cascadia/TerminalControl/TermControl.idl` | IDL定義 | CharSent イベントの宣言 |
| TermControl.h | `src/cascadia/TerminalControl/TermControl.h` | ソース | CharSent の til::typed_event 宣言 |
| TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | ソース | _CharacterHandler 内での CharSent イベント発火ロジック |
