    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Util.Ungrab
    -- Description :  Release xmonad's keyboard and pointer grabs immediately.
    -- Copyright   :  (c) 2016 Brandon S Allbery
    -- License     :  BSD-style (see xmonad/LICENSE)
    --
    -- Maintainer  :  allbery.b@gmail.com
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Allow releasing xmonad's keyboard grab
    --
    -----------------------------------------------------------------------------

    module XMonad.Util.Ungrab
        ( -- * Usage:
          -- $usage
          unGrab
        ) where

    import Graphics.X11.Xlib (sync)
    import Graphics.X11.Xlib.Extras (currentTime)
    import Graphics.X11.Xlib.Misc (ungrabKeyboard, ungrabPointer)
    import XMonad.Core

    -- $usage
    -- Start a keyboard action with this if it is going to run something
    -- that needs to do a keyboard, pointer, or server grab. For example,
    --
    -- > , ((modm .|. controlMask, xK_p), unGrab >> spawn "scrot")
    --
    -- (Other examples are screen lockers and "gksu".)
    -- This avoids needing to insert a pause/sleep before running the
    -- command.
    --
    -- xmonad retains the keyboard grab during key actions because if they
    -- use a Submap, they need the keyboard to be grabbed, and if they had
    -- to assert their own grab then the asynchronous nature of X11 allows
    -- race conditions between xmonad, other clients, and the X server that
    -- would cause keys to sometimes be "leaked" to the focused window.

    -- | Release xmonad's keyboard grab, so other grabbers can do their thing.
    unGrab :: X ()
    unGrab :: X ()
    unGrab = (Display -> X ()) -> X ()
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X ()) -> X ()) -> (Display -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \Display
    d -> IO () -> X ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (Display -> Time -> IO ()
    ungrabKeyboard Display
    d Time
    currentTime IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Display -> Time -> IO ()
    ungrabPointer Display
    d Time
    currentTime IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Display -> Bool -> IO ()
    sync Display
    d Bool
    False)