{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeApplications #-}
module XMonad.Actions.UpKeys
(
useUpKeys,
UpKeysConfig (..),
ezUpKeys,
)
where
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import XMonad
import XMonad.Prelude
import XMonad.Util.EZConfig (mkKeymap)
import qualified XMonad.Util.ExtensibleConf as XC
data UpKeysConfig = UpKeysConfig
{
UpKeysConfig -> Bool
grabKeys :: !Bool
, UpKeysConfig -> Map (KeyMask, KeySym) (X ())
upKeys :: !(Map (KeyMask, KeySym) (X ()))
}
instance Default UpKeysConfig where
def :: UpKeysConfig
def :: UpKeysConfig
def = UpKeysConfig { grabKeys :: Bool
grabKeys = Bool
False, upKeys :: Map (KeyMask, KeySym) (X ())
upKeys = Map (KeyMask, KeySym) (X ())
forall a. Monoid a => a
mempty }
instance Semigroup UpKeysConfig where
(<>) :: UpKeysConfig -> UpKeysConfig -> UpKeysConfig
UpKeysConfig Bool
g Map (KeyMask, KeySym) (X ())
u <> :: UpKeysConfig -> UpKeysConfig -> UpKeysConfig
<> UpKeysConfig Bool
g' Map (KeyMask, KeySym) (X ())
u' = Bool -> Map (KeyMask, KeySym) (X ()) -> UpKeysConfig
UpKeysConfig (Bool
g Bool -> Bool -> Bool
&& Bool
g') (Map (KeyMask, KeySym) (X ())
u Map (KeyMask, KeySym) (X ())
-> Map (KeyMask, KeySym) (X ()) -> Map (KeyMask, KeySym) (X ())
forall a. Semigroup a => a -> a -> a
<> Map (KeyMask, KeySym) (X ())
u')
useUpKeys :: UpKeysConfig -> (XConfig l -> XConfig l)
useUpKeys :: forall (l :: * -> *). UpKeysConfig -> XConfig l -> XConfig l
useUpKeys UpKeysConfig
upKeysConf = ((XConfig l -> XConfig l)
-> UpKeysConfig -> XConfig l -> XConfig l)
-> UpKeysConfig
-> (XConfig l -> XConfig l)
-> XConfig l
-> XConfig l
forall a b c. (a -> b -> c) -> b -> a -> c
flip (XConfig l -> XConfig l) -> UpKeysConfig -> XConfig l -> XConfig l
forall a (l :: * -> *).
(Semigroup a, Typeable a) =>
(XConfig l -> XConfig l) -> a -> XConfig l -> XConfig l
XC.once UpKeysConfig
upKeysConf \XConfig l
conf -> XConfig l
conf
{ handleEventHook = handleEventHook conf <> (\Event
e -> Event -> X ()
handleKeyUp Event
e X () -> All -> X All
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Bool -> All
All Bool
True)
, startupHook = startupHook conf <> when (grabKeys upKeysConf) grabUpKeys
}
where
grabUpKeys :: X ()
grabUpKeys :: X ()
grabUpKeys = do
XConf{ display = dpy, theRoot = rootw } <- X XConf
forall r (m :: * -> *). MonadReader r m => m r
ask
realKeys <- maybe mempty upKeys <$> XC.ask @X @UpKeysConfig
let grab :: (KeyMask, KeyCode) -> X ()
grab (KeyMask
km, KeyCode
kc) = IO () -> X ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO () -> X ()) -> IO () -> X ()
forall a b. (a -> b) -> a -> b
$ Display
-> KeyCode -> KeyMask -> KeySym -> Bool -> CInt -> CInt -> IO ()
grabKey Display
dpy KeyCode
kc KeyMask
km KeySym
rootw Bool
True CInt
grabModeAsync CInt
grabModeAsync
traverse_ grab =<< mkGrabs (Map.keys realKeys)
ezUpKeys :: XConfig l -> [(String, X ())] -> Map (KeyMask, KeySym) (X ())
ezUpKeys :: forall (l :: * -> *).
XConfig l -> [(String, X ())] -> Map (KeyMask, KeySym) (X ())
ezUpKeys = XConfig l -> [(String, X ())] -> Map (KeyMask, KeySym) (X ())
forall (l :: * -> *).
XConfig l -> [(String, X ())] -> Map (KeyMask, KeySym) (X ())
mkKeymap
handleKeyUp :: Event -> X ()
handleKeyUp :: Event -> X ()
handleKeyUp KeyEvent{ EventType
ev_event_type :: EventType
ev_event_type :: Event -> EventType
ev_event_type, KeyMask
ev_state :: KeyMask
ev_state :: Event -> KeyMask
ev_state, KeyCode
ev_keycode :: KeyCode
ev_keycode :: Event -> KeyCode
ev_keycode }
| EventType
ev_event_type EventType -> EventType -> Bool
forall a. Eq a => a -> a -> Bool
== EventType
keyRelease = (Display -> X ()) -> X ()
forall a. (Display -> X a) -> X a
withDisplay \Display
dpy -> do
s <- IO KeySym -> X KeySym
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO KeySym -> X KeySym) -> IO KeySym -> X KeySym
forall a b. (a -> b) -> a -> b
$ Display -> KeyCode -> CInt -> IO KeySym
keycodeToKeysym Display
dpy KeyCode
ev_keycode CInt
0
cln <- cleanMask ev_state
ks <- maybe mempty upKeys <$> XC.ask @X @UpKeysConfig
userCodeDef () $ whenJust (ks Map.!? (cln, s)) id
handleKeyUp Event
_ = () -> X ()
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()