From dfc9ea5316a48d02bbd0247728a2825b377ab463 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 9 Feb 2018 11:10:33 -0500 Subject: initial commit of kbd-xmodmap --- public/kbd-xmodmap.md | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 public/kbd-xmodmap.md diff --git a/public/kbd-xmodmap.md b/public/kbd-xmodmap.md new file mode 100644 index 0000000..5dbccc1 --- /dev/null +++ b/public/kbd-xmodmap.md @@ -0,0 +1,129 @@ +GNU/Linux Keyboard Maps: xmodmap +================================ +--- +date: "2017-10-01" +--- + +The modmap subsystem is part of the core [X11 protocol][xproto]. +However, it has been replaced by the [X Keyboard (XKB) +Extension][kbproto] to the protocol, which defines a facade that +emulates the legacy modmap subsystem so that old programs still +work---including those that manipulate the modmap directly! + +[xproto]: https://www.x.org/releases/current/doc/xproto/x11protocol.html +[kbproto]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html + +For people who like to Keep It Stupid Simple, the XKB extension looks +horribly complicated and gross---even ignoring protocol details, the +configuration syntax is a monstrosity! There's no way to say +something like "I'd like to remap Caps-Lock to be Control", you have +to copy and edit the entire keyboard definition, which includes +mucking with vector graphics of the physical keyboard layout! So it's +very tempting to pretend that XKB doesn't exist, and it's still using +modmap. + +However, this is a leaky abstraction; for instance: when running the +`xmodmap` command to manipulate the modmap, if you have multiple +keyboards plugged in, the result can depend on which keyboard you used +to press "enter" after typing the command! + +Despite only existing as a compatibility shim today, I think it is +important to understand the modmap subsystem to understand modern XKB. + +Conceptual overview +------------------- + +There are 3 fundamental tasks that the modmap subsystem performs: + + 1. `keyboard: map keycode -> keysym` + 2. `keyboard: map keysym -> modifier bit` WAIT? + 3. `pointer: map physical button -> logical button` + +You're thinking: "Great, so the X server does these things for us!" +Nope! It exposes those mappings, and leaves the actual +transformations up to the client. Generally, the actual +transformations are performed automatically inside of libX11/libxcb. + +Vocab: +------ + + - keycode: A numeric ID for a hardware button; this is as close + the the hardware as X11 modmaps let us get. These are + conceptually identical to Linux kernel keycodes, but the numbers + don't match up. Xorg keycodes are typically linux_keycode+8. + + - keysym: A 29-bit integer code that is meaningful to + applications. A mapping of these to symbolic names is defined + in and augmented by + . See: XStringToKeysym() and + XKeysymToString(). We will generally use the symbolic name in + the modmap file. The symbolic names are case-sensitive. + + - Modifier state: An 8-bit bitmask of modifier keys (names are + case-insensitive): + + 1 << 0 : shift + 1 << 1 : lock + 1 << 2 : control + 1 << 3 : mod1 + 1 << 4 : mod2 + 1 << 5 : mod3 + 1 << 6 : mod4 + 1 << 7 : mod5 + +Commands by task: +----------------- + +The `xmodmap` command has its own little quirky syntax. There are 8 +commands that it recognizes. Let's look at those, grouped by the 3 +tasks that the modmap subsystem performs: + + 1. `keyboard: map keycode -> keysym` + + - `keycode KEYCODE = PLAIN [SHIFT [MODE_SWITCH [MODE_SWITCH+SHIFT ]]]` + + Actually takes a list of up to 8 keysyms, but only the first + 4 have standard uses. + + - `keysym OLD_KEYSYM = NEW_KEYSYMS...` + + Takes the keycodes mapped to `OLD_KEYSYM` and maps them to + `NEW_KEYSYM`. + + - `keysym any = KEYSYMS...` + + Finds an otherwise unused keycode, and has it map to the + specified keysyms. + + 2. `keyboard: map keysym -> modifier bit` + + - `clear MODIFIER` + - `add MODIFIERNAME = KEYSYMS...` + - `remove MODIFIER = KEYSYMS...` + + 3. `pointer: map physical button -> logical button` + + - `pointer = default` + + This is equivalent to `pointer = 1 2 3 4 5 6...` where the + list is as long as the number of buttons that there are. + + - `pointer = NUMBERS...` + + TODO + +Appendix: +========= + +I use this snippet in my Emacs configuration to make editing xmodmap +files nicer: + + ;; http://www.emacswiki.org/emacs/XModMapMode + (when (not (fboundp 'xmodmap-mode)) + (define-generic-mode 'xmodmap-mode + '(?!) + '("add" "clear" "keycode" "keysym" "pointer" "remove") + nil + '("[xX]modmap\\(rc\\)?\\'") + nil + "Simple mode for xmodmap files.")) -- cgit v1.1-4-g5e80