Cool Mouse Stuff with Linux

Linux has built-in tools for programming the buttons on your mouse or trackball. You don’t need any drivers or proprietary software. Just a few simple tools you can install from the repos. I’m doing this on Ubuntu 16 and 18, but it should work on any recent Linux distro.

First, use xev to detect how your system is recognizing the mouse buttons. Start xev from a command prompt, then hover over its window, click each button, and look at the text in the command prompt window. This will tell you the # for each button. The first 3 buttons are always defined the same way: left-click is button 1, middle-click 2, right-click 3. Extra buttons are “non-standard” and can be defined in any way.

To change what a button does, use xbindkeys. Its control script is a file in your home directory called .xbindkeysrc. The app xte fabricates keystrokes and mouseclicks.

For example: here’s an .xbindkeysrc that does 2 things:

  • Single click of button 2 (middle button) causes double-click of button 1 (left)
  • Single click of button 9 causes Control-click of button 1.
# button 2 (scroll wheel) is double click
"/usr/bin/xte 'mouseclick 1' 'mouseclick 1'"
b:2 + release

# button 9 (upper left alternate) is control + left click
"/usr/bin/xte 'keydown Control_L' 'mouseclick 1' 'keyup Control_L'"
b:9 + release

This should work everywhere in all apps. It does work in some apps (like Thunar), but not in others (like Firefox). I wondered – why?

Limitation 1

After experimenting, I discovered that xte is too fast for some apps. I added a few strategically located brief (10 ms) delays and it worked everywhere.

Example: change the above to this:

# button 2 (scroll wheel) is double click
"/usr/bin/xte 'mouseclick 1' 'usleep 10000' 'mouseclick 1'"
b:2 + release

# button 9 (upper left alternate) is control + left click
"/usr/bin/xte 'keydown Control_L' 'mousedown 1' 'usleep 10000' 'mouseup 1' 'keyup Control_L'"
b:9 + release

The usleep param is in microseconds, so 10,000 is 10 milliseconds. This now works in all apps.

Limitation 2

Another limitation: it’s hard to make the same button duplicate itself from xbindkeys. If you do this, it can lead to infinite loops. For example: xbindkeys can easily make a single click of button 2, cause a double-click of button 1. But xbindkeys can’t make a single click of button 1, cause a double-click of the same button. This will fail or cause an infinite loop.

For that, use imwheel. Originally intended to adjust the sensitivity of the scroll wheel, it is also useful for other things. This is because internally, a scroll wheel is just 2 buttons: up and down. To make it more sensitive, imwheel duplicates each click of those buttons. But imwheel can do this with any buttons, not just the scroll wheel. Its config file is .imwheelrc, in your home directory.

Here’s an imwheel config that doubles the scroll wheel sensitivity:

# Apply to all apps (individual apps can be customized)
".*"
# Amplify scroll up/down
None,    Up,    Button4,    2
None,    Down,    Button5,    2
# Amplify scroll left/right
None,    Left,    Button6,    10
None,    Right,    Button7,    10

On my trackball, the scroll wheel is Button 4 and Button 5. The scroll wheel tilts L and R; these are buttons 6 and 7. Yours may be different; check it with xev.