# 通知設計書 7-KeyboardServiceWarningInfoBar

## 概要

本ドキュメントは、Windows Terminal におけるキーボードサービス警告 InfoBar（KeyboardServiceWarningInfoBar）の設計仕様を定義する。Windows の「タッチ キーボードと手書きパネル サービス」（TabletInputService）が無効化されている場合に表示される警告バーである。

### 本通知の処理概要

KeyboardServiceWarningInfoBar は、ユーザーの環境でキーボード入力に必要な Windows サービスが無効化されている場合に、アプリケーション画面上部に警告を表示する InfoBar 通知である。

**業務上の目的・背景**：Windows Terminal はテキスト入力にシステムのキーボードサービス（TabletInputService / TextInputManagementService）を利用する。このサービスが無効化されていると、ターミナルへのキーボード入力が正常に動作しない場合がある。本通知はユーザーに問題の原因を知らせ、サービスの有効化を促すことで入力不能状態の解消を支援する。

**通知の送信タイミング**：アプリケーションのウィンドウがロード完了した時（`_OnLoaded` イベント）に、設定で `InputServiceWarning` が有効であり、かつ `_IsKeyboardServiceEnabled()` が false（サービスが無効）の場合に表示される。

**通知の受信者**：アプリケーションを使用するユーザー自身。ウィンドウ上部の InfoBar 領域に持続的に表示される。

**通知内容の概要**：OS がローカライズしたサービス名を含む警告メッセージ（`KeyboardServiceWarningText` リソース）が、Warning レベルの InfoBar として表示される。閉じるボタン（Dismiss）が付属する。

**期待されるアクション**：ユーザーはメッセージを確認し、Windows の「サービス」管理ツールで TabletInputService を有効化する。または、Dismiss ボタンでメッセージを非表示にする（アプリケーションステートに記録され、再表示されない）。

## 通知種別

アプリ内通知（InfoBar / 警告バー）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（_OnLoaded イベントハンドラ内で直接表示） |
| 優先度 | 高（キーボード入力不能の可能性） |
| リトライ | 無し（一度 Dismiss されると再表示されない） |

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

ウィンドウロード時に自動的にチェックされ、条件を満たすウィンドウに対して表示される。

## 通知テンプレート

### InfoBar の場合

| 項目 | 内容 |
|-----|------|
| UIコントロール | `Microsoft.UI.Xaml.Controls.InfoBar` |
| 名前 | `KeyboardServiceWarningInfoBar` |
| Severity | Warning |
| IsClosable | True |
| IsIconVisible | True |
| CornerRadius | 0 |

### 本文テンプレート

```
Message: {KeyboardServiceDisabledText}
         (例: "タッチ キーボードと手書きパネル サービス が無効になっています。...")
ActionButton: InfoBarDismissButton (x:Uid)
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| KeyboardServiceDisabledText | OS ローカライズされたサービス名を含む警告メッセージ | TerminalPage.KeyboardServiceDisabledText()（Mode=OneWay） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| アプリケーション起動 | TerminalWindow._OnLoaded | InputServiceWarning 設定が true かつ _IsKeyboardServiceEnabled() が false | ウィンドウロード時にサービス状態をチェック |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| InputServiceWarning 設定が false | グローバル設定で警告が無効化されている場合 |
| サービスが有効 | _IsKeyboardServiceEnabled() が true の場合 |
| メッセージが既にDismiss済み | _IsMessageDismissed(InfoBarMessage::KeyboardServiceWarning) が true の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[TerminalWindow._OnLoaded] --> B{InputServiceWarning有効?}
    B -->|No| C[表示スキップ]
    B -->|Yes| D[_IsKeyboardServiceEnabled]
    D --> E{サービス有効?}
    E -->|Yes| C
    E -->|No| F[_root->ShowKeyboardServiceWarning]
    F --> G{メッセージDismiss済み?}
    G -->|Yes| C
    G -->|No| H[FindName でInfoBar取得]
    H --> I[InfoBar.IsOpen = true]
    I --> J[ユーザーが確認]
    J --> K{Dismissボタン押下?}
    K -->|Yes| L[_KeyboardServiceWarningInfoDismissHandler]
    L --> M[_DismissMessage でアプリ状態に記録]
    M --> N[InfoBar.IsOpen = false]
```

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

### 参照テーブル一覧

該当なし（Windows サービス管理 API を使用）

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| ApplicationState（DismissedMessages） | UPDATE | Dismiss 時にメッセージIDを追加 |

#### ApplicationState

| 操作 | 項目 | 更新値 | 備考 |
|-----|------|-------|------|
| UPDATE | DismissedMessages | InfoBarMessage::KeyboardServiceWarning を追加 | アプリケーション状態ファイルに永続化 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| サービスマネージャーオープン失敗 | OpenSCManagerW が失敗した場合 | true を返す（ノイズ低減のため警告を出さない） |
| サービスオープン失敗 | OpenServiceW が失敗した場合 | true を返す |
| サービス名取得失敗 | GetServiceDisplayNameW が失敗した場合 | キー名 "TabletInputService" をそのまま使用 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | ウィンドウロード時に1回のみチェック |

### 配信時間帯

制限なし（アプリケーション起動時に自動チェック）

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

- Windows サービスの状態を照会するために `OpenSCManagerW` / `OpenServiceW` を使用する。権限不足の場合は警告を出さない方向で安全に失敗する。
- サービス名はOS のローカライズ情報から取得されるため、機密情報は含まれない。

## 備考

- Windows 11 では TabletInputService が TextInputManagementService にリネームされた（コード内コメント参照）。`_getTabletServiceName()` 関数で OS ローカライズされたサービス名を取得し、ユーザーに分かりやすい名前で表示する。
- Dismiss 操作はアプリケーション状態（`ApplicationState::SharedInstance().DismissedMessages()`）に永続化され、以降のセッションでは再表示されない。
- `x:Load="False"` が設定されており、必要になるまでXAML要素はロードされない。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ApplicationState.idl | `src/cascadia/TerminalSettingsModel/ApplicationState.idl` | `InfoBarMessage` 列挙型と `DismissedMessages` プロパティの定義 |

**読解のコツ**: InfoBarMessage 列挙型は InfoBar 通知の永続化管理に使われる。DismissedMessages は配列として保持される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TerminalWindow.cpp | `src/cascadia/TerminalApp/TerminalWindow.cpp` | `_OnLoaded()` メソッド（行514-524）。InputServiceWarning 設定チェック、_IsKeyboardServiceEnabled チェック、ShowKeyboardServiceWarning 呼び出し |
| 2-2 | TerminalWindow.cpp | `src/cascadia/TerminalApp/TerminalWindow.cpp` | `_IsKeyboardServiceEnabled()` メソッド（行547-）。Windows サービス API を使用したサービス状態チェック |

**主要処理フロー**:
1. **行517**: `_settings.GlobalSettings().InputServiceWarning()` で設定チェック
2. **行519**: `_IsKeyboardServiceEnabled()` でサービス状態チェック
3. **行522**: `_root->ShowKeyboardServiceWarning()` で InfoBar 表示を要求

#### Step 3: InfoBar 表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `ShowKeyboardServiceWarning()` メソッド（行4426-4434）。Dismiss チェック、FindName、IsOpen 設定 |
| 3-2 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `KeyboardServiceDisabledText()` メソッド（行4484-4489）。メッセージテキスト生成 |
| 3-3 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_getTabletServiceName()` ヘルパー関数（行4443-4475）。OS ローカライズされたサービス名を取得 |
| 3-4 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_KeyboardServiceWarningInfoDismissHandler()`（行4813-4820）。Dismiss 処理 |

#### Step 4: XAML定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | `KeyboardServiceWarningInfoBar` InfoBar の定義（行30-42）。Severity, Message バインディング, ActionButton を確認 |

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

```
TerminalWindow::_OnLoaded() (行514)
    |
    +-- [InputServiceWarning 設定チェック] (行517)
    +-- _IsKeyboardServiceEnabled() (行547)
    |      |
    |      +-- OpenSCManagerW() ... サービスマネージャーを開く
    |      +-- OpenServiceW("TabletInputService") ... サービスを開く
    |      +-- QueryServiceStatus() ... サービス状態を照会
    |
    +-- _root->ShowKeyboardServiceWarning() (行522)
           |
           +-- TerminalPage::ShowKeyboardServiceWarning() (行4426)
                  |
                  +-- _IsMessageDismissed(KeyboardServiceWarning) (行4428)
                  +-- FindName("KeyboardServiceWarningInfoBar") (行4430)
                  +-- InfoBar.IsOpen(true) (行4432)

[ユーザーDismiss時]
_KeyboardServiceWarningInfoDismissHandler() (行4813)
    |
    +-- _DismissMessage(KeyboardServiceWarning) (行4815)
    +-- InfoBar.IsOpen(false) (行4818)
```

### データフロー図

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

_OnLoaded イベント           _IsKeyboardServiceEnabled()          InfoBar 表示
(ウィンドウロード)     --->  サービス状態チェック            --->  Severity: Warning
                             |                                     Message: ローカライズ
_getTabletServiceName()      ShowKeyboardServiceWarning()          されたサービス名を
(OSローカライズ名)    --->   _IsMessageDismissed チェック          含む警告文
                             FindName → IsOpen(true)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | XAML | KeyboardServiceWarningInfoBar のUI定義 |
| TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | ソース | ShowKeyboardServiceWarning, KeyboardServiceDisabledText, Dismiss ハンドラ |
| TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | ソース | ShowKeyboardServiceWarning メソッド宣言 |
| TerminalPage.idl | `src/cascadia/TerminalApp/TerminalPage.idl` | IDL | ShowKeyboardServiceWarning の公開定義 |
| TerminalWindow.cpp | `src/cascadia/TerminalApp/TerminalWindow.cpp` | ソース | _OnLoaded, _IsKeyboardServiceEnabled の実装 |
| ApplicationState.idl | `src/cascadia/TerminalSettingsModel/ApplicationState.idl` | IDL | InfoBarMessage, DismissedMessages の定義 |
