2021-12-23 04:35:24 +00:00
# 𝑋𝑟𝑒𝑚𝑎𝑝 :keyboard: [![cargo](https://github.com/k0kubun/xremap/actions/workflows/build.yml/badge.svg)](https://github.com/k0kubun/xremap/actions/workflows/build.yml)
2021-12-22 09:34:09 +00:00
`xremap` is a key remapper for Linux. Unlike `xmodmap` , it supports app-specific remapping and Wayland.
2021-12-23 07:49:50 +00:00
## Concept
2021-12-22 09:34:09 +00:00
* **Fast** - Xremap is written in Rust, which is faster than JIT-less interpreters like Python.
* **Cross-platform** - Xremap uses `evdev` and `uinput` , which works whether you use X11 or Wayland.
2021-12-22 13:25:03 +00:00
* **Language-agnostic** - The config is JSON-compatible. Generate it from any language,
e.g. [Ruby ](https://github.com/xremap/xremap-ruby ), [Python ](https://github.com/xremap/xremap-python ).
2021-12-22 09:34:09 +00:00
2021-12-23 07:53:05 +00:00
## Features
2021-12-29 06:45:47 +00:00
* Remap any keys, e.g. Ctrl or CapsLock.
* Remap any key combination to another, even to a key sequence.
* Remap a key sequence as well. You could do something like Emacs's `C-x C-c` .
* Remap a key to two different keys depending on whether it's pressed alone or held.
2021-12-23 07:53:05 +00:00
* Application-specific remapping. Even if it's not supported by your application, xremap can.
2021-12-29 06:46:37 +00:00
* Automatically remap newly connected devices by starting xremap with `--watch` .
2022-01-01 05:43:16 +00:00
* Support [Emacs-like key remapping ](example/emacs.yml ), including the mark mode.
2022-08-13 20:38:15 +00:00
* Trigger commands on key press/release events.
2022-08-14 20:00:22 +00:00
* Use a non-modifier key as a virtual modifier key.
2021-12-23 07:53:05 +00:00
2021-12-22 09:34:09 +00:00
## Installation
2022-01-13 04:34:30 +00:00
Download a binary from [Releases ](https://github.com/k0kubun/xremap/releases ).
2021-12-22 09:34:09 +00:00
If it doesn't work, please [install Rust ](https://doc.rust-lang.org/cargo/getting-started/installation.html )
2021-12-24 04:12:25 +00:00
and run one of the following commands:
2021-12-22 09:34:09 +00:00
```bash
2022-01-13 04:32:32 +00:00
cargo install xremap --features x11 # X11
cargo install xremap --features gnome # GNOME Wayland
cargo install xremap --features sway # Sway
cargo install xremap # Others
2021-12-22 09:34:09 +00:00
```
2021-12-23 05:23:33 +00:00
You may also need to install `libx11-dev` to run the `xremap` binary for X11.
2022-01-29 20:58:51 +00:00
### Arch Linux
If you are on Arch Linux and X11, you can install [xremap-x11-bin ](https://aur.archlinux.org/packages/xremap-x11-bin/ ) from AUR.
2021-12-22 09:34:09 +00:00
## Usage
2021-12-22 13:25:03 +00:00
Write [a config file ](#Configuration ) directly, or generate it with
[xremap-ruby ](https://github.com/xremap/xremap-ruby ) or [xremap-python ](https://github.com/xremap/xremap-python ).
Then run:
2021-12-22 09:34:09 +00:00
```
2022-01-13 04:32:32 +00:00
sudo xremap config.yml
2021-12-22 09:34:09 +00:00
```
2022-05-07 07:01:22 +00:00
< details >
< summary > If you want to run xremap without sudo, click here.< / summary >
2021-12-22 09:34:09 +00:00
2022-05-25 03:51:34 +00:00
### Running xremap without sudo
2022-05-07 07:01:22 +00:00
To do so, your normal user should be able to use `evdev` and `uinput` without sudo.
In Ubuntu, this can be configured by running the following commands and rebooting your machine.
2021-12-22 09:34:09 +00:00
2022-05-07 07:01:22 +00:00
```bash
sudo gpasswd -a YOUR_USER input
echo 'KERNEL=="uinput", GROUP="input"' | sudo tee /etc/udev/rules.d/input.rules
```
2022-01-13 04:32:32 +00:00
2022-05-25 03:51:34 +00:00
#### Arch Linux
2022-05-24 19:55:47 +00:00
The following can be used on Arch.
```bash
lsmod | grep uinput
```
If this module is not loaded, add to `/etc/modules-load.d/uinput.conf` :
```bash
uinput
```
Then add udev rule.
```bash
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules
```
2022-05-25 03:51:34 +00:00
#### Other platforms
2022-05-07 07:01:22 +00:00
In other platforms, you might need to create an `input` group first
and run `echo 'KERNEL=="event*", NAME="input/%k", MODE="660", GROUP="input"' | sudo tee /etc/udev/rules.d/input.rules` as well.
If you do this, in some environments, `--watch` may fail to recognize new devices due to temporary permission issues.
Using `sudo` might be more useful in such cases.
2022-05-25 03:51:34 +00:00
---
2022-05-07 07:01:22 +00:00
< / details >
See the following instructions for your environment to make `application` -specific remapping work.
2022-01-13 04:32:32 +00:00
2022-05-07 07:01:22 +00:00
### X11
2022-01-13 04:32:32 +00:00
2022-05-07 07:01:22 +00:00
If you use `sudo` to run `xremap` , you may need to run `xhost +SI:localuser:root` if you see `No protocol specified` .
2022-01-13 04:36:13 +00:00
2022-05-07 07:01:22 +00:00
### GNOME Wayland
2022-01-13 04:36:13 +00:00
2022-05-08 04:27:45 +00:00
Install xremap's GNOME Shell extension from [this link ](https://extensions.gnome.org/extension/5060/xremap/ ),
switching OFF to ON.
2022-05-07 07:01:22 +00:00
< details >
< summary > If you use < code > sudo< / code > to run < code > xremap< / code > , also click here.< / summary >
2022-01-13 04:36:13 +00:00
Update `/usr/share/dbus-1/session.conf` as follows, and reboot your machine.
2022-01-13 04:32:32 +00:00
```diff
< policy context = "default" >
+ < allow user = "root" / >
<!-- Allow everything to be sent -->
< allow send_destination = "*" eavesdrop = "true" / >
<!-- Allow everything to be received -->
```
2022-01-13 04:36:13 +00:00
< / details >
2021-12-22 09:34:09 +00:00
## Configuration
Your `config.yml` should look like this:
```yml
modmap:
- name: Except Chrome
application:
not: Google-chrome
remap:
CapsLock: Esc
keymap:
- name: Emacs binding
application:
only: Slack
remap:
C-b: left
C-f: right
C-p: up
C-n: down
```
2022-01-01 06:50:56 +00:00
See also: [example/config.yml ](example/config.yml ) and [example/emacs.yml ](example/emacs.yml )
2021-12-22 09:34:09 +00:00
### modmap
`modmap` is for key-to-key remapping like xmodmap.
2021-12-23 17:58:45 +00:00
Note that remapping a key to a modifier key, e.g. CapsLock to Control\_L,
2021-12-23 19:56:48 +00:00
is supported only in `modmap` since `keymap` handles modifier keys differently.
2021-12-22 09:34:09 +00:00
```yml
modmap:
2021-12-28 07:04:17 +00:00
- name: Name # Optional
2021-12-22 09:34:09 +00:00
remap: # Required
2022-08-14 09:35:38 +00:00
# Replace a key with another
2021-12-26 05:31:09 +00:00
KEY_XXX: KEY_YYY # Required
2022-08-14 09:35:38 +00:00
# Dispatch different keys depending on whether you hold it or press it alone
2021-12-26 05:31:09 +00:00
KEY_XXX:
held: KEY_YYY # Required
alone: KEY_ZZZ # Required
alone_timeout_millis: 1000 # Optional
2022-08-21 17:07:38 +00:00
# Hook `keymap` action on key press/release events.
2022-08-13 20:38:15 +00:00
KEY_XXX:
press: { launch: ["xdotool", "mousemove", "0", "7200"] } # Required
release: { launch: ["xdotool", "mousemove", "0", "0"] } # Required
2021-12-22 09:34:09 +00:00
application: # Optional
not: [Application, ...]
# or
only: [Application, ...]
```
For `KEY_XXX` and `KEY_YYY` , use [these names ](https://github.com/emberian/evdev/blob/1d020f11b283b0648427a2844b6b980f1a268221/src/scancodes.rs#L26-L572 ).
You can skip `KEY_` and the name is case-insensitive. So `KEY_CAPSLOCK` , `CAPSLOCK` , and `CapsLock` are the same thing.
Some [custom aliases ](src/config/key.rs ) like `SHIFT_R` , `CONTROL_L` , etc. are provided.
2021-12-26 05:31:09 +00:00
If you specify a map containing `held` and `alone` , you can use the key for two purposes.
The key is considered `alone` if it's pressed and released within `alone_timeout_millis` (default: 1000)
before any other key is pressed. Otherwise it's considered `held` .
2021-12-22 09:34:09 +00:00
### keymap
2021-12-23 17:54:15 +00:00
`keymap` is for remapping a sequence of key combinations to another sequence of key combinations or other actions.
2021-12-22 09:34:09 +00:00
```yml
2021-12-26 12:24:46 +00:00
keymap:
2021-12-28 07:04:17 +00:00
- name: Name # Optional
2021-12-22 09:34:09 +00:00
remap: # Required
2022-08-13 20:38:15 +00:00
# Key press -> Key press
2021-12-22 09:34:09 +00:00
MOD1-KEY_XXX: MOD2-KEY_YYY
2022-08-13 20:38:15 +00:00
# Sequence (MOD1-KEY_XXX, MOD2-KEY_YYY) -> Key press (MOD3-KEY_ZZZ)
2021-12-22 09:34:09 +00:00
MOD1-KEY_XXX:
remap:
MOD2-KEY_YYY: MOD3-KEY_ZZZ
2022-04-08 03:55:49 +00:00
timeout_millis: 200 # Optional. No timeout by default.
2022-08-13 20:38:15 +00:00
# Key press (MOD1-KEY_XXX) -> Sequence (MOD2-KEY_YYY, MOD3-KEY_ZZZ)
2021-12-22 09:34:09 +00:00
MOD1-KEY_XXX: [MOD2-KEY_YYY, MOD3-KEY_ZZZ]
2022-08-13 20:38:15 +00:00
# Execute a command
2021-12-30 21:17:54 +00:00
MOD1-KEY_XXX:
launch: ["bash", "-c", "echo hello > /tmp/test"]
2022-08-13 20:38:15 +00:00
# Let `with_mark` also press a Shift key (useful for Emacs emulation)
2022-01-01 05:43:16 +00:00
MOD1-KEY_XXX: { set_mark: true } # use { set_mark: false } to disable it
2022-08-13 20:38:15 +00:00
# Also press Shift only when { set_mark: true } is used before
2022-01-01 05:43:16 +00:00
MOD1-KEY_XXX: { with_mark: MOD2-KEY_YYY }
2022-08-13 20:38:15 +00:00
# The next key press will ignore keymap
2022-02-10 04:24:48 +00:00
MOD1-KEY_XXX: { escape_next_key: true }
2022-08-13 20:38:15 +00:00
# Set mode to configure Vim-like modal remapping
2022-06-22 04:37:06 +00:00
MOD1-KEY_XXX: { set_mode: default }
2021-12-22 09:34:09 +00:00
application: # Optional
not: [Application, ...]
# or
only: [Application, ...]
2022-06-22 04:37:06 +00:00
mode: default # Optional
default_mode: default # Optional
2021-12-22 09:34:09 +00:00
```
For `KEY_XXX` , use [these names ](https://github.com/emberian/evdev/blob/1d020f11b283b0648427a2844b6b980f1a268221/src/scancodes.rs#L26-L572 ).
You can skip `KEY_` and the name is case-insensitive. So `KEY_CAPSLOCK` , `CAPSLOCK` , and `CapsLock` are the same thing.
For the `MOD1-` part, the following prefixes can be used (also case-insensitive):
* Shift: `SHIFT-`
* Control: `C-` , `CTRL-` , `CONTROL-`
* Alt: `M-` , `ALT-`
* Windows: `SUPER-` , `WIN-` , `WINDOWS-`
2022-01-02 05:35:24 +00:00
You can use multiple prefixes like `C-M-Shift-a` .
2022-01-02 05:49:16 +00:00
You may also suffix them with `_L` or `_R` (case-insensitive) so that
remapping is triggered only on a left or right modifier, e.g. `Ctrl_L-a` .
2021-12-22 09:34:09 +00:00
2022-08-14 20:00:22 +00:00
If you use `virtual_modifiers` explained below, you can use it in the `MOD1-` part too.
2022-08-14 09:35:38 +00:00
2021-12-22 09:34:09 +00:00
### application
`application` can be used for both `modmap` and `keymap` , which allows you to specify application-specific remapping.
```yml
application:
not: Application
# or
not: [Application, ...]
# or
only: Application
# or
only: [Application, ...]
```
2022-08-14 00:31:57 +00:00
The application name can be specified as a normal string to exactly match the name,
or a regex surrounded by `/` s like `/application/` .
2021-12-22 09:34:09 +00:00
To check the application names, you can use the following commands:
#### X11
```
$ wmctrl -x -l
2022-08-14 00:31:57 +00:00
0x02800003 0 slack.Slack ubuntu-jammy Slack | general | ruby-jp
0x05400003 0 code.Code ubuntu-jammy application.rs - xremap - Visual Studio Code
2021-12-22 09:34:09 +00:00
```
2022-08-14 00:31:57 +00:00
You may use the entire string of the third column (`slack.Slack`, `code.Code` ),
or just the last segment after `.` (`Slack`, `Code` ).
2021-12-22 09:34:09 +00:00
#### GNOME Wayland
```
busctl --user call org.gnome.Shell /org/gnome/Shell org.gnome.Shell Eval s 'global.get_window_actors().map(a => a.get_meta_window().get_wm_class());'
```
#### Sway
```
swaymsg -t get_tree
```
Locate `app_id` in the output.
2022-08-14 20:00:22 +00:00
### virtual\_modifiers
You can declare keys that should act like a modifier.
2022-08-14 20:11:43 +00:00
```yml
2022-08-14 20:00:22 +00:00
virtual_modifiers:
- CapsLock
keymap:
- remap:
CapsLock-i: Up
CapsLock-j: Left
CapsLock-k: Down
CapsLock-l: Right
```
2021-12-22 09:34:09 +00:00
## License
2022-04-02 04:45:47 +00:00
`xremap` is available as open source under the terms of the [MIT License ](https://opensource.org/licenses/MIT ).