キー拡張機能アーキテクチャ技術解説書 (Key Extension Architecture)
本書は、fjFlow のキー拡張機能(Key Extension)を構成するステートマシンエンジン、タイマー制御、および出力パイプラインの技術アーキテクチャを解説するドキュメントです。...
決定論的 4-State FSM、文字順序逆転防止、0ms即時リマップを支える内部アーキテクチャ
本書は、fjFlow のキー拡張機能(Key Extension)を構成するステートマシンエンジン、タイマー制御、および出力パイプラインの技術アーキテクチャを解説するドキュメントです。
目次
- 1. コア設計思想:判定フェーズと出力フェーズの完全分離
- 2. 決定論的 4-State FSM (状態遷移マシン) の動作モデル
- 3. 可変長シーケンスと文字数スケーリングタイマーの仕組み
- 4. 静寂バイパスによる 0ms 即時リマップの実装手順
- 5. 中間候補と最長一致のスマート共存アルゴリズム
- 6. Shiftキーによる安全なコンボキャンセル制御
- 7. 文字順序の逆転(追い越し)を物理的に防止する直列フック
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文字)が同時に登録されている場合でも、両立して入力できる仕組みです。
u➔sと入力した時点で、完全一致_を中間候補として保持しつつ、状態をSTATE_WAIT_NEXTで維持します。- 3打目
aが入力された場合 ➔ 最長一致usaに進み、米国を出力します。 - 次のキーが来ずにタイムアウトした場合 ➔ 保持していた中間候補
_を出力します。 - 関係ないキーが来た場合 ➔ 保留されていたキーを順序通り生出力します。
6. Shiftキーによる安全なコンボキャンセル制御
コンボ入力を中断して生文字を出力する際の誤爆防止手順です。
- コンボ待機中に
Shiftキーを押します。 FsmOnShiftDown()が発動し、タイマーが直ちに強制停止されます(この時点では文字を出力しません)。Shiftキーを離します。FsmFlushOnShiftUp()が発動し、Shiftが離された状態で保留キー(u,s,a)が 小文字のまま安全にフラッシュ出力 されます。
7. 文字順序の逆転(追い越し)を物理的に防止する直列フック
通常タイピング時におけるキーの順序逆転(sh ➔ hs)を構造的に防止する設計です。
- マッピング対象となるすべてのキーを、通常レイヤー(L0)においても漏れなく
$keyとして網羅フック登録します。 - すべてのキー打鍵が FSM エンジンを直列に通過するため、OSネイティブ入力とフック入力の間のレースコンディションが物理的にゼロになります。