Linux - remapping of mouse buttons

This is how I remapped a mouse button to do the same action as the mouse wheel click (because that other button was way more convenient to press than the mouse wheel).

Option 1: polling script

Create a bash file e.g. as ~/bin/mouse_buttons.sh:

#/bin/bash

required="1 2 3 4 5 6 7 8 9 10 11 2 " # (1)
mouse_name="ELECOM" # (2)

while true
do
  for id in $(xinput --list --id-only)
  do
    name=$(xinput --list --name-only $id)
    if [[ $name == *"$mouse_name"* ]]; then
      current=$(xinput get-button-map $id 2> /dev/null)
      if [ "$current" != "" ] && [ "$current" != "$required" ]; then # (3)
        echo "setting"
        xinput set-button-map $id $required
      fi
    fi
  done
  sleep 2 # (4)
done

Notes:

  • (1) Define the target (required) buttons mapping. Experiment with xinput set-button-map to set your desired mapping. Then, after everything works, use xinput get-button-map to get the current mapping. In my case, the change can be described as: change the button with ID 12 to button with ID 2 (the mouse wheel had ID 2). Note the space at the end - we will later compare this simply as a string and this is exactly the format in which xinput get-button-map returns it.
  • (2) Part of the name of your mouse, as identified in xinput list. We want to target only this one device.
  • (3) Get current button map state and change it only if needed (to not do xinput set-button-map unnecessarily).
  • (4) Do the actions repeatedly, every 2 seconds. Mostly, the script only does xinput get-button-map to find out that the current state is OK and there is nothing to do. However, the loop is good for the cases when you disconnect and re-connect the mouse - in such case the button mapping will be lost and needs to be done again.

Maybe there is some way how to listen for device changes which would avoid sleep and unnecessary polling.

The script presented here can be ran without any special (root) privileges.

Then, add this to ~/.xinitrc before starting the window manager:

bin/mouse_buttons.sh &

Option 2: xorg configuration

This is better. It does not need any custom always running script with polling.

Simply create file /etc/X11/xorg.conf.d/20-mouse-buttons.conf:

Section "InputClass"
  Identifier  "mouse buttons"
  MatchProduct "ELECOM TrackBall Mouse HUGE TrackBall"
  MatchIsPointer "on"
  Option  "ButtonMapping" "1 2 3 4 5 6 7 8 9 10 11 2"
EndSection

The value for MatchProduct can be obtained using xinput list.

Written on February 7, 2022