interception-tools - ArchWiki

Jump to content
From ArchWiki

Related articles

- Linux console/Keyboard configuration
- Xbindkeys
- Xmodmap

interception-tools is a set of utilities to control and customize the behavior of keyboard input mappings.

Interception-tools operates at a lower level compared to other similar tools (xcape, xmodmap) by using libevdev and libudev. This makes it one of the only options available for customizing the keyboard behavior across X11, Wayland, and the Linux console.

## Installation

Install interception-tools.

Many plugins are available:

- interception-caps2esc to switch `CapsLock` with `Ctrl`/`Esc`
- interception-caps2esc-delay-gitAUR
- interception-caps2esc-nocaps-gitAUR
- interception-dual-function-keys to modify the behavior of a key when held.
- interception-hideawayAUR
- interception-k2k-gitAUR
- interception-ralt2hyperAUR
- interception-space2metaAUR
- interception-uswitchAUR
- interception-vimproved-gitAUR
- interception-xswitchAUR

## Configure jobs and plugins

### How it works

Interception-tool makes use of libevdev, which according to its wiki is essentially a read(2) on steroids for `/dev/input/eventX` devices. It sits in between the kernel and the process handling an event. In the simplest scenario would look like this:

    kernel | libevdev | evtest

For X.Org input modules, the stack would look like this:

    kernel | libevdev | xf86-input-evdev | X server | X client

For Wayland, the stack would look like this:

    kernel | libevdev | Compositor | Wayland client

In other words, `libevdev` is so low level that it does not have knowledge of X/Wayland clients.

### Practical examples

Interception-tools makes 4 utilities available:

- `intercept`: redirect device input events to stdout,
- `mux`: combine streams of input events,
- `udevmon`: monitor input devices for launching tasks,
- `uinput`: redirect device input events from stdin to virtual device.

#### Increase niceness

Since the tool is going to be sitting down at the lowest level of the device inputs, make sure it will behave consistently by increasing `udevmon` priority:

    # nice -n -20 udevmon -c udevmon.yaml > udevmon.log 2> udevmon.err &

#### Simple redirection

The simplest way or redirecting the event to the stdin (without doing nothing) is:

    $ intercept -g DEVNODE | uinput -d DEVNODE

where `DEVNODE` is the path to the actual device: e.g. `/dev/input/by-path/platform-i8042-serio-0-event-kbd`.

#### Embbed commands

To actually perform an operation in between the key event and the input, simply pipe it in between `intercept` and `uinput`.

E.g. with the interception-caps2esc plugin installed:

    $ intercept -g DEVNODE | caps2esc | uinput -d DEVNODE

If we omitted the `-g` flag, then device event would have been just observed, not grabbed.

#### Feed as YAML

Note: Configuration files found on `/etc/interception/udevmon.d/` are read first, and fallbacks on `/etc/interception/udevmon.yaml`.

This way of intercepting the input can quickly become sub-optimal, this is where `udevmon` comes in handy. udevmon accepts a YAML configuration with a list of jobs (sh commands by default) to be executed.

In case the device matches a given description:

    $ udevmon -c caps2esc.conf.yml

    - JOB: intercept -gDEVNODE | caps2esc | uinput -d DEVNODE
      DEVICE:
        LINK: /dev/input/by-path/platform-i8042-serio-0-event-kbd

The `LINK` configuration will match a device with a specific name, but it will accept also a regex option. This can be combined with multiple job specifications to create a default behavior, in each case only the first matching job is going to be executed:

    - JOB: intercept -g DEVNODE | caps2esc -m 2 | uinput -d DEVNODE
      DEVICE:
        LINK: /dev/input/by-id/usb-SEMITEK_USB-HID_Gaming_Keyboard_SN0000000001-event-kbd
    - JOB: intercept -g DEVNODE | caps2esc | uinput -d DEVNODE
      DEVICE:
        EVENTS:
          EV_KEY: [[KEY_CAPSLOCK, KEY_ESC]]
        LINK: .*-event-kbd

#### Combine devices

Beside input emulation, the `uinput` tool also serves purpose to print a device's description in YAML format:

    $ uinput -p -d /dev/input/by-id/my-kbd

which itself can be fed back to `uinput` as:

    $ uinput -c my-kbd.yaml

It can also merge device and YAML characteristics, which can be used for instance to combine events coming from keyboard and mouse:

e.g. instance `CapsLock+Click` as `Ctrl+Click`

    $ uinput -p -d /dev/input/by-id/my-kbd -d /dev/input/by-id/my-mouse -c my-extra.yaml

#### Handle multiple jobs

The `mux` is used to combine multiple pipelines into a single one. A muxer needs to be created first, and it can later be used as the input or the output of a given pipeline. In a YAML specification file, the muxer is created using the `CMD` key:

    - CMD: mux -c caps2esc
    - JOB: mux -i caps2esc | caps2esc | uinput -c /etc/interception/gaming-keyboard.yaml
    - JOB: intercept -g DEVNODE | mux -o caps2esc
      DEVICE:
        LINK: /dev/input/by-id/my-kbd
    - JOB: intercept DEVNODE | mux -o caps2esc
      DEVICE:
        LINK: /dev/input/by-id/my-mouse

In the example above, when the keyboard is connected, it's grabbed and its input events are sent to the `caps2esc` muxer that was initially created. Observed input (not grabbed) from mouse is also sent to the same muxer. The buttons of the mouse generate `EV_KEY` events, so `caps2esc` will accept them.

## See also

- Official website
- kmonad - advanced keyboard remapping tool daemon
- Hawck - similar low-level key rebinding daemon

Category:

- Keyboard configuration