# 通知設計書 37-NOTIFICATION_FOCUS_ENTER

## 概要

本ドキュメントは、GodotエンジンのControlクラスにおけるNOTIFICATION_FOCUS_ENTER通知の設計仕様を記載する。この通知はUIコントロールがキーボードフォーカスを取得した際に発火され、フォーカス状態の視覚的表示やキーボード入力の受け入れ開始を可能にする重要なイベントである。

### 本通知の処理概要

NOTIFICATION_FOCUS_ENTERは、Controlノードがキーボードフォーカスを取得した際に発行される通知である。この通知により、フォーカスリングの描画、キーボードショートカットの有効化、テキスト入力の準備などが可能になる。

**業務上の目的・背景**：アクセシビリティとキーボード操作において、フォーカス状態の管理は極めて重要である。視覚的なフォーカスインジケータはスクリーンリーダーユーザーやキーボードユーザーにとって必須であり、Tab/Shift+Tabキーでのフォーカス移動に応じたUI更新を実現するためにこの通知が使用される。

**通知の送信タイミング**：grab_focus()メソッドの呼び出し、Tab/Shift+Tabキーによるフォーカス移動、マウスクリックによるフォーカス取得時に発火される。focus_modeがFOCUS_NONEの場合はフォーカスを取得できない。

**通知の受信者**：focus_modeがFOCUS_CLICKまたはFOCUS_ALLに設定されたControlノード。LineEdit、TextEdit、Button、OptionButton、SpinBox、Slider、Treeなどのインタラクティブ要素が主な受信者。

**通知内容の概要**：通知値は43（NOTIFICATION_FOCUS_ENTER = 43）として定義され、コントロールがキーボードフォーカスを取得したことを示す。

**期待されるアクション**：受信ノードはフォーカス状態の外観を適用する。典型的な処理として、フォーカスリングの描画、カーソルの表示、キーボードイベントの受け入れ準備がある。通知後には「focus_entered」シグナルとqueue_redraw()が呼び出される。

## 通知種別

ゲームエンジン内部通知（Object._notificationで受信）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（フォーカス変更時に即座に発行） |
| 優先度 | 高（アクセシビリティに必須） |
| リトライ | なし（一度のみ発行） |

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

1. focus_modeがFOCUS_NONEでないこと
2. grab_focus()が呼び出されるか、Tab/Shift+Tab/クリックでフォーカス取得
3. ノードが可視でツリー内に存在すること
4. 上記条件を満たすControlノードに対してnotification()が呼び出される

## 通知テンプレート

### 内部通知の場合

| 項目 | 内容 |
|-----|------|
| 通知定数名 | NOTIFICATION_FOCUS_ENTER |
| 通知値 | 43 |
| 逆順送信 | false（通常順） |
| 形式 | 整数値（int p_what） |

### 本文テンプレート

```cpp
// _notification()での受信例
void MyLineEdit::_notification(int p_what) {
    switch (p_what) {
        case NOTIFICATION_FOCUS_ENTER: {
            // フォーカスを取得した
            caret_visible = true;
            // フォーカス状態の描画に切り替え
            queue_redraw();
        } break;
    }
}

// GDScriptでの例
func _notification(what):
    if what == NOTIFICATION_FOCUS_ENTER:
        # フォーカス取得時の処理
        $FocusRing.visible = true
```

### 添付ファイル

該当なし（内部通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| p_what | 通知種別 | notification()引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プログラム呼び出し | grab_focus() | focus_mode != FOCUS_NONE | コードからのフォーカス取得 |
| Tab移動 | Tabキー押下 | focus_mode == FOCUS_ALL | 次のフォーカス可能コントロールへ |
| Shift+Tab移動 | Shift+Tabキー押下 | focus_mode == FOCUS_ALL | 前のフォーカス可能コントロールへ |
| マウスクリック | マウスボタン押下 | focus_mode == FOCUS_CLICK or FOCUS_ALL | クリックによるフォーカス取得 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| focus_mode=NONE | FOCUS_NONE設定時はフォーカス不可 |
| 非可視 | visible=falseの場合はフォーカス不可 |
| ツリー外 | シーンツリー外のノードはフォーカス不可 |
| 既にフォーカス中 | 同一コントロールへの再フォーカスでは発火しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[フォーカス取得要求] --> B{focus_mode確認}
    B -->|FOCUS_NONE| C[処理終了]
    B -->|FOCUS_CLICK/ALL| D{可視性・ツリー確認}
    D -->|No| C
    D -->|Yes| E{既にフォーカス中?}
    E -->|Yes| C
    E -->|No| F[前のコントロールにFOCUS_EXIT通知]
    F --> G[新コントロールにFOCUS_ENTER通知]
    G --> H[派生クラス_notification処理]
    H --> I[focus_enteredシグナル発行]
    I --> J[queue_redraw呼び出し]
    J --> C
```

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

### 参照テーブル一覧

該当なし（ゲームエンジン内部処理のためデータベースは使用しない）

### テーブル別参照項目詳細

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| フォーカス不可 | focus_modeがNONEで呼び出し | grab_focus()は何もしない |
| 無効なノード | 削除予定ノードへのフォーカス | 有効性チェック |
| 循環フォーカス | フォーカスチェーンが循環 | 次/前フォーカス検索で制限 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（ユーザー操作に依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

エンジン実行中、フォーカス変更時に発火。

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

エンジン内部通知のため、外部からの直接的なセキュリティリスクはない。ただし、悪意のあるスクリプトがフォーカスを強制的に奪うことでユーザー入力を傍受する可能性に注意。

## 備考

- NOTIFICATION_FOCUS_EXIT（値44）とペアで使用される
- focus_modeの値：FOCUS_NONE(0)、FOCUS_CLICK(1)、FOCUS_ALL(2)
- マウス/タッチ入力によるフォーカス取得では視覚的なフォーカスインジケータは表示されない（アクセシビリティ考慮）
- _notification()処理後にfocus_enteredシグナルとqueue_redraw()が呼び出される（control.cpp 3944-3947行目）

---

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

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

### 推奨読解順序

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

まず、Controlクラスの構造と通知定数の定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | control.h | `scene/gui/control.h` | NOTIFICATION_FOCUS_ENTER = 43定義（429行目）、FocusMode enum（80-84行目） |

**読解のコツ**: 値43はControl固有の通知定数。FocusModeの設定がフォーカス取得可否に影響する。

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

フォーカス取得のメカニズムを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | control.cpp | `scene/gui/control.cpp` | grab_focus()メソッド |
| 2-2 | control.cpp | `scene/gui/control.cpp` | _notification() NOTIFICATION_FOCUS_ENTER処理（3944-3947行目） |

**主要処理フロー**:
- **3945行目**: emit_signal(SceneStringName(focus_entered))
- **3946行目**: queue_redraw()

#### Step 3: 派生クラスでの処理例を理解する

LineEditなどの派生クラスでの具体的な処理パターンを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | line_edit.cpp | `scene/gui/line_edit.cpp` | NOTIFICATION_FOCUS_ENTER処理（キャレット表示） |
| 3-2 | text_edit.cpp | `scene/gui/text_edit.cpp` | NOTIFICATION_FOCUS_ENTER処理（編集モード開始） |
| 3-3 | base_button.cpp | `scene/gui/base_button.cpp` | NOTIFICATION_FOCUS_ENTER処理 |

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

```
Control::grab_focus() / Tab移動 / クリック
    │
    └─ Viewport::gui_focus()
           │
           ├─ 前コントロール::notification(FOCUS_EXIT)
           │
           └─ 新コントロール::notification(FOCUS_ENTER)
                  │
                  └─ Control::_notification(NOTIFICATION_FOCUS_ENTER)
                         │
                         ├─ emit_signal("focus_entered")
                         │
                         └─ queue_redraw()
```

### データフロー図

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

grab_focus() ───▶ Viewport処理 ───▶ notification(43)
Tab/クリック          │                     │
                      ├─ focus_mode確認     ├─▶ 派生クラス処理
                      │                     │    (フォーカス状態)
                      └─ フォーカス管理     ├─▶ "focus_entered"シグナル
                                            │
                                            └─▶ queue_redraw()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| control.h | `scene/gui/control.h` | ヘッダ | Controlクラス定義、NOTIFICATION定数 |
| control.cpp | `scene/gui/control.cpp` | ソース | grab_focus()、_notification()実装 |
| viewport.cpp | `scene/main/viewport.cpp` | ソース | フォーカス管理、通知発行 |
| line_edit.cpp | `scene/gui/line_edit.cpp` | ソース | 行エディタでの通知処理例 |
| text_edit.cpp | `scene/gui/text_edit.cpp` | ソース | テキストエディタでの通知処理例 |
| base_button.cpp | `scene/gui/base_button.cpp` | ソース | ボタンでの通知処理例 |
| spin_box.cpp | `scene/gui/spin_box.cpp` | ソース | スピンボックスでの通知処理例 |
| tree.cpp | `scene/gui/tree.cpp` | ソース | ツリーでの通知処理例 |
| item_list.cpp | `scene/gui/item_list.cpp` | ソース | アイテムリストでの通知処理例 |
| Control.xml | `doc/classes/Control.xml` | ドキュメント | 公式APIドキュメント |
