    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE TypeSynonymInstances #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.VoidBorders
    -- Description :  Set borders to 0 for all windows in the workspace.
    -- Copyright   :  Wilson Sales <spoonm@spoonm.org>
    -- License     :  BSD-style (see LICENSE)
    --
    -- Maintainer  :  <spoonm@spoonm.org>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Modifies a layout to set borders to 0 for all windows in the workspace.
    --
    -- Unlike "XMonad.Layout.NoBorders", the 'voidBorders' modifier will not
    -- restore the window border if the windows are moved to a different workspace
    -- or the layout is changed. There is, however, a companion 'normalBorders'
    -- modifier which explicitly restores the border.
    --
    -- This modifier's primary use is to eliminate the "border flash" you get
    -- while switching workspaces with the "XMonad.Layout.NoBorders" modifier.
    --
    -----------------------------------------------------------------------------

    module XMonad.Layout.VoidBorders ( -- * Usage
                                       -- $usage
                                       voidBorders
                                     , normalBorders
                                     ) where

    import XMonad
    import XMonad.Layout.LayoutModifier
    import XMonad.StackSet (integrate)

    -- $usage
    -- You can use this module with the following in your @xmonad.hs@
    -- file:
    --
    -- > import XMonad.Layout.VoidBorders
    --
    -- and modify the layouts to call 'voidBorders' on the layouts you want to
    -- remove borders from windows, and 'normalBorders' on the layouts you want
    -- to keep borders for:
    --
    -- > layoutHook = ... ||| voidBorders Full ||| normalBorders Tall ...
    --
    -- For more detailed instructions on editing the layoutHook see
    -- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial> and
    -- "XMonad.Doc.Extending#Editing_the_layout_hook".

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

    instance LayoutModifier VoidBorders Window where
      modifierDescription :: VoidBorders Window -> String
    modifierDescription = String -> VoidBorders Window -> String
    forall a b. a -> b -> a
    const String
    "VoidBorders"

      redoLayout :: VoidBorders Window
    -> Rectangle
    -> Maybe (Stack Window)
    -> [(Window, Rectangle)]
    -> X ([(Window, Rectangle)], Maybe (VoidBorders Window))
    redoLayout VoidBorders Window
    VoidBorders Rectangle
    _ Maybe (Stack Window)
    Nothing [(Window, Rectangle)]
    wrs = ([(Window, Rectangle)], Maybe (VoidBorders Window))
    -> X ([(Window, Rectangle)], Maybe (VoidBorders Window))
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(Window, Rectangle)]
    wrs, Maybe (VoidBorders Window)
    forall a. Maybe a
    Nothing)
      redoLayout VoidBorders Window
    VoidBorders Rectangle
    _ (Just Stack Window
    s) [(Window, Rectangle)]
    wrs = do
        (Window -> X ()) -> [Window] -> X ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ Window -> X ()
    setZeroBorder ([Window] -> X ()) -> [Window] -> X ()
    forall a b. (a -> b) -> a -> b
    $ Stack Window -> [Window]
    forall a. Stack a -> [a]
    integrate Stack Window
    s
        ([(Window, Rectangle)], Maybe (VoidBorders Window))
    -> X ([(Window, Rectangle)], Maybe (VoidBorders Window))
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(Window, Rectangle)]
    wrs, Maybe (VoidBorders Window)
    forall a. Maybe a
    Nothing)

    voidBorders :: l Window -> ModifiedLayout VoidBorders l Window
    voidBorders :: forall (l :: * -> *).
    l Window -> ModifiedLayout VoidBorders l Window
    voidBorders = VoidBorders Window
    -> l Window -> ModifiedLayout VoidBorders l Window
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout VoidBorders Window
    forall a. VoidBorders a
    VoidBorders

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

    instance LayoutModifier NormalBorders Window where
      modifierDescription :: NormalBorders Window -> String
    modifierDescription = String -> NormalBorders Window -> String
    forall a b. a -> b -> a
    const String
    "NormalBorders"

      redoLayout :: NormalBorders Window
    -> Rectangle
    -> Maybe (Stack Window)
    -> [(Window, Rectangle)]
    -> X ([(Window, Rectangle)], Maybe (NormalBorders Window))
    redoLayout NormalBorders Window
    NormalBorders Rectangle
    _ Maybe (Stack Window)
    Nothing [(Window, Rectangle)]
    wrs = ([(Window, Rectangle)], Maybe (NormalBorders Window))
    -> X ([(Window, Rectangle)], Maybe (NormalBorders Window))
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(Window, Rectangle)]
    wrs, Maybe (NormalBorders Window)
    forall a. Maybe a
    Nothing)
      redoLayout NormalBorders Window
    NormalBorders Rectangle
    _ (Just Stack Window
    s) [(Window, Rectangle)]
    wrs = do
        (Window -> X ()) -> [Window] -> X ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ Window -> X ()
    resetBorders ([Window] -> X ()) -> [Window] -> X ()
    forall a b. (a -> b) -> a -> b
    $ Stack Window -> [Window]
    forall a. Stack a -> [a]
    integrate Stack Window
    s
        ([(Window, Rectangle)], Maybe (NormalBorders Window))
    -> X ([(Window, Rectangle)], Maybe (NormalBorders Window))
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(Window, Rectangle)]
    wrs, Maybe (NormalBorders Window)
    forall a. Maybe a
    Nothing)

    normalBorders :: l Window -> ModifiedLayout NormalBorders l Window
    normalBorders :: forall (l :: * -> *).
    l Window -> ModifiedLayout NormalBorders l Window
    normalBorders = NormalBorders Window
    -> l Window -> ModifiedLayout NormalBorders l Window
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout NormalBorders Window
    forall a. NormalBorders a
    NormalBorders

    -- | Sets border width to 0 for every window from the specified layout.
    setZeroBorder :: Window -> X ()
    setZeroBorder :: Window -> X ()
    setZeroBorder Window
    w = Window -> Dimension -> X ()
    setBorders Window
    w Dimension
    0

    -- | Resets the border to the value read from the current configuration.
    resetBorders :: Window -> X ()
    resetBorders :: Window -> X ()
    resetBorders Window
    w = (XConf -> Dimension) -> X Dimension
    forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
    asks (XConfig Layout -> Dimension
    forall (l :: * -> *). XConfig l -> Dimension
    borderWidth (XConfig Layout -> Dimension)
    -> (XConf -> XConfig Layout) -> XConf -> Dimension
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . XConf -> XConfig Layout
    config) X Dimension -> (Dimension -> X ()) -> X ()
    forall a b. X a -> (a -> X b) -> X b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Window -> Dimension -> X ()
    setBorders Window
    w

    setBorders :: Window -> Dimension -> X ()
    setBorders :: Window -> Dimension -> X ()
    setBorders Window
    w Dimension
    bw = (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 (IO () -> X ()) -> IO () -> X ()
    forall a b. (a -> b) -> a -> b
    $ Display -> Window -> Dimension -> IO ()
    setWindowBorderWidth Display
    d Window
    w Dimension
    bw