    {-# LANGUAGE LambdaCase #-}

    --------------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Util.Grab
    -- Description :  Utilities for grabbing/ungrabbing keys.
    -- Copyright   :  (c) 2018  L. S. Leary
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  L. S. Leary
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- This module should not be directly used by users. Its purpose is to
    -- facilitate grabbing and ungrabbing keys.
    --------------------------------------------------------------------------------

    -- --< Imports & Exports >-- {{{

    module XMonad.Util.Grab
      (
     -- * Usage
     -- $Usage
        grabKP
      , ungrabKP
      , grabUngrab
      , grab
      , customRegrabEvHook
      ) where

    -- core
    import           XMonad

    import           Control.Monad                  ( when )
    import           Data.Foldable                  ( traverse_ )
    -- base
    import           Data.Semigroup                 ( All(..) )

    -- }}}

    -- --< Usage >-- {{{

    -- $Usage
    --
    -- This module should not be directly used by users. Its purpose is to
    -- facilitate grabbing and ungrabbing keys.

    -- }}}

    -- --< Public Utils >-- {{{

    -- | A more convenient version of 'grabKey'.
    grabKP :: KeyMask -> KeyCode -> X ()
    grabKP :: KeyMask -> KeyCode -> X ()
    grabKP KeyMask
    mdfr KeyCode
    kc = do
      XConf { display = dpy, theRoot = rootw } <- X XConf
    forall r (m :: * -> *). MonadReader r m => m r
    ask
      io (grabKey dpy kc mdfr rootw True grabModeAsync grabModeAsync)

    -- | A more convenient version of 'ungrabKey'.
    ungrabKP :: KeyMask -> KeyCode -> X ()
    ungrabKP :: KeyMask -> KeyCode -> X ()
    ungrabKP KeyMask
    mdfr KeyCode
    kc = do
      XConf { display = dpy, theRoot = rootw } <- X XConf
    forall r (m :: * -> *). MonadReader r m => m r
    ask
      io (ungrabKey dpy kc mdfr rootw)

    -- | A convenience function to grab and ungrab keys
    grabUngrab
      :: [(KeyMask, KeySym)] -- ^  Keys to grab
      -> [(KeyMask, KeySym)] -- ^ Keys to ungrab
      -> X ()
    grabUngrab :: [(KeyMask, Window)] -> [(KeyMask, Window)] -> X ()
    grabUngrab [(KeyMask, Window)]
    gr [(KeyMask, Window)]
    ugr = do
      ((KeyMask, KeyCode) -> X ()) -> [(KeyMask, KeyCode)] -> X ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ ((KeyMask -> KeyCode -> X ()) -> (KeyMask, KeyCode) -> X ()
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry KeyMask -> KeyCode -> X ()
    ungrabKP) ([(KeyMask, KeyCode)] -> X ()) -> X [(KeyMask, KeyCode)] -> X ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< [(KeyMask, Window)] -> X [(KeyMask, KeyCode)]
    mkGrabs [(KeyMask, Window)]
    ugr
      ((KeyMask, KeyCode) -> X ()) -> [(KeyMask, KeyCode)] -> X ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    (a -> f b) -> t a -> f ()
    traverse_ ((KeyMask -> KeyCode -> X ()) -> (KeyMask, KeyCode) -> X ()
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry KeyMask -> KeyCode -> X ()
    grabKP)   ([(KeyMask, KeyCode)] -> X ()) -> X [(KeyMask, KeyCode)] -> X ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< [(KeyMask, Window)] -> X [(KeyMask, KeyCode)]
    mkGrabs [(KeyMask, Window)]
    gr

    -- | A convenience function to grab keys. This also ungrabs all
    -- previously grabbed keys.
    grab :: [(KeyMask, KeySym)] -> X ()
    grab :: [(KeyMask, Window)] -> X ()
    grab [(KeyMask, Window)]
    ks = do
      XConf { display = dpy, theRoot = rootw } <- X XConf
    forall r (m :: * -> *). MonadReader r m => m r
    ask
      io (ungrabKey dpy anyKey anyModifier rootw)
      grabUngrab ks []

    -- | An event hook that runs a custom action to regrab the necessary keys.
    customRegrabEvHook :: X () -> Event -> X All
    customRegrabEvHook :: X () -> Event -> X All
    customRegrabEvHook X ()
    regr = \case
      e :: Event
    e@MappingNotifyEvent{} -> do
        IO () -> X ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (Event -> IO ()
    refreshKeyboardMapping Event
    e)
        Bool -> X () -> X ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Event -> MappingRequest
    ev_request Event
    e MappingRequest -> [MappingRequest] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [MappingRequest
    mappingKeyboard, MappingRequest
    mappingModifier])
          (X () -> X ()) -> X () -> X ()
    forall a b. (a -> b) -> a -> b
    $  X ()
    cacheNumlockMask
          X () -> X () -> X ()
    forall a b. X a -> X b -> X b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> X ()
    regr
        All -> X All
    forall a. a -> X a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Bool -> All
    All Bool
    False)
      Event
    _ -> All -> X All
    forall a. a -> X a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Bool -> All
    All Bool
    True)

    -- }}}