Description
Feature Request Type
- Core functionality
- Add-on hardware support (eg. audio, RGB, OLED screen, etc.)
- Alteration (enhancement/optimization) of existing feature(s)
- New behavior
Description
process_record_quantum orders many effects.
We don't have a good reason for some orders.
We should document why we order what how (so we know where to put new things).
This idea was suggested in https://github.com/qmk/qmk_firmware/pull/25940
First we need to categorize what does what.
I use the following words to mean:
- stats/read: always returns true (= continue)
- handle: for specific keys returns false, otherwise true
Current (see quantum.c):
(process_record_quantum){
(preprocess){ // sequence unless break
secure // can break; unlock device
tap_dance // change keycode (handle end of previous tap dance)
rgblight // stats
wpm // stats
}
(process){ // first matching
key_lock // lock standard and oneshot keys
dynamic_macro // remember last n keys ; repeat last n keys
{last_key // remember last 1 key
repeat_key} // repeat last 1 key
audio_clicky // feedback
haptic // feedback
auto_mouse // layer switch with hold/tap disambiguation
modules // extensability
kb // calls user
via
secure // QK_SECURE_.* key handling
sequencer // QK_SEQUENCER_.* key handling
midi_advanced // (QK_)?MIDI_.* key handling
audio // QK_AUDIO_.* key handling
backlight // QK_BACKLIGHT_.* key handling
led_matrix // QK_LED_MATRIX_.* key handling
steno // QK_STENO_.* key handling
music // QK_MUSIC_.*|QK_MIDI_.* key handling & catches ([Modifier]|[Arrow]) if (music|midi) activated
caps_word // QK_CAPS_WORD_.* key handling & handles alpha
key_override // replace any key
tap_dance // TD([Index]) key handling
unicode_common // UC([WChar]) key handling
leader // QK_LEADER handing & any key handling if leader_active
auto_shift // key handling when held and shiftable, reads all keys for timer
dynamic_tapping_term // QK_DYNAMIC_TAPPING_TERM_.* key handling
space_cadet // QK_SPACE_CADET_.* key handling, read other keys
magic // QK_MAGIC_.* key handling
grave_esc // QK_GRAVE_ESCAPE key handling
underglow // QK_UNDERGLOW_.* key handling
rgb_matrix // QK_RGB_MATRIX_.* key handling
joystick // QK_JOYSTICK range key handling
programmable_button // QK_PROGRAMMABLE_BUTTON range key handling
autocorrect // handles word keys & resets on other keys
tri_layer // QK_TRI_LAYER_.* key handling
default_layer // DF([Index]) key handling
layer_lock // QK_LAYER_LOCK|MO(.*)|LT(.*)|LM(.*) key handling
connection // QK_OUTPUT_.*|QK_BLUETOOTH_.* key handling
oneshot // QK_ONESHOT_.* key handling
quantum // QK_BOOTLOADER|QK_REBOOT|... key handling
}
}
Possible Algorithm to sort given a partial order:
- Optionally split stages with read/handle distinction (read has fewer restrictions) (see e.g. last_key and repeat_key).
- Specify partial order on stages (which must occur before which).
- Assign each stage a number, where stages are performed in ascending order.
- Minimize sum.
Proposed order (as sorted list of sets) (I did not use the algorithm) (set entries ordered according to current behavior) (this includes some order that is not supported by requirements):
[ {preproces.secure} // unlock
, {preprocess.tap_dance} // fixup layer handling
, {rgblight, wpm} // stats
, {dynamic_macro, last_key, leader} // buffer last keys
, {key_lock, override, auto_shift, caps_word, autocorrect} // change to alternative key behavior (in my opinion these features do not really work together, so any ordering between should be irrelevant, but best we can do is being consistent)
, {auto_mouse} // read input keys (not sure about where to place this)
, {modules}
, {kb}
, {via}
, {repeat_key, audio_clicky, haptic, secure, sequencer, midi_advanced, audio, backlight, led_matrix, steno, music, tap_dance, unicode_common, dynamic_tapping_term, space_cadet, magic, grave_esc, underglow, rgb_matrix, joystick, programmable_button, tri_layer, default_layer, layer_lock, connection, oneshot, quantum} // handle some specific keys
]
Requirements:
secure = 0 // unlock first
preprocess.tap_dance < any read // changes active layer
stats < any handle // for correct stats
leader < override // Overrides(etc.) should not steal keys from buffering
auto_mouse < layer_lock // both handle same (layer) keys
auto_mouse < modules // auto_mouse changes active layer (not sure, requesting feedback from someone using auto_mouse)
modules < kb // current module behavior
kb < via // current via behavior
specific key handler = infinity // do special key handling last (no point in sorting handlers that do not overlap. If they overlap that is currently a bug/unreachable code)
If you think the proposed order has flaws, please try to find and explain a minimal order constraint that contradicts the proposal. I am aware that I surely made a mistake somewhere, and happy if you point it out, so I can correct it.
We could formulate this as SAT. If there are many suggestions/ideas, a git managed file for the requirements would be useful.