2

This answer show the command lines to swap the mouse primary and secondary button. However, I would like a script to automatically swap the mouse buttons every time is executed. Could somebody hint me on how to do this, I know near to nothing about bash scripts.

2
  • so if you execute it twice it swaps them back?
    – Jasen
    May 22, 2016 at 0:46
  • No, it just swap them once and it stay in that configuration, that is my main problem
    – Fachicon
    May 22, 2016 at 1:08

5 Answers 5

2

Without providing the output of xinput list on your system, no one can offer an answer which you could use directly. That is because xinput can show different devices than illustrated in How do I swap mouse buttons to be left handed from the terminal?.

For example, here's the output on OSX:

$ xinput list
⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ xquartz virtual pointer                   id=6    [slave  pointer  (2)]
⎜   ↳ pen                                       id=8    [slave  pointer  (2)]
⎜   ↳ cursor                                    id=9    [slave  pointer  (2)]
⎜   ↳ eraser                                    id=10   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ xquartz virtual keyboard                  id=7    [slave  keyboard (3)]

and here is the output on my Debian/testing:

$ xinput list
⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ VMware VMware Virtual USB Mouse           id=7    [slave  pointer  (2)]
⎜   ↳ VirtualPS/2 VMware VMMouse                id=9    [slave  pointer  (2)]
⎜   ↳ VirtualPS/2 VMware VMMouse                id=10   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=8    [slave  keyboard (3)]

so that on one system, there's possibly one id to choose (xquartz virtual pointer), while on another there are three possibilities. If you read through these, you'll find that the examples cited here are not contrived:

Given the variation (and vague documentation for xinput), you probably cannot automate the part about obtaining the mouse device's id.

Supposing that you do choose a usable identifier, and for the sake of discussion, call that "12". A script can read the output of

xinput get-button-map 12

into an array. Some scripting languages provide arrays, e.g., bash. But there are several pitfalls:

  • on my OSX system, that returns a list "1 2 3", while on the Debian system that returns a list "1 2 3 4 5 6 7 8 9 10 11 12".
  • you have to guess whether the extra buttons mean something, and
  • even the assignment of three button numbers may be not the obvious left/middle/right.

Then the script to toggle the keys has to save its state someplace, e.g., a file in your home directory. A script to manage that would have to

  • initialize the file with the current buttons
  • update it according to your scheme of toggling buttons (with 3 there are "3!" possible arrangements)

Supposing you have the simplest configuration (and interpretation), you could do something like this in a script:

#!/bin/sh
id=$1
cfg=$HOME/.mousebuttons
[ -f "$cfg" ] || xinput get-button-map $id | awk ' { printf "normal: %s\n", $0; }' >$cfg
mode=$(awk '{print $1;}' <$cfg)
# read and toggle
list=$(awk '{printf "%d %d %d\n", $3, $2, $4; }' <$cfg)
if [ "x$mode" = "xnormal" ]
then
    mode=reverse
else
    mode=normal
fi
# update the configuration
echo "$mode $list" | awk '{ printf "%s %d %d %d\n", $1, $2, $3, $4; }' >$cfg
xinput set-button-map $id $list
# show result
xinput get-button-map $id

The script accepts one parameter (the identifier of the mouse device). For the given example (and naming the script "toggle-buttons", making it executable and putting it in your $PATH):

toggle-buttons 12

should do the job.

1
  • Awesome, it worked like a charm ;).
    – Fachicon
    May 22, 2016 at 22:12
2

I'll add my own solution to this as the other answers sometimes seems overly complicated for the simple task of swapping the primary buttons (1 and 3) of a mouse.

#!/bin/bash                                                                                           
set -e

# To get the name of a devices, do "xinput list --name-only"                                          
DEVICE_NAME="PixArt Microsoft USB Optical Mouse"

current_button_map=$(xinput get-button-map "$DEVICE_NAME")

if [[ $current_button_map =~ "1 2 3" ]]; then
    echo "Making the mouse a lefty"
    xinput set-button-map "$DEVICE_NAME" 3 2 1
else
    echo "Making the mouse a righty"
    xinput set-button-map "$DEVICE_NAME" 1 2 3
fi
1

I'd do something like:

#!/bin/sh

mxid=$(xinput --list --short | awk '/Razer/{gsub(/.*id=/, "");gsub(/[[:blank:]].*/, "");print}')
bmap=$(xinput get-button-map $mxid)
nmap=$(awk '{s=$1;$1=$3;$3=s};1' <<<$bmap)
xinput set-button-map $mxid $nmap

This assumes you know the "name" of your mouse (in my case it's Razer) and you know the default button mapping (i.e. which buttons are left and right so that you can swap them) that you get with xinput list $mxid:

Button labels: "Button Left" "Button Middle" "Button Right"....

and xinput get-button-map $mxid:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

As you can see, in my case 1 =>> left and 3 =>> right so the script above just reads the current mapping and swaps first and third values and then sets the new mapping.

1

You can put the command line into a file:

#!/bin/bash
# swap two mouse buttons for better ergonomics, e.g. BACK, FORWARD    
xinput set-button-map 12 3 2 1 

Once you have done that make it executable (if the file is named swap_buttons.sh):

chmod +x swap_buttons.sh

Now you can run the script with:

./swap_buttons.sh
2
  • The problem with that is the command only swap the once, i.e., it maps the buttons to a fixed configuration. I what them to swap iteratively.
    – Fachicon
    May 22, 2016 at 1:11
  • why on earth would one do such a thing?
    – dotbit
    Dec 15, 2019 at 16:38
0

If you need to toggle a state (and your reverse/unreverse the order of the mouse keys is such a state), of device you either have to be able to query the device for the current state, or keep the state in some file.

As I couldn't find if xinput does have a way of asking a mouse for the button mapping, you should probably go with storing the state in a file e.g. ~/.config/mousebuttons. Your script should write 'reverse' to the file when it executes:

xinput set-button-map 12 3 2 1 and write 'normal' to that file when executing:

xinput set-button-map 12 2 3 The actual action to take depends on reading the file: do the first step if the file contents when the script starts are normal (or the file doesn't exist), and do the second if the contents are reverse.

The file contents flip from reverse to normal on each invocation. Your actual state might not reflect the content of the file, e.g. after a reboot, therefore print out to the screen what the new state is as well for a visual reminder. If the file is out of sync with the state, a single invocation of your script will sync it again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.