Use key press and key release to trigger different scripts

Using applications, configuring, problems
Post Reply
Message
Author
User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

Use key press and key release to trigger different scripts

#1 Post by greengeek »

Imagine that I want to use the Win key on my keyboard to trigger one script when I hold it down, and a different script when I release it - how can I achieve this?

I know that I can program a key binding into /etc/xdg/templates/_root_jwmrc but that method generally only attaches a single script to the entire keydown/keyup sequence. I realise that I could program the two scripts to follow each other after the keydown/keyup - but that will not give me the effect that I need.

Script 1 needs to run as soon as I hold the Win key down, and script 2 must not run until I release the Win key - which will be an unspecified time later - potentially even minutes.

I have used xev to determine the following data from my keyboard:

This event means the Windows key has been pressed down:
KeyPress event, state 0x0, keycode 115

This event means the Windows key has been released:
KeyRelease event, state 0x40, keycode 115


I see a number of web tutorials that appear to suggest that javascript can be used to monitor keypress and keyrelease separately but I don't think javascript is going to be a suitable answer for me as I need this to be more or less a couple of hardcoded keyboard shortcuts - not a browser function.

Any thoughts?

EDIT :Amongst all the javascript noise I saw some QT tutorials and also this:
https://gist.github.com/javiercantero/7753445
It looks as if that may have potential.

Let me offer further explanatory information - here are two possible hypothetical scenarios:

1) I want to take a screenshot at the moment I hold the Win key down and then some time later i want to take a second screenshot at the moment I release the Win key.

2) Lets say I have a dead leftclick mouse button and I want to use the Win key to simulate mouse leftclick actions. I already have this set up to some extent so that pressing the Win key triggers xdotool to send a click1 event. However, this doesn't help me if I want to drag a window by it's title bar - under those conditions I need the KeyRelease event to be avoided until I actually release the Win key.

I hope these two examples serve to explain the required functionality better.

Note to self - check out this post and included c snippet to see if it has anything to offer.
.
Last edited by greengeek on Tue 04 Oct 2016, 03:29, edited 2 times in total.

User avatar
Flash
Official Dog Handler
Posts: 13071
Joined: Wed 04 May 2005, 16:04
Location: Arizona USA

#2 Post by Flash »

Sadly I don't know the answer to your question. This thread might have some clues.

mostly_lurking
Posts: 328
Joined: Wed 25 Jun 2014, 20:31

#3 Post by mostly_lurking »

You can probably use xbindkeys for this.

First of all, stop your Windows key from auto-repeating:

Code: Select all

xset -r 115
When you test it with xev now, it should generate only one press and release event, no matter how long you keep it pressed.

Now configure xbindkeys. The config tool in the post that I linked doesn't seem to cover key release events, so you'll have to edit ~/.xbindkeysrc manually to include that one (example for the left Windows key):

Code: Select all

#example-press
"put your command here"
    m:0x0 + c:115
    NoSymbol 

#example-release
"put your command here"
    m:0x0 + c:115 + Release
    NoSymbol  
Then run xbindkeys.

It kinda works, running the first command when pressing the key, and the second one upon release.

It's not very good for emulating a mouse button, though. I tried that using xdotool to generate mousedown and mouseup events: it works well enough for simple clicking and dragging, but fails to drag program windows and operate menus; they open, at least after double-clicking, but clicking any options does nothing. (I'm using Openbox; no idea if it works better with JWM.) Testing it with xev revealed that it generates a "FocusIn" event which normal mouse clicks don't produce.

To emulate a mouse, you could use mouse keys, if your keyboard has a number pad. On my Puppy, this feature is turned on and off by pressing Shift + Numlock. Of course, this means you can't use the number pad for other things anymore. If you prefer to use the Windows key rather than the numpad "5" for clicking, you can map the Win key to the "5" one, which is "KP_Begin" or "KP_5", using xmodmap (which your Puppy should have already):

Code: Select all

xmodmap -e "keycode 115 = KP_Begin"
And maybe put that all into some script that runs at startup.

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#4 Post by greengeek »

mostly_lurking wrote:You can probably use xbindkeys for this.
Many thanks for this idea - basic testing so far suggests that it does indeed distinguish between KeyPress and KeyRelease.
First of all, stop your Windows key from auto-repeating:

Code: Select all

xset -r 115
When you test it with xev now, it should generate only one press and release event, no matter how long you keep it pressed.
This already seemed to be the case on my system (Slacko 5.6 derivative) - normal keyboard characters do have auto repeat set but the Win key (and also ctrl) do not autorepeat.
Now configure xbindkeys. The config tool in the post that I linked doesn't seem to cover key release events, so you'll have to edit ~/.xbindkeysrc manually to include that one (example for the left Windows key):

Code: Select all

#example-press
"put your command here"
    m:0x0 + c:115
    NoSymbol 

#example-release
"put your command here"
    m:0x0 + c:115 + Release
    NoSymbol  
Then run xbindkeys.
Initially the release portion of this did not work for me - I had to change m:0x0 to m:0x40

This is the test code i am using and it seems to be triggering separate events successfully:

Code: Select all

#example-press
"leafpad"
    m:0x0 + c:115
    NoSymbol

#example-release
"urxvt"
    m:0x40 + c:115 + Release
    NoSymbol  

##################################
# End of xbindkeys configuration #
##################################
Testing it with xev revealed that it generates a "FocusIn" event which normal mouse clicks don't produce.
Hmmmm, thanks for the tip. I will do sme more testing and see how far I can get.
cheers!

User avatar
Pete
Posts: 660
Joined: Sun 02 Mar 2014, 18:36

#5 Post by Pete »

@greengeek

Not to throw a spanner in the works as you seem to be making good progress, but have you considered the condition where the key may be released before the key press script has finished executing?

Let's say key_down script takes 40mS to complete, but the key is released after just 35mS thereby triggering the key_up script.
This could create problems if both scripts try and access the same file, for example a file that is used to store settings or other data that your scripts generate.

You mention an example of taking two screen shots, one on key_down and another on key_up.
Did a quick test by timming how long it takes ffmpeg to grab a screen shot from my web cam, 120mS, well within human reaction times of pressing and releasing the key.

Since ffmpeg is still using /dev/video0 (in my case), when it tries to grab the second screen grab, there will be an error as /dev/video0 is still in use, by the first instance of ffmpeg.

How are you safe guarding against it? Or is this a condition that is not likely to occur with your application/uses?

My post is not meant to discourage you, but rather to give some thought to "what if?"

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#6 Post by greengeek »

Pete wrote:have you considered the condition where the key may be released before the key press script has finished executing?
Good point - I had not considered that yet as I was focused mostly on simulating mouse control - however the issue you raise could be very important if the "two script" function is the focus.
mostly_lurking wrote:It's not very good for emulating a mouse button, though. I tried that using xdotool to generate mousedown and mouseup events: it works well enough for simple clicking and dragging, but fails to drag program windows and operate menus;.
It looks as if my two examples have different solutions. The solution provided by mostly_lurking does allow my original request of running different scripts dependent on whether the Win key is pressed or released. However as he mentioned this does not seem to be the best way to use a key to emulate a mouse button as my second example required. Xdotool had limitations in terms of focus and window control - however there is another possible method:

There seem to be "xkb" functions that operate at a lower level than xdotool (and another similar utility called xte). It is possible to use a utility called xkbset to assist with mapping mouse functions etc to keys.

My puppy does not come with xkbset so I downloaded a debian file that seems to be compatible with my Slacko 5.6 derivative. This is how I can use it to remap mouse button 1 to the Win key:

Enter the following command in a terminal:

Code: Select all

xkbset m
Then remap the appropriate key to mouse button 1:

Code: Select all

xmodmap -e "keycode 115 = Pointer_Button1"
This seems to make the Win key work just like mouse button 1.

This web page had a mixture of useful ideas:
http://askubuntu.com/questions/254424/h ... m-keyboard

That tutorial had the following to say about getting the changes to persist over reboots. I don't know yet if this is relevant to puppy but I will post it anyway:
Using xmodmap

Now that we have obtained the information on the keys that we wish to change from xev, we will use xmodmap to modify the keymaps. From the command terminal(Ctrl+Alt+t), run the following commands:

