Baeldung Pro – Linux – NPI EA (cat = Baeldung on Linux)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (tag=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Introduction

Although a computer mouse usually has two to three buttons, on occasion, one might come with extra buttons. So, a situation could arise when we plug the mouse in, and the system doesn’t recognize them. Fortunately, we can often manually configure those buttons.

In this tutorial, we’ll show how to set and register mouse buttons with xremap.

2. Solution and Considerations

Let’s summarize the approach we take:

  1. find the button names
  2. write a configuration to map the buttons to a key, a key combination, or a command
  3. run a program that monitors input events and executes actions according to the configuration

The program that listens to events needs to be running continuously. So, ideally, we should run it as a service or daemon at system startup.

In addition, Linux systems use a windowing system to handle device input. In fact, many use X11, so a broad toolset is written for X11. However, newer systems, like Ubuntu 22 and later, switched to Wayland.

Therefore, it’s important to know which system we have when dealing with key events. For that, we check the XDG_SESSION_TYPE environment variable:

$ echo $XDG_SESSION_TYPE
x11

Nonetheless, we work with a tool that supports both windowing systems.

3. xremap

Let’s dive into the implementation, namely xremap, a Rust program.

3.1. Installation

First, we install Rust and restart the shell.

Next, we can install xremap using Rust’s package manager, cargo:

$ cargo install xremap --features x11

As usual, there are installation options for other systems as well.

3.2. Setup

Let’s assume we have a trackball mouse with no scroll wheel. So, we might want to configure the extra buttons as a substitute for scrolling.

We start by creating an empty config file:

$ mkdir ~/.config/xremap/
$ touch ~/.config/xremap/config.yml

Next, we run xremap to get the list of available devices:

$ sudo xremap ~/.config/xremap/config.yml

Selecting devices from the following list:
------------------------------------------------------------------------------
/dev/input/event0 : Power Button
/dev/input/event1 : Sleep Button
/dev/input/event2 : AT Keyboard
/dev/input/event3 : Logitech Mouse
...
/dev/input/event7 : HDA Intel Speaker
------------------------------------------------------------------------------
Selected keyboards automatically since --device options weren't specified:
------------------------------------------------------------------------------
/dev/input/event2 : AT Keyboard
------------------------------------------------------------------------------

Logitech Mouse is the device we’re looking for. We can use either the name or the address of the mouse with the –device option. If we skip specifying the device, xremap picks a keyboard.

sudo is necessary because xremap needs device access. In case we get a command not found error, we should make sure the xremap installation path is whitelisted.

Now, let’s find the button names. By running xremap with RUST_LOG=debug and –device options, we see names in the logs when clicking the buttons:

$ sudo RUST_LOG=debug xremap ~/.config/xremap/config.yml --device /dev/input/event3
...
Selected devices matching ["/dev/input/event3"]:
------------------------------------------------------------------------------
/dev/input/event3 : Logitech Mouse
------------------------------------------------------------------------------
[2024-09-26T12:22:02Z DEBUG xremap::event_handler] => 1: BTN_SIDE
[2024-09-26T12:22:02Z DEBUG xremap::action_dispatcher] 1: BTN_SIDE
[2024-09-26T12:22:02Z DEBUG xremap::event_handler] => 0: BTN_SIDE
[2024-09-26T12:22:02Z DEBUG xremap::action_dispatcher] 0: BTN_SIDE
[2024-09-26T12:22:04Z DEBUG xremap::event_handler] => 1: BTN_EXTRA
[2024-09-26T12:22:04Z DEBUG xremap::action_dispatcher] 1: BTN_EXTRA
[2024-09-26T12:22:04Z DEBUG xremap::event_handler] => 0: BTN_EXTRA
[2024-09-26T12:22:04Z DEBUG xremap::action_dispatcher] 0: BTN_EXTRA

So, the buttons are named BTN_SIDE and BTN_EXTRA.

3.3. Mapping

Finally, let’s edit the config file to map the buttons.

With a fairly simple configuration, we map BTN_SIDE and BTN_EXTRA to PAGEUP and PAGEDOWN, respectively:

modmap:
  - name: main remaps
    remap:
      BTN_SIDE: PAGEUP
      BTN_EXTRA: PAGEDOWN

We save the changes, then run xremap again:

$ sudo xremap ~/.config/xremap/config.yml --device /dev/input/event3

At this point, clicking the extra mouse buttons should trigger page up and page down events.

To go further, let’s install xdotool, a widely supported input event automation tool:

$ sudo apt install xdotool

An alternative for it on Wayland is ydotool, but it requires manual installation.

We change the configuration to launch xdotool and trigger a more controlled scroll event:

modmap:
  - name: main remaps
	remap:
  	BTN_SIDE:
    	  skip_key_event: true
    	  press: { launch: ["xdotool", "click", "4"] }
    	  release: { launch: ["sleep", "0.05"] }
  	BTN_EXTRA:
    	  skip_key_event: true
    	  press: { launch: ["xdotool", "click", "5"] }
    	  release: { launch: ["sleep", "0.05"] }

Since both press and release are required, we use sleep as a placeholder. Of course, this solution can be developed with a more complex configuration.

4. Conclusion

In this article, we’ve looked into a basic algorithm for mapping mouse keys. We’ve also showcased a real-world example of configuring mouse buttons using xremap. Although we looked into a simple single key mapping, xremap offers a lot more.