How to detect no keys pressed while a meta key was held


I’m trying to set up my config such that:
1 - if super_l is pressed then other keys pressed… then popup various menus
2 - if super_l is pressed then released with no other keys pressed… then popup a different menu

Bindings for the first case are normal.
The second I’m finding hard: the closest I seem to have come is a convoluted loop of scheduling and testing as per the sample below.
But this only detects another meta key being pressed while super_l was held, not any arbitrary key.
And it gives odd functionality to F12!
One option that occurs is to call SuperTestOff on every key binding that uses super_l as one of the meta keys. But that’s really kludgy.
Better would be some way of registering a callback for any keypress event, and in that handler call SuperTestOff. Is such a thing possble (I’ve not come across it in the man pages etc).
Or alternatively is there a better way to achieve my goal??

What would be really nice is something like

  Key Super_L    A   N  (OnRelease NoOtherKeyPressed) Menu "StartMenu" Nop


My current convoluted partial mechanism:

DestroyFunc SuperPress
AddToFunc SuperPress
+ I       Echo in SuperPress
+ I       SuperTest

DestroyFunc SuperDepress
AddToFunc SuperDepress
+ I       Echo in SuperDepress
+ I       Deschedule 10
+ I       Menu "StartMenu" Nop

DestroyFunc SuperTestOff
AddToFunc SuperTestOff
+ I       Echo in SuperTestOff
+ I       Deschedule 10

DestroyFunc SuperTest
AddToFunc SuperTest
+ I       Echo in SuperTest
+ I       NoWindow FakeKeypress depth 1 press F12
+ I       Deschedule 10
+ I       Schedule 50 10 SuperTest

Key Super_L     A       A       SuperPress

# Fake keys to handle Super press / release (super is meta 4 here)
# NB order important as last overrides first
Key F12         A       A       SuperTestOff # another meta pressed - stop
Key F12         A       N       SuperDepress # released on its own
Key F12         A       4       Nop          # still pressed - carry on testing


Key-release events are not supported in all XServers, hence it’s not reliable for FVWM, and FVWM does not support them either.

– Thomas Adam

I realize the post to which I am replying is heading for 2 years old, but I didn’t see an answer to this problem when I searched the forums, so…

After playing with gnome shell (gnome3) I kind of liked this behavior, so I have come up with a hack to do the same in fvwm. It’s an ugly, filthy, disgusting hack on many levels, but it seems to be working, so I thought I’d share it.

This hack requires a python script (and python-xlib) that uses xlib to check the status of the Super_L key and a function that invokes that script. In the example here, I’m going to just launch an xterm when Super_L is tapped.

Create a function that will be responsible for launching some command when Super_L is pressed, like so:

DestroyFunc SuperLPress
AddToFunc SuperLPress
+ I PipeRead 'python $[FVWM_USERDIR]/ && echo Exec exec xterm'

And bind Super_L to the function:

Key Super_L A N SuperLPress

Create a python script ( and put it in your .fvwm (or other appropriate) directory:

import Xlib.display
import sys 
import time

class fake_out:
    def write(self,stuff=None):

#redirect stdout temporarily to silence the bad xlib implementation
saved = sys.stdout
sys.stdout = fake_out()
sys.stdout = saved

#need a delay that is long enough to allow the caller to let go of the button

if display.query_keymap()[16]!= 0:

If the key state is still being held, the script returns error 1 so that the piperead will not run the next command. The time.sleep is responsible for the delay so that there’s enough time to release the key before the key state is checked. The extra bit of craziness just before that is reassigning stdout so that the constructor for the Display object, or whatever part of Xlib is responsible for it, isn’t able to write any of its garbage to stdout and muck up the Piperead.

Now, other key bindings that make use of Super_L as a modifier will still work.

(Edit: typographical error in function, was missing space before I in +I PipeRead… and had a typo in FVWM_USERDIR)
(Edit: removed :0 argument to display constructor)