This command modifies the Caps Lock to use the same behavior as Esc

xmodmap -e "keycode 66 = Escape"

This option prints a keymap table as expressions into the file ~/.Xmodmap

xmodmap -pke > ~/.Xmodmap

Activate the changes(for this login session only) with following command:

xmodmap ~/.Xmodmap

Making changes persistent across reboots:

If it doesn't exist, create a file in your home folder called .xinitrc.

touch .xinitrc

Place the following line in the file and save the file:

xmodmap ~/.Xmodmap
And here is another ubuntu page which may also be relevant to some uses:
http://askubuntu.com/questions/325272/p ... 382#347382

mostly_lurking
Posts: 328
Joined: Wed 25 Jun 2014, 20:31

#7 Post by mostly_lurking »

greengeek wrote:There seem to be "xkb" functions that operate at a lower level than xdotool (and another similar utility called xte). It is possible to use a utility called xkbset to assist with mapping mouse functions etc to keys.

My puppy does not come with xkbset so I downloaded a debian file that seems to be compatible with my Slacko 5.6 derivative. This is how I can use it to remap mouse button 1 to the Win key:

Enter the following command in a terminal:

Code: Select all

xkbset m
Then remap the appropriate key to mouse button 1:

Code: Select all

xmodmap -e "keycode 115 = Pointer_Button1"
This seems to make the Win key work just like mouse button 1.
Yes, this works as well. What xkbset m does is turning "mouse keys" on. So it's essentially an alternative to pressing a key combination. I wonder if it would work that way on computers with no number pad. I googled around a bit, but didn't find anything conclusive.

BTW, it's also possible to remap the mouse buttons with xmodmap (I forgot about that yesterday), so you could, for example, swap the left and middle button around. However, I'm not sure if that's a better alternative - if I tried to keep my fingers on the middle and right buttons and use the scroll wheel as left click, I'd get a cramp in my hand...

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#8 Post by greengeek »

mostly_lurking wrote:BTW, it's also possible to remap the mouse buttons with xmodmap (I forgot about that yesterday), so you could, for example, swap the left and middle button around. However, I'm not sure if that's a better alternative
Actually that is part of the solution to one of the problems I am trying to solve.

One of my netbooks has a touchpad that doesn't get the synaptics driver loaded so I have been looking for other ways to turn off tap-to-click (which I seriously dislike...) and I was able to use xmodmap to remap the mouse button 1 (and therefore the touchpad tap-to-click function too) to mouse button 6 (an unused function on my machine).

Then I used xdotool attached to a keyboard key to simulate the normal mouse function. (Thread post here). It was more or less successful except for the xdotool limitations you have mentioned.

I spent a good deal of yesterday trying to see if I could replace the xdotool part of that functionality with the xmodmap reprogramming of the Winkey as you had suggested, along with the variant of "Pointer_Button1" so that the Winkey acquired the functionality of the normal mouse button 1.

This works if I use xmodmap to reprogram mousebutton 1 to mousebutton 2,3,4 or 5.

The good side of this is that the touchpad loses it's tap-to-click function but the down side is it means that the touchpad acquires the function of mousebutton 2,3,4 or 5. This gave me some odd pointer movements which were almost as bad as tap-to-click.

I was hopeful that I could map mousebutton 1 to button 6 (which I feel would have less undesirable behaviour of the touchpad) but the problem with this is that xmodmap does not allow the keysym of "Pointer_Button6". It's just not a meaningful term to xkb (or whatever is the old lowlevel handler of mouse button events). Apparently there are around 10 possible mousebutton events (here is a list of them) but the older utilities don't seem to recognise past button 5.

Xdotool is happy with "click 6" but xmodmap is not happy with "Pointer_Button6" so that's where I'm stuck so far.

EDIT : Here is the list of keysyms I was working with:
http://www.cs.cmu.edu/afs/cs/project/gw ... ib/Keysyms
There are some interesting looking ones concerning Pointer functions so maybe I can stumble across some other way forward...

EDIT 2 : I have it in my mind that xfree86 may offer some newer options. Interesting info here
.

Post Reply