11

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.

  • You can certainly detect mouse events, but I don't believe there's a way to ask the system if the mouse button is currently being pressed right now. Every mouse activity parser I've seen watches for, if you'll forgive the pseudocode, MouseButton1Down and MouseButton1Up events to act upon. – DopeGhoti Dec 27 '13 at 0:42
  • I need some script which will watch the mouse and when left button gets pressed, it will do something. – MartinP Dec 27 '13 at 0:46
  • Need clarification. Are you wanting something where when you're in a shell, and you click the terminal window, that specific shell does something? Or do you want it so that when you click a specific mouse button anywhere a script is run (and you don't need to see the script in a terminal)? – Patrick Dec 27 '13 at 2:11
  • I need script, which will I run and then it will watch for mouse buttons anywhere on desktop. It won't block the mouse, it will only listen to it. I tried to write program for it in C with Xlib, but it only has XGrabButton and XGrabPointer and that I don' want, because it grabs the pointer and another windows don't register click events. – MartinP Dec 27 '13 at 9:03
11
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.

  • xinput --list gives me X Input extension not available.. Sadly Google for this matter does not reveal anything which is helpful in my case: Xvnc4 in a minimal Debian VM. Likely I am out of luck – Tino Jun 21 '16 at 7:42
6

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

  • 2
    But that works only for the created window. How can I catch that event globally? – MartinP Dec 27 '13 at 1:31
4

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)

  • Please, can you explain? – lucaswxp Aug 29 at 14:50
2

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.

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.