# 機能設計書 233-Shortcut

## 概要

本ドキュメントは、ImGuiライブラリにおけるショートカットキー処理機能「Shortcut」の設計仕様を定義する。

### 本機能の処理概要

Shortcut関数は、キーボードショートカット（キーコード）の検出と処理を行う高度な機能である。IsKeyChordPressed関数と異なり、ショートカットルーティング、フォーカスチェック、キーオーナーシップ管理を統合的に処理する。これにより、複数のウィンドウやウィジェットが同じショートカットを登録しても、適切なコンポーネントにのみショートカットが配信される。

**業務上の目的・背景**：複雑なGUIアプリケーションでは、複数のウィンドウやコンポーネントが同じキーボードショートカットを使用する場合がある。例えば、各エディタウィンドウがCtrl+Sで保存機能を持つ場合、現在フォーカスされているウィンドウのみがショートカットを受け取るべきである。Shortcut関数は、このようなショートカットの競合を解決するためのルーティング機能を提供する。

**機能の利用シーン**：
- アプリケーション全体のキーボードショートカット（ファイル操作、編集操作等）
- ウィンドウ固有のショートカット（ウィンドウを閉じる、タブを切り替える等）
- メニューアイテムのショートカット表示と処理
- コンテキスト依存のショートカット（フォーカスに応じた動作切り替え）
- ナビゲーション操作のショートカット

**主要な処理内容**：
1. ルーティングタイプの決定（デフォルトはImGuiInputFlags_RouteFocused）
2. オーナーIDの自動割り当て（フォーカススコープに基づく）
3. 無効化状態のチェック（ItemFlags_Disabled）
4. ショートカットルーティングの登録と競合解決
5. リピート動作の設定（修飾キー変更まで繰り返し）
6. キーコード押下の判定（IsKeyChordPressed経由）
7. 修飾キーのオーナーシップ設定

**関連システム・外部連携**：ショートカットルーティングシステム、フォーカス管理システム、キーオーナーシップシステムと連携する。

**権限による制御**：フォーカス状態、ルーティング優先度、無効化フラグによりショートカットの有効性が制御される。ImGuiInputFlags_RouteGlobalを使用すると、グローバルショートカットとして登録できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | Inputs | 参照画面 | ショートカットキーのデモ表示 |

## 機能種別

入力処理 / ショートカットルーティング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key_chord | ImGuiKeyChord | Yes | ショートカットキーコード（修飾キー + キー） | なし |
| flags | ImGuiInputFlags | No | ルーティングフラグ（デフォルトは0、ImGuiInputFlags_RouteFocusedが自動設定） | ImGuiInputFlags_SupportedByShortcutでサポート範囲を検証 |
| owner_id | ImGuiID | No | キーオーナーID（デフォルトはImGuiKeyOwner_Any、自動割り当て） | なし |

### 入力フラグの詳細

| フラグ | 説明 |
|--------|------|
| ImGuiInputFlags_Repeat | リピート機能を有効化 |
| ImGuiInputFlags_RouteActive | アクティブアイテムにのみルーティング |
| ImGuiInputFlags_RouteFocused | フォーカスされたウィンドウにルーティング（デフォルト） |
| ImGuiInputFlags_RouteGlobal | グローバルルーティング（フォーカスに関係なく） |
| ImGuiInputFlags_RouteAlways | 常にルーティング（登録なし、直接ポーリング） |
| ImGuiInputFlags_RouteOverFocused | グローバルでフォーカスより優先 |
| ImGuiInputFlags_RouteOverActive | グローバルでアクティブアイテムより優先 |
| ImGuiInputFlags_RouteUnlessBgFocused | 背景フォーカス時は無効 |
| ImGuiInputFlags_Tooltip | ツールチップでショートカット表示 |

### 入力データソース

- ImGuiIO.KeyMods：現在のモディファイアキー状態
- ImGuiIO.KeysData配列：各キーの状態情報
- ImGuiRoutingTable：ショートカットルーティングテーブル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | ショートカットがアクティブ化された場合true、それ以外はfalse |

### 出力先

呼び出し元への戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. パブリックAPI呼び出し（Shortcut(key_chord, flags)）
   └─ owner_idをImGuiKeyOwner_Anyとして内部版を呼び出し

2. ルーティングタイプの設定
   └─ flagsにRouteTypeMask_がない場合、RouteFocusedを設定

3. オーナーIDの自動割り当て
   └─ owner_idがAny/NoOwnerの場合、GetRoutingIdFromOwnerId()で自動割り当て

4. 無効化チェック
   └─ CurrentItemFlags & ImGuiItemFlags_Disabledの場合、false返却

5. ショートカットルーティングの登録
   └─ SetShortcutRouting()でルーティング登録、失敗時はfalse

6. リピート動作の設定
   └─ Repeatフラグがある場合、RepeatUntilKeyModsChangeを設定

7. キーコード押下の判定
   └─ IsKeyChordPressed()で判定、false時はfalse返却

8. 修飾キーのオーナーシップ設定
   └─ SetKeyOwnersForKeyChord()で修飾キーを所有

9. 結果の返却
   └─ trueを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: Shortcut] --> B{RouteTypeMask_が設定?}
    B -->|No| C[flags |= RouteFocused]
    B -->|Yes| D[flagsをそのまま使用]
    C --> E{owner_id == Any/NoOwner?}
    D --> E
    E -->|Yes| F[GetRoutingIdFromOwnerId で自動割り当て]
    E -->|No| G[owner_idをそのまま使用]
    F --> H{ItemFlags_Disabled?}
    G --> H
    H -->|Yes| I[return false]
    H -->|No| J[SetShortcutRouting でルーティング登録]
    J --> K{ルーティング成功?}
    K -->|No| L[return false]
    K -->|Yes| M{Repeat && RepeatUntilMask_なし?}
    M -->|Yes| N[flags |= RepeatUntilKeyModsChange]
    M -->|No| O[flagsをそのまま使用]
    N --> P[IsKeyChordPressed で押下判定]
    O --> P
    P --> Q{押下検出?}
    Q -->|No| R[return false]
    Q -->|Yes| S[SetKeyOwnersForKeyChord で修飾キー所有]
    S --> T[return true]
    I --> U[終了]
    L --> U
    R --> U
    T --> U
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-233-01 | フォーカスルーティングデフォルト | ルーティングタイプ未指定時は、フォーカスされたウィンドウにルーティングする | RouteTypeMask_未設定時 |
| BR-233-02 | 自動オーナー割り当て | owner_id未指定時は、現在のフォーカススコープに基づいて自動割り当てする | owner_id == Any/NoOwner時 |
| BR-233-03 | 無効化アイテム除外 | 無効化されたアイテムはショートカットを受け付けない | ItemFlags_Disabled設定時 |
| BR-233-04 | 修飾キー変更でリピート停止 | Repeatモード時、修飾キーを離すとリピートが停止する | Repeat && RepeatUntilMask_未設定時 |
| BR-233-05 | 修飾キー所有権取得 | ショートカット発動時、関連する修飾キーの所有権を取得する | 常時 |

### 計算ロジック

ショートカット判定ロジック：
```
Shortcut = !Disabled && SetShortcutRouting(成功) && IsKeyChordPressed(key_chord)
```

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

該当なし（メモリ上のキー状態データおよびルーティングテーブルのみ操作）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーションエラー | サポートされていないフラグが指定された場合 | デバッグビルドでアサーション発生 |
| - | 無視 | アイテムが無効化されている場合 | falseを返却して処理継続 |
| - | 無視 | ルーティングに失敗した場合 | falseを返却して処理継続 |

### リトライ仕様

該当なし（毎フレーム呼び出す設計のため）

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

該当なし

## パフォーマンス要件

- 処理時間：O(n)、nはルーティングエントリ数
- 1フレームあたり複数回呼び出し可能
- ルーティングテーブルはフレームごとに再構築

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

該当なし（UIライブラリ内部の入力処理のみ）

## 備考

- IsKeyChordPressedと異なり、ルーティングとフォーカスチェックが組み込まれている
- SetNextItemShortcut()と組み合わせて使用することで、ウィジェットにショートカットを割り当てられる
- macOS環境では、CmdキーとCtrlキーが自動スワップされる

---

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

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

### 推奨読解順序

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

ショートカットルーティングに関連するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiInputFlags_列挙型（1680-1699行目）でルーティングフラグを確認 |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiKeyRoutingData構造体でルーティングデータ構造を確認 |
| 1-3 | imgui_internal.h | `imgui_internal.h` | ImGuiKeyRoutingTable構造体でルーティングテーブルを確認 |

**読解のコツ**: ショートカットルーティングは、同じキーコードに対して複数の登録を管理し、フォーカスやアクティブ状態に基づいて最適な受信者を決定するシステム。

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

パブリックAPI関数の宣言と実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | Shortcut関数の宣言（1086行目） |
| 2-2 | imgui.cpp | `imgui.cpp` | パブリックAPI版の実装（10686-10689行目） |

**主要処理フロー**:
1. **10686-10689行目**: パブリックAPI - owner_idにImGuiKeyOwner_Anyを設定して内部版を呼び出し

#### Step 3: 内部実装を理解する

ショートカット処理の詳細ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | 内部API版Shortcutの実装（10691-10725行目） |
| 3-2 | imgui.cpp | `imgui.cpp` | SetShortcutRouting関数（9643-9680行目）でルーティング登録処理を確認 |
| 3-3 | imgui.cpp | `imgui.cpp` | GetRoutingIdFromOwnerId関数でオーナーID自動割り当てを確認 |

**主要処理フロー**:
- **10697-10698行目**: RouteTypeMask_がない場合、RouteFocusedを設定
- **10702-10703行目**: owner_idがAny/NoOwnerの場合、自動割り当て
- **10705-10706行目**: 無効化チェック
- **10709-10710行目**: SetShortcutRoutingでルーティング登録
- **10714-10715行目**: Repeatフラグ時のRepeatUntilKeyModsChange設定
- **10717-10718行目**: IsKeyChordPressedで押下判定
- **10721行目**: 修飾キーの所有権設定
- **10724行目**: trueを返却

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

```
ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)  [Public - imgui.cpp:10686]
    │
    └─ ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)  [Internal - imgui.cpp:10691]
           │
           ├─ GetRoutingIdFromOwnerId(owner_id)  [条件付き]
           │
           ├─ SetShortcutRouting(key_chord, flags, owner_id)  [imgui.cpp:9643]
           │      │
           │      ├─ FixupKeyChord(key_chord)
           │      │
           │      └─ CalcRoutingScore() / GetShortcutRoutingData()
           │
           ├─ IsKeyChordPressed(key_chord, flags, owner_id)  [imgui.cpp:10636]
           │      │
           │      └─ IsKeyPressed(key, flags, owner_id)
           │
           └─ SetKeyOwnersForKeyChord(key_chord & ImGuiMod_Mask_, owner_id)
```

### データフロー図

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

ImGuiKeyChord key_chord  ───▶ ルーティング登録
ImGuiInputFlags flags          SetShortcutRouting()
                                     │
                                     ▼
                               キーコード押下判定
                               IsKeyChordPressed()
                                     │
                                     ▼
                               修飾キー所有権設定
                               SetKeyOwnersForKeyChord()
                                     │
                                     ▼
                               bool結果を返却        ───▶ 呼び出し元
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | パブリックAPIの宣言、ImGuiInputFlags定義 |
| imgui.cpp | `imgui.cpp` | ソース | Shortcutの実装、ルーティングシステム |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | 内部API、ルーティングデータ構造 |
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | 使用例のデモコード |
