| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Configuration | Example | Functional principle | keymapperctl | Installation | Building | Changelog
A cross-platform context-aware key remapper. It allows to:
Configuration files are easily written by hand and mostly consist of lines with input expressions and corresponding output expressions separated by >>:
# comments start with # and continue until the end of a line
CapsLock >> Backspace
Z >> Y
Y >> Z
Control{Q} >> Alt{F4}Unless overridden using the command line argument -c, the configuration is read from keymapper.conf, which is looked for in the common places:
each with an optional keymapper subdirectory and finally in the working directory.
The command line argument -u causes the configuration to be automatically reloaded whenever the configuration file changes.
⚠️ In case of emergency: You can always press the special key combination Shift+Escape+K to terminate keymapperd.
The keys are named after their scan codes and are not affected by the present keyboard layout. The names have been chosen to match on what the web browsers have agreed upon, so this handy website can be used to get a key's name. For convenience the letter and digits keys are also named A to Z and 0 to 9. The logical keys Shift, Control, Alt and Meta are also defined (each matches the left and right modifier keys). There are also virtual keys for state switching and an Any key.
The mouse buttons are named ButtonLeft, ButtonRight, ButtonMiddle, ButtonBack and ButtonForward, the wheel is named WheelUp, WheelDown, WheelLeft and WheelRight.
It is also possible to directly provide the scan code instead of the key name in decimal or hex notation (e.g. 159, 0x9F).
⚠️ Beware that the configuration file is case sensitive.
Input expressions consist of one or more key names separated by spaces or parenthesis, which give them different meaning:
The output expression format is analogous to the input expression format:
Mappings are applied in consecutive order until a match is found, therefore their order is of importance. While the following outputs A as soon as Meta is pressed:
Meta >> A
Meta{X} >> BThe other way round, nothing is output when Meta is pressed alone because depending on whether an X follows, either B or A is output:
Meta{X} >> B
Meta >> A⚠️ You may want to add a @forward-modifiers directive to your configuration, which ensures that the common mouse-modifiers are never held back:
@forward-modifiers Shift Control AltFor a detailed description of how the mapping is applied, see the Functional principle section.
Context blocks allow to enable mappings only in specific contexts. A context can be defined by system, the focused window title, window class, process path or the input device/device-id an event originates from.
A block continues until the next block (respectively the end of the file). The block which applies in all contexts can be reopened using default. e.g.:
[default]
[title = "Visual Studio"]
[system = "Linux", class != "qtcreator"] # '!=' inverses a condition
[device = "Some Device Name"] # consecutive blocks share mappings
[device = "Some Other Device"]
[system = "Windows" path = "notepad.exe"] # comma separator is optional⚠️ The device/device-id filters on Windows require the installation of a virtual device driver. The process path may not be available on Wayland and for processes with higher privileges. The window title is not available on MacOS.
The values of a context can be easily obtained using the Next Key Info function of the tray icon or keymapperctl.
Class and device filters match contexts with the exact same string, others match contexts containing the string. For finer control regular expressions can be used. These have to be delimited with slashes. Optionally i can be appended to make the comparison case insensitive:
[title = /Visual Studio Code|Code OSS/i]Additionally a modifier filter allows to activate blocks depending on the state of one or more keys:
# active when Virtual1 is down and Virtual2 is not
[modifier = "Virtual1 !Virtual2"]Finally blocks can be activated depending on whether two strings match. Macros may be used for generating the strings. e.g.:
# active when environment variable has some specific value
[getenv["HOSTNAME"] = "LaptopMum"]To simplify mapping of one input expression to different output expressions, it can be mapped to an abstract command first. The command name can be chosen arbitrarily but must not be a key name. The configuration is case sensitive and all key names start with a capital letter, so it is advisable to begin command names with a lowercase letter:
Control{B} >> buildSubsequently this command can be mapped to one output expression per context. The last active mapping overrides the previous ones:
build >> Control{B}
[title="Visual Studio"]
build >> (Shift Control){B}By inserting [stage] a configuration can be split into stages, which are evaluated separately. The output of a stage is the input of the following stage, where it can be mapped further:
# adjust keyboard layout
Z >> Y
Y >> Z
# map keys output by previous stage
[stage]
Control{Z} >> undoWhen an output expression contains ^, it is only applied up to this point, when the input key is pressed. The part after the ^ is not applied until the input is released. Both parts can be empty:
# type "cmd" after the Windows run dialog appeared
Meta{C} >> Meta{R} ^ "cmd" Enter
# prevent key repeat
A >> B^
# output B when A is released
A >> ^BVirtual0 to Virtual255 are virtual keys, which can be used as state switches. They are toggled when used in output expressions:
# toggle Virtual1 whenever ScrollLock is pressed
ScrollLock >> Virtual1
# release Virtual1 when Escape is pressed
Escape >> !Virtual1They can be used as modifiers in input expressions:
# map A to B when Virtual1 is down
Virtual1{A} >> B
# map E to F when Virtual1 is NOT down
!Virtual1 E >> F
# keep G held as long as Virtual1 is down
Virtual1 >> G
# output H when Virtual1 is released
!Virtual1 >> HToggling virtual keys can also have immediate effects. Using them as modifiers is toggling them twice:
# toggle Virtual1 before and after pressing B
# this effectively maps D to A B C
Virtual1 >> A ^ C
D >> Virtual1{B}
# {} may also be empty. This maps C to A B
Virtual2 >> B
Virtual1 >> A Virtual2{}
C >> Virtual1{}ContextActive exists separately for each context and is toggled when the context becomes active/inactive:
# toggle Virtual1 when entering and when leaving context
[title="Firefox"]
ContextActive >> Virtual1 ^ !Virtual1Any can be used in input and output expressions. In input expressions it matches any key and in output expressions it outputs the matched input.
# swap Control and Shift
Control{Any} >> Shift{Any}
Shift{Any} >> Control{Any}To exclude an application from any mapping this can be added to the top of the configuration:
[title="Remote Desktop"]
Any >> Any
[default]On the output side it can also be used to release previously pressed modifiers first:
A >> !Any AInput expressions can contain timeouts in milliseconds e.g. 500ms to specify the minimum duration a key needs to be held, or the minimum duration between two events. This can also be negated like !500ms to specify maximum durations:
# output Escape when CapsLock is held for a while
CapsLock{500ms} >> Escape
# output Escape when Control is pressed and released quickly
Control{!250ms} >> Escape
# output C when B quickly follows an A
A !250ms B >> C
# output D when A is tapped twice quickly
A{!200ms} !200ms A{!200ms} >> DIn output expressions it can be used to delay output or keep a key held for a while. e.g.:
A >> B 500ms C{1000ms}⚠️ Delaying output also stops the processing of input for the given duration. For pressing and releasing keys asynchronously one has to resort to keymapperctl. e.g.:
# keep mouse button held for 5 seconds
Meta{Space} >> $(keymapperctl --press ButtonLeft --wait 5000 --release ButtonLeft)Output expressions can contain string literals with characters to type. The typeable characters depend on your keyboard layout. e.g.:
AltRight{A} >> '@'
# long lines can be split using '\'
Meta{A} K >> \
"Kind regards,\n" \
"Douglas Quaid"They can also be used in input expressions to match when the character are typed. e.g.:
? 'Abc' >> Backspace Backspace "Matched!"⚠️ The keyboard layout is evaluated when the configuration is loaded, switching is not yet supported.
For convenience aliases for keys and even sequences can be defined. e.g.:
Win = Meta
Boss = Virtual # assigns an unused virtual key
Alt = AltLeft | AltRight # defines a logical key
proceed = Tab Tab EnterIn strings, regular expressions and terminal commands aliases can be inserted using ${Var} or $Var. e.g.:
greet = "Hello"
F1 >> "${greet} World"An alias can also be parameterized to create a macro. The arguments are provided in square brackets and referenced by $0, $1... e.g.:
print = $(echo $0 $1 >> ~/keymapper.txt)
F1 >> print["pressed the key", F1]
# multiple mappings on one line can be separated using ;
swap = $0 >> $1; \
$1 >> $0
swap[Y, Z]There are a few builtin macros repeat[EXPR, N], length[STR], default[A, B], apply[EXPR, ARGS...], add/sub/mul/div/mod/min/max[A, B], getenv["VAR"] which allow to generate mappings and define some more advanced macros. e.g.:
# when last character of string is typed, undo using backspace and output new string
substitute = ? "$0" >> repeat[Backspace, sub[length["$0"], 1]] "$1"
substitute["Cat", "Dog"]
# generate the string to output with an external program
substituteExec = ? "$0" >> repeat[Backspace, sub[length["$0"], 1]] \
$(keymapperctl --type "$($1)")
substituteExec[":whoami", "whoami"]
# add a `FN >> Meta{N}` mapping for each function key
apply[F$0 >> Meta{$0}, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]$$ is substituted with the actual parameter count, which allows to add overloads:
log1 = $(echo "$0" >> $LOG_FILE)
log2 = $(echo "[$1]" "$0" >> $LOG_FILE)
# switch builds log1 or log2, which is then called with the second argument list
switch = $0$1
log = switch["log", $$][$0, $1]
F1 >> log["info message"]
F2 >> log["error message", "state"]$() can be used to embed terminal commands in output expressions, which should be executed when triggered. e.g.:
Meta{C} >> $(C:\windows\system32\calc.exe) ^
Meta{W} >> $(exo-open --launch WebBrowser) ^
# on Windows console applications are revealed by prepending 'start'
Meta{C} >> $(start powershell) ^⚠️ You may want to append ^ to ensure that the command is not executed repeatedly as long as the input is kept held.
The following directives, which are lines starting with an @, can be inserted in the configuration file:
forward-modifiers allows to set a list of keys which should never be held back. e.g.:
@forward-modifiers Shift Control AltIt effectively forwards these keys in each stage immediately, like:
Shift >> Shift
Control >> Control
Alt >> Altand automatically suppresses the forwarded keys in the output:
# implicitly turned into 'Control{A} >> !Control Shift{B}'
Control{A} >> Shift{B}allow-unmapped-commands and enforce-lowercase-commands change the way commands are validated. When used, then best together, so typing errors in key names are still detected. e.g.:
@allow-unmapped-commands
@enforce-lowercase-commands
A >> command1 # OK, even though 'command1' has no output mapped
command2 >> B # OK, even though no input maps to 'command2'
C >> Command3 # error: invalid key 'Command3'
Command4 >> D # error: invalid key 'Command4'virtual-keys-toggle allows to change the behavior of virtual keys in outputs. e.g.
@virtual-keys-toggle true # true is (still) the default
# toggle Virtual1
F1 >> Virtual1@virtual-keys-toggle false
# press Virtual1
F1 >> Virtual1
# release Virtual1
F2 >> !Virtual1
# toggle Virtual1
Virtual1{F3} >> !Virtual1
F3 >> Virtual1grab-device, skip-device, grab-device-id, skip-device-id allow to explicitly specify the devices which keymapperd should grab. By default all keyboard devices are grabbed and mice only when mouse buttons or wheels were mapped. The filters work like the context filters. e.g.:
# do not grab anything but this one keyboard
@skip-device /.*/
@grab-device "Some Device Name"include and include-optional can be used to include a file in the configuration. e.g.:
@include "filename.conf"
# does not fail when the file is missing
@include-optional "$HOME/.keymapper.conf"done stops parsing the configuration.
options allows to set the command line options in the configuration. e.g.:
@options update no-tray no-notify verbose no-updatetoggle-active allows to set a sequence which de-/activates keymapper. e.g.:
@toggle-active ScrollLockThe following directives are for working around current limitations and can hopefully be removed in the future:
linux-compose-key sets the key to use for composing special characters on Linux. e.g.:
@linux-compose-key AltRight{Insert}linux-highres-wheel-events enables the handling of high-resolution wheel events on Linux.
macos-toggle-fn allows to toggle the default state of the FN key on MacOS.
macos-iso-keyboard should be added when the IntlBackslash and the Backquote keys are mixed up on MacOS.
Please see and consider contributing to the ever growing wiki.
The author's personal configuration may also serve as an inspiration (which itself took some inspiration from DreymaR's Big Bag Of Keyboard Tricks).
To get an impression of what a very advanced configuration can look like, check out a power-user's configuration.
For advanced application it is good to know how the mapping is applied:
The application keymapperctl allows to control the running keymapper process from external applications.
It can be run arbitrarily often with one or more of the following arguments:
--input <sequence> injects an input key sequence. --output <sequence> injects an output key sequence. --type "string" types a string of characters. --type-stdin types a string of characters read from stdin. --notify "string" shows a notification. --next-key-info outputs information about the next key press. --set-config "file" sets a new configuration. --is-pressed <key> sets the result code 0 when a virtual key is down. --is-released <key> sets the result code 0 when a virtual key is up. --press <key> presses a key. --release <key> releases a key. --toggle <key> toggles a virtual key. --wait-pressed <key> waits until a virtual key is pressed. --wait-released <key> waits until a virtual key is released. --wait-toggled <key> waits until a virtual key is toggled (can also be Any). --timeout <millisecs> sets a timeout for the following operation. --wait <millisecs> unconditionally waits a given amount of time. --instance <id> replaces another keymapperctl process with the same id. --print "string" outputs the string to the console. --result outputs the result code to the console (0 is success). --restart starts processing the first operation again.
The program is split into two parts:
For security and efficiency reasons, the communication between the two parts is kept as minimal as possible.
The command line argument -v can be passed to both processes to output verbose logging information to the console.
Pre-built packages can be downloaded from the latest release page. Arch Linux users can install an up to date build from the AUR.
After installation you can try it out by creating a configuration file and starting it using:
sudo systemctl start keymapperd
keymapper -uTo install permanently, add keymapper to the desktop environment's auto-started applications and enable the keymapperd service:
sudo systemctl enable keymapperdTo make context awareness work under Wayland, the compositor has to inform keymapper about the focused window. For wlroots-based compositors this works out of the box, other compositors need to send the information using the D-Bus interface. A GNOME Shell extension and a KWin script are provided doing this.
The values for the device-id context filters are obtained by looking for symlinks in /dev/input/by-id.
The MacOS build depends on Karabiner-Element's virtual device driver. One can install it either directly from Karabiner-DriverKit-VirtualHIDDevice v8.x, or along with Karabiner Elements v16.x.
A Homebrew formula is provided for building and installing keymapper:
brew tap houmain/tap
brew install --HEAD keymapperFinally keymapperd and keymapper can be added to the launchd daemons/agents by calling:
sudo keymapper-launchd addAn installer and a portable build can be downloaded from the latest release page.
Most conveniently but possibly not always the very latest version can be installed using a package manager:
# install using winget
winget install keymapper
# install using Chocolatey
choco install keymapperThe installer configures the Windows task scheduler to start keymapper.exe and keymapperd.exe at logon.
After installation you can open the configuration file by clicking the "Configuration" entry in the tray icon menu.
To use the portable build, simply start both keymapper.exe and keymapperd.exe. It is advisable to start keymapperd.exe with elevated privileges. Doing not so has a few limitations. Foremost the Windows key cannot be mapped reliably and applications which are running as administrator (like the task manager) resist any mapping.
When no virtual device driver is installed, one can explicitly enable/disable the two hooks keyboard and mouse. e.g.: @grab-device mouse.
The device filter requires the installation of a virtual device driver. The only known freely available is Interception, which unfortunately has a severe bug, that makes devices stop working after being dis-connected too often. Until this is fixed it not advisable to use it and it should only be installed when filtering by device is absolutely required. The interception.dll needs to be placed next to the keymapperd.exe.
A C++17 conforming compiler is required. A script for the CMake build system is provided.
Installing dependencies on Linux systems:
On Arch Linux and derivativessudo pacman -S git base-devel
sudo pacman -S libusb dbus
# optional for Wayland support
sudo pacman -S wayland libxkbcommon
# optional for X11 support
sudo pacman -S libx11 libxkbcommon-x11
# optional for tray icon support
sudo pacman -S libappindicator-gtk3sudo apt install git cmake build-essential
sudo apt install libudev-dev libusb-1.0-0-dev libdbus-1-dev
# optional for Wayland support
sudo apt install libwayland-dev libxkbcommon-dev
# optional for X11 support
sudo apt install libx11-dev libx11-xcb-dev libxkbcommon-x11-dev
# optional for tray icon support
sudo apt install libayatana-appindicator3-devsudo dnf install git cmake make gcc-c++
sudo dnf install libudev-devel libusb1-devel dbus-devel
# optional for Wayland support
sudo dnf wayland-devel libxkbcommon-devel
# optional for X11 support
sudo dnf install libX11-devel
# optional for tray icon support
sudo dnf install libappindicator-gtk3-develChecking out the source:
git clone https://github.com/houmain/keymapperBuilding:
cd keymapper
# to build with debug symbols append: -DCMAKE_BUILD_TYPE=Debug
cmake -B build
cmake --build build -j4Testing:
To try it out, simply create a configuration file and start it using:
sudo build/keymapperd -vand
build/keymapper -vIt is released under the GNU GPLv3. It comes with absolutely no warranty. Please see LICENSE for license details.
| Back | FazBrowse Home | New Git URL |