# 通知設計書 14-キーシーケンス通知

## 概要

本ドキュメントは、Ghosttyターミナルエミュレーターにおける「キーシーケンス通知」機能の設計を記載するものである。マルチキーシーケンスバインディングが開始、継続、または停止した際にUIに通知を送信し、ユーザーにシーケンスキーモード中であることを視覚的に示す機能について詳述する。

### 本通知の処理概要

**業務上の目的・背景**：キーシーケンス通知は、Vimライクなマルチキーバインディング（例：`Ctrl+A` → `C`でタブを閉じる）の状態をユーザーに伝達するために実装されている。キーシーケンスは複数のキー入力の組み合わせで特定のアクションを実行する機能であり、ユーザーがシーケンスの途中にいることを明示的に示すことで、入力待ち状態であることを理解しやすくする。これにより、ユーザーは次に押すべきキーを認識し、意図しない入力を避けることができる。

**通知の送信タイミング**：キーシーケンスの状態が変化したタイミングでトリガーされる。具体的には以下の3つのケースがある：
1. シーケンスの開始時（リーダーキーが押された時）
2. シーケンスの継続時（中間キーが押された時）
3. シーケンスの終了時（最終キーが押された、タイムアウトした、またはキャンセルされた時）

**通知の受信者**：当該ターミナルサーフェスを管理するアプリケーションランタイム（macOS/GTK等）が受信者となる。受信したランタイムは、キーシーケンスオーバーレイの表示・更新・非表示を行い、ユーザーに現在のシーケンス状態を視覚的にフィードバックする。

**通知内容の概要**：通知にはKeySequence unionが含まれ、「trigger」（シーケンス進行中）または「end」（シーケンス終了）の状態を示す。triggerの場合は、現在のトリガー情報（キー、修飾キーなど）が含まれる。

**期待されるアクション**：ユーザーは表示されたオーバーレイを参考に、次のキーを押すか、Escapeキー等でシーケンスをキャンセルする。UIはtrigger通知を受けてオーバーレイを表示・更新し、end通知を受けてオーバーレイを非表示にする。

## 通知種別

アプリ内通知（UIオーバーレイ表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（キー入力処理内で直接呼び出し） |
| 優先度 | 高（ユーザー入力への即時フィードバック） |
| リトライ | 無し |

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

通知は、キー入力を受け取ったサーフェスに対応するアプリケーションランタイムに送信される。performAction関数を通じてkey_sequenceアクションとして処理される。

## 通知テンプレート

### オーバーレイ表示の場合

| 項目 | 内容 |
|-----|------|
| 種別 | キーシーケンスオーバーレイ |
| 状態 | trigger（進行中）/ end（終了） |
| 表示内容 | 押されたキーの組み合わせ |

### 本文テンプレート

```
[triggerの場合]
Ctrl+A [待機中...]

[複数キー押下の場合]
Ctrl+A → G [待機中...]

[endの場合]
（オーバーレイ非表示）
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルはサポートしない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| active | シーケンスがアクティブかどうか | KeySequence union tag | Yes |
| trigger | 現在のトリガー情報 | input.Trigger | triggerの場合Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| キー入力 | リーダーキー押下 | キーバインディングのシーケンスにマッチ | シーケンス開始通知 |
| キー入力 | 中間キー押下 | 既存シーケンスの継続にマッチ | シーケンス継続通知 |
| キー入力 | 最終キー押下 | シーケンスが完了 | シーケンス終了通知 |
| タイムアウト | シーケンスタイムアウト | 一定時間キー入力なし | シーケンス終了通知 |
| キャンセル | end_key_sequenceアクション | ユーザーによるキャンセル | シーケンス終了通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| global/allフラグ付き | グローバルバインディングやallフラグ付きバインディングはシーケンスにできない |
| performAction失敗 | アプリランタイムへの通知失敗時は警告ログ出力のみ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[キー入力受信] --> B[keyCallback処理]
    B --> C{バインディング検索}
    C -->|シーケンスマッチ| D{リーダー/中間キー?}
    C -->|マッチなし| E[通常入力処理]
    D -->|Yes| F[key_sequence trigger通知]
    D -->|No| G[アクション実行]
    F --> H[UIオーバーレイ表示]
    G --> I[key_sequence end通知]
    I --> J[UIオーバーレイ非表示]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | データベースは使用しない |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | データベースは使用しない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| performAction失敗 | アプリランタイムエラー | 警告ログ出力、処理続行 |
| 無効なシーケンス | global/allフラグ付きシーケンス | InvalidFormat エラーを返す |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（キー入力ベース） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（キー入力時に即座に処理）

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

- キーシーケンス情報は入力内容を含むため、画面共有やスクリーンキャプチャ時に表示される
- セキュア入力モード中のキーシーケンス表示については、機密入力の漏洩に注意が必要

## 備考

- KeySequence unionはC ABI互換の構造体（C）を持ち、libghosttyとの相互運用性を確保
- macOSではKeyStateIndicator SwiftUIコンポーネントでオーバーレイを表示
- GTKではKeyStateOverlay Zigクラスでオーバーレイを表示
- シーケンスのタイムアウトは設定により調整可能

---

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

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

### 推奨読解順序

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

キーシーケンス通知のデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | action.zig | `src/apprt/action.zig` | KeySequence union定義（行770-786）を確認 |
| 1-2 | Binding.zig | `src/input/Binding.zig` | Trigger構造体の定義を確認 |

**読解のコツ**: KeySequence unionは`trigger`と`end`の2つのバリアントを持ち、C ABI互換のためのC構造体を内包している。

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

キーシーケンス通知が発生する処理の入口を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Surface.zig | `src/Surface.zig` | key_sequence通知の送信箇所（行2888-2894, 3087-3093） |

**主要処理フロー**:
1. **行2888-2894**: シーケンス開始/継続時のtrigger通知
2. **行3087-3093**: シーケンス終了時のend通知

#### Step 3: バインディングパーサーを理解する

シーケンスバインディングの解析処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Binding.zig | `src/input/Binding.zig` | Parser.next関数でのleader/binding判定（行189-200） |

**主要処理フロー**:
- **行196-197**: global/allフラグ付きシーケンスはエラー
- **行197**: リーダーキーの場合はleaderを返す

#### Step 4: UI実装を理解する

各プラットフォームでのオーバーレイ表示を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SurfaceView.swift | `macos/Sources/Ghostty/Surface View/SurfaceView.swift` | KeyStateIndicator（行132-135） |
| 4-2 | key_state_overlay.zig | `src/apprt/gtk/class/key_state_overlay.zig` | GTKでのオーバーレイ実装 |

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

```
キー入力イベント
    |
    +-- Surface.keyCallback() [Surface.zig]
           |
           +-- キーバインディング検索
           |
           +-- シーケンスマッチ?
                  |
                  +-- [Yes] performAction(.key_sequence, .trigger)
                  |            |
                  |            +-- [macOS] KeyStateIndicator更新
                  |            +-- [GTK] KeyStateOverlay更新
                  |
                  +-- [シーケンス完了/キャンセル]
                         |
                         +-- performAction(.key_sequence, .end)
                                |
                                +-- オーバーレイ非表示
```

### データフロー図

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

キー入力           --->  バインディング検索   --->   マッチ結果
                              |
                              v
                         シーケンス判定
                         (leader/final)
                              |
                              v
                         performAction
                         (key_sequence)
                              |
                              +--> trigger通知     --->   オーバーレイ表示
                              |
                              +--> end通知         --->   オーバーレイ非表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| action.zig | `src/apprt/action.zig` | ソース | KeySequence型とkey_sequenceアクション定義 |
| Surface.zig | `src/Surface.zig` | ソース | キー入力処理とシーケンス通知送信 |
| Binding.zig | `src/input/Binding.zig` | ソース | バインディングパーサーとシーケンス処理 |
| SurfaceView.swift | `macos/Sources/Ghostty/Surface View/SurfaceView.swift` | ソース | macOS UIとKeyStateIndicator |
| key_state_overlay.zig | `src/apprt/gtk/class/key_state_overlay.zig` | ソース | GTKオーバーレイ実装 |
| surface.zig | `src/apprt/gtk/class/surface.zig` | ソース | GTKサーフェス実装 |
