mirror of
https://github.com/k0kubun/xremap
synced 2024-11-03 23:15:37 +00:00
249 lines
8.2 KiB
Markdown
249 lines
8.2 KiB
Markdown
# 𝑋𝑟𝑒𝑚𝑎𝑝 :keyboard: [![cargo](https://github.com/k0kubun/xremap/actions/workflows/build.yml/badge.svg)](https://github.com/k0kubun/xremap/actions/workflows/build.yml)
|
|
|
|
`xremap` is a key remapper for Linux. Unlike `xmodmap`, it supports app-specific remapping and Wayland.
|
|
|
|
## Concept
|
|
|
|
* **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.
|
|
|
|
* **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).
|
|
|
|
## Features
|
|
|
|
* 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.
|
|
* Application-specific remapping. Even if it's not supported by your application, xremap can.
|
|
* Automatically remap newly connected devices by starting xremap with `--watch`.
|
|
* Support [Emacs-like key remapping](example/emacs.yml), including the mark mode.
|
|
|
|
## Installation
|
|
|
|
Download a binary from [Releases](https://github.com/k0kubun/xremap/releases).
|
|
|
|
If it doesn't work, please [install Rust](https://doc.rust-lang.org/cargo/getting-started/installation.html)
|
|
and run one of the following commands:
|
|
|
|
```bash
|
|
cargo install xremap --features x11 # X11
|
|
cargo install xremap --features gnome # GNOME Wayland
|
|
cargo install xremap --features sway # Sway
|
|
cargo install xremap # Others
|
|
```
|
|
|
|
You may also need to install `libx11-dev` to run the `xremap` binary for X11.
|
|
|
|
### 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.
|
|
|
|
## Usage
|
|
|
|
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:
|
|
|
|
```
|
|
sudo xremap config.yml
|
|
```
|
|
|
|
### Dynamic binding
|
|
|
|
Xremap supports application-specific key remapping.
|
|
|
|
While Xremap uses `evdev` and `uinput` for key remapping, which is a lower layer than X11 and Wayland,
|
|
Xremap also uses X11 or Wayland compositor-specific protocols to support `application` config.
|
|
If you use this feature, make sure you use the appropriate binary for your platform,
|
|
and follow one of the following options to make it work.
|
|
|
|
<details>
|
|
<summary>Option 1: Allow root to talk to the compositor</summary>
|
|
|
|
If you use `sudo xremap`, root user usually cannot interact with the compositor for your normal user.
|
|
You may need to allow it as follows:
|
|
|
|
#### X11
|
|
|
|
You may need to run `xhost +SI:localuser:root` if you see `No protocol specified`.
|
|
|
|
#### GNOME Wayland
|
|
|
|
Update `/usr/share/dbus-1/session.conf` as follows, and reboot your machine.
|
|
|
|
```diff
|
|
<policy context="default">
|
|
+ <allow user="root"/>
|
|
<!-- Allow everything to be sent -->
|
|
<allow send_destination="*" eavesdrop="true"/>
|
|
<!-- Allow everything to be received -->
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Option 2: Run xremap without sudo</summary>
|
|
|
|
Alternatively, you could run `xremap` without sudo to solve the problem.
|
|
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.
|
|
|
|
```bash
|
|
sudo gpasswd -a YOUR_USER input
|
|
echo 'KERNEL=="uinput", GROUP="input"' | sudo tee /etc/udev/rules.d/input.rules
|
|
```
|
|
|
|
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 take this path, in some environments, `--watch` may fail to recognize new devices due to temporary permission issues.
|
|
Option 1 might be more useful in such cases.
|
|
|
|
</details>
|
|
|
|
## 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
|
|
```
|
|
|
|
See also: [example/config.yml](example/config.yml) and [example/emacs.yml](example/emacs.yml)
|
|
|
|
### modmap
|
|
|
|
`modmap` is for key-to-key remapping like xmodmap.
|
|
Note that remapping a key to a modifier key, e.g. CapsLock to Control\_L,
|
|
is supported only in `modmap` since `keymap` handles modifier keys differently.
|
|
|
|
```yml
|
|
modmap:
|
|
- name: Name # Optional
|
|
remap: # Required
|
|
KEY_XXX: KEY_YYY # Required
|
|
# or
|
|
KEY_XXX:
|
|
held: KEY_YYY # Required
|
|
alone: KEY_ZZZ # Required
|
|
alone_timeout_millis: 1000 # Optional
|
|
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.
|
|
|
|
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`.
|
|
|
|
### keymap
|
|
|
|
`keymap` is for remapping a sequence of key combinations to another sequence of key combinations or other actions.
|
|
|
|
```yml
|
|
keymap:
|
|
- name: Name # Optional
|
|
remap: # Required
|
|
# key press -> key press
|
|
MOD1-KEY_XXX: MOD2-KEY_YYY
|
|
# sequence (MOD1-KEY_XXX, MOD2-KEY_YYY) -> key press (MOD3-KEY_ZZZ)
|
|
MOD1-KEY_XXX:
|
|
remap:
|
|
MOD2-KEY_YYY: MOD3-KEY_ZZZ
|
|
# key press (MOD1-KEY_XXX) -> sequence (MOD2-KEY_YYY, MOD3-KEY_ZZZ)
|
|
MOD1-KEY_XXX: [MOD2-KEY_YYY, MOD3-KEY_ZZZ]
|
|
# execute a command
|
|
MOD1-KEY_XXX:
|
|
launch: ["bash", "-c", "echo hello > /tmp/test"]
|
|
# let `with_mark` also press a Shift key (useful for Emacs emulation)
|
|
MOD1-KEY_XXX: { set_mark: true } # use { set_mark: false } to disable it
|
|
# also press Shift only when { set_mark: true } is used before
|
|
MOD1-KEY_XXX: { with_mark: MOD2-KEY_YYY }
|
|
# the next key press will ignore keymap
|
|
MOD1-KEY_XXX: { escape_next_key: true }
|
|
application: # Optional
|
|
not: [Application, ...]
|
|
# or
|
|
only: [Application, ...]
|
|
```
|
|
|
|
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-`
|
|
|
|
You can use multiple prefixes like `C-M-Shift-a`.
|
|
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`.
|
|
|
|
### 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, ...]
|
|
```
|
|
|
|
To check the application names, you can use the following commands:
|
|
|
|
#### X11
|
|
|
|
```
|
|
$ wmctrl -x -l
|
|
0x0280000a 0 gnome-terminal-server.Gnome-terminal ubuntu-focal Terminal
|
|
0x02600001 0 nocturn.Nocturn ubuntu-focal Nocturn
|
|
```
|
|
|
|
Use the name after `.` in the third column (`WM_CLASS`), i.e. `Gnome-terminal` or `Nocturn` in the above output.
|
|
|
|
#### 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.
|
|
|
|
## License
|
|
|
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|