{-# 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