aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--XMonad/Hooks/DebugKeyEvents.hs107
-rw-r--r--xmonad-contrib.cabal1
2 files changed, 108 insertions, 0 deletions
diff --git a/XMonad/Hooks/DebugKeyEvents.hs b/XMonad/Hooks/DebugKeyEvents.hs
new file mode 100644
index 0000000..edacb6c
--- /dev/null
+++ b/XMonad/Hooks/DebugKeyEvents.hs
@@ -0,0 +1,107 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : XMonad.Hooks.DebugKeyEvents
+-- Copyright : (c) 2011 Brandon S Allbery <allbery.b@gmail.com>
+-- License : BSD
+--
+-- Maintainer : Brandon S Allbery <allbery.b@gmail.com>
+-- Stability : unstable
+-- Portability : unportable
+--
+-- A debugging module to track key events, useful when you can't tell whether
+-- xmonad is processing some or all key events.
+-----------------------------------------------------------------------------
+
+module XMonad.Hooks.DebugKeyEvents (-- * Usage
+ -- $usage
+ debugKeyEvents
+ ) where
+
+import XMonad.Core
+import XMonad.Operations (cleanMask)
+
+import Graphics.X11.Xlib
+import Graphics.X11.Xlib.Extras
+
+import Control.Monad.State (gets)
+import Data.Bits
+import Data.List (intercalate)
+import Data.Monoid
+import Numeric (showHex)
+import System.IO (hPutStrLn
+ ,stderr)
+
+-- $usage
+-- Add this to your handleEventHook to print received key events to the
+-- log (the console if you use @startx@/@xinit@, otherwise usually
+-- @~/.xsession-errors@).
+--
+-- > , handleEventHook = debugKeyEvents
+--
+-- If you already have a handleEventHook then you should append it:
+--
+-- > , handleEventHook = ... <+> debugKeyEvents
+--
+-- Logged key events look like:
+--
+-- @keycode 53 sym 120 (0x78, "x") mask 0x0 () clean 0x0 ()@
+--
+-- The @mask@ and @clean@ indicate the modifiers pressed along with
+-- the key; @mask@ is raw, and @clean@ is what @xmonad@ sees after
+-- sanitizing it (removing @numberLockMask@, etc.)
+--
+-- For more detailed instructions on editing the logHook see:
+--
+-- "XMonad.Doc.Extending#The_log_hook_and_external_status_bars"
+
+-- | Print key events to stderr for debugging
+debugKeyEvents :: Event -> X All
+debugKeyEvents (KeyEvent {ev_event_type = t, ev_state = m, ev_keycode = code})
+ | t == keyPress =
+ withDisplay $ \dpy -> do
+ sym <- io $ keycodeToKeysym dpy code 0
+ msk <- cleanMask m
+ nl <- gets numberlockMask
+ io $ hPutStrLn stderr $ intercalate " " ["keycode"
+ ,show code
+ ,"sym"
+ ,show sym
+ ," ("
+ ,hex sym
+ ," \""
+ ,keysymToString sym
+ ,"\") mask"
+ ,hex m
+ ,"(" ++ vmask nl m ++ ")"
+ ,"clean"
+ ,hex msk
+ ,"(" ++ vmask nl msk ++ ")"
+ ]
+ return (All True)
+debugKeyEvents _ = return (All True)
+
+-- | Convenient showHex variant
+hex :: Integral n => n -> String
+hex v = "0x" ++ showHex v ""
+
+-- | Convert a modifier mask into a useful string
+vmask :: KeyMask -> KeyMask -> String
+vmask numLockMask msk = intercalate " " $
+ reverse $
+ fst $
+ foldr vmask' ([],msk) masks
+ where
+ masks = map (\m -> (m,show m)) [0..toEnum (bitSize msk - 1)] ++
+ [(numLockMask,"num" )
+ ,( lockMask,"lock" )
+ ,(controlMask,"ctrl" )
+ ,( shiftMask,"shift")
+ ,( mod5Mask,"mod5" )
+ ,( mod4Mask,"mod4" )
+ ,( mod3Mask,"mod3" )
+ ,( mod2Mask,"mod2" )
+ ,( mod1Mask,"mod1" )
+ ]
+ vmask' _ a@( _,0) = a
+ vmask' (m,s) (ss,v) | v .&. m == m = (s:ss,v .&. complement m)
+ vmask' _ r = r
diff --git a/xmonad-contrib.cabal b/xmonad-contrib.cabal
index cca4862..fd2bdfc 100644
--- a/xmonad-contrib.cabal
+++ b/xmonad-contrib.cabal
@@ -137,6 +137,7 @@ library
XMonad.Config.Sjanssen
XMonad.Config.Xfce
XMonad.Hooks.CurrentWorkspaceOnTop
+ XMonad.Hooks.DebugKeyEvents
XMonad.Hooks.DynamicHooks
XMonad.Hooks.DynamicLog
XMonad.Hooks.EwmhDesktops