.\" Generated by scdoc 1.11.2 .\" Complete documentation for this program is not available as a GNU info page .ie \n(.g .ds Aq \(aq .el .ds Aq ' .nh .ad l .\" Begin generated content: .TH "keyd" "1" "2024-07-27" .P .SH NAME .P \fBkeyd\fR - A key remapping daemon.\& .P .SH SYNOPSIS .P \fBkeyd\fR [command] [options] .P .SH COMMANDS .P \fBmonitor [-t]\fR .RS 4 Print key events.\& If -t is supplied, also prints time since the last event in ms.\& Useful for discovering key names/device ids and debugging.\& .P .RE \fBlisten\fR .RS 4 Print layer state changes of the running keyd daemon to stdout.\& Useful for scripting.\& .P .RE \fBbind reset| [.\&.\&.\&]\fR .RS 4 Apply the supplied bindings.\& See \fIBindings\fR for details.\& .P .RE \fBreload\fR .RS 4 Reload config files.\& .P .RE \fBlist-keys\fR .RS 4 List valid key names.\& .P .RE \fBinput [-t ] [.\&.\&.\&]\fR .RS 4 Input the supplied text.\& If no arguments are given, read the input from STDIN.\& A timeout in microseconds may optionally be supplied corresponding to the time between emitted events.\& .P .RE \fBdo [-t ] []\fR .RS 4 Execute the supplied expression.\& See MACROS for the format of .\& If no arguments are given, the expression is read from STDIN.\& If supplied, corresponds to the macro_sequence_timeout.\& .P .RE .SH OPTIONS .P \fB-v, --version\fR .RS 4 Print the current version and exit.\& .P .RE \fB-h, --help\fR .RS 4 Print help and exit.\& .P .RE .SH DESCRIPTION .P keyd is a system wide key remapping daemon which supports features like layering, oneshot modifiers, and macros.\& In its most basic form it can be used to define a custom key layout that persists across display server boundaries (e.\&g wayland/X/tty).\& .P The program runs in the foreground, printing diagnostic information to the standard output streams, and is intended to be run as a single instance managed by the init system.\& .P \fBNOTE:\fR .P Because keyd modifies your primary input device, it is possible to render your machine unusable with a bad config file.\& If you find yourself in this situation the panic sequence \fB++\fR will force keyd to terminate.\& .P .SH CONFIGURATION .P Configuration files loosely follow an INI style format consisting of headers of the form \fI[section_name]\fR followed by a set of \fIbindings\fR.\& Lines beginning with a hash are ignored.\& .P Config files are stored in \fI/etc/keyd/\fR and loaded upon initialization.\& The reload command can be used to update the working set of config files (e.\&g sudo keyd reload).\& .P A valid config file has the extension \fI.\&conf\fR and \fBmust\fR begin with an \fI[ids]\fR section that has one of the following forms: .P .nf .RS 4 [ids] \&.\&.\&. .fi .RE .P or .P .nf .RS 4 [ids] * - - \&.\&.\&. .fi .RE .P The first form specifies a list of ids to be explicitly matched, while the second matches any id which has not been explicitly excluded.\& .P For example: .P .nf .RS 4 [ids] * -0123:4567 .fi .RE .P .P Will match all keyboards which \fBdo not\fR(2) have the id \fI0123:4567\fR, while: .P .nf .RS 4 [ids] 0123:4567 .fi .RE .P will exclusively match any devices which do.\& Device ids can be obtained from the monitor command (see \fICOMMANDS\fR).\& Note that a device id may only be listed in a single config file.\& .P Each subsequent section of the file corresponds to a \fIlayer\fR (with the exception of \fI[global]\fR (see \fIGLOBALS\fR).\& .P Config errors will appear in the log output and can be accessed in the usual way using your system'\&s service manager (e.\&g sudo journalctl -eu keyd).\& .P If an id matches more than one device type, the prefix k: may be used to exclusively match keyboards and the prefix m: may be used to exclusively match mice.\& (E.\&g m:046d:b01d) .P Note: All keyboards defined within a given config file will share the same state.\& This is useful for linking separate input devices together (e.\&g foot pedals).\& .P Note 2: The wildcard will only match devices which keyd identifies as keyboards.\& keyd is also capable of \fBmanaging mice\fR (e.\&g to facilitate clearing of oneshot modifiers on click), but their ids must be explicitly listed.\& .P Note 3: \fBMouse support is currently experimental\fR, and is mostly confined to traditional mice (e.\&g touchpads).\& Adding some mice to your ids section may break your pointer.\& \fBIt may also be necessary to explicitly blacklist mice which are misidentified as keyboards (e.\&g if you find your moused misbehaving).\&\fR .P .SS Layers .P A layer is a collection of \fIbindings\fR, each of which specifies the behaviour of a particular key.\& Multiple layers may be active at any given time, forming a stack of occluding keymaps consulted in activation order.\& The default layer is called \fImain\fR and is where common bindings should be defined.\& .P For example, the following config snippet defines a layer called \fInav\fR and creates a toggle for it in the \fImain\fR layer: .P .nf .RS 4 [main] capslock = layer(nav) [nav] h = left k = up j = down l = right .fi .RE .P When capslock is held, the \fInav\fR layer occludes the \fImain\fR layer causing \fIhjkl\fR to function as the corresponding arrow keys.\& .P Unlike most other remapping tools, keyd provides first class support for modifiers.\& A layer name may optionally end with a '\&:'\& followed by a set of modifiers to emulate in the absence of an explicit mapping.\& \fBLayer names may consist of a maximum of 64 characters\fR (including all modifiers).\& .P These layers play nicely with other modifiers and preserve existing stacking semantics.\& .P For example: .P .nf .RS 4 [main] capslock = layer(capslock) [capslock:C] j = down .fi .RE .P will cause \fIcapslock\fR to behave as \fIcontrol\fR, except in the case of \fIcapslock+j\fR, which will emit \fIdown\fR.\& This makes it trivial to define custom modifiers which don'\&t interfere with one another.\& .P Note that bindings are not affected by the modifiers of the layer in which they are defined.\& Thus \fBcapslock+j\fR will produce an unmodified \fBdown\fR keypress, while \fBshift+capslock+j\fR will produce \fBshift+down\fR as expected.\& .P .P Formally, each layer heading has the following form: .P .nf .RS 4 "[" [:] "]" .fi .RE .P Where \fI\fR has the form: .P .RS 4 \fI[-].\&.\&.\&\fR .P .RE and each modifier is one of: .P .RS 4 \fBC\fR - Control .br \fBM\fR - Meta/Super .br \fBA\fR - Alt .br \fBS\fR - Shift .br \fBG\fR - AltGr .P .RE Finally, each layer heading is followed by a set of bindings which take the form: .P .RS 4 | = || .P .RE for a description of and see \fIACTIONS\fR and \fIMACROS\fR.\& .P By default, each key is bound to itself within the main layer.\& The exception to this are the modifier keys, which are instead bound to eponymously named layers with the corresponding modifiers.\& .P For example, \fImeta\fR is actually bound to \fIlayer(meta)\fR, where \fImeta\fR is internally defined as \fImeta:M\fR.\& .P The full set of modifier bindings are as follows: .P .nf .RS 4 control = layer(control) meta = layer(meta) shift = layer(shift) leftalt = layer(alt) rightalt = layer(altgr) .fi .RE .P A consequence of this is that overriding modifier keys is a simple matter of adding the desired bindings to an appropriate pre-defined layer.\& .P Thus .P .nf .RS 4 [ids] * [control] j = down .fi .RE .P is a completely valid config, which does what the benighted user might expect.\& Internally, the full config actually looks something like this: .P .nf .RS 4 [ids] * [main] leftcontrol = layer(control) rightcontrol = layer(control) [control:C] j = down .fi .RE .P If multiple bindings for the same key are present, the most recent one takes precedence.\& .P A layer heading may also appear multiple times, in which case the layer will contain the sum of all bindings.\& Note that the layer type may not be reassigned.\& .P That is: .P .nf .RS 4 [mylayer:A] a = b c = d [mylayer:C] a = x b = c .fi .RE .P is equivalent to: .P .nf .RS 4 [mylayer:A] a = x b = c c = d .fi .RE .P .SS Composite Layers .P A special kind of layer called a \fBcomposite layer\fR can be defined by creating a layer with a name consisting of existing layers delimited by \fI+\fR.\& The resultant layer will be activated and given precedence when all of its constituents are activated.\& Composite layers are not allowed to have modifiers attached and cannot be explicitly assigned.\& .P E.\&g.\& .P .nf .RS 4 [control+alt] h = left .fi .RE .P will cause the sequence \fIcontrol+alt+h\fR to produce \fIleft\fR (ignoring the control and alt modifiers attached to the active control and alt layers), while pressing \fIcontrol+alt+f1\fR preserves those modifiers, emitting exactly what was pressed, as there is no explicit binding for \fIf1\fR on the composite layer.\& .P .P .nf .RS 4 [main] capslock = layer(capslock) [capslock:C] [capslock+shift] h = left .fi .RE .P Will cause the sequence \fIcapslock+shift+h\fR to produce \fIleft\fR, while preserving the expected functionality of \fIcapslock\fR and \fIshift\fR in isolation.\& .P \fBNote:\fR composite layers \fBmust\fR always be defined \fIafter\fR the layers of which they are comprised.\& .P That is: .P .nf .RS 4 [layer1] [layer2] [layer1+layer2] .fi .RE .P and not .P .nf .RS 4 [layer1+layer2] [layer1] [layer2] .fi .RE .P .SS Layouts .P A layout is a special kind of layer intended for modifying alpha keys.\& Unlike layers, layouts cannot have any associated modifiers, and only one layout may be active at a given time.\& The default layout is called '\&main'\&, and can be changed using the \fIsetlayout()\fR action.\& .P For convenience, keyd ships with a number of common letter layouts in /usr/share/keyd/layouts.\& Before including these, it is instructive to inspect them.\& Non-english layouts include a dedicated shift layer (making order of inclusion important) and \fBrequire the use of keyd'\&s compose definitions\fR (see \fBUnicode Support\fR) .P E.\&g.\& .P .nf .RS 4 # Include the shipped colemak layout\&. include layouts/colemak [global] default_layout = mylayout [mylayout:layout] a = b b = c #etc\&.\&.\&. [control] 1 = setlayout(customlayout) 2 = setlayout(colemak) .fi .RE .P .P .SS Chording .P \fIChords\fR are groups of keys which are treated as a unit when simultaneously depressed.\& A chord can be defined by using a group of + delimited key names as a left hand value.\& The corresponding action will be activated if all keys are struck within the chording interval (\fIchord_timeout\fR).\& .P E.\&g .P .nf .RS 4 j+k = esc .fi .RE .P will cause \fIesc\fR to be produced if both \fIj\fR and \fIk\fR are simultaneously depressed.\& .P Note: It may be desirable to change the default chording interval (50ms) to account for the physical characteristics of your keyboard.\& .P .SS Unicode Support .P If keyd encounters a valid UTF8 sequence as a right hand value, it will try and translate that sequence into a macro which emits a keyd-specific XKB sequence.\& .P In order for this to work, the sequences defined in the compose file shipped with keyd (\fI/usr/share/keyd/keyd.\&compose\fR) must be accessible.\& This can be achieved globally by copying the file to the appropriate location in \fI/usr/share/X11/locale\fR, or on a per-user basis by symlinking it to ~/.\&XCompose.\& .P E.\&g.\& .P .RS 4 ln -s /usr/share/keyd/keyd.\&compose ~/.\&XCompose .P .RE \fB\fRAdditionally you will need to be using the default US layout on your display server.\&\fB\fR Users of non-english layouts are advised to set their layout within keyd (see \fB\fRLayouts\fB\fR) to avoid conflicts between the display server layout and keyd'\&s unicode functionality.\& .P \fB\fRNote:\fB\fR You may have to restart your applications for this to take effect.\& .P \fB\fRNote 2:\fB\fR The generated compose sequences are affected by modifiers in the normal way.\& If you want shift to produce a different symbol, you will need to define a custom shift layer (see the included layout files for an example).\& .P \fB\fRNote 3:\fB\fR GTK4 currently has a bug which causes it to crash in the presence of large XCompose files (like /usr/share/keyd/keyd.\&compose).\& .P .SS Aliases .P Each key may optionally be assigned an \fBalias\fR.\& This alias may be used in place of the key as a valid left hand value.\& Multiple keys may be bound to the same alias, but only one alias may be assigned to a key at a given time.\& .P For example, the keys '\&leftmeta'\& and '\&rightmeta'\& are bound to the alias \fBmeta\fR by default.\& Thus the binding '\&meta = a'\& is equivalent to the bindings '\&leftmeta = a'\& and '\&rightmeta = a'\&.\& .P Aliases are defined in a special section called '\&aliases'\& where each line takes the form: .P .RS 4 = .P .RE where \fI\fR must be a valid key name.\& .P Note that may itself be a valid key name, in which case all references to the key within the config file will be replaced with the new key.\& Additionally, if the assigned alias is a valid key name, the corresponding keycode will be assigned to the key by default.\& This makes it possible to redefine keys before any bindings are applied and is particularly useful in conjunction with the include mechanism to account for variations in hardware.\& .P For example: .P .nf .RS 4 /etc/keyd/common: meta = oneshot(meta) alt = oneshot(alt) a = a s = o # etc\&.\&. /etc/keyd/default\&.conf: [ids] * [main] include common /etc/keyd/magic_keyboard\&.conf: [ids] 004c:0267 [aliases] leftalt = meta rightalt = meta rightmeta = alt leftmeta = alt [main] include common .fi .RE .P Allows the user to define a set of universal bindings in /etc/keyd/common without having to explicitly account for the transposed meta and alt keys within the included config snippet.\& .P .SS File Inclusion .P Config files may include other files located within the config directory using the \fIinclude\fR keyword.\& A line of the form \fBinclude \fR may appear at any point after the [ids] section.\& The resultant config will behave as though the contents of the included file appear in place of the include statement.\& .P Making strategic use of these statements makes it possible to share common functionality between configs.\& .P Include paths are relative and must be placed in one of the following directories: .RS 4 .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} /etc/keyd/ .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} /usr/share/keyd/ .RE .P .RE E.\&g.\& .P .nf .RS 4 /etc/keyd/default\&.conf: [ids] * # Add our shared custom bindings\&. include common # Appends bindings to the main layer # defined in /etc/keyd/common (order matters) [main] capslock = layer(capslock) [capslock] 1 = setlayout(colemak) 2 = setlayout(dvorak) /etc/keyd/common: [main] rightmeta = layer(nav) [nav] h = left j = down k = up l = right /usr/share/keyd/layouts/dvorak: a = a s = o \&.\&.\&. .fi .RE .P Limitations: .P .RS 4 .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} All include statements should appear after the [ids] section in the including file.\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} Included files should not contain an ids section.\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} Included files should not include other files (inclusion is non-recursive).\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} Included files should not end in .\&conf.\& .RE .P .P .RE .SH GLOBALS .P A special section called \fI[global]\fR may be defined in the file and can contain any of the following options: .P .RS 4 \fBmacro_timeout:\fR The time (in milliseconds) separating the initial execution of a macro sequence and the first repetition.\& (default: 600) .P \fBmacro_repeat_timeout:\fR The time separating successive executions of a macro.\& (default: 50) .P \fBlayer_indicator:\fR If set, this will turn the capslock light on whenever a layer is active.\& Note: Some wayland compositors will aggressively toggle LED state rendering this option unusable.\& .P (default: 0) .P \fBmacro_sequence_timeout:\fR If set, this will add a timeout (\fBin microseconds\fR) between each emitted key in a macro sequence.\& This is useful to avoid overflowing the input buffer on some systems.\& .P \fBchord_timeout:\fR The maximum time between successive keys interpreted as part of a chord.\& (default: 50) .P \fBchord_hold_timeout:\fR The length of time a chord must be held before being activated.\& (default: 0) .P \fBoneshot_timeout:\fR If non-zero, timeout a oneshot layer activation after the supplied number of milliseconds.\& (default: 0) .P \fBdisable_modifier_guard:\fR By default, keyd will inject additional control keypresses where necessary in order to prevent programs from seeing additional modifier taps (E.\&g alt in firefox).\& If set, this option disables that behaviour.\& (default: 0) .P \fBoverload_tap_timeout:\fR If non-zero, ignore the tap behaviour of an overloaded key if it is held for the given number of miliseconds.\& (default: 0).\& .P .P .RE \fBNote:\fR Unicode characters and key sequences are treated as macros, and are consequently affected by the corresponding timeout options.\& .P .SH MACROS .P Various keyd actions accept macro expressions.\& .P A macro expression has one of the following forms: .P .RS 4 .RS 4 .ie n \{\ \h'-04'1.\h'+03'\c .\} .el \{\ .IP 1. 4 .\} macro() .RE .RS 4 .ie n \{\ \h'-04'2.\h'+03'\c .\} .el \{\ .IP 2. 4 .\} [[-.\&.\&.\&]- .RE .RS 4 .ie n \{\ \h'-04'3.\h'+03'\c .\} .el \{\ .IP 3. 4 .\} .RE .P .RE Where \fI\fR is a valid unicode character and \fI\fR has the form \fI [.\&.\&.\&]\fR and each token is one of: .P .RS 4 .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} A valid key code.\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} A type 2 macro.\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} A contiguous group of unicode characters.\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} A group of key codes delimited by + to be depressed as a unit.\& .RE .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .IP \(bu 4 .\} A timeout of the form \fI