𝑋𝑟𝑒𝑚𝑎𝑝 :keyboard: cargo

xremap is a key remapper for Linux. Unlike xmodmap, it supports app-specific remapping and Wayland.

Concept

Features

Prerequisite

xremap assumes that you can use evdev and uinput without sudo. You can configure it as follows:

bash sudo gpasswd -a YOUR_USER input echo 'KERNEL=="uinput", GROUP="input"' | sudo tee /etc/udev/rules.d/input.rules

Then reboot your machine to make sure the udev rule is applied.

Installation

After the reboot, download a binary from Releases.

If it doesn't work, please install Rust and run one of the following commands:

```bash

X11

cargo install xremap --features x11

GNOME Wayland

cargo install xremap --features gnome

Sway

cargo install xremap --features sway

Others

cargo install xremap ```

You may also need to install libx11-dev to run the xremap binary for X11.

Usage

Write a config file directly, or generate it with xremap-ruby or xremap-python. Then run:

xremap config.yml

Dynamic binding

Xremap supports application-specific key remapping.

While Xremap uses evdev and uinput, which is a lower layer than X11 and Wayland, Xremap also uses X11 or Wayland compositor-specific protocols to support application config. If you need this feature, make sure you use the correct binary or --features option, and pay attention to the error messages from xremap.

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 and 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. You can skip KEY_ and the name is case-insensitive. So KEY_CAPSLOCK, CAPSLOCK, and CapsLock are the same thing. Some custom aliases 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 } application: # Optional not: [Application, ...] # or only: [Application, ...]

For KEY_XXX, use these names. 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):

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.