[xmonad] Capturing modkey release
Matthew Hague
matthewhague at zoho.com
Tue Jul 3 11:06:39 CEST 2012
> This is because there are no grabs established on the bare modifiers, nor
> is there a generic "send all key events" mask in place, so X11 doesn't
> bother to send events for them. A If it sent an event for every little
> thing that happened, unsolicited, most programs would be busy-looping on
> noise events instead of doing useful work; as such, you should always
> remember to *request* the events you want.
> So in this case you probably want to use grabKey (aka XGrabKey()) to
> select for interest in the modifier key by itself; the handleEventHook
> handler should ungrab the keyboard (you don't *really* want xmonad to
> seize ownership of the keyboard every time you touch the key), do whatever
> you want to do, and pass the event on.
> (This is largely what the other suggestion does, once you poke at the
> code.)
Bearing all this in mind, and stealing liberally from CycleWindows (suggested
by wagnerdm, though it doesn't quite do what i wanted), i finally settled on
this arrangement (modulo a bunch of conditionals on when i want it to switch to
master):
For the key bindings:
...
, ((modm, xK_j), changeFocus W.focusDown)
, ((modm, xK_k), changeFocus W.focusUp )
...
For the capture:
changeFocus f = do
windows f
setModReleaseCatch
setModReleaseCatch :: X ()
setModReleaseCatch = do
XConf { theRoot = root, display = disp } <- ask
io $ grabKeyboard disp root False grabModeAsync grabModeAsync currentTime
return ()
onModRelease = do
XConf { display = disp, theRoot = root } <- ask
io $ ungrabKeyboard disp currentTime
windows W.shiftMaster
return (All True)
Plus an adjustment to event hooks:
modKeyEvents :: Event -> X All
modKeyEvents (KeyEvent {ev_event_type = t, ev_keycode = code})
| (t == keyRelease) && (code == modKeyCode) = onModRelease
myEventHook = modKeyEvents
This isn't super elegant, being spread around my config like that, and grabbing the whole keyboard, but there are reasons for this:
1) Using the following instead of grabKeyboard:
io $ grabKey disp modkc anyModifier root False grabModeAsync grabModeAsync
io $ ungrabKey disp modkc anyModifier root
had the problem that i didn't get the next release of the modkey, but
the second release. That is: i pressed mod4, pressed and released j,
released mod4, got no notification, pressed mod4 again, released it
again, got notified.
2) Putting everything together, a-la the implementation of cycleStacks' in
CycleWindows:
http://xmonad.org/xmonad-docs/xmonad-contrib/src/XMonad-Actions-CycleWindows.html
meant that the whole keyboard had to be intercepted while the window
selection was taking place -- so new implementations for mod4+j, mod4+k had
to be provided, plus bindings for any other keys you might want to still
use. I decided to do it my slightly messy way and keep all the xmonad
bindings.
Thanks for feedback,
Matt
More information about the xmonad
mailing list