    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TupleSections #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Hooks.ScreenCorners
    -- Description :  Run X () actions by touching the edge of your screen with your mouse.
    -- Copyright   :  (c) 2009 Nils Schweinsberg, 2015 Evgeny Kurnevsky, 2024 Yuanle Song
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  Nils Schweinsberg <mail@n-sch.de>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Run @X ()@ actions by touching the edge of your screen with your mouse.
    --
    -----------------------------------------------------------------------------

    module XMonad.Hooks.ScreenCorners
        (
        -- * Usage
        -- $usage

        -- * Adding screen corners
          ScreenCorner (..)
        , addScreenCorner
        , addScreenCorners

        -- * Event hook
        , screenCornerEventHook

        -- * Layout hook
        , screenCornerLayoutHook
        ) where

    import XMonad.Prelude
    import XMonad
    import XMonad.Layout.LayoutModifier

    import qualified Data.Map as M
    import qualified XMonad.Util.ExtensibleState as XS

    data ScreenCorner = SCUpperLeft
                      | SCUpperRight
                      | SCLowerLeft
                      | SCLowerRight
                      | SCTop
                      | SCBottom
                      | SCLeft
                      | SCRight
                      deriving (ScreenCorner -> ScreenCorner -> Bool
    (ScreenCorner -> ScreenCorner -> Bool)
    -> (ScreenCorner -> ScreenCorner -> Bool) -> Eq ScreenCorner
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ScreenCorner -> ScreenCorner -> Bool
    == :: ScreenCorner -> ScreenCorner -> Bool
    $c/= :: ScreenCorner -> ScreenCorner -> Bool
    /= :: ScreenCorner -> ScreenCorner -> Bool
    Eq, Eq ScreenCorner
    Eq ScreenCorner =>
    (ScreenCorner -> ScreenCorner -> Ordering)
    -> (ScreenCorner -> ScreenCorner -> Bool)
    -> (ScreenCorner -> ScreenCorner -> Bool)
    -> (ScreenCorner -> ScreenCorner -> Bool)
    -> (ScreenCorner -> ScreenCorner -> Bool)
    -> (ScreenCorner -> ScreenCorner -> ScreenCorner)
    -> (ScreenCorner -> ScreenCorner -> ScreenCorner)
    -> Ord ScreenCorner
    ScreenCorner -> ScreenCorner -> Bool
    ScreenCorner -> ScreenCorner -> Ordering
    ScreenCorner -> ScreenCorner -> ScreenCorner
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ScreenCorner -> ScreenCorner -> Ordering
    compare :: ScreenCorner -> ScreenCorner -> Ordering
    $c< :: ScreenCorner -> ScreenCorner -> Bool
    < :: ScreenCorner -> ScreenCorner -> Bool
    $c<= :: ScreenCorner -> ScreenCorner -> Bool
    <= :: ScreenCorner -> ScreenCorner -> Bool
    $c> :: ScreenCorner -> ScreenCorner -> Bool
    > :: ScreenCorner -> ScreenCorner -> Bool
    $c>= :: ScreenCorner -> ScreenCorner -> Bool
    >= :: ScreenCorner -> ScreenCorner -> Bool
    $cmax :: ScreenCorner -> ScreenCorner -> ScreenCorner
    max :: ScreenCorner -> ScreenCorner -> ScreenCorner
    $cmin :: ScreenCorner -> ScreenCorner -> ScreenCorner
    min :: ScreenCorner -> ScreenCorner -> ScreenCorner
    Ord, Int -> ScreenCorner -> ShowS
    [ScreenCorner] -> ShowS
    ScreenCorner -> String
    (Int -> ScreenCorner -> ShowS)
    -> (ScreenCorner -> String)
    -> ([ScreenCorner] -> ShowS)
    -> Show ScreenCorner
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ScreenCorner -> ShowS
    showsPrec :: Int -> ScreenCorner -> ShowS
    $cshow :: ScreenCorner -> String
    show :: ScreenCorner -> String
    $cshowList :: [ScreenCorner] -> ShowS
    showList :: [ScreenCorner] -> ShowS
    Show)

    --------------------------------------------------------------------------------
    -- ExtensibleState modifications
    --------------------------------------------------------------------------------

    newtype ScreenCornerState = ScreenCornerState (M.Map Window (ScreenCorner, X ()))

    instance ExtensionClass ScreenCornerState where
        initialValue :: ScreenCornerState
    initialValue = Map Window (ScreenCorner, X ()) -> ScreenCornerState
    ScreenCornerState Map Window (ScreenCorner, X ())
    forall k a. Map k a
    M.empty

    -- | Add one single @X ()@ action to a screen corner
    addScreenCorner :: ScreenCorner -> X () -> X ()
    addScreenCorner :: ScreenCorner -> X () -> X ()
    addScreenCorner ScreenCorner
    corner X ()
    xF = do

        ScreenCornerState m <- X ScreenCornerState
    forall a (m :: * -> *). (ExtensionClass a, XLike m) => m a
    XS.get
        (win,xFunc) <- case find (\(Window
    _,(ScreenCorner
    sc,X ()
    _)) -> ScreenCorner
    sc ScreenCorner -> ScreenCorner -> Bool
    forall a. Eq a => a -> a -> Bool
    == ScreenCorner
    corner) (M.toList m) of

                            Just (Window
    w, (ScreenCorner
    _,X ()
    xF')) -> (Window, X ()) -> X (Window, X ())
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Window
    w, X ()
    xF' 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 ()
    xF) -- chain X actions
                            Maybe (Window, (ScreenCorner, X ()))
    Nothing           -> (, X ()
    xF) (Window -> (Window, X ())) -> X Window -> X (Window, X ())
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ScreenCorner -> X Window
    createWindowAt ScreenCorner
    corner

        XS.modify $ \(ScreenCornerState Map Window (ScreenCorner, X ())
    m') -> Map Window (ScreenCorner, X ()) -> ScreenCornerState
    ScreenCornerState (Map Window (ScreenCorner, X ()) -> ScreenCornerState)
    -> Map Window (ScreenCorner, X ()) -> ScreenCornerState
    forall a b. (a -> b) -> a -> b
    $ Window
    -> (ScreenCorner, X ())
    -> Map Window (ScreenCorner, X ())
    -> Map Window (ScreenCorner, X ())
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert Window
    win (ScreenCorner
    corner,X ()
    xFunc) Map Window (ScreenCorner, X ())
    m'

    -- | Add a list of @(ScreenCorner, X ())@ tuples
    addScreenCorners :: [ (ScreenCorner, X ()) ] -> X ()
    addScreenCorners :: [(ScreenCorner, X ())] -> X ()
    addScreenCorners = ((ScreenCorner, X ()) -> X ()) -> [(ScreenCorner, X ())] -> X ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ((ScreenCorner -> X () -> X ()) -> (ScreenCorner, X ()) -> X ()
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry ScreenCorner -> X () -> X ()
    addScreenCorner)

    --------------------------------------------------------------------------------
    -- Xlib functions
    --------------------------------------------------------------------------------

    -- "Translate" a ScreenCorner to real (x,y) Positions with proper width and
    -- height.
    createWindowAt :: ScreenCorner -> X Window
    createWindowAt :: ScreenCorner -> X Window
    createWindowAt ScreenCorner
    SCUpperLeft = Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' Position
    0 Position
    0 Dimension
    1 Dimension
    1
    createWindowAt ScreenCorner
    SCUpperRight = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let w :: CInt
    w = Display -> Dimension -> CInt
    displayWidth  Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' (CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    w) Position
    0 Dimension
    1 Dimension
    1

    createWindowAt ScreenCorner
    SCLowerLeft = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let h :: CInt
    h = Display -> Dimension -> CInt
    displayHeight Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' Position
    0 (CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    h) Dimension
    1 Dimension
    1

    createWindowAt ScreenCorner
    SCLowerRight = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let w :: CInt
    w = Display -> Dimension -> CInt
    displayWidth  Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            h :: CInt
    h = Display -> Dimension -> CInt
    displayHeight Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' (CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    w) (CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    h) Dimension
    1 Dimension
    1

    createWindowAt ScreenCorner
    SCTop = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let w :: CInt
    w = Display -> Dimension -> CInt
    displayWidth  Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            -- leave some gap so corner and edge can work nicely when they overlap
            threshold :: Position
    threshold = Position
    150
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' Position
    threshold Position
    0 (Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi (Position -> Dimension) -> Position -> Dimension
    forall a b. (a -> b) -> a -> b
    $ CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    w Position -> Position -> Position
    forall a. Num a => a -> a -> a
    - Position
    threshold Position -> Position -> Position
    forall a. Num a => a -> a -> a
    * Position
    2) Dimension
    1

    createWindowAt ScreenCorner
    SCBottom = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let w :: CInt
    w = Display -> Dimension -> CInt
    displayWidth  Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            h :: CInt
    h = Display -> Dimension -> CInt
    displayHeight Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            threshold :: Position
    threshold = Position
    150
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' Position
    threshold (CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    h) (Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi (Position -> Dimension) -> Position -> Dimension
    forall a b. (a -> b) -> a -> b
    $ CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    w Position -> Position -> Position
    forall a. Num a => a -> a -> a
    - Position
    threshold Position -> Position -> Position
    forall a. Num a => a -> a -> a
    * Position
    2) Dimension
    1

    createWindowAt ScreenCorner
    SCLeft = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let h :: CInt
    h = Display -> Dimension -> CInt
    displayHeight Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            threshold :: Position
    threshold = Position
    150
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' Position
    0 Position
    threshold Dimension
    1 (Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi (Position -> Dimension) -> Position -> Dimension
    forall a b. (a -> b) -> a -> b
    $ CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    h Position -> Position -> Position
    forall a. Num a => a -> a -> a
    - Position
    threshold Position -> Position -> Position
    forall a. Num a => a -> a -> a
    * Position
    2)

    createWindowAt ScreenCorner
    SCRight = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy ->
        let w :: CInt
    w = Display -> Dimension -> CInt
    displayWidth  Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            h :: CInt
    h = Display -> Dimension -> CInt
    displayHeight Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy) CInt -> CInt -> CInt
    forall a. Num a => a -> a -> a
    - CInt
    1
            threshold :: Position
    threshold = Position
    150
        in Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' (CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    w) Position
    threshold Dimension
    1 (Position -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi (Position -> Dimension) -> Position -> Dimension
    forall a b. (a -> b) -> a -> b
    $ CInt -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi CInt
    h Position -> Position -> Position
    forall a. Num a => a -> a -> a
    - Position
    threshold Position -> Position -> Position
    forall a. Num a => a -> a -> a
    * Position
    2)

    -- Create a new X window at a (x,y) Position, with given width and height.
    createWindowAt' :: Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' :: Position -> Position -> Dimension -> Dimension -> X Window
    createWindowAt' Position
    x Position
    y Dimension
    width Dimension
    height = (Display -> X Window) -> X Window
    forall a. (Display -> X a) -> X a
    withDisplay ((Display -> X Window) -> X Window)
    -> (Display -> X Window) -> X Window
    forall a b. (a -> b) -> a -> b
    $ \Display
    dpy -> IO Window -> X Window
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    io (IO Window -> X Window) -> IO Window -> X Window
    forall a b. (a -> b) -> a -> b
    $ do

        rootw <- Display -> Dimension -> IO Window
    rootWindow Display
    dpy (Display -> Dimension
    defaultScreen Display
    dpy)

        let
            visual   = Screen -> Visual
    defaultVisualOfScreen (Screen -> Visual) -> Screen -> Visual
    forall a b. (a -> b) -> a -> b
    $ Display -> Screen
    defaultScreenOfDisplay Display
    dpy
            attrmask = Window
    cWOverrideRedirect

        w <- allocaSetWindowAttributes $ \Ptr SetWindowAttributes
    attributes -> do

            Ptr SetWindowAttributes -> Bool -> IO ()
    set_override_redirect Ptr SetWindowAttributes
    attributes Bool
    True
            Display
    -> Window
    -> Position
    -> Position
    -> Dimension
    -> Dimension
    -> CInt
    -> CInt
    -> CInt
    -> Visual
    -> Window
    -> Ptr SetWindowAttributes
    -> IO Window
    createWindow Display
    dpy        -- display
                         Window
    rootw      -- parent window
                         Position
    x          -- x
                         Position
    y          -- y
                         Dimension
    width      -- width
                         Dimension
    height     -- height
                         CInt
    0          -- border width
                         CInt
    0          -- depth
                         CInt
    inputOnly  -- class
                         Visual
    visual     -- visual
                         Window
    attrmask   -- valuemask
                         Ptr SetWindowAttributes
    attributes -- attributes

        -- we only need mouse entry events
        selectInput dpy w enterWindowMask
        mapWindow dpy w
        sync dpy False
        return w

    --------------------------------------------------------------------------------
    -- Event hook
    --------------------------------------------------------------------------------

    -- | Handle screen corner events
    screenCornerEventHook :: Event -> X All
    screenCornerEventHook :: Event -> X All
    screenCornerEventHook CrossingEvent { ev_window :: Event -> Window
    ev_window = Window
    win } = do

        ScreenCornerState m <- X ScreenCornerState
    forall a (m :: * -> *). (ExtensionClass a, XLike m) => m a
    XS.get

        case M.lookup win m of
             Just (ScreenCorner
    _, X ()
    xF) -> X ()
    xF
             Maybe (ScreenCorner, X ())
    Nothing      -> () -> X ()
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

        return (All True)

    screenCornerEventHook Event
    _ = All -> X All
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool -> All
    All Bool
    True)

    --------------------------------------------------------------------------------
    -- Layout hook
    --------------------------------------------------------------------------------

    data ScreenCornerLayout a = ScreenCornerLayout
        deriving ( ReadPrec [ScreenCornerLayout a]
    ReadPrec (ScreenCornerLayout a)
    Int -> ReadS (ScreenCornerLayout a)
    ReadS [ScreenCornerLayout a]
    (Int -> ReadS (ScreenCornerLayout a))
    -> ReadS [ScreenCornerLayout a]
    -> ReadPrec (ScreenCornerLayout a)
    -> ReadPrec [ScreenCornerLayout a]
    -> Read (ScreenCornerLayout a)
    forall a. ReadPrec [ScreenCornerLayout a]
    forall a. ReadPrec (ScreenCornerLayout a)
    forall a. Int -> ReadS (ScreenCornerLayout a)
    forall a. ReadS [ScreenCornerLayout a]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: forall a. Int -> ReadS (ScreenCornerLayout a)
    readsPrec :: Int -> ReadS (ScreenCornerLayout a)
    $creadList :: forall a. ReadS [ScreenCornerLayout a]
    readList :: ReadS [ScreenCornerLayout a]
    $creadPrec :: forall a. ReadPrec (ScreenCornerLayout a)
    readPrec :: ReadPrec (ScreenCornerLayout a)
    $creadListPrec :: forall a. ReadPrec [ScreenCornerLayout a]
    readListPrec :: ReadPrec [ScreenCornerLayout a]
    Read, Int -> ScreenCornerLayout a -> ShowS
    [ScreenCornerLayout a] -> ShowS
    ScreenCornerLayout a -> String
    (Int -> ScreenCornerLayout a -> ShowS)
    -> (ScreenCornerLayout a -> String)
    -> ([ScreenCornerLayout a] -> ShowS)
    -> Show (ScreenCornerLayout a)
    forall a. Int -> ScreenCornerLayout a -> ShowS
    forall a. [ScreenCornerLayout a] -> ShowS
    forall a. ScreenCornerLayout a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Int -> ScreenCornerLayout a -> ShowS
    showsPrec :: Int -> ScreenCornerLayout a -> ShowS
    $cshow :: forall a. ScreenCornerLayout a -> String
    show :: ScreenCornerLayout a -> String
    $cshowList :: forall a. [ScreenCornerLayout a] -> ShowS
    showList :: [ScreenCornerLayout a] -> ShowS
    Show )

    instance LayoutModifier ScreenCornerLayout a where
        hook :: ScreenCornerLayout a -> X ()
    hook ScreenCornerLayout a
    ScreenCornerLayout = (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
    dpy -> do
            ScreenCornerState m <- X ScreenCornerState
    forall a (m :: * -> *). (ExtensionClass a, XLike m) => m a
    XS.get
            io $ mapM_ (raiseWindow dpy) $ M.keys m
        unhook :: ScreenCornerLayout a -> X ()
    unhook = ScreenCornerLayout a -> X ()
    forall (m :: * -> *) a. LayoutModifier m a => m a -> X ()
    hook

    screenCornerLayoutHook :: l a -> ModifiedLayout ScreenCornerLayout l a
    screenCornerLayoutHook :: forall (l :: * -> *) a.
    l a -> ModifiedLayout ScreenCornerLayout l a
    screenCornerLayoutHook = ScreenCornerLayout a
    -> l a -> ModifiedLayout ScreenCornerLayout l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout ScreenCornerLayout a
    forall a. ScreenCornerLayout a
    ScreenCornerLayout

    --------------------------------------------------------------------------------
    -- $usage
    --
    -- This extension adds KDE-like screen corners and GNOME Hot Edge like
    -- features to XMonad. By moving your cursor into one of your screen corners
    -- or edges, you can trigger an @X ()@ action, for example
    -- @"XMonad.Actions.GridSelect".goToSelected@ or
    -- @"XMonad.Actions.CycleWS".nextWS@ etc.
    --
    -- To use it, import it on top of your @xmonad.hs@:
    --
    -- > import XMonad.Hooks.ScreenCorners
    --
    -- Then add your screen corners in our startup hook:
    --
    -- > myStartupHook = do
    -- >     ...
    -- >     addScreenCorner SCUpperRight (goToSelected def { gs_cellwidth = 200})
    -- >     addScreenCorner SCBottom (goToSelected def)
    -- >     addScreenCorners [ (SCLowerRight, nextWS)
    -- >                      , (SCLowerLeft,  prevWS)
    -- >                      ]
    --
    -- Then add layout hook:
    --
    -- > myLayout = screenCornerLayoutHook $ tiled ||| Mirror tiled ||| Full where
    -- >     tiled   = Tall nmaster delta ratio
    -- >     nmaster = 1
    -- >     ratio   = 1 / 2
    -- >     delta   = 3 / 100
    --
    -- And finally wait for screen corner events in your event hook:
    --
    -- > myEventHook e = do
    -- >     ...
    -- >     screenCornerEventHook e