技術仕様・設計

キー拡張機能アーキテクチャ技術解説書 (Key Extension Architecture)

本書は、fjFlow のキー拡張機能(Key Extension)を構成するステートマシンエンジン、タイマー制御、および出力パイプラインの技術アーキテクチャを解説するドキュメントです。...

決定論的 4-State FSM、文字順序逆転防止、0ms即時リマップを支える内部アーキテクチャ

本書は、fjFlow のキー拡張機能(Key Extension)を構成するステートマシンエンジン、タイマー制御、および出力パイプラインの技術アーキテクチャを解説するドキュメントです。


目次


1. コア設計思想:判定フェーズと出力フェーズの完全分離

キー拡張エンジンは、「判定フェーズ」 と 「出力フェーズ」 を完全に分離して設計されています。

┌────────────────────────────────────────────────────────┐
│ 1. 判定フェーズ (FSM Engine)                           │
│   ・純粋な物理キー打鍵イベント & タイムスタンプを受信  │
│   ・修飾ロックやレイヤーのリアルタイム変化を遮断       │
│   ・押下瞬間のレイヤースナップショット (downCond) 保持 │
│   ・完全一致 / 前方一致 / 静寂成立を決定論的に判定     │
└──────────────────────────┬─────────────────────────────┘
                           │ 確定 (Execute / Flush)
┌──────────────────────────▼─────────────────────────────┐
│ 2. 出力フェーズ (Output Pipeline)                      │
│   ・保持されたレイヤースナップショットでターゲット実行 │
│   ・修飾キーロック (Ctrl/Alt/Win/Shift) を合成適用     │
│   ・{Blind} モードによる OS アトミック送信             │
└────────────────────────────────────────────────────────┘

ユーザーがキーを打鍵した直後に修飾キー(Space 等)を離した場合でも、押下時のスナップショット(g_FsmKey1Cond)に基づいて評価されるため、レイヤーの戻りによる誤出力を100%防止します。


2. 決定論的 4-State FSM (状態遷移マシン) の動作モデル

エンジンは、以下の4状態をもつ決定論的ステートマシンによって駆動されます。

  • STATE_READY: 初期待機状態。保留中のキーがない状態。
  • STATE_WAIT_HOLD: 長押し判定待ち状態(前段静寂後にキーが押し続けられるのを待機)。
  • STATE_WAIT_NEXT: 次キー / 静寂単打待ち状態(シーケンスの1打目が保留され、次キーまたはタイムアウトを待機)。
  • STATE_WAIT_POST_SILENCE: 後段静寂待ち状態(最長一致に達し、高速な後続打鍵がないか確認するために一息を待機)。
stateDiagram-v2
    [*] --> STATE_READY

    state STATE_READY {
        [*] --> Idle
    }

    STATE_READY --> STATE_READY : ① a (通常単打)<br/>0ms 即時リマップ実行
    STATE_READY --> STATE_READY : ② タイピング中 (前段静寂なし)<br/>通常キー出力
    STATE_READY --> STATE_WAIT_HOLD : ③ 前段静寂成立 + <a>(長押し定義)<br/>長押しタイマー起動 (holdMs)
    STATE_READY --> STATE_WAIT_NEXT : ④ 前段静寂成立 + [a](静寂単打) / シーケンス<br/>1打目を保留 (comboMs)

    state STATE_WAIT_HOLD {
        [*] --> HoldWaiting
    }

    STATE_WAIT_HOLD --> STATE_READY : ⑤ holdMs 経過 (押し続けた)<br/>長押しターゲット確定実行!
    STATE_WAIT_HOLD --> STATE_READY : ⑥ holdMs 未満で KeyUp (離した)<br/>長押しキャンセル ➔ 単打処理
    STATE_WAIT_HOLD --> STATE_READY : ⑦ holdMs 未満で別キー入力<br/>直ちにキャンセル ➔ 保留キーフラッシュ

    state STATE_WAIT_NEXT {
        [*] --> Pending
    }

    STATE_WAIT_NEXT --> STATE_WAIT_NEXT : ⑧ 前方一致あり (例: 'us' in 'usa')<br/>キー追加保留 (Timer: Nx ms)
    STATE_WAIT_NEXT --> STATE_WAIT_POST_SILENCE : ⑨ 最長完全一致到達 (例: 'usa')<br/>後段静寂待ち (Timer: Nx ms)
    STATE_WAIT_NEXT --> STATE_READY : ⑩ タイムアウト (手を止めた)<br/>[a] 単打 / 中間候補を実行
    STATE_WAIT_NEXT --> STATE_READY : ⑪ コンボ不一致 / 時間切れ<br/>保留キーを順次 Raw 出力

    state STATE_WAIT_POST_SILENCE {
        [*] --> PostSilenceWait
    }

    STATE_WAIT_POST_SILENCE --> STATE_READY : ⑫ 後段静寂成立 (手を止めた)<br/>ターゲット (例: '米国') を確定実行!
    STATE_WAIT_POST_SILENCE --> STATE_READY : ⑬ 後続キー高速打鍵 (例: 'usaa')<br/>後段静寂破綻!全キー Raw 出力

    STATE_WAIT_HOLD --> STATE_READY : ⑭ Shift Up<br/>小文字 Raw フラッシュ
    STATE_WAIT_NEXT --> STATE_READY : ⑭ Shift Up<br/>小文字 Raw フラッシュ
    STATE_WAIT_POST_SILENCE --> STATE_READY : ⑭ Shift Up<br/>小文字 Raw フラッシュ

3. 可変長シーケンスと文字数スケーリングタイマーの仕組み

文字数 $N$ に応じてタイマー待機時間を自動調整するスケーリングアルゴリズムです。

$$\text{判定時間} = N \times x \text{ (ms)}$$

  • 基本間隔 $x = 300\text{ms}$ の場合:
    • 1文字: $300\text{ms}$(単打判定)
    • 2文字: $600\text{ms}$(hh, eq 等の2文字コンボ)
    • 3文字: $900\text{ms}$(usa 等の3文字コンボ)
  • 長いシーケンスほど入力猶予が自然に広がり、焦らず確実に入力できます。

4. 静寂バイパスによる 0ms 即時リマップの実装手順

キーを角括弧 [] で定義することで、静寂判定を完全にバイパスして即時出力する仕組みです。

  • 単打 [a]: 高速タイピング中であっても、キーを押した瞬間に 0ms 完全無遅延で即座に目的のキーへ置換出力 されます。
  • コンボ [ca]: 2打目 a を押した瞬間に、後段静寂(待機時間)を経由せず即時確定実行されます。

5. 中間候補と最長一致のスマート共存アルゴリズム

us ➔ _(2文字)と usa ➔ 米国(3文字)が同時に登録されている場合でも、両立して入力できる仕組みです。

  1. u ➔ s と入力した時点で、完全一致 _ を中間候補として保持しつつ、状態を STATE_WAIT_NEXT で維持します。
  2. 3打目 a が入力された場合 ➔ 最長一致 usa に進み、米国 を出力します。
  3. 次のキーが来ずにタイムアウトした場合 ➔ 保持していた中間候補 _ を出力します。
  4. 関係ないキーが来た場合 ➔ 保留されていたキーを順序通り生出力します。

6. Shiftキーによる安全なコンボキャンセル制御

コンボ入力を中断して生文字を出力する際の誤爆防止手順です。

  1. コンボ待機中に Shift キーを押します。
  2. FsmOnShiftDown() が発動し、タイマーが直ちに強制停止されます(この時点では文字を出力しません)。
  3. Shift キーを離します。FsmFlushOnShiftUp() が発動し、Shiftが離された状態で保留キー(u, s, a)が 小文字のまま安全にフラッシュ出力 されます。

7. 文字順序の逆転(追い越し)を物理的に防止する直列フック

通常タイピング時におけるキーの順序逆転(sh ➔ hs)を構造的に防止する設計です。

  • マッピング対象となるすべてのキーを、通常レイヤー(L0)においても漏れなく $key として網羅フック登録します。
  • すべてのキー打鍵が FSM エンジンを直列に通過するため、OSネイティブ入力とフック入力の間のレースコンディションが物理的にゼロになります。