# 機能設計書 53-TouchDevice

## 概要

本ドキュメントは、Avaloniaフレームワークにおけるタッチデバイス（TouchDevice）機能の設計仕様を定義する。TouchDeviceは、タッチスクリーン入力イベントの処理、マルチタッチポインターの管理、およびタッチジェスチャーの処理を担当するコア入力処理コンポーネントである。

### 本機能の処理概要

TouchDeviceは、Avaloniaアプリケーションにおけるタッチ入力のハンドリングを一元的に管理するクラスである。プラットフォームから受信した生のタッチイベントを処理し、各タッチポイントに対応するPointerオブジェクトを管理する。マルチタッチ操作やジェスチャー認識と連携し、モバイル・タブレット環境での操作性を提供する。

**業務上の目的・背景**：タッチスクリーンは、モバイルデバイスやタブレット、現代のノートPCにおける主要な入力手段である。TouchDeviceは、クロスプラットフォームで一貫したタッチ入力処理を提供し、開発者がプラットフォーム固有の実装を意識することなくタッチイベントを処理できるようにする。シングルタッチ、マルチタッチ、ピンチズーム、回転などの操作を統一的に実装できる。

**機能の利用シーン**：
- タッチスクリーンでのタップ操作
- ピンチイン・ピンチアウトによるズーム
- 2本指での回転操作
- スワイプによるスクロール
- マルチタッチジェスチャー

**主要な処理内容**：
1. プラットフォームからの生タッチイベント（RawPointerEventArgs）の受信と解析
2. タッチポイントごとのPointerオブジェクト管理（Dictionary<long, Pointer>）
3. TouchBegin/TouchEnd/TouchUpdate/TouchCancelイベントの処理
4. ダブルタップ検出（タップ回数カウント）
5. ジェスチャーレコグナイザーとの連携
6. プライマリポインターの管理（最初のタッチ）

**関連システム・外部連携**：InputManager、GestureRecognizer、Pointerクラスと連携し、入力処理パイプラインを構成する。プラットフォーム層から生イベントを受信する。

**権限による制御**：特になし。すべてのUIコンポーネントがタッチ入力を受信可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 34 | Gestures | 補助機能 | タッチ入力とマルチタッチジェスチャー処理 |

## 機能種別

入力デバイス管理 / イベント処理 / マルチタッチ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| RawPointerEventArgs | RawPointerEventArgs | Yes | 生タッチイベントデータ | nullチェック |

### 入力データソース

- プラットフォーム固有のタッチドライバ（Windows Touch、Android Touch、iOS Touch等）
- InputManager経由で配信される生入力イベント

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| PointerPressedEventArgs | PointerPressedEventArgs | タッチ開始イベント |
| PointerReleasedEventArgs | PointerReleasedEventArgs | タッチ終了イベント |
| PointerEventArgs | PointerEventArgs | タッチ移動イベント |

### 出力先

- ヒットテストで特定されたInputElement（イベント配信先）
- キャプチャされたInputElement（キャプチャ時）

## 処理フロー

### 処理シーケンス

```
1. ProcessRawEvent受信
   └─ RawPointerEventArgsをTouchDeviceが受信
2. デバイス状態チェック
   └─ Handled/Disposedチェック
3. ポインター取得/作成
   └─ RawPointerIdに対応するPointerを取得、なければ新規作成
4. イベント種別判定
   └─ TouchBegin/TouchEnd/TouchUpdate/TouchCancelを判定
5. ターゲット要素決定
   └─ Captured ?? GestureTarget ?? HitTest結果
6. ルーテッドイベント生成・発火
   └─ 各種PointerEventArgsを生成してRaiseEvent
7. ポインター管理
   └─ TouchEnd/TouchCancelでポインター削除・Dispose
```

### フローチャート

```mermaid
flowchart TD
    A[ProcessRawEvent開始] --> B{Handled or Disposed?}
    B -->|Yes| Z[処理終了]
    B -->|No| C{ポインター存在?}
    C -->|No| D{TouchEnd?}
    D -->|Yes| Z
    D -->|No| E[新規Pointer作成]
    E --> F[Capture設定]
    C -->|Yes| G[既存Pointer取得]
    F --> H{イベント種別判定}
    G --> H
    H -->|TouchBegin| I[ダブルタップ判定]
    I --> J[PointerPressedEvent発火]
    H -->|TouchEnd| K[PointerReleasedEvent発火]
    K --> L[Pointer削除・Dispose]
    H -->|TouchUpdate| M[PointerMovedEvent発火]
    H -->|TouchCancel| N[Capture解除]
    N --> O[Pointer削除・Dispose]
    J --> Z
    L --> Z
    M --> Z
    O --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | ポインターID管理 | 各タッチポイントはRawPointerIdで識別 | タッチイベント受信時 |
| BR-53-02 | プライマリポインター | 最初のタッチがプライマリポインターとなる | _pointers.Count == 0 |
| BR-53-03 | マルチタッチ時クリックリセット | 2点目以降のタッチでclickCount=1にリセット | _pointers.Count > 1 |
| BR-53-04 | ダブルタップ判定 | 時間とエリア内での連続タップをカウント | シングルタッチ時 |
| BR-53-05 | TouchCancel処理 | キャプチャ解除とポインター破棄 | OS/プラットフォームからのキャンセル時 |

### 計算ロジック

**ダブルタップ判定**：
- 前回タップ位置からdoubleClickSize範囲内
- 前回タップからdoubleClickTime以内
- シングルタッチの場合のみ判定
- マルチタッチ時はclickCount = 1にリセット

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

### 操作別データベース影響一覧

該当なし（UIフレームワークのためデータベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | 必須パラメータがnull | 呼び出し元でのnullチェック |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- タッチイベント処理は16ms以内（60fps維持のため）
- マルチタッチ時も各ポインターを個別に追跡

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

- タッチ位置情報のログ出力は最小限に抑える
- マルチタッチ情報はプライバシーに配慮した処理

## 備考

- TouchDeviceはPrivateApiとしてマークされており、直接のインスタンス化は非推奨
- トップレベルごとに個別のインスタンスを使用することが推奨
- IDisposable実装により、すべてのポインターの適切な解放をサポート

---

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

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

### 推奨読解順序

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

タッチイベント処理で使用される型定義を先に把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Pointer.cs | `src/Avalonia.Base/Input/Pointer.cs` | Pointerクラスの定義、PointerType.Touch |
| 1-2 | TouchDevice.cs | `src/Avalonia.Base/Input/TouchDevice.cs` | _pointersディクショナリの構造 |

**読解のコツ**: TouchDeviceはDictionary<long, Pointer>でRawPointerIdとPointerの対応を管理。PointerType.Touchで生成されたPointerはタッチ専用となる。

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

タッチ入力処理の開始点を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TouchDevice.cs | `src/Avalonia.Base/Input/TouchDevice.cs` | ProcessRawEventメソッドがエントリーポイント |

**主要処理フロー**:
1. **38-41行目**: ProcessRawEventの入口、Handled/Disposedチェック
2. **43-52行目**: ポインター取得または新規作成ロジック
3. **54-57行目**: ターゲット要素とジェスチャーターゲットの決定

#### Step 3: タッチイベント処理を理解する

各タッチイベント種別の処理ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TouchDevice.cs | `src/Avalonia.Base/Input/TouchDevice.cs` | TouchBegin/End/Update/Cancel処理 |

**主要処理フロー**:
- **59-92行目**: TouchBegin処理
  - **61-66行目**: マルチタッチ時のclickCountリセット
  - **69-86行目**: シングルタッチ時のダブルタップ判定
  - **88-91行目**: PointerPressedEventArgs生成・発火
- **94-113行目**: TouchEnd処理
  - **96行目**: ポインター削除
  - **100-110行目**: ジェスチャーまたは通常イベント発火
- **115-125行目**: TouchCancel処理
  - **120-123行目**: キャプチャ解除、フラグリセット
- **127-143行目**: TouchUpdate処理
  - **135-141行目**: ジェスチャーまたは通常移動イベント発火

#### Step 4: リソース管理を理解する

Disposeパターンとポインター管理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TouchDevice.cs | `src/Avalonia.Base/Input/TouchDevice.cs` | Disposeメソッドとポインター解放 |

**主要処理フロー**:
- **146-155行目**: Disposeメソッド
  - **150-151行目**: ポインター配列コピーとクリア
  - **153-154行目**: 各ポインターのDispose呼び出し

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

```
InputManager.ProcessRawEvent
    │
    └─ TouchDevice.ProcessRawEvent
           │
           ├─ ポインター取得/作成
           │      └─ new Pointer(id, PointerType.Touch, isPrimary)
           │
           ├─ TouchBegin処理
           │      ├─ ダブルタップ判定
           │      └─ target.RaiseEvent(PointerPressedEventArgs)
           │
           ├─ TouchEnd処理
           │      ├─ GestureRecognizer.PointerReleasedInternal
           │      ├─ target.RaiseEvent(PointerReleasedEventArgs)
           │      └─ Pointer.Dispose()
           │
           ├─ TouchUpdate処理
           │      ├─ GestureRecognizer.PointerMovedInternal
           │      └─ target.RaiseEvent(PointerMovedEvent)
           │
           └─ TouchCancel処理
                  ├─ Pointer.Capture(null)
                  └─ Pointer.Dispose()
```

### データフロー図

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

RawPointerEventArgs ───▶ TouchDevice ───▶ PointerPressedEventArgs
  ├─ RawPointerId          ├─ Pointer管理                ├─▶ target.RaiseEvent
  ├─ Position              ├─ ClickCount計算
  ├─ Type (Touch*)         └─ GestureRecognizer連携
  └─ InputModifiers
                                                    PointerReleasedEventArgs
                                                         └─▶ target.RaiseEvent

                                                    PointerEventArgs (Move)
                                                         └─▶ target.RaiseEvent
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TouchDevice.cs | `src/Avalonia.Base/Input/TouchDevice.cs` | ソース | メインクラス、タッチ入力処理 |
| Pointer.cs | `src/Avalonia.Base/Input/Pointer.cs` | ソース | ポインター管理、キャプチャ |
| IPointerDevice.cs | `src/Avalonia.Base/Input/IPointerDevice.cs` | ソース | インターフェース定義 |
| PointerEventArgs.cs | `src/Avalonia.Base/Input/PointerEventArgs.cs` | ソース | ポインターイベント引数基底 |
| PointerPressedEventArgs.cs | `src/Avalonia.Base/Input/PointerPressedEventArgs.cs` | ソース | タッチ開始イベント |
| PointerReleasedEventArgs.cs | `src/Avalonia.Base/Input/PointerReleasedEventArgs.cs` | ソース | タッチ終了イベント |
| PointerPointProperties.cs | `src/Avalonia.Base/Input/PointerPointProperties.cs` | ソース | ポインタープロパティ |
| GestureRecognizer.cs | `src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs` | ソース | ジェスチャー認識基底 |
| InputElement.cs | `src/Avalonia.Base/Input/InputElement.cs` | ソース | ポインターイベント定義 |
