You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
762 lines
17 KiB
762 lines
17 KiB
keyd(1) |
|
|
|
# NAME |
|
|
|
*keyd* - A key remapping daemon. |
|
|
|
# SYNOPSIS |
|
|
|
*keyd* [command] [options] |
|
|
|
# COMMANDS |
|
|
|
*monitor* |
|
Print key events. Useful for discovering key names and debugging. |
|
|
|
*bind <binding> [<binding>...]* |
|
Add the supplied bindings to all active configs. See _Bindings_ for details. |
|
|
|
*listen* |
|
Print layer state changes of the running keyd daemon to stdout. Useful for scripting. |
|
|
|
*list-keys* |
|
List valid key names. |
|
|
|
# OPTIONS |
|
|
|
*-v, --version* |
|
Print the current version and exit. |
|
|
|
*-h, --help* |
|
Print help and exit. |
|
|
|
# DESCRIPTION |
|
|
|
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). |
|
|
|
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. |
|
|
|
*NOTE:* |
|
|
|
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 *<backspace>+<escape>+<enter>* will force keyd to |
|
terminate. |
|
|
|
# CONFIGURATION |
|
|
|
Configuration files are stored in _/etc/keyd/_ and are loaded upon initialization. |
|
Changes to these files can be triggered using the reload command (sudo keyd reload). |
|
|
|
A valid config file has the extension _.conf_ and *must* begin with an _[ids]_ |
|
section that has one of the following forms: |
|
|
|
``` |
|
[ids] |
|
|
|
<vendor id 1>:<product id 1> |
|
<vendor id 2>:<product id 2> |
|
... |
|
``` |
|
|
|
or |
|
|
|
``` |
|
[ids] |
|
|
|
* |
|
-<vendor id 1>:<product id 1> |
|
-<vendor id 2>:<product id 2> |
|
... |
|
``` |
|
|
|
The first form specifies a list of ids to be explicitly matched, while the |
|
second matches any id which has not been explicitly excluded. |
|
|
|
For example: |
|
|
|
``` |
|
[ids] |
|
* |
|
-0123:4567 |
|
``` |
|
|
|
|
|
Will match all devices which *do not*(2) have the id _0123:4567_, while: |
|
|
|
``` |
|
[ids] |
|
0123:4567 |
|
``` |
|
|
|
will exclusively match any devices which do. |
|
|
|
Each subsequent section of the file corresponds to a _layer_ (with the exception |
|
of _[global]_ (see _GLOBALS_). |
|
|
|
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`). |
|
|
|
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). |
|
|
|
Note 2: The wildcard will only match devices which keyd identifies as keyboards. |
|
keyd is also capable of *managing mice* (e.g to facilitate clearing |
|
of oneshot modifiers on click), but their ids must be explicitly listed. |
|
|
|
## Layers |
|
|
|
A layer is a collection of _bindings_, 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 _main_ and is where common bindings should be defined. |
|
|
|
For example, the following config snippet defines a layer called _nav_ |
|
and creates a toggle for it in the _main_ layer: |
|
|
|
``` |
|
[main] |
|
|
|
capslock = layer(nav) |
|
|
|
[nav] |
|
|
|
h = left |
|
k = up |
|
j = down |
|
l = right |
|
``` |
|
|
|
When capslock is held, the _nav_ layer occludes the _main_ layer |
|
causing _hjkl_ to function as the corresponding arrow keys. |
|
|
|
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. |
|
|
|
These layers play nicely with other modifiers and preserve existing stacking |
|
semantics. |
|
|
|
For example: |
|
|
|
``` |
|
[main] |
|
|
|
capslock = layer(capslock) |
|
|
|
[capslock:C] |
|
|
|
j = down |
|
``` |
|
|
|
will cause _capslock_ to behave as _control_, except in the case of _control+j_, which will |
|
emit _down_. This makes it trivial to define custom modifiers which don't interfere with |
|
one another. |
|
|
|
Formally, each layer heading has the following form: |
|
|
|
``` |
|
"[" <layer name>[:<modifier set>] "]" |
|
``` |
|
|
|
Where _<modifier_set>_ has the form: |
|
|
|
_<modifier1>[-<modifier2>]..._ |
|
|
|
and each modifier is one of: |
|
|
|
*C* - Control++ |
|
*M* - Meta/Super++ |
|
*A* - Alt++ |
|
*S* - Shift++ |
|
*G* - AltGr |
|
|
|
Finally, each layer heading is followed by a set of bindings which take the form: |
|
|
|
<key> | <alias> = <key>|<macro>|<action> |
|
|
|
for a description of <action> and <macro> see _ACTIONS_ and _MACROS_. |
|
|
|
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. |
|
|
|
For example, _meta_ is actually bound to _layer(meta)_, where _meta_ is |
|
internally defined as _meta:M_. |
|
|
|
A consequence of this is that overriding modifier keys is a simple matter of |
|
adding the desired bindings to appropriate pre-defined layer. |
|
|
|
Thus |
|
|
|
``` |
|
[ids] |
|
* |
|
|
|
[control] |
|
j = down |
|
``` |
|
|
|
is a completely valid config, which does what the benighted user might expect. Internally, |
|
the full config actually looks something like this: |
|
|
|
``` |
|
[ids] |
|
* |
|
|
|
[main] |
|
leftcontrol = layer(control) |
|
rightcontrol = layer(control) |
|
|
|
[control:C] |
|
j = down |
|
``` |
|
|
|
|
|
|
|
## Composite Layers |
|
|
|
A special kind of layer called a *composite layer* can be defined by creating a |
|
layer with a name consisting of existing layers delimited by _+_. The resultant |
|
layer will be activated and given precedence when all of its constituents are |
|
activated. Composite layers always inherit the modifiers of their constituent |
|
layers and cannot be explicitly assigned. |
|
|
|
E.G |
|
|
|
``` |
|
[main] |
|
capslock = layer(capslock) |
|
|
|
[capslock:C] |
|
[capslock+shift] |
|
|
|
h = left |
|
``` |
|
|
|
Will cause the sequence _control+shift+h_ to produce _left_, while preserving |
|
the expected functionality of _capslock_ and _shift_ in isolation. |
|
|
|
*Note:* composite layers *must* always be defined _after_ the layers of which they |
|
are comprised. |
|
|
|
That is: |
|
|
|
``` |
|
[layer1] |
|
[layer2] |
|
[layer1+layer2] |
|
``` |
|
|
|
and not |
|
|
|
``` |
|
[layer1+layer2] |
|
[layer1] |
|
[layer2] |
|
``` |
|
|
|
## Layouts |
|
|
|
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 current layout can be set using the _setlayout_ |
|
action. |
|
|
|
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 *require the use of keyd's compose definitions* (see *Unicode |
|
Support*) |
|
|
|
E.G |
|
|
|
``` |
|
# 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) |
|
``` |
|
|
|
|
|
## Unicode Support |
|
|
|
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. |
|
|
|
In order for this to work, the sequences defined in the compose file shipped |
|
with keyd (_/usr/share/keyd/keyd.compose_) must be accessible. This can be achieved |
|
globally by copying the file to the appropriate location in |
|
_/usr/share/X11/locale_, or on a per-user basis by symlinking it to |
|
~/.XCompose. |
|
|
|
E.G |
|
|
|
ln -s /usr/share/keyd/keyd.compose ~/.XCompose |
|
|
|
*Note:* You may have to restart your applications for this to take effect. |
|
|
|
## Aliases |
|
|
|
Each key may optionally be assigned to an *alias*. 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. |
|
|
|
For example, the keys 'leftmeta' and |
|
'rightmeta' are bound to the alias *meta* by default. Thus the binding 'meta = |
|
a' is equivalent to the bindings 'leftmeta = a' and 'rightmeta = a'. |
|
|
|
Aliases are defined in a special section called 'aliases' where each line takes |
|
the form: |
|
|
|
<key> = <name> |
|
|
|
where _<key>_ must be a valid key name. |
|
|
|
Note that <name> 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. |
|
|
|
For example: |
|
|
|
``` |
|
/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 |
|
``` |
|
|
|
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. |
|
|
|
## File Inclusion |
|
|
|
Config files may include other files located within the config directory using |
|
the _include_ keyword. A line of the form *include <file>* 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. |
|
|
|
Making strategic use of these statements makes it possible to share common |
|
functionality between configs. |
|
|
|
Include paths are relative and must be placed in one of the following |
|
directories: |
|
- /etc/keyd/ |
|
- /usr/share/keyd/ |
|
|
|
E.G |
|
|
|
``` |
|
/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 |
|
... |
|
|
|
``` |
|
|
|
Limitations: |
|
|
|
- All include statements should appear after the [ids] section in the including file. |
|
- Included files should not contain an ids section. |
|
- Included files should not include other files (inclusion is non-recursive). |
|
- Included files should not end in .conf. |
|
|
|
|
|
# GLOBALS |
|
|
|
A special section called _[global]_ may be defined in the file |
|
and can contain any of the following options: |
|
|
|
*macro_timeout:* The time (in milliseconds) separating the initial execution of a macro |
|
sequence and the first repetition. |
|
(default: 600) |
|
|
|
*macro_repeat_timeout:* The time separating successive executions of a macro. |
|
(default: 50) |
|
|
|
*layer_indicator:* If set, this will turn the capslock light on whenever a layer with a non-empty modifier set |
|
is active. |
|
(default: 0) |
|
|
|
*Note:* Unicode characters and key sequences are treated as macros, and |
|
are consequently affected by the corresponding timeout options. |
|
|
|
# MACROS |
|
|
|
Various keyd actions accept macro expressions. |
|
|
|
A valid macro expression has one of the following forms: |
|
|
|
. macro(<exp>) |
|
. [<modifier 1>[-<modifier 2>...]-<key> |
|
|
|
Where _<exp>_ has the form _<token1> [<token2>...]_ and each token is one of: |
|
|
|
- a valid key code. |
|
- a type 2. macro. |
|
- a contiguous group of characters, each of which is a valid key code. |
|
- a group of key codes delimited by + to be depressed as a unit. |
|
- a timeout of the form _<time>ms_ (where _<time>_ < 1024). |
|
|
|
The following are all valid macro expressions: |
|
|
|
- C-a |
|
- macro(C-a) |
|
- macro(control+a) |
|
- A-M-x |
|
- macro(Hello space World) |
|
- macro(h e l l o space w o r ld) (identical to the above) |
|
- macro(C-t 100ms google.com enter) |
|
|
|
|
|
# ACTIONS |
|
|
|
A key may optionally be bound to an _action_ which accepts zero or more |
|
arguments. |
|
|
|
*oneshot(<layer>)* |
|
If tapped, activate the supplied layer for the duration of the next keypress. |
|
If _<layer>_ is a modifier layer then it will cause the key to behave as the |
|
corresponding modifiers while held. |
|
|
|
*layer(<layer>)* |
|
Activate the given layer for the duration of the keypress. |
|
|
|
*setlayout(<layout>)* |
|
Set the current layout. |
|
|
|
*toggle(<layer>)* |
|
Permanently toggle the state of the given layer. |
|
|
|
*toggle2(<layer>, <macro>)* |
|
Equivalent to *toggle*, but additionally executes the supplied macro before |
|
toggling the layer. |
|
|
|
*overload(<layer>, <action>)* |
|
Activates the given layer while held and executes <action> on tap. |
|
|
|
*clear()* |
|
Clear any active layers (the active layout is preserved). |
|
|
|
*timeout(<action 1>, <timeout>, <action 2>)* |
|
If the key is held in isolation for more than _<timeout> ms_, activate the first |
|
action, if the key is held for less than _<timeout> ms_ or another key is struck |
|
before <timeout> ms expires, execute the first action. |
|
|
|
E.G |
|
|
|
timeout(a, 500, layer(control)) |
|
|
|
Will cause the assigned key to behave as _control_ if it is held for more than |
|
500 ms. |
|
|
|
*swap(<layer>)* |
|
Swap the currently active layer with the supplied one. The supplied layer is |
|
active for the duration of the depression of the current layer's activation |
|
key. |
|
|
|
``` |
|
[control] |
|
|
|
x = swap(xlayer) |
|
|
|
[xlayer] |
|
|
|
s = C-s |
|
b = S-insert |
|
``` |
|
|
|
*swap2(<layer>, <macro>)* |
|
|
|
Identical to *swap*, but accepts a macro to be executed immediately after the layer change. |
|
|
|
*macro2(<timeout>, <repeat timeout>, <macro>)* |
|
Creates a macro with the given timeout and repeat timeout. If a timeout value of 0 is used, |
|
macro repeat is disabled. |
|
|
|
Note that <macro> must be a valid macro expression. |
|
|
|
E.G |
|
``` |
|
macro2(400, 50, macro(Hello space World)) |
|
macro2(120, 80, left) |
|
``` |
|
|
|
*command(<shell command>)* |
|
Execute the given shell command. |
|
|
|
E.G |
|
|
|
command(brightness down) |
|
|
|
*NOTE:* Commands are executed by the user running the keyd process (probably root), |
|
use this feature judiciously. |
|
|
|
*noop* |
|
Do nothing. |
|
|
|
# IPC |
|
|
|
To facilitate extensibility, keyd employs a client-server model accessible |
|
through the use of *-e*. The keymap can thus be conceived of as a |
|
living entity that can be modified at run time. |
|
|
|
In addition to allowing the user to try new bindings on the fly, this |
|
enables the user to fully leverage keyd's expressive power from other programs |
|
without incurring a performance penalty. |
|
|
|
For instance, the user may use this functionality to write a script which |
|
alters the keymap when they switch between different tmux sessions. |
|
|
|
The application remapping tool (*keyd-application-mapper(1)*) which ships with keyd |
|
is a good example of this. It is a small python script which performs event |
|
detection for the various display servers (e.g X/sway/gnome, etc) and feeds the |
|
desired mappings to the core using _-e_. |
|
|
|
*NOTE:* Users with access to the keyd socket should be considered privileged |
|
(i.e assumed to have access to the entire system.). |
|
|
|
## Bindings |
|
|
|
The _bind_ command accepts one or more _bindings_, each of which must have the following form: |
|
|
|
\[<layer>.\]<key> = <key>|<macro>|<action> |
|
|
|
Where _<layer>_ is the name of an (existing) layer in which the key is to be bound. |
|
|
|
As a special case, the string "reset" may be used in place of a binding, in |
|
which case the current keymap will revert to its original state (all |
|
dynamically applied bindings will be dropped). |
|
|
|
Examples: |
|
|
|
``` |
|
$ keyd bind '- = C-c' |
|
$ keyd bind reset '+ = C-c' # Reset the keyboard before applying the '+' binding (drops the previous '-' binding) |
|
``` |
|
|
|
By default expressions apply to the most recently active keyboard. |
|
|
|
# EXAMPLES |
|
|
|
## Example 1 |
|
|
|
Make _esc+q_ toggle the dvorak letter layout. |
|
|
|
``` |
|
[ids] |
|
* |
|
|
|
[main] |
|
esc = layer(esc) |
|
|
|
[dvorak] |
|
|
|
a = a |
|
s = o |
|
... |
|
|
|
[esc] |
|
|
|
q = toggle(dvorak) |
|
``` |
|
|
|
## Example 2 |
|
|
|
Invert the behaviour of the shift key without breaking modifier behaviour. |
|
|
|
``` |
|
[ids] |
|
* |
|
|
|
[main] |
|
1 = ! |
|
2 = @ |
|
3 = # |
|
4 = $ |
|
5 = % |
|
6 = ^ |
|
7 = & |
|
8 = * |
|
9 = ( |
|
0 = ) |
|
|
|
[shift] |
|
0 = 0 |
|
1 = 1 |
|
2 = 2 |
|
3 = 3 |
|
4 = 4 |
|
5 = 5 |
|
6 = 6 |
|
7 = 7 |
|
8 = 8 |
|
9 = 9 |
|
``` |
|
|
|
## Example 3 |
|
|
|
Tapping control once causes it to apply to the next key, tapping it twice |
|
activates it until it is pressed again, and holding it produces expected |
|
behaviour. |
|
|
|
``` |
|
[main] |
|
|
|
control = oneshot(control) |
|
|
|
[control] |
|
|
|
control = toggle(control) |
|
``` |
|
|
|
## Example 4 |
|
|
|
Meta behaves as normal except when \` is pressed, after which the alt_tab layer |
|
is activated for the duration of the leftmeta keypress. Subsequent actuations |
|
of _will thus produce A-tab instead of M-\\_. |
|
|
|
``` |
|
[meta] |
|
|
|
` = swap(alt_tab, A-tab) |
|
|
|
[alt_tab:A] |
|
|
|
tab = A-S-tab |
|
` = A-tab |
|
``` |
|
|
|
## Example 5 |
|
|
|
``` |
|
# Uses the compose key functionality of the display server to generate |
|
# international glyphs. # For this to work 'setxkbmap -option |
|
# compose:menu' must # be run after keyd has started. |
|
|
|
# A list of sequences can be found in /usr/share/X11/locale/en_US.UTF-8/Compose |
|
# on most systems. |
|
|
|
|
|
[main] |
|
|
|
rightalt = layer(dia) |
|
|
|
[dia] |
|
|
|
# Map o to ö |
|
o = macro(compose o ") |
|
|
|
# Map e to € |
|
e = macro(compose c =) |
|
``` |
|
|
|
## Example 6 |
|
|
|
``` |
|
# Tapping both shift keys will activate capslock. |
|
|
|
[shift] |
|
|
|
leftshift = capslock |
|
rightshift = capslock |
|
``` |
|
|
|
## Example 7 |
|
|
|
Capslock will behave as control in all instances except when used |
|
in conjunction with 'h/j/k/l' in which case it will produce arrow |
|
keys. If tapped, it will function as escape. |
|
|
|
``` |
|
[main] |
|
capslock = overload(capslock, esc) |
|
esc = capslock |
|
|
|
[capslock:C] |
|
h = left |
|
k = up |
|
j = down |
|
l = right |
|
``` |
|
|
|
# AUTHOR |
|
|
|
Written by Raheman Vaiya (2017-). |
|
|
|
# BUGS |
|
|
|
Please file any bugs or feature requests at the following url: |
|
|
|
<https://github.com/rvaiya/keyd/issues>
|
|
|