# 通知設計書 57-NOTIFICATION_OS_IME_UPDATE

## 概要

本ドキュメントは、GodotエンジンにおけるIME（Input Method Engine）入力更新時に発火するNOTIFICATION_OS_IME_UPDATE通知の設計仕様を定義する。

### 本通知の処理概要

NOTIFICATION_OS_IME_UPDATEは、IME（日本語入力、中国語入力などの入力メソッドエンジン）の状態が更新された際に発火するシステム通知である。この通知により、IMEカーソル位置の変更、変換候補文字列の更新、確定文字列の入力などをリアルタイムで検知し、テキスト入力UIを適切に更新することができる。

**業務上の目的・背景**：日本語、中国語、韓国語などのCJK言語圏では、IMEを使用したテキスト入力が一般的である。ゲームやアプリケーションのテキスト入力フィールドでIMEによる入力をサポートするためには、IMEの状態変更を適切に処理し、変換中の文字列（プリエディット）や確定文字列を正しく表示する必要がある。

**通知の送信タイミング**：IMEカーソル位置の変更、変換候補文字列の更新、確定処理など、IMEの状態が変化した時点で発火する。DisplayServerからのIME関連イベント受信時に送信される。

**通知の受信者**：SceneTreeのルートノードから全ての子ノードに対して`propagate_notification`を通じて伝播される。特にLineEditやTextEditなどのテキスト入力コントロールが主な受信者となる。

**通知内容の概要**：通知値2013を持つ整数通知として送信される。追加のパラメータは含まれないが、受信時にDisplayServerのime_get_selection()やime_get_text()で現在のIME状態を取得できる。

**期待されるアクション**：受信者はIMEの現在の状態を取得し、プリエディット文字列の表示更新、変換候補ウィンドウの位置調整、確定文字列のテキストフィールドへの反映などを実行することが期待される。

## 通知種別

エンジン内部通知（Object._notification経由）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | なし |

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

SceneTree::_notification()で受信後、get_root()->propagate_notification()を通じてルートノードから全ての子ノードに伝播される。

## 通知テンプレート

### 通知定数定義

| 項目 | 内容 |
|-----|------|
| 定数名 | NOTIFICATION_OS_IME_UPDATE |
| 値 | 2013 |
| 定義場所 | core/os/main_loop.h（Nodeで再定義） |

### 受信処理例

```gdscript
func _notification(what):
    if what == NOTIFICATION_OS_IME_UPDATE:
        # IME状態を取得
        var ime_text = DisplayServer.ime_get_text()
        var ime_selection = DisplayServer.ime_get_selection()
        # プリエディット文字列を表示
        _update_ime_display(ime_text, ime_selection)

func _update_ime_display(text, selection):
    # 変換中文字列を表示
    $ImePreview.text = text
    # カーソル位置を更新
    $ImePreview.set_caret_position(selection.y)
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| ime_text | IMEテキスト | DisplayServer.ime_get_text() | No |
| ime_selection | IME選択範囲 | DisplayServer.ime_get_selection() | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| システムイベント | IMEプリエディット更新 | 変換中文字列変更時 | IME変換中の文字列が変更された |
| システムイベント | IME確定 | 文字列確定時 | IME変換が確定した |
| システムイベント | IMEカーソル移動 | カーソル位置変更時 | IMEカーソルが移動した |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| IME非アクティブ | IMEが無効な状態 |
| SceneTree未初期化 | ルートノードが存在しない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[OSからIMEイベント受信] --> B[DisplayServer::process_events]
    B --> C{IME状態変更?}
    C -->|Yes| D[MainLoop::notification発火]
    D --> E[SceneTree::_notification]
    E --> F{ルートノード存在?}
    F -->|Yes| G[get_root->propagate_notification]
    G --> H[全ノードへ通知伝播]
    H --> I[テキスト入力コントロール更新]
    I --> J[終了]
    C -->|No| J
    F -->|No| J
```

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

### 参照テーブル一覧

該当なし（データベースを使用しない内部通知）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| IME状態取得失敗 | DisplayServerエラー | 空文字列を返却 |
| ルートノード未存在 | SceneTreeが初期化されていない場合 | 通知をスキップ |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（IME操作に応じて随時発火）

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

- パスワード入力時はIMEプリエディット文字列がマスクされるべき
- IME入力内容はログに記録しないこと

## 備考

- デスクトッププラットフォーム（Windows、macOS、Linux）およびWebプラットフォームで実装
- LineEditとTextEditが主要な受信コントロール
- IME変換中はキー入力イベントの処理が異なる場合がある
- 各プラットフォームでIMEの挙動が若干異なる場合がある

---

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

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

### 推奨読解順序

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

通知の定数値とその定義場所を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | main_loop.h | `core/os/main_loop.h` | NOTIFICATION_OS_IME_UPDATE = 2013 の定義（54行目） |
| 1-2 | node.h | `scene/main/node.h` | Nodeクラスでの再定義（493行目） |

**読解のコツ**: MainLoopで定義された通知定数がNodeクラスで再定義されていることを確認する。

#### Step 2: プラットフォーム固有のIME実装を理解する

各プラットフォームのDisplayServer実装でのIME処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | display_server_windows.cpp | `platform/windows/display_server_windows.cpp` | Windows IME実装 |
| 2-2 | display_server_macos.mm | `platform/macos/display_server_macos.mm` | macOS IME実装 |
| 2-3 | display_server_x11.cpp | `platform/linuxbsd/x11/display_server_x11.cpp` | X11 IME実装 |
| 2-4 | display_server_wayland.cpp | `platform/linuxbsd/wayland/display_server_wayland.cpp` | Wayland IME実装 |
| 2-5 | display_server_web.cpp | `platform/web/display_server_web.cpp` | Web IME実装 |

**主要処理フロー**:
1. OSからのIMEイベント受信
2. IME状態の内部更新
3. MainLoopへの通知発火

#### Step 3: 通知伝播処理を理解する

SceneTreeでの通知処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | scene_tree.cpp | `scene/main/scene_tree.cpp` | _notification()メソッドでのNOTIFICATION_OS_IME_UPDATE処理（912行目） |

#### Step 4: テキスト入力コントロールでの処理を理解する

LineEditとTextEditでのIME処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | line_edit.cpp | `scene/gui/line_edit.cpp` | LineEditでのIME通知処理 |
| 4-2 | text_edit.cpp | `scene/gui/text_edit.cpp` | TextEditでのIME通知処理 |

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

```
OS IME Event
    │
    ├─ [Windows] DisplayServerWindows::_handle_ime_update()
    │
    ├─ [macOS] DisplayServerMacOS::ime_update_callback()
    │
    ├─ [X11] DisplayServerX11::_xim_preedit_changed()
    │
    ├─ [Wayland] DisplayServerWayland::_handle_ime_event()
    │
    └─ MainLoop::notification(NOTIFICATION_OS_IME_UPDATE)
           │
           └─ SceneTree::_notification()
                  │
                  └─ get_root()->propagate_notification()
                         │
                         ├─ LineEdit::_notification()
                         │      └─ IMEプリエディット表示更新
                         │
                         └─ TextEdit::_notification()
                                └─ IMEプリエディット表示更新
```

### データフロー図

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

OS IME        DisplayServer           MainLoop通知
イベント   ───▶ IME処理    ───▶      発火
                      │
                      ▼
                SceneTree
              _notification()
                      │
                      ▼
              全ノードへ伝播
                      │
                      ├───▶ LineEdit IME更新
                      │
                      └───▶ TextEdit IME更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main_loop.h | `core/os/main_loop.h` | ソース | 通知定数の定義 |
| main_loop.cpp | `core/os/main_loop.cpp` | ソース | MainLoopの通知バインド |
| node.h | `scene/main/node.h` | ソース | Nodeクラスでの通知定数再定義 |
| scene_tree.cpp | `scene/main/scene_tree.cpp` | ソース | 通知の伝播処理 |
| display_server_windows.cpp | `platform/windows/display_server_windows.cpp` | ソース | Windows IME実装 |
| display_server_macos.mm | `platform/macos/display_server_macos.mm` | ソース | macOS IME実装 |
| display_server_x11.cpp | `platform/linuxbsd/x11/display_server_x11.cpp` | ソース | X11 IME実装 |
| display_server_wayland.cpp | `platform/linuxbsd/wayland/display_server_wayland.cpp` | ソース | Wayland IME実装 |
| display_server_web.cpp | `platform/web/display_server_web.cpp` | ソース | Web IME実装 |
| line_edit.cpp | `scene/gui/line_edit.cpp` | ソース | LineEditでのIME処理 |
| text_edit.cpp | `scene/gui/text_edit.cpp` | ソース | TextEditでのIME処理 |
| MainLoop.xml | `doc/classes/MainLoop.xml` | ドキュメント | 通知の公式ドキュメント |
