{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable #-} {-# LANGUAGE PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : XMonad.Layout.Spacing -- Copyright : (c) Brent Yorgey -- License : BSD-style (see LICENSE) -- -- Maintainer : -- Stability : unstable -- Portability : portable -- -- Add a configurable amount of space around windows. ----------------------------------------------------------------------------- module XMonad.Layout.Spacing ( -- * Usage -- $usage spacing, Spacing, spacingWithEdge, SpacingWithEdge, smartSpacing, SmartSpacing, smartSpacingWithEdge, SmartSpacingWithEdge, ModifySpacing(..), setSpacing, incSpacing ) where import Graphics.X11 (Rectangle(..)) import Control.Arrow (second) import XMonad.Operations (sendMessage) import XMonad.Core (X,runLayout,Message,fromMessage,Typeable) import XMonad.StackSet (up, down, Workspace(..)) import XMonad.Util.Font (fi) import XMonad.Layout.LayoutModifier -- $usage -- You can use this module by importing it into your @~\/.xmonad\/xmonad.hs@ file: -- -- > import XMonad.Layout.Spacing -- -- and modifying your layoutHook as follows (for example): -- -- > layoutHook = spacing 2 $ Tall 1 (3/100) (1/2) -- > -- put a 2px space around every window -- -- | Surround all windows by a certain number of pixels of blank space. spacing :: Int -> l a -> ModifiedLayout Spacing l a spacing p = ModifiedLayout (Spacing p) data Spacing a = Spacing Int deriving (Show, Read) -- | Message to dynamically modify (e.g. increase/decrease/set) the size of the window spacing data ModifySpacing = ModifySpacing (Int -> Int) deriving (Typeable) instance Message ModifySpacing -- | Set spacing to given amount setSpacing :: Int -> X () setSpacing n = sendMessage $ ModifySpacing $ const n -- | Increase spacing by given amount incSpacing :: Int -> X () incSpacing n = sendMessage $ ModifySpacing $ (+n) instance LayoutModifier Spacing a where pureModifier (Spacing p) _ _ wrs = (map (second $ shrinkRect p) wrs, Nothing) pureMess (Spacing px) m | Just (ModifySpacing f) <- fromMessage m = Just $ Spacing $ max 0 $ f px | otherwise = Nothing modifierDescription (Spacing p) = "Spacing " ++ show p -- | Surround all windows by a certain number of pixels of blank space, and -- additionally adds the same amount of spacing around the edge of the screen. spacingWithEdge :: Int -> l a -> ModifiedLayout SpacingWithEdge l a spacingWithEdge p = ModifiedLayout (SpacingWithEdge p) data SpacingWithEdge a = SpacingWithEdge Int deriving (Show, Read) instance LayoutModifier SpacingWithEdge a where pureModifier (SpacingWithEdge p) _ _ wrs = (map (second $ shrinkRect p) wrs, Nothing) pureMess (SpacingWithEdge px) m | Just (ModifySpacing f) <- fromMessage m = Just $ SpacingWithEdge $ max 0 $ f px | otherwise = Nothing modifyLayout (SpacingWithEdge p) w r = runLayout w (shrinkRect p r) modifierDescription (SpacingWithEdge p) = "SpacingWithEdge " ++ show p shrinkRect :: Int -> Rectangle -> Rectangle shrinkRect p (Rectangle x y w h) = Rectangle (x+fi p) (y+fi p) (w-2*fi p) (h-2*fi p) -- | Surrounds all windows with blank space, except when the window is the only -- visible window on the current workspace. smartSpacing :: Int -> l a -> ModifiedLayout SmartSpacing l a smartSpacing p = ModifiedLayout (SmartSpacing p) data SmartSpacing a = SmartSpacing Int deriving (Show, Read) instance LayoutModifier SmartSpacing a where pureModifier _ _ _ [x] = ([x], Nothing) pureModifier (SmartSpacing p) _ _ wrs = (map (second $ shrinkRect p) wrs, Nothing) modifierDescription (SmartSpacing p) = "SmartSpacing " ++ show p -- | Surrounds all windows with blank space, and adds the same amount of spacing -- around the edge of the screen, except when the window is the only visible -- window on the current workspace. smartSpacingWithEdge :: Int -> l a -> ModifiedLayout SmartSpacingWithEdge l a smartSpacingWithEdge p = ModifiedLayout (SmartSpacingWithEdge p) data SmartSpacingWithEdge a = SmartSpacingWithEdge Int deriving (Show, Read) instance LayoutModifier SmartSpacingWithEdge a where pureModifier _ _ _ [x] = ([x], Nothing) pureModifier (SmartSpacingWithEdge p) _ _ wrs = (map (second $ shrinkRect p) wrs, Nothing) modifyLayout (SmartSpacingWithEdge p) w r | maybe False (\s -> null (up s) && null (down s)) (stack w) = runLayout w r | otherwise = runLayout w (shrinkRect p r) modifierDescription (SmartSpacingWithEdge p) = "SmartSpacingWithEdge " ++ show p