summaryrefslogtreecommitdiff
path: root/README.md
blob: 02b87e1e45ba788960cb4709635266beb91662f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# evremap

*A keyboard input remapper for Linux/Wayland systems, written by <a href="https://github.com/wez/">@wez</a>*

## Why?

I couldn't find a good solution for the following:

* Remap the `CAPSLOCK` key so that it produces `CTRL` when held, but `ESC` if tapped
* Remap N keys to M keys.  Eg: `F3` -> `CTRL+c`, and `ALT+LEFT` to `HOME`

## How?

`evremap` works by grabbing exclusive access to an input device and maintaining
a model of the keys that are pressed.  It then applies your remapping configuration
to produce the effective set of pressed keys and emits appropriate changes to a virtual
output device.

Because `evremap` targets the evdev layer of libinput, its remapping
is effective system-wide: in Wayland, X11 and the linux console.

## Configuration

Here's an example configuration that makes capslock useful:

```toml
# The name of the device to remap.
# Run `sudo evremap list-devices` to see the devices available
# on your system.
device_name = "AT Translated Set 2 keyboard"

# If you have multiple devices with the same name, you can optionally
# specify the `phys` value that is printed by the `list-devices` subcommand
# phys = "usb-0000:07:00.3-2.1.1/input0"

# Configure CAPSLOCK as a Dual Role key.
# Holding it produces LEFTCTRL, but tapping it
# will produce ESC.
# Both `tap` and `hold` can expand to multiple output keys.
[[dual_role]]
input = "KEY_CAPSLOCK"
hold = ["KEY_LEFTCTRL"]
tap = ["KEY_ESC"]
```

You can also express simple remapping entries:

```toml
# This config snippet is useful if your keyboard has an arrow
# cluster, but doesn't have page up, page down, home or end
# keys.  Here we're configuring ALT+arrow to map to those functions.
[[remap]]
input = ["KEY_LEFTALT", "KEY_UP"]
output = ["KEY_PAGEUP"]

[[remap]]
input = ["KEY_LEFTALT", "KEY_DOWN"]
output = ["KEY_PAGEDOWN"]

[[remap]]
input = ["KEY_LEFTALT", "KEY_LEFT"]
output = ["KEY_HOME"]

[[remap]]
input = ["KEY_LEFTALT", "KEY_RIGHT"]
output = ["KEY_END"]
```

When applying remapping configuration, ordering is important:

* Dual Role entries are always processed first
* Remap entries are applied in the order that they appear in
  your configuration file

Here's an example where ordering is important: on the PixelBook Go keyboard,
the function key row has alternate functions on the keycaps.  It is natural
to want the mute button to mute by default, but to emit the F8 key when
holding alt.  We can express that with the following configuration:

```toml
[[remap]]
input = ["KEY_LEFTALT", "KEY_F8"]
# When our `input` is matched, our list of `output` is prevented from
# matching as the `input` of subsequent rules.
output = ["KEY_F8"]

[[remap]]
input = ["KEY_F8"]
output = ["KEY_MUTE"]
```

* How do I list available input devices?
  `sudo evremap list-devices`

* How do I list available key codes?
  `evremap list-keys`

## Building it

```console
$ sudo dnf install libevdev-devel # redhat/centos
## or
$ sudo apt install libevdev-dev # debian/ubuntu

$ cargo build --release
```

## Running it

To run the remapper, invoke it *as root* (so that it can grab exclusive access to the input device):

```console
$ sudo target/release/evremap remap my-config-file.toml
```

Or, grant an unprivileged user access to `evdev` and `uinput`.
On Ubuntu, this can be configured by running the following commands and rebooting:

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

For some 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.

## Systemd

A sample system service unit is included in the repo.  You'll want to adjust the paths to match
your system and then install and enable it:

```console
$ sudo cp evremap.service /usr/lib/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable evremap.service
$ sudo systemctl start evremap.service
```

## Runit

If you're using Runit instead of Systemd, follow these steps to create a service.

* Create a directory called `evremap` and create a file called `run` under it
```console
sudo mkdir /etc/sv/evremap
sudo touch /etc/sv/evremap/run
```

* Copy these lines into the run file
```console
#!/bin/sh
set -e 
exec <PATH_TO_EVREMAP> remap <CONFIG>
```

Replace `<PATH_TO_EVREMAP>` with the path to your evremap executable and `<CONFIG>` with the path 
to your configuration file

* Finally, symlink the evremap directory to `/var/service`
```console
sudo ln -s /etc/sv/evremap /var/service
```


## How do I make this execute a command when a key is pressed?

That feature is not implemented.