{"id":15067232,"url":"https://github.com/alekamerlin/keyaboard-remap-guide","last_synced_at":"2025-06-15T11:02:46.200Z","repository":{"id":257208843,"uuid":"857570105","full_name":"Alekamerlin/keyaboard-remap-guide","owner":"Alekamerlin","description":"A user-friendly guide to remap keyboard keys in Linux.","archived":false,"fork":false,"pushed_at":"2024-09-15T05:35:13.000Z","size":10,"stargazers_count":18,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T12:39:32.249Z","etag":null,"topics":["guide","keyborad","linux","remapped-keys","remapping","remapping-keyboards"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Alekamerlin.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2024-09-15T02:17:19.000Z","updated_at":"2025-03-19T16:03:25.000Z","dependencies_parsed_at":"2024-09-15T10:22:24.694Z","dependency_job_id":null,"html_url":"https://github.com/Alekamerlin/keyaboard-remap-guide","commit_stats":null,"previous_names":["alekamerlin/keyaboard-remap-guide"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alekamerlin%2Fkeyaboard-remap-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alekamerlin%2Fkeyaboard-remap-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alekamerlin%2Fkeyaboard-remap-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alekamerlin%2Fkeyaboard-remap-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alekamerlin","download_url":"https://codeload.github.com/Alekamerlin/keyaboard-remap-guide/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248229440,"owners_count":21068893,"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":["guide","keyborad","linux","remapped-keys","remapping","remapping-keyboards"],"created_at":"2024-09-25T01:18:22.639Z","updated_at":"2025-04-10T13:54:40.731Z","avatar_url":"https://github.com/Alekamerlin.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# keyaboard-remap-guide\nA user-friendly guide to remap keyboard keys in Linux.\n\n### Knowledge base\n\nBefore begin, it's better to explore these resources:\n- About **sysfs** in [Wikipedia](https://en.wikipedia.org/wiki/Sysfs) or [Linux kernel docs](https://www.kernel.org/doc/html/v6.11-rc4/filesystems/sysfs.html).\n- About **udev** in [Wikipedia](https://en.wikipedia.org/wiki/Udev) or [Arch docs](https://wiki.archlinux.org/title/Udev).\n- What is the sysfs [**modalias**](https://wiki.archlinux.org/title/Modalias).\n- What is the [**scancodes**](https://en.wikipedia.org/wiki/Scancode).\n- How to identify [**scancodes**](https://wiki.archlinux.org/title/Keyboard_input).\n- How to map [**scancodes** to **keycodes**](https://wiki.archlinux.org/title/Map_scancodes_to_keycodes).\n\nIn short, keyboards send **scancodes** to the computer and the Linux kernel maps the **scancodes** to **keycodes**. The **keycodes** are some interpretation of **scancodes**. They exist because different keyboards can send different **scancodes** to the same button, or the same **scancode** to different buttons. On a ThinkPad keyboard, the screenshot tool button sends a **scancode** of 46, while the `Q` button sends the same **scancode**, for example.\n\n### A step-by-step example\n\nSo in this guide we will map **scancodes** to **keycodes** using **udev**. We will take a ThinkPad T14 Gen 3 and map `Fn + PrtScr` to the `Menu` **keycode** so that this combination opens a context menu.\n\n#### 1. Find the right input device\n\nFirst we should select the input device we want to work with. They are listed in the `/dev/input` directory as `event1`, `event2`, `event3` etc., and the easiest way to find the one we need is to run the `evtest` utility:\n```\n# evtest\n```\nThe utility will print a list of devices, by selecting one of them, we can get reports by pressing buttons on the selected input device.\n\nSo we can find that the device **AT Translated Set 2 keyboard** is listed as `/dev/input/event3` on the ThinkPad T14 Gen 3, but note that most ThinkPad keyboards work as two separate input devices: **AT Translated Set 2 keyboard** and **ThinkPad Extra Buttons**. So, the **AT Translated Set 2 keyboard** works like a typical keyboard, and the **ThinkPad Extra Buttons** represents functions that are available in combination with the `Fn` button, such as sleep mode (`Fn + 4`) and screenshot (`Fn + S`). For a deeper experience, we'll work with the **ThinkPad Extra Buttons** (`/dev/input/event4`).\n\n#### 2. Find the right scancode\n\nAfter choosing the right input device, we need to find the **scancode** of the button we want to remap. At this stage, by running the `evtest` utility again, selecting the right input device and pressing the button, we will get the report like this:\n```\n...\nEvent: time 1726200548.302346, type 4 (EV_MSC), code 4 (MSC_SCAN), value 46\nEvent: time 1726200548.302346, type 1 (EV_KEY), code 149 (KEY_PROG2), value 1\nEvent: time 1726200548.302346, -------------- SYN_REPORT ------------\nEvent: time 1726200548.302363, type 1 (EV_KEY), code 149 (KEY_PROG2), value 0\nEvent: time 1726200548.302363, -------------- SYN_REPORT ------------\n```\nHere we need to look at the value of `MSC_SCAN` and as you can see the value of combination `Fn + PrtScr` is `46` and the **scancode** is `KEY_PROG2`. Thus, we found out that the **scancode** `46` of the `PrtScr` button of the **ThinkPad Extra Buttons** is mapped as the `KEY_PROG2` **keycode**.\n\n#### 3. Find the right keycode\n\nSo we already know the right **scancode** and the next step is to find the right **keycode**. A better way is to look at the default Linux **keycodes** in the `/usr/include/linux/input-event-codes.h` file. Here we have to look at the `KEY_*` definitions and for our example the variants are: `KEY_MENU`, `KEY_CONTEXT_MENU`, `KEY_ROOT_MENU`, `KEY_MEDIA_TOP_MENU`, `KEY_BRIGHTNESS_MENU`, `KEY_KBD_LCD_MENU1`, `KEY_KBD_LCD_MENU2`, `KEY_KBD_LCD_MENU3`, `KEY_KBD_LCD_MENU4` and `KEY_KBD_LCD_MENU5`. The `KEY_MENU` and `KEY_CONTEXT_MENU` **keycodes** look right ones, but we can be determine which one will work by trying them. In order, not to waste time the right **keycode** for our example is `KEY_MENU`.\n\n#### 4. Get the right device ID\n\nOk, we know the **scancode** and what the **keycode** to map it to, and the mapping is best done for a specific device, but not for all, so we need to find the ID of the input device. There are two options: the kernel **modalias** and the device name with DMI:\n1. We can find **modalias** in the **sysfs** input directory:\n```\n$ cat /sys/class/input/event4/device/modalias\n```\nThe output for this example will be:\n```\ninput:b0019v17AAp5054e4101-e0,1,4,5,k71,72,73,78,8C,8E,90,93,94,95,98,9C,9E,AB,AD,BE,BF,C2,CA,CB,CD,D4,D8,D9,DA,DF,E0,E1,E3,E4,EC,ED,EE,F0,168,174,176,1D2,1DB,1DC,246,250,27A,ram4,lsfw3,\n```\nwhich we can shorten to:\n```\ninput:b0019v17AAp5054e4101*\n```\n2. For the second option, we can also find in the `/sys/class/input/event4/device/name` and `/sys/devices/virtual/dmi/id/modalias`, but it's better to use `evemu-describe` command from the `evemu` package:\n```\n# evemu-describe /dev/input/event4\n```\nFrom the output, we need to look at the **DMI** and **Input device name** rows and concatenate them into a string:\n```\nname:ThinkPad Extra Buttons:dmi:bvnLENOVO:bvrN3MET09W(1.06):bd10/11/2022:br1.6:efr1.12:svnLENOVO:pn21AH00B9RA:pvrThinkPadT14Gen3:rvnLENOVO:rn21AH00B9RA:rvrNotDefined:cvnLENOVO:ct10:cvrNone:skuLENOVO_MT_21AH_BU_Think_FM_ThinkPadT14Gen3:\n```\nwhich we can shorten to:\n```\nname:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*\n```\nBefore moving to the next step, it's best to check the default **keycode** mapping for availability of the required input device and use that ID, as the option from the default mapping might intefere with your option. The default **keycode** mappings are defined in `/usr/lib/udev/hwdb.d/60-keyboard.hwdb`. And for our example there is a default mapping:\n```\n...\n###########################################################\n# Lenovo\n###########################################################\n\n# thinkpad_acpi driver\nevdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*\n KEYBOARD_KEY_01=screenlock\n...\n KEYBOARD_KEY_46=prog2                                  # Fn + PrtSc, on Windows: Snipping tool\n...\n```\nTherefore, it's better to use the `name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*` ID instead of `input:b0019v17AAp5054e4101*`.\n\n#### 5. Create a file for the hardware database\n\nFinally, we can create a file with our mapping. Each map consists of a pair: `KEYBOARD_KEY_` + **scancode** and **keycode** in lowercase:\n```\nKEYBOARD_KEY_46=menu\n```\nAnd with the input ID our file will looks like this:\n```\nevdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*\n KEYBOARD_KEY_46=menu\n```\n\u003e Note that before the input ID should be the `evdev:` prefix.\nSo we can create a file for the hardware database with this command:\n```\n# echo -e 'evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*\\n KEYBOARD_KEY_46=menu' \u003e /etc/udev/hwdb.d/90-remap.hwdb\n```\n\u003e Note that the file name doesn't matter, but the number at beggining of the file name must be greater than the number of all `.hwdb` files that have mappings for the input device.\n\n#### 6. Apply the changes\n\nAfter creating a file with the remap, we need to update the Hardware Database Index:\n```\n# systemd-hwdb update\n```\nand reload it:\n```\n# udevadm trigger\n```\n\n#### 7. Check if the changes have been applied\n\nNow we can check if our remap is applied:\n```\n# udevadm info /dev/input/event4 | grep KEYBOARD_KEY\n```\nThe output should have our remap:\n```\n...\nE: KEYBOARD_KEY_46=menu\n...\n```\nWe can also check the remap using the `evtest` utility.\n\nNext, it's best to reboot the system because X11 and Wayland may not see you changes until the reboot. After rebooting, it's best to check the remap in [`xev`](https://archlinux.org/packages/extra/x86_64/xorg-xev/) for X11 or [`wev`](https://archlinux.org/packages/extra/x86_64/wev/) for Wayland, because display servers have their own understanding of **keycodes**, and things can go wrong.\n\n### Troubleshooting\n\nThe display server may identify some **keycodes** incorrectly because the **XKB** (from the `libxkbcommon` package) has its own understanding of **keycodes**. In `/usr/share/X11/xkb/keycodes/evdev` you can find translations from `evdev` **keycodes** (**scancodes**) to the `xfree86` variant.\n\nSo the `KEY_MENU` **keycode** from the example above is indentified as `XF86MenuKB` but not as `Menu`, and thus doesn't open a context menu in the **GUI**. In this case, it's better to check the `/usr/share/X11/xkb/keycodes/evdev` file and look at the aliases, where we can find the alias for our `Menu`:\n```\nalias \u003cMENU\u003e = \u003cCOMP\u003e;\n```\nWhich means the `Comp` **keycode** works as `Menu` and looking below we can find another one alias:\n```\nalias \u003cI135\u003e = \u003cCOMP\u003e;\t// #define KEY_COMPOSE             127\n```\nAt the end of the line, the comment tells us the `KEY_COMPOSE` **keycode**, and looking in the `/usr/include/linux/input-event-codes.h` file, we can find the same code:\n```\n#define KEY_COMPOSE\t\t127\n```\nSo using the `KEY_COMPOSE` **keycode**:\n```\n# echo -e 'evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:*\\n KEYBOARD_KEY_46=compose' \u003e /etc/udev/hwdb.d/90-remap.hwdb\n```\nsolves the problem, but yeah, it's super unfriendly and not unintuitive.\n\nAlternatively, you can try configure **XKB**.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falekamerlin%2Fkeyaboard-remap-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falekamerlin%2Fkeyaboard-remap-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falekamerlin%2Fkeyaboard-remap-guide/lists"}