# 機能設計書 38-libghostty

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおける libghostty（組み込みターミナルエンジン）の設計を定義する。

### 本機能の処理概要

libghostty機能は、Zigで実装されたターミナルコアを外部アプリケーション（macOS/iOS）に組み込むための埋め込みランタイムを提供する。ホストアプリケーションがターミナルエンジンを自身のUIに統合できるようにするC互換APIを提供する。

**業務上の目的・背景**：ネイティブUIフレームワーク（SwiftUI/AppKit）を使用するmacOS/iOSアプリケーションに、Zigで実装された高性能ターミナルエンジンを提供する。これにより、ターミナルコアロジックの再利用性とプラットフォームネイティブなUI体験を両立させる。

**機能の利用シーン**：
- macOSアプリがlibghosttyをターミナルエンジンとして組み込む場合
- iOSアプリがlibghosttyをターミナルエンジンとして組み込む場合
- サードパーティアプリケーションがGhosttyエンジンを利用する場合

**主要な処理内容**：
1. App構造体によるアプリケーション管理
2. Surface構造体による個別ターミナルセッション管理
3. キーイベント、マウスイベントの処理
4. クリップボード操作のコールバック連携
5. Inspector（デバッグ用UI）のサポート

**関連システム・外部連携**：
- macOS SwiftUI/AppKit（TerminalController、TerminalView）
- iOS UIKit
- Metal（レンダリング）
- CoreText（フォント）

**権限による制御**：ホストアプリケーションがコールバック経由で各種機能を制御する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | ターミナルサーフェス管理 |
| 2 | クイックターミナル | 補助画面 | ターミナルサーフェス管理 |

## 機能種別

ライブラリ / 組み込みランタイム

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Options | extern struct | Yes | ランタイム設定（コールバック関数群） | - |
| Surface.Options | extern struct | Yes | サーフェス初期化オプション | - |
| KeyEvent | struct | Yes | キーイベント情報 | - |

### App.Options構造体

```zig
pub const Options = extern struct {
    userdata: ?*anyopaque = null,
    supports_selection_clipboard: bool = false,
    wakeup: *const fn (AppUD) callconv(.c) void,
    action: *const fn (*App, apprt.Target.C, apprt.Action.C) callconv(.c) bool,
    read_clipboard: *const fn (SurfaceUD, c_int, *apprt.ClipboardRequest) callconv(.c) void,
    confirm_read_clipboard: *const fn (...) callconv(.c) void,
    write_clipboard: *const fn (...) callconv(.c) void,
    close_surface: ?*const fn (SurfaceUD, bool) callconv(.c) void = null,
};
```

### Surface.Options構造体

```zig
pub const Options = extern struct {
    platform_tag: c_int = 0,
    platform: Platform.C = undefined,
    userdata: ?*anyopaque = null,
    scale_factor: f64 = 1,
    font_size: f32 = 0,
    working_directory: ?[*:0]const u8 = null,
    command: ?[*:0]const u8 = null,
    env_vars: ?[*]EnvVar = null,
    env_var_count: usize = 0,
    initial_input: ?[*:0]const u8 = null,
    wait_after_command: bool = false,
    context: apprt.surface.NewSurfaceContext = .window,
};
```

### 入力データソース

- ホストアプリケーションからのコールバック
- ユーザー入力（キー、マウス）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | bool | アクション実行結果 |
| - | Surface* | 作成されたサーフェス |

### 出力先

- ホストアプリケーションへのコールバック
- 描画サーフェス（Metal経由）

## 処理フロー

### 処理シーケンス

```
1. アプリケーション初期化
   └─ ghostty_app_new
       ├─ CoreApp.create
       ├─ App.init
       │      ├─ Config.clone
       │      └─ Keymap.init
       └─ App返却
2. サーフェス作成
   └─ ghostty_surface_new
       ├─ App.newSurface
       │      ├─ Surface.init
       │      │      ├─ Platform.init（macOS/iOS判定）
       │      │      ├─ core_app.addSurface
       │      │      └─ core_surface.init
       │      └─ Surface返却
3. イベント処理
   └─ ghostty_surface_key / ghostty_surface_mouse_*
       ├─ イベント変換
       └─ core_surface.xxxCallback
4. アクション実行
   └─ performAction
       ├─ performPreAction（前処理）
       └─ opts.action（ホストへコールバック）
5. 終了処理
   └─ ghostty_app_free
       ├─ App.terminate
       └─ CoreApp.destroy
```

### フローチャート

```mermaid
flowchart TD
    A[ホストアプリ起動] --> B[ghostty_app_new]
    B --> C[CoreApp作成]
    C --> D[App初期化]
    D --> E{サーフェス作成要求?}
    E -->|Yes| F[ghostty_surface_new]
    F --> G[Surface.init]
    G --> H[Platform判定]
    H --> I{macOS?}
    I -->|Yes| J[NSView取得]
    I -->|No| K[UIView取得]
    J --> L[core_surface初期化]
    K --> L
    L --> M[イベントループ]
    M --> N{イベント種別}
    N -->|キー| O[ghostty_surface_key]
    N -->|マウス| P[ghostty_surface_mouse_*]
    N -->|描画| Q[ghostty_surface_draw]
    O --> R[コールバック実行]
    P --> R
    Q --> R
    R --> M
    E -->|No/終了| S[ghostty_app_free]
    S --> T[リソース解放]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-01 | C ABI互換 | extern構造体とcallconv(.c)でC互換API提供 | 常時 |
| BR-38-02 | Platform判定 | macOS(1)/iOS(2)のタグで対象プラットフォームを識別 | サーフェス作成時 |
| BR-38-03 | コールバック必須 | wakeup/action/read_clipboard/write_clipboardは必須 | App初期化時 |
| BR-38-04 | サーフェス独立 | 各Surfaceは独立して動作、複数同時作成可能 | 常時 |
| BR-38-05 | 設定クローン | Configは内部でクローンして保持 | App初期化時 |

### 計算ロジック

特になし。

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | OutOfMemory | メモリ確保失敗 | null返却 |
| - | NSViewMustBeSet | macOSでNSViewが未設定 | エラー返却 |
| - | UIViewMustBeSet | iOSでUIViewが未設定 | エラー返却 |
| - | UnsupportedPlatform | 非対応プラットフォーム | エラー返却 |

### リトライ仕様

リトライは行わない。エラー発生時はホストアプリケーションが処理する。

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

トランザクションは使用しない。

## パフォーマンス要件

- API呼び出しオーバーヘッド: 最小限（C ABI直接呼び出し）
- イベント処理遅延: 1ms以内

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

- クリップボード読み取り確認（confirm_read_clipboard）でセキュリティ確保
- ホストアプリケーションがサンドボックス境界を管理

## 備考

- macOS/iOS両対応のクロスプラットフォームライブラリ
- CoreText/Metalを使用したネイティブレンダリング
- ImGuiベースのInspectorをサポート

---

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

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

### 推奨読解順序

#### Step 1: 組み込みランタイムのエントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | embedded.zig | `src/apprt/embedded.zig` | 組み込みランタイム全体 |

**主要処理フロー**:
- **28-79行目**: App構造体とOptions定義
- **81-116行目**: KeyEvent構造体（キーイベント変換）
- **125-145行目**: App.init関数（初期化処理）
- **147-150行目**: App.terminate関数（終了処理）
- **178-204行目**: App.keyEvent関数（キーイベント処理）
- **265-285行目**: App.performAction関数（アクション実行）

#### Step 2: Platformを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | embedded.zig | `src/apprt/embedded.zig` | Platform union |

**主要処理フロー**:
- **341-397行目**: Platform union定義（macOS/iOS）
- **391-397行目**: PlatformTag enum（プラットフォーム識別）

#### Step 3: Surface構造体を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | embedded.zig | `src/apprt/embedded.zig` | Surface構造体 |

**主要処理フロー**:
- **407-462行目**: Surface構造体とOptions定義
- **464-584行目**: Surface.init関数（サーフェス初期化）
- **586-598行目**: Surface.deinit関数（サーフェス終了）
- **751-763行目**: Surface.refresh/draw（描画制御）
- **809-893行目**: マウス/カーソルコールバック

#### Step 4: Inspector（デバッグUI）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | embedded.zig | `src/apprt/embedded.zig` | Inspector構造体 |

**主要処理フロー**:
- **979-1228行目**: Inspector構造体（ImGuiベース）
- **1002-1018行目**: Inspector.init関数
- **1033-1051行目**: Inspector.initMetal（Metal初期化）
- **1053-1096行目**: Inspector.renderMetal（Metal描画）

#### Step 5: C APIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | embedded.zig | `src/apprt/embedded.zig` | CAPI構造体 |

**主要処理フロー**:
- **1230-2220行目**: CAPI構造体（C API関数群）
- **1386-1410行目**: ghostty_app_new（アプリ作成）
- **1530-1549行目**: ghostty_surface_new/free（サーフェス管理）
- **1751-1762行目**: ghostty_surface_key（キーイベント）
- **2103-2219行目**: Darwin専用API（macOS/iOS固有）

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

```
ghostty_app_new (C API)
    │
    ├─ CoreApp.create
    │      └─ アロケータ設定
    │
    └─ App.init
           ├─ config.clone
           ├─ Keymap.init
           └─ App構造体初期化

ghostty_surface_new (C API)
    │
    └─ App.newSurface
           │
           └─ Surface.init
                  ├─ Platform.init
                  │      ├─ macOS: NSView取得
                  │      └─ iOS: UIView取得
                  │
                  ├─ core_app.addSurface
                  │
                  ├─ apprt.surface.newConfig
                  │
                  └─ core_surface.init
                         ├─ ターミナル初期化
                         ├─ PTY作成
                         └─ レンダラー初期化

ghostty_surface_key (C API)
    │
    └─ App.keyEvent
           │
           ├─ KeyEvent.core (変換)
           │
           └─ target判定
                  ├─ .app: core_app.keyEvent
                  └─ .surface: core_surface.keyCallback

ghostty_app_tick (C API)
    │
    └─ core_app.tick
           ├─ イベント処理
           └─ 描画更新

ghostty_app_free (C API)
    │
    ├─ App.terminate
    │      ├─ keymap.deinit
    │      └─ config.deinit
    │
    └─ CoreApp.destroy
```

### データフロー図

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

ホストアプリ ──────────▶ ghostty_app_new ────────────────▶ App*
                               │
                          Config解析
                               │
ホストアプリ ──────────▶ ghostty_surface_new ────────────▶ Surface*
(Options)                      │
                          Platform判定
                          core_surface初期化
                               │
キーイベント ──────────▶ ghostty_surface_key ────────────▶ bool (consumed)
(KeyEvent)                     │
                          キー変換
                          バインディング処理
                               │
マウスイベント ─────────▶ ghostty_surface_mouse_* ───────▶ bool
                               │
                          イベントコールバック
                               │
wakeupコールバック ────▶ ghostty_app_tick ───────────────▶ 描画更新
                               │
                          core_app.tick
                               │
performAction ─────────▶ opts.action ───────────────────▶ ホストアプリ
                          (コールバック)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| embedded.zig | `src/apprt/embedded.zig` | ソース | 組み込みランタイム（メイン） |
| App.zig | `src/App.zig` | ソース | コアアプリケーション |
| Surface.zig | `src/Surface.zig` | ソース | コアサーフェス |
| apprt.zig | `src/apprt.zig` | ソース | アプリケーションランタイム抽象化 |
| action.zig | `src/apprt/action.zig` | ソース | アクション定義 |
| Config.zig | `src/config/Config.zig` | ソース | 設定構造体 |
| Keymap.zig | `src/input/Keymap.zig` | ソース | キーマップ管理 |
| Ghostty.swift | `macos/Sources/Ghostty/Ghostty.swift` | ソース | Swift側ラッパー |
| TerminalController.swift | `macos/Sources/Features/Terminal/TerminalController.swift` | ソース | ターミナルコントローラー |
| SurfaceView.swift | `macos/Sources/Ghostty/SurfaceView.swift` | ソース | サーフェスビュー |
