TAPPING_TERM コードリーディング
-
キーマトリックスを読み取って、変化のあったそれぞれのキーについて action_exec を呼ぶ
-
引数は (key_event_t){ .key = { .row, .col }, .pressed, .time }
- 変化したキーの位置と、変化が押し下げか押し上げかと、変化の時刻
-
一つのキーにも変化がなかった場合、 action_exec が1度だけ呼ばれる
- 引数はダミーの key_event "TICK"
- (key_event_t){ .key = { .row = 255, .col = 255 }, .pressed = false, .time = }
- 引数はダミーの key_event "TICK"
-
渡ってきた key_event_t を (key_record_t){ .event, .tap = (tap_t){ .interrupted, .count } } でラップ
- .interrupted は現時点で不明
- tapping key が押されてから TAPPING_TERM 以内に別のキーが押された場合に true になるっぽい
- .count は押し下げられた時点では 0 、押し上げられると 1 になるっぽい
- 2 以上にはなるのか?これもまだ現時点で不明
- TAPPING_TOGGLE ?のために?2以上もカウントするっぽい
- 2 以上にはなるのか?これもまだ現時点で不明
-
この key_record を action_tapping_process に投げる
- tapping 機能が無効になっている場合は直接 process_record に投げる
- (action_tapping_process も結局 process_record に良い感じの key_record を投げる)
- store_or_get_action してそれを process_action に投げる
-
PREVENT_STUCK_MODIFIERS がセットされていない場合、または process_record_nocache 経由で呼ばれた場合
- たんにキーマップからキーに対応するアクションを探して返す
-
それ以外の場合
- もし渡されたのが押し上げイベントだった場合
- 現在のレイヤーを記録してから、キーマップからキーに対応するアクションを探して返す
- 押し下げイベントだった場合
- 「押し上げイベントが起こった時点のレイヤーにおける」アクションを探して返す
- もし渡されたのが押し上げイベントだった場合
-
キーの押し下げ・押し上げに応じて適切なキーコードを生成する
-
count が 0 (押し下げのみ) か 1 以上か (押して離す) によって、レイヤーを切り替えたり単発キーを入力したり切り替わるみたい
難しいので後で読む
-
もしイベントが押し下げだったら、 weak mod (直後の1キーだけ有効な mod ?) をクリアしておく
- weak mod 参考 qmk/qmk_firmware#1503
-
ワンショットモディファイアのなんか前処理 (省略)
-
アクションの種類によって分岐
- 通常のキー入力 (通常の MOD 含む) の場合
- 押し下げの場合
- MOD を適切にセット
- send_keyboard_report を呼び出す (キーボードの状態を送信? ... まだ追えてない)
- 押し上げの場合
- MOD を適切に解除
- send_keyboard_report を呼び出す
- 押し下げの場合
- MOD TAP の場合
- ワンショットの場合
- 押し下げの場合
- 初の押し下げの場合 (tap_count == 0)
- MOD を適切にセット
- 二度目の押し下げの場合 (tap_count == 1)
- MOD をワンショットにセット
- ONESHOT_TAP_TOGGLE 回目の押し下げの場合 (tap_count == ONESHOT_TAP_TOGGLE)
- ワンショット MOD を解除して別の MOD を?セット
- それ以外の場合 (2回目以降 ONESHOT_TAP_TOGGLE 回未満?)
- たんに MOD をセット
- 初の押し下げの場合 (tap_count == 0)
- 押し上げの場合
- 初の押し下げの場合
- ワンショット MOD をクリア、 MOD もクリア
- ...
- 初の押し下げの場合
- 押し下げの場合
- ワンショットの場合
- トグルの場合 (省略)
- ... (読めてない)
- 通常のキー入力 (通常の MOD 含む) の場合
-
直近の tapping key (長押しで機能が変化するキー) 操作を記録するための tapping_key (keyrecord_t)
-
tapping key の処理中に後回しにしたイベントをためておくキュー waiting_buffer (keyrecord_t[])
- waiting_buffer になにかが enqueue されるのは何かしらの tapping key の処理途中だけ
- たとえば、あるキー X の押し上げ処理時に、対応する押し下げイベントがキューにいないこともある
- tapping key ではないキー X を押し下げ
- tapping key Y を押し下げ
- X 押し上げ
- たとえば、あるキー X の押し上げ処理時に、対応する押し下げイベントがキューにいないこともある
- waiting_buffer になにかが enqueue されるのは何かしらの tapping key の処理途中だけ
-
渡された key_record を process_tapping に投げる
- もし false が返ってきた場合(処理に失敗した場合)は waiting_buffer に enqueue しておく
-
waiting_buffer に溜まっている各イベントについて、先頭から順に:
- 改めて process_tapping に投げてみる
- だめだったらそこでループ終了
- たぶん TICK とかで TAPPING_TERM 時限発火したりする用?
- 改めて process_tapping に投げてみる
※失敗と明記されているもの以外は成功が返る
-
イベントが tap key で、かつ押し下げの場合
- tapping_key に key_record をセット
- waiting_buffer_scan_tap を呼ぶ (waiting_buffer で待っているキーの押し上げを処理)
- ?? 初めての押し下げ時は waiting_buffer は空ではないのか ??
- どうやら tapping_key をクリアするときに一緒に waiting_buffer をクリアするとは限らないっぽい
- ?? 初めての押し下げ時は waiting_buffer は空ではないのか ??
- ※この時点では押し下げは処理されない (長押しか単押しか未確定で、この時点ではやることがない?)
-
それ以外の場合 (tap key でないか、押し上げイベント)
- たんに process_record に投げる
- もし tapping_key の count がまだ 0 なら (まだ押し上げを検出していないなら)
- waiting_buffer から、「tapping_key から TAPPING_TERM 以内の、そのキーに対する押し上げイベント」を探して、もし見つかれば
- そのイベントと tapping_key の count を 1 にする
- waiting_buffer から、「tapping_key から TAPPING_TERM 以内の、そのキーに対する押し上げイベント」を探して、もし見つかれば
これはなんなんだ?どっかのタイミングで bugfix として入ったコードっぽい (PR になっていないので謎)。
新しい tap key を開始する時に、前の tap key で queue に積まれたイベントをお掃除するっぽい?
もとはなかったコードなので、いったん読み飛ばしても良いかも
次のどれか:
-
新しいイベントが tapping_key に対応する押し上げイベントだった場合 (1 度目の tap 終了)
- tapping_key とイベントの count を 1 にして process_record に投げ (キー押し上げを処理)、 失敗 (enqueue)
- 押し上げイベントが enqueue される
- !TAPPING_FORCE_HOLD のときに二回目のタップを特別扱いするので、そのために残すのかな?
- けど TICK で処理されちゃいそうな気もする?
- というか tapping_key にもセットしたままなわけだから、二回目以降のタップもそこでよくない?
- tapping_key とイベントの count を 1 にして process_record に投げ (キー押し上げを処理)、 失敗 (enqueue)
-
PERMISSIVE_HOLD が有効で、waiting_buffer 内の押し下げに対応する押し上げイベントだった場合
- (A Dn -> B Dn -> B Up と操作するとこうなる? B Dn で interrupt されてる気がするけど、合ってる?)
- tapping_key を process_record に投げて、tapping_key を無にセットして、 失敗 (enqueue)
- enqueue されるのは B Up の方
- A Dn が長押しで確定なので押し下げを処理して、 tapping_key は次の tap key に備える?
-
waiting_buffer にない押し下げに対する押し上げイベントだった場合
- (B Dn -> A Dn (tap key) -> B Up と操作するとこうなる?)
- それが modifier key だったら 失敗 (enqueue)
- modifier key の押し上げだけ処理を後回しにするのはなぜ?
- さもなければ押し上げイベントを普通に処理 (process_record)
-
押し下げイベントだった場合
- (A Dn (tap key) -> B Dn と操作するとこうなる?)
- tapping_key の interrupted を true にして、 失敗 (enqueue)
-
それ以外の場合 (PERMISSIVE_HOLD が無効かつ waiting_buffer に対応する押し上げ?)
- 失敗 (enqueue)
- PERMISSIVE_HOLD が無効だと、TAPPING_TERM 以内に A Dn -> B Dn -> B Up と打っても振る舞いが未確定
- 失敗 (enqueue)
-
tapping_key に対する押し上げだった場合 (二度目の押し上げ…?)
- そのイベントの tap を tapping_key.tap (count, interrupted) で上書きして、 process_record に投げる
- tapping_key をそのイベントにセット
- event の時刻が更新される、 TAPPING_TERM の処理とかに影響がある?
-
tap key の押し下げだった場合 (Shift Dn -> Shift Up -> Ctrl Dn とか?)
- tapping_key.count が 2 以上だった場合、強制的に tapping_key の押し上げを発行する
- 新しいイベントを tapping_key にセット
- waiting_buffer_scan_tap を呼ぶ
-
それ以外の場合
- たんに process_record に投げる
- まだ tapping_key の押し上げが検出されていない場合 (タイムアウト)
- tapping_key を process_record に投げてクリア後、 失敗 (enqueue)
- 失敗しておくのは、例によって再び押し下げが来た時に !TAPPING_FORCE_HOLD の処理をするため?
- tapping_key を process_record に投げてクリア後、 失敗 (enqueue)
ここから下は TAPPING_TERM 以内に tapping_key 押し上げ→何かしら押し下げ した場合と同じっぽい
-
tapping_key に対する押し上げイベントの場合 (タイムアウト済みの tap のおわり)
- そのイベントの tap を tapping_key.tap を上書きして、 process_record に投げる
- tapping_key をそのイベントにセット
-
tap key の押し下げだった場合 (Shift Dn -> タイムアウト -> Ctrl Dn とか?)
- tapping_key.count が 2 以上だった場合、強制的に tapping_key の押し上げを発行する
- 新しいイベントを tapping_key にセット
- waiting_buffer_scan_tap を呼ぶ
-
それ以外の場合
- たんに process_record に投げる
-
新しいイベントが押し上げイベントだった場合
- たんに process_record に投げる
-
新しいイベントが押し上げられた tapping_key の押し下げだった場合
- TAPPING_FORCE_HOLD でなく、 tapping_key が interrupt されず (単押しとして) 押し上げられている場合
- 新しいイベントの tap を tapping_key.tap で上書き
- もし tap.count が 15 回未満なら count をインクリメント
- process_record にイベントを投げる
- 新しいイベントを tapping_key にセット
- TAPPING_FORCE_HOLD でなく、 tapping_key が interrupt されず (単押しとして) 押し上げられている場合
-
tap key の押し下げだった場合
- 新しいイベントを tapping_key にセット
- waiting_buffer_scan_tap を呼び出す
-
それ以外 (tap key 以外の押し下げ) の場合
- たんに process_record に投げる
(process_action すべき?という FIXME がある)
- tapping_key をクリアして 失敗 (enqueue)