{"id":13894144,"url":"https://github.com/houmain/keymapper","last_synced_at":"2025-05-15T04:06:09.536Z","repository":{"id":39584440,"uuid":"177397013","full_name":"houmain/keymapper","owner":"houmain","description":"A cross-platform context-aware key remapper.","archived":false,"fork":false,"pushed_at":"2025-05-12T19:22:37.000Z","size":1295,"stargazers_count":845,"open_issues_count":10,"forks_count":35,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-05-12T20:43:05.078Z","etag":null,"topics":["accessibility","automation","context-awareness","cross-platform","keyboard-layout","keyboard-shortcuts","keymapper","productivity","wayland"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/houmain.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-03-24T09:57:51.000Z","updated_at":"2025-05-12T19:22:40.000Z","dependencies_parsed_at":"2023-01-23T04:46:06.079Z","dependency_job_id":"e571c59c-40bd-4628-b645-951d1b1ac2aa","html_url":"https://github.com/houmain/keymapper","commit_stats":null,"previous_names":[],"tags_count":90,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houmain%2Fkeymapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houmain%2Fkeymapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houmain%2Fkeymapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houmain%2Fkeymapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/houmain","download_url":"https://codeload.github.com/houmain/keymapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270646,"owners_count":22042859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","automation","context-awareness","cross-platform","keyboard-layout","keyboard-shortcuts","keymapper","productivity","wayland"],"created_at":"2024-08-06T18:01:24.968Z","updated_at":"2025-05-15T04:06:04.522Z","avatar_url":"https://github.com/houmain.png","language":"C++","funding_links":[],"categories":["C++","Tools"],"sub_categories":["Input"],"readme":"\nkeymapper\n=========\n\u003cp\u003e\n\u003ca href=\"https://github.com/houmain/keymapper/actions/workflows/build.yml\"\u003e\n\u003cimg alt=\"Build\" src=\"https://github.com/houmain/keymapper/actions/workflows/build.yml/badge.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/houmain/keymapper/issues\"\u003e\n\u003cimg alt=\"Issues\" src=\"https://img.shields.io/github/issues-raw/houmain/keymapper.svg\"/\u003e\u003c/a\u003e\n\n\u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e |\n\u003ca href=\"#example-configuration\"\u003eExample\u003c/a\u003e |\n\u003ca href=\"#functional-principle\"\u003eFunctional principle\u003c/a\u003e |\n\u003ca href=\"#keymapperctl\"\u003ekeymapperctl\u003c/a\u003e |\n\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e |\n\u003ca href=\"#building\"\u003eBuilding\u003c/a\u003e |\n\u003ca href=\"https://github.com/houmain/keymapper/releases\"\u003eChangelog\u003c/a\u003e\n\u003c/p\u003e\n\nA cross-platform context-aware key remapper. It allows to:\n\n* Redefine your keyboard layout and shortcuts systemwide or per application.\n* Manage all your keyboard shortcuts in a single configuration file.\n* Change shortcuts for similar actions in different applications at once.\n* Share configuration files between multiple systems (GNU/Linux, Windows, MacOS).\n* Specify input and output as [characters](#character-typing) instead of the keys required to type them.\n* Bind keyboard shortcuts to [launch applications](#application-launching).\n* Control the state from external applications using [keymapperctl](#keymapperctl).\n* Use [mouse buttons and wheel](#key-names) in your mappings.\n\nConfiguration\n-------------\nConfiguration files are easily written by hand and mostly consist of lines with [input expressions](#input-expressions) and corresponding [output expressions](#output-expressions) separated by `\u003e\u003e`:\n\n```bash\n# comments start with # and continue until the end of a line\nCapsLock \u003e\u003e Backspace\nZ \u003e\u003e Y\nY \u003e\u003e Z\nControl{Q} \u003e\u003e Alt{F4}\n```\n\nUnless overridden using the command line argument `-c`, the configuration is read from `keymapper.conf`, which is looked for in the common places:\n  * on all systems in `$XDG_CONFIG_HOME` and `$HOME/.config`,\n  * on Linux and MacOS also in `/etc`,\n  * on Windows also in the user's profile, `AppData\\Local` and `AppData\\Roaming` folders,\n\neach with an optional `keymapper` subdirectory and finally in the working directory.\n\nThe command line argument `-u` causes the configuration to be automatically reloaded whenever the configuration file changes.\n\n:warning: **In case of emergency:** You can always press the special key combination \u003ckbd\u003eShift\u003c/kbd\u003e+\u003ckbd\u003eEscape\u003c/kbd\u003e+\u003ckbd\u003eK\u003c/kbd\u003e to terminate `keymapperd`.\n\n### Key names\n\nThe keys are named after their scan codes and are not affected by the present keyboard layout.\nThe names have been chosen to match on what the [web browsers](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values) have agreed upon, so this [handy website](http://keycode.info/) can be used to get a key's name.\nFor 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](#virtual-keys) for state switching, an [Any key](#any-key) and a [No key](#no-key).\n\nThe mouse buttons are named `ButtonLeft`, `ButtonRight`, `ButtonMiddle`, `ButtonBack` and `ButtonForward`, the wheel is named `WheelUp`, `WheelDown`, `WheelLeft` and `WheelRight`.\n\nIt is also possible to directly provide the scan code instead of the key name in decimal or hex notation (e.g. `159`, `0x9F`).\n\n:warning: Beware that the configuration file is **case sensitive**.\n\n### Input expressions\n\nInput expressions consist of one or more key names separated by spaces or parenthesis, which give them different meaning:\n\n  * `A B` means that keys have to be pressed successively (released in any order).\n  * `(A B)` means that keys have to be pressed simultaneously in any order.\n  * `A{B}` means that a key has to be held while another is pressed.\n  * `!A` means that a key must not be pressed.\n  * Groups and modifiers can also be nested like `A{B{C}}` or `(A B){C}`.\n  * `\"...\"` string literals match when the enclosed [characters are typed](#character-typing).\n  * With an initial `?` the mapping gets skipped as long as it only partially matches.\n\n### Output expressions\n\nThe output expression format is analogous to the input expression format:\n\n  * `A B` means that keys are pressed successively.\n  * `(A B)` means that both keys are pressed simultaneously.\n  * `A{B}` means that a key is held while another is pressed.\n  * `!A` means that the (potentially pressed) key should be released before the rest of the expression is applied. This also works for virtual keys.\n  * `^` splits the output in two parts, one which is applied when the input key is pressed and one when the [key is released](#output-on-key-release).\n  * `\"...\"` string literals allow to specify [characters to type](#character-typing).\n  * `$()` can be used for [launching applications](#application-launching).\n  * An empty expression can be used to suppress any output.\n\n### Order of mappings\n\nMappings 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:\n\n```bash\nMeta    \u003e\u003e A\nMeta{X} \u003e\u003e B\n```\n\nThe other way round, nothing is output when `Meta` is pressed alone because depending on whether an `X` follows, either `B` or `A` is output:\n\n```bash\nMeta{X} \u003e\u003e B\nMeta    \u003e\u003e A\n```\n\n:warning: You may want to add a `@forward-modifiers` [directive](#directives) to your configuration, which ensures that the common mouse-modifiers are never held back:\n\n```python\n@forward-modifiers Shift Control Alt\n```\n\nFor a detailed description of how the mapping is applied, see the [Functional principle](#functional-principle) section.\n\n### Context awareness\n\nContext 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.\\\nA 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.:\n\n```bash\n[default]\n\n[title = \"Visual Studio\"]\n\n[system = \"Linux\", class != \"qtcreator\"] # '!=' inverses a condition\n\n[device = \"Some Device Name\"] # consecutive blocks share mappings\n[device = \"Some Other Device\"]\n\n[system = \"Windows\" path = \"notepad.exe\"] # comma separator is optional\n```\n\n:warning: The `device`/`device-id` filters on Windows require the installation of a [virtual device driver](#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.\n\nThe values of a context can be easily obtained using the _Next Key Info_ function of the tray icon or [keymapperctl](#keymapperctl).\n\nClass and device filters match contexts with the _exact_ same string, others match contexts _containing_ the string.\nFor finer control [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) can be used. These have to be delimited with slashes. Optionally `i` can be appended to make the comparison case insensitive:\n\n```javascript\n[title = /Visual Studio Code|Code OSS/i]\n```\n\nAdditionally a `modifier` filter allows to activate blocks depending on the state of one or more keys:\n\n```bash\n# active when Virtual1 is down and Virtual2 is not\n[modifier = \"Virtual1 !Virtual2\"]\n```\n\n### Abstract commands\n\nTo 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:\n\n```bash\nControl{B} \u003e\u003e build\n```\n\nSubsequently this command can be mapped to one output expression per context. The last active mapping overrides the previous ones:\n\n```bash\nbuild \u003e\u003e Control{B}\n\n[title=\"Visual Studio\"]\nbuild \u003e\u003e (Shift Control){B}\n```\n\n### Multiple stages\n\nBy 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:\n\n```bash\n# adjust keyboard layout\nZ \u003e\u003e Y\nY \u003e\u003e Z\n\n# map keys output by previous stage\n[stage]\nControl{Z} \u003e\u003e undo\n```\n\n### Output on key release\n\nWhen 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:\n\n```bash\n# type \"cmd\" after the Windows run dialog appeared\nMeta{C} \u003e\u003e Meta{R} ^ \"cmd\" Enter\n\n# prevent key repeat\nA \u003e\u003e B^\n\n# output B when A is released\nA \u003e\u003e ^B\n```\n\n### Virtual keys\n\n`Virtual0` to `Virtual255` are virtual keys, which can be used as state switches. They are toggled when used in output expressions and can be used as modifiers in input expressions:\n\n```bash\n# Virtual1 is toggled whenever ScrollLock is pressed\nScrollLock \u003e\u003e Virtual1\n\n# map A to B when Virtual1 is down\nVirtual1{A} \u003e\u003e B\n\n# map E to F when Virtual1 is NOT down\n!Virtual1 E \u003e\u003e F\n\n# keep G held as long as Virtual1 is down\nVirtual1 \u003e\u003e G\n```\n\n`ContextActive` exists separately for each context and is toggled when the context becomes active/inactive:\n\n```bash\n# toggle Virtual1 when entering and when leaving context\n[title=\"Firefox\"]\nContextActive \u003e\u003e Virtual1 ^ Virtual1\n```\n\n### Any key\n\n```Any``` can be used in input and output expressions.\nIn input expressions it matches any key and in output expressions it outputs the matched input.\n\n```bash\n# swap Control and Shift\nControl{Any} \u003e\u003e Shift{Any}\nShift{Any} \u003e\u003e Control{Any}\n```\n\nTo exclude an application from any mapping this can be added to the top of the configuration:\n\n```bash\n[title=\"Remote Desktop\"]\nAny \u003e\u003e Any\n\n[default]\n```\n\nOn the output side it can also be used to release previously pressed modifiers first:\n\n```bash\nA \u003e\u003e !Any A\n```\n\n### No key\n\nInput expressions can contain timeouts in milliseconds e.g. `500ms`, to specify a time in which no key is pressed:\n\n```bash\n# output Escape when CapsLock is held for a while\nCapsLock{500ms} \u003e\u003e Escape\n\n# output Escape when Control is pressed and released quickly\nControl{!250ms} \u003e\u003e Escape\n\n# output C when B quickly follows an A\nA !250ms B \u003e\u003e C\n```\n\nIn output expressions it can be used to delay output or keep a key held for a while. e.g:\n\n```bash\nA \u003e\u003e B 500ms C{1000ms}\n```\n\n### Character typing\n\nOutput expressions can contain string literals with characters to type. The typeable characters depend on your keyboard layout. e.g:\n\n```bash\nAltRight{A} \u003e\u003e '@'\n\n# long lines can be split using '\\'\nMeta{A} K \u003e\u003e \\\n  \"Kind regards,\\n\" \\\n  \"Douglas Quaid\"\n```\n\nThey can also be used in input expressions to match when the character are typed. e.g.:\n\n```bash\n? 'Abc' \u003e\u003e Backspace Backspace \"Matched!\"\n```\n\n:warning: The keyboard layout is evaluated when the configuration is loaded, switching is not yet supported.\n\n### Key aliases / Macros\n\nFor convenience aliases for keys and even sequences can be defined. e.g.:\n\n```bash\nWin = Meta\nBoss = Virtual1\nAlt = AltLeft | AltRight  # defines a logical key\nproceed = Tab Tab Enter\ngreet = \"Hello\"\n```\n\nIn strings, regular expressions and terminal commands aliases can be inserted using `${Var}` or `$Var`. e.g.:\n\n```bash\nF1 \u003e\u003e \"${greet} World\"\n```\n\nAn alias can also be parameterized to create a macro. The arguments are provided in square brackets and referenced by `$0`, `$1`... e.g.:\n```bash\nprint = $(echo $0 $1 \u003e\u003e ~/keymapper.txt)\nF1 \u003e\u003e print[\"pressed the key\", F1]\n```\n\nThere 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]` which allow to generate mappings and define some more advanced macros. e.g:\n\n```bash\n# when last character of string is typed, undo using backspace and output new string\nsubstitute = ? \"$0\" \u003e\u003e repeat[Backspace, sub[length[\"$0\"], 1]] \"$1\"\n\n# generate the string to output with an external program\nsubstituteExec = ? \"$0\" \u003e\u003e \\\n  repeat[Backspace, sub[length[\"$0\"], 1]] \\\n  $(keymapperctl --type \"$($1)\")\n\nsubstitute[\"Cat\", \"Dog\"]\nsubstituteExec[\":whoami\", \"whoami\"]\n\n# add a `FN \u003e\u003e Meta{N}` mapping for each function key\napply[F$0 \u003e\u003e Meta{$0}, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n```\n\n`$$` is substituted with the actual parameter count, which allows to add overloads:\n```bash\nlog1 = $(echo \"$0\" \u003e\u003e $LOG_FILE)\nlog2 = $(echo \"[$1]\" \"$0\" \u003e\u003e $LOG_FILE)\n\n# switch builds log1 or log2, which is then called with the second argument list\nswitch = $0$1\nlog = switch[\"log\", $$][$0, $1]\n\nF1 \u003e\u003e log[\"info message\"]\nF2 \u003e\u003e log[\"error message\", \"state\"]\n```\n\n### Application launching\n\n`$()` can be used to embed terminal commands in output expressions, which should be executed when triggered. e.g.:\n\n```bash\nMeta{C} \u003e\u003e $(C:\\windows\\system32\\calc.exe) ^\nMeta{W} \u003e\u003e $(exo-open --launch WebBrowser) ^\n\n# on Windows console applications are revealed by prepending 'start'\nMeta{C} \u003e\u003e $(start powershell) ^\n```\n\n:warning: You may want to append `^` to ensure that the command is not executed repeatedly as long as the input is kept held.\n\n### Directives\n\nThe following directives, which are lines starting with an `@`, can be inserted in the configuration file:\n\n- `forward-modifiers` allows to set a list of keys which should never be [held back](#order-of-mappings). e.g.:\n  ```python\n  @forward-modifiers Shift Control Alt\n  ```\n  It effectively forwards these keys in each [stage](#multiple-stages) immediately, like:\n  ```bash\n  Shift   \u003e\u003e Shift\n  Control \u003e\u003e Control\n  Alt     \u003e\u003e Alt\n  ```\n  and automatically suppresses the forwarded keys in the output:\n  ```bash\n  # implicitly turned into 'Control{A} \u003e\u003e !Control Shift{B}'\n  Control{A} \u003e\u003e Shift{B}\n  ```\n\n- `allow-unmapped-commands` and `enforce-lowercase-commands` change the way [commands](#abstract-commands) are validated. When used, then best together, so typing errors in key names are still detected. e.g.:\n  ```python\n  @allow-unmapped-commands\n  @enforce-lowercase-commands\n  A \u003e\u003e command1   # OK, even though 'command1' has no output mapped\n  command2 \u003e\u003e B   # OK, even though no input maps to 'command2'\n  C \u003e\u003e Command3   # error: invalid key 'Command3'\n  Command4 \u003e\u003e D   # error: invalid key 'Command4'\n  ```\n\n- `grab-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.\nThe filters work like the [context filters](#context-awareness). e.g.:\n  ```python\n  # do not grab anything but this one keyboard\n  @skip-device /.*/\n  @grab-device \"Some Device Name\"\n  ```\n\n- `include` can be used to include a file in the configuration. e.g.:\n  ```python\n  @include \"filename.conf\"\n  ```\n\n- `done` stops parsing the configuration.\n\n- `options` allows to set the command line options in the configuration. e.g.:\n\n  ```python\n  @options update no-tray no-notify verbose no-update\n  ```\n\nThe following directives are for working around current limitations and can hopefully be removed in the future:\n\n- `macos-toggle-fn` allows to toggle the default state of the `FN` key on MacOS.\n\n- `macos-iso-keyboard` should be added when the `IntlBackslash` and the `Backquote` keys are mixed up on MacOS.\n\n- `compose-key` sets the key to use for composing special characters on Linux. e.g.:\n\n  ```python\n  @compose-key AltRight{Insert}\n  ```\n\nExample configuration\n---------------------\n\nThe [author's personal configuration](keymapper.conf) may serve as an inspiration (which itself took some inspiration from [DreymaR's Big Bag Of Keyboard Tricks](https://dreymar.colemak.org/layers-extend.html)).\n\nTo get an impression of what a very advanced configuration can look like, check out a [power-user's configuration](https://github.com/ristomatti/keymapper-config/blob/main/keymapper.conf).\n\nFunctional principle\n--------------------\n\nFor advanced application it is good to know how the mapping is applied:\n\n  * All key strokes are intercepted and appended to a key sequence.\n  * On every key stroke the key sequence is matched with all input expressions in consecutive order, until an expression matches or might match (when more strokes follow). Mappings in inactive contexts are skipped.\n  * When the key sequence can no longer match any input expression (because more strokes followed), the longest exact match is looked for (by ignoring the last strokes). As long as still nothing can match, the first strokes are removed and forwarded as output.\n  * When an input expression matches, the keys are removed from the sequence and the mapped expression is output.\n  * Keys which already matched but are still physically pressed participate in expression matching as an optional prefix to the key sequence.\n\nkeymapperctl\n------------\n\nThe application `keymapperctl` allows to control the running `keymapper` process from external applications.\n\nIt can be run arbitrarily often with one or more of the following arguments:\n```\n--input \u003csequence\u003e    injects an input key sequence.\n--output \u003csequence\u003e   injects an output key sequence.\n--type \"string\"       types a string of characters.\n--next-key-info       outputs information about the next key press.\n--set-config \"file\"   sets a new configuration.\n--is-pressed \u003ckey\u003e    sets the result code 0 when a virtual key is down.\n--is-released \u003ckey\u003e   sets the result code 0 when a virtual key is up.\n--press \u003ckey\u003e         presses a virtual key.\n--release \u003ckey\u003e       releases a virtual key.\n--toggle \u003ckey\u003e        toggles a virtual key.\n--wait-pressed \u003ckey\u003e  waits until a virtual key is pressed.\n--wait-released \u003ckey\u003e waits until a virtual key is released.\n--wait-toggled \u003ckey\u003e  waits until a virtual key is toggled.\n--timeout \u003cmillisecs\u003e sets a timeout for the following operation.\n--wait \u003cmillisecs\u003e    unconditionally waits a given amount of time.\n--instance \u003cid\u003e       replaces another keymapperctl process with the same id.\n--restart             starts processing the first operation again.\n--stdout              outputs the result code.\n```\n\nInstallation\n------------\nThe program is split into two parts:\n* `keymapperd` is the service which needs to be given the permissions to grab the keyboard devices and inject keys.\n* `keymapper` should be run as normal user in a graphical environment. It loads the configuration, informs the service about it and the active context and also executes mapped terminal commands.\n\nFor security and efficiency reasons, the communication between the two parts is kept as minimal as possible.\n\nThe command line argument `-v` can be passed to both processes to output verbose logging information to the console.\n\n### Linux\n\nPre-built packages can be downloaded from the [latest release](https://github.com/houmain/keymapper/releases/latest) page. Arch Linux users can install an up to date build from the [AUR](https://aur.archlinux.org/packages/?K=keymapper).\n\nAfter installation you can try it out by creating a [configuration](#configuration) file and starting it using:\n```bash\nsudo systemctl start keymapperd\nkeymapper -u\n```\n\nTo install permanently, add `keymapper` to the desktop environment's auto-started applications and enable the `keymapperd` service:\n```bash\nsudo systemctl enable keymapperd\n```\n\nTo make context awareness work under Wayland, the compositor has to inform `keymapper` about the focused window. For [wlroots-based](https://wiki.archlinux.org/title/Wayland#Compositors) compositors this works out of the box, other compositors need to send the information using the [D-Bus](https://freedesktop.org/wiki/Software/dbus/) interface. A [GNOME Shell extension](https://github.com/houmain/keymapper/tree/main/extra/share/gnome-shell/extensions/keymapper%40houmain.github.com) and a [KWin script](https://github.com/houmain/keymapper/tree/main/extra/share/kwin/scripts/keymapper) are provided doing this.\n\nThe values for the `device-id` context filters are obtained by looking for symlinks in `/dev/input/by-id`.\n\n### MacOS\n\nThe MacOS build depends on [Karabiner-Element's](https://karabiner-elements.pqrs.org) virtual device driver.\nOne can install it either directly from [Karabiner-DriverKit-VirtualHIDDevice](https://github.com/pqrs-org/Karabiner-DriverKit-VirtualHIDDevice/releases) (version 5.x.x) or along with [Karabiner Elements](https://github.com/pqrs-org/Karabiner-Elements/releases) (version 15.x.x).\n\nA [Homebrew](https://brew.sh) formula is provided for building and installing keymapper:\n```bash\nbrew tap houmain/tap\nbrew install --HEAD keymapper\n```\n\nFinally `keymapperd` and `keymapper` can be added to the `launchd` daemons/agents by calling:\n```bash\nsudo keymapper-launchd add\n```\n\n### Windows\nAn installer and a portable build can be downloaded from the [latest release](https://github.com/houmain/keymapper/releases/latest) page.\n\nMost conveniently but possibly not always the very latest version can be installed using a package manager:\n```bash\n# install using winget\nwinget install keymapper\n\n# install using Chocolatey\nchoco install keymapper\n```\n\nThe installer configures the Windows task scheduler to start `keymapper.exe` and `keymapperd.exe` at logon.\n\nAfter installation you can open the [configuration](#configuration) file by clicking the \"Configuration\" entry in the tray icon menu.\n\nTo 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.\n\n#### Virtual device driver\n\nThe [device](#context-awareness) filter requires the installation of a virtual device driver. The only known freely available is [Interception](https://github.com/oblitum/Interception), which unfortunately has a [severe bug](https://github.com/oblitum/Interception/issues/25), 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`.\n\nBuilding\n--------\n\nA C++17 conforming compiler is required. A script for the\n[CMake](https://cmake.org) build system is provided.\n\n**Installing dependencies on Debian Linux and derivatives:**\n```bash\nsudo apt install build-essential git cmake libudev-dev libusb-1.0-0-dev libx11-dev libx11-xcb-dev libdbus-1-dev libwayland-dev libxkbcommon-dev libxkbcommon-x11-dev libgtk-3-dev libayatana-appindicator3-dev\n```\n\n**Checking out the source:**\n```bash\ngit clone https://github.com/houmain/keymapper\n```\n\n**Building:**\n```bash\ncd keymapper\ncmake -B build\ncmake --build build\n```\n\n**Testing:**\n\nTo try it out, simply create a [configuration](#configuration) file and start it using:\n\n```bash\nsudo build/keymapperd -v\n```\n\nand\n\n```bash\nbuild/keymapper -v\n```\n\n\nLicense\n-------\nIt is released under the GNU GPLv3. It comes with absolutely no warranty. Please see `LICENSE` for license details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoumain%2Fkeymapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoumain%2Fkeymapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoumain%2Fkeymapper/lists"}