Decision — the function keys belong to the user

Status: accepted 2026-10-17. Amends egui applications (AGENTS.md §4.1) and builds on key bindings are desktop settings.

The decision

  • F1–F12 belong to the person. No program gives a command a default chord on a function key: not bare, and not with Ctrl, Alt, Shift or any mix of them. This covers every command registry and every default key table, in apps, the desktop furniture and the session.

  • The person may bind them. A keymap entry in the desktop profile (keymaps.<app>.<action>, applied by Registry::rebind) may put any command on any function key, with any modifiers. Nothing in this decision narrows what a person can bind.

  • A command that wants a key gets another one. Conventional non-F chords are used where they exist:

    • Keyboard Shortcuts: Ctrl+/;
    • Refresh: Ctrl+R.

    Where there is no good chord, the command keeps its menu row and has no default key.

What is allowed and what is not

Allowed
A default chord on F1–F12, any modifiers, in any registry or key tableno
A further default chord (Registry::add_shortcuts) on F1–F12no
A person's keymap override onto F1–F12, any modifiersyes
An application passing a function key through as input (a terminal sending its escape sequence to the program inside)yes: that is not a binding
The keyboard layout's own keysyms (XF86Switch_VT_n from Ctrl+Alt+Fn)yes: they are the layout's, and compd binds the keysym, not the F-key

How it is enforced

  • The toolkit's command registry refuses one. Registry::add (and so add_toggle and the theme menu) and Registry::add_shortcuts panic when a default chord's key is F1–F12, whatever its modifiers. The message names the command id and this decision. Every app builds its registry in its own tests, so a violation fails cargo test before it can ship.
  • Registry::rebind is not checked. It applies the person's bindings, and those may use any key. The toolkit's tests prove both sides: default bare, Ctrl and Shift function-key chords are refused, and an override to F5 binds and runs.
  • One list. toolkit::keymap::USER_KEYS and toolkit::keymap::user_only name the keys. A default key table that is not a toolkit registry checks its chords against them in its own test.
  • AGENTS.md §4.1 states the rule.

Why

  • The person's own bindings come first. People put their global shortcuts, compositor actions, assistive tools, dictation, push-to-talk and macros on the function keys, because those keys are otherwise spare. A default an app ships on one either shadows that binding while the app has focus or is shadowed by it, and the person loses either way.
  • Predictability across apps. F1, F2, F5 and the rest mean different things in different programs elsewhere. When no MixOS program claims them, a function key does in every app exactly what the person bound it to, or nothing.
  • A private note was not enough. The rule lived in a note and in one app's test (screenshot's no_bare_function_key_is_bound), and new apps kept breaking it. A rule the registry enforces cannot be forgotten.

Alternatives considered

Allow the modified F-keys (Ctrl+F*, Alt+F*) and refuse only the bare ones. Rejected: nearly every modified function key is already taken before an app starts.

  • Ctrl+Alt+F1–F12 switch virtual terminals. The keyboard layout turns them into the XKB SwitchVt1–SwitchVt12 keysyms, compd maps those (services/compd/crates/slots/src/library/input/keyboard/format/format.rs), and MixOS's VT-separated sessions depend on them.
  • Ctrl+F*: a typical stock KDE Plasma session binds Ctrl+F1–F4 (desktops 1–4), plus Ctrl+F7, Ctrl+F9, Ctrl+F10 and Ctrl+F12 (window effects and the overview). Those are global grabs, so an app's default on one would silently never fire.
  • Alt+F*: Alt+F1 (application menu), Alt+F3 (window operations) and Alt+F4 (close window) are near-universal desktop conventions.
  • Shift+F10 is the standard keyboard context-menu key, which keyboard-only and assistive use relies on.
  • Meta/Super+F* belong to the compositor.
  • Terminal programs: F-key chords must reach TUI programs inside a terminal (mc, htop) unclaimed.

What is left free changes from desktop to desktop and release to release. One simple rule, no default on a function key at all, holds everywhere; a deny-list would be tied to one desktop's current configuration. A person who wants any F-chord binds it in their keymap.

A typed check (a default-chord type that cannot hold a function key). Rejected for now: it would change the shortcut field of every command in every app, for a guard the registry already gives at start-up and in every app's own tests.

Migration

The existing default function-key chords on main are removed. Each command keeps its menu row:

AppCommandWasNow
Monitorfile.refreshF5Ctrl+R
Monitorhelp.shortcutsF1Ctrl+/
BusViewerhelp.shortcutsF1Ctrl+/
Prefshelp.shortcutsF1Ctrl+/
dopushelp.shortcutsF1Ctrl+/
dopusfile.renameF2, Ctrl+ECtrl+E
dopusnav.switch-paneF6, TabTab
dopusview.refreshF5, Ctrl+RCtrl+R
cedsearch.find_nextF3none (Enter in the find field)
cedsearch.find_prevShift+F3none

dopus's Parent Folder gains Alt+ArrowUp beside Backspace, the usual file manager chord. ced's list of contextual keys no longer claims F10 for the menu bar; no code bound it. screenshot's own test is removed: the registry now refuses what it checked, with modifiers too.

A person who wants an old key back binds it in their profile, for example keymaps.dopus.file.rename = ["F2", "Ctrl+E"].

Consequences

  • AGENTS.md §4.1 gains the rule.
  • A new app that binds a function key by default fails its own registry tests at once, with a message pointing here.
  • The affected apps' manuals list the new keys.

This page as Markdown · This page describes the current main branch of MixOS.