Detect if mouse button is pressed, then invoke a script or command

All we need is an easy explanation of the problem, so here it is.

Is there any way to get mouse button state from bash? Xdotool can only get mouse location.

I’d like to set something up where I can define a rule where when a mouse button is pressed, a script can get executed.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

xinput --query-state <mouse_id>

This give you a state for all mouse buttons, that looks like this:

2 classes :
ButtonClass
    button[1]=up
    button[2]=up
    button[3]=up
    button[4]=up
    button[5]=up
    button[6]=up
    button[7]=up
    button[8]=up
    button[9]=up
    button[10]=up
    button[11]=up
    button[12]=up
    button[13]=up
    button[14]=up
    button[15]=up
    button[16]=up
ValuatorClass Mode=Relative Proximity=In
    valuator[0]=313
    valuator[1]=667
    valuator[2]=-20

The mouse_id can be obtained from:

xinput --list

Here is a little mouse button watcher script:

#!/bin/bash

MOUSE_ID=$(xinput --list | grep -i -m 1 'mouse' | grep -o 'id=[0-9]\+' | grep -o '[0-9]\+')

STATE1=$(xinput --query-state $MOUSE_ID | grep 'button\[' | sort)
while true; do
    sleep 0.2
    STATE2=$(xinput --query-state $MOUSE_ID | grep 'button\[' | sort)
    comm -13 <(echo "$STATE1") <(echo "$STATE2")
    STATE1=$STATE2
done

You may need to change MOUSE_ID detection string(‘mouse’) to something else.

Method 2

You can use the command line tool xev to find out the state of your mouse’s buttons within the X environment.

Example

$ xev
...
ButtonPress event, serial 36, synthetic NO, window 0x3800001,
    root 0x86, subw 0x0, time 319064320, (164,14), root:(166,101),
    state 0x0, button 1, same_screen YES

ButtonRelease event, serial 36, synthetic NO, window 0x3800001,
    root 0x86, subw 0x0, time 319064439, (164,14), root:(166,101),
    state 0x100, button 1, same_screen YES

ButtonPress event, serial 36, synthetic NO, window 0x3800001,
    root 0x86, subw 0x0, time 319065208, (164,14), root:(166,101),
    state 0x0, button 1, same_screen YES

ButtonRelease event, serial 36, synthetic NO, window 0x3800001,
    root 0x86, subw 0x0, time 319065337, (164,14), root:(166,101),
    state 0x100, button 1, same_screen YES

ButtonPress event, serial 36, synthetic NO, window 0x3800001,
    root 0x86, subw 0x0, time 319066059, (164,14), root:(166,101),
    state 0x0, button 1, same_screen YES

But this information only gets you partially to a solution. The key information you want to extract from above is which number is associated with a particular button on your mouse. In my example I’m pressing the left button, “buton 1”.

xbindkeys

You can use this tool to setup a action that’s associated with a button being pressed. You can even setup a rule that requires a key press or even a key + button pressed together.

Example

You’ll need to first make sure the packages xbindkeys is installed.

Then you’ll need to run the following command, one time only, to create a template xbindkeys configuration file.

$ xbindkeys --defaults > /home/saml/.xbindkeysrc

With the file created you can open it in a text editor and add a rule like this:

"xterm"
  b:3

This rule states that we want to run the program xterm when the button 3 is pressed. The “button 3” is my right mouse button.

With the above change made we need to kill xbindkeys if it’s already running and then restart it.

$ killall xbindkeys
$ xbindkeys

Now with this running any time I click the right mouse button, an xterm will get executed.

References

Method 3

if you just want to run bash command in xterm on mouse click (or wheel event) you can try this example:

$ echo -e "\e[?1000h"
$ while read -n 6; do echo hellowworld; done

this is for wheel event (for click set 12 instead)

Method 4

You can’t have your cake button press event and eat it. If you want your script to receive a mouse event, then the mouse event will be sent to your script instead of any other application — that means your script has to grab the mouse event. If your script doesn’t claim the event then the window that should get it gets it.

If you want, you can resend the mouse event to the focused window or the window at given coordinates (xdotool click).

You can use XBindKeys to execute a script on certain mouse or keyboard events.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply