qmk/qmk_firmware

Optimize process_record_quantum call order

Open

#26048 opened on Mar 5, 2026

View on GitHub
 (2 comments) (1 reaction) (0 assignees)C (20,368 stars) (43,867 forks)batch import
discussionenhancementhelp wanted

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.

Contributor guide