{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-} ----------------------------------------------------------------------------- -- | -- Module : XMonad.Layout.FixedColumn -- Copyright : (c) 2008 Justin Bogner -- License : BSD3-style (as xmonad) -- -- Maintainer : Justin Bogner -- Stability : unstable -- Portability : unportable -- -- A layout much like Tall, but using a multiple of a window's minimum -- resize amount instead of a percentage of screen to decide where to -- split. This is useful when you usually leave a text editor or -- terminal in the master pane and like it to be 80 columns wide. -- ----------------------------------------------------------------------------- module XMonad.Layout.FixedColumn ( -- * Usage -- $usage FixedColumn(..) ) where import Control.Monad (msum) import Data.Maybe (fromMaybe) import Graphics.X11.Xlib (Window, rect_width) import Graphics.X11.Xlib.Extras ( getWMNormalHints , getWindowAttributes , sh_base_size , sh_resize_inc , wa_border_width) import XMonad.Core (X, LayoutClass(..), fromMessage, io, withDisplay) import XMonad.Layout (Resize(..), IncMasterN(..), tile) import XMonad.StackSet as W -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Layout.FixedColumn -- -- Then edit your @layoutHook@ by adding the FixedColumn layout: -- -- > myLayout = FixedColumn 1 20 80 10 ||| Full ||| etc.. -- > main = xmonad defaultConfig { layoutHook = myLayout } -- -- For more detailed instructions on editing the layoutHook see: -- -- "XMonad.Doc.Extending#Editing_the_layout_hook" -- | A tiling mode based on preserving a nice fixed width -- window. Supports 'Shrink', 'Expand' and 'IncMasterN'. data FixedColumn a = FixedColumn !Int -- Number of windows in the master pane !Int -- Number to increment by when resizing !Int -- Default width of master pane !Int -- Column width for normal windows deriving (Read, Show) instance LayoutClass FixedColumn Window where doLayout (FixedColumn nmaster _ ncol fallback) r s = do fws <- mapM (widthCols fallback ncol) ws let frac = maximum (take nmaster fws) // rect_width r rs = tile frac r nmaster (length ws) return $ (zip ws rs, Nothing) where ws = W.integrate s x // y = fromIntegral x / fromIntegral y pureMessage (FixedColumn nmaster delta ncol fallback) m = msum [fmap resize (fromMessage m) ,fmap incmastern (fromMessage m)] where resize Shrink = FixedColumn nmaster delta (max 0 $ ncol - delta) fallback resize Expand = FixedColumn nmaster delta (ncol + delta) fallback incmastern (IncMasterN d) = FixedColumn (max 0 (nmaster+d)) delta ncol fallback description _ = "FixedColumn" -- | Determine the width of @w@ given that we would like it to be @n@ -- columns wide, using @inc@ as a resize increment for windows that -- don't have one widthCols :: Int -> Int -> Window -> X Int widthCols inc n w = withDisplay $ \d -> io $ do sh <- getWMNormalHints d w bw <- fmap (fromIntegral . wa_border_width) $ getWindowAttributes d w let widthHint f = f sh >>= return . fromIntegral . fst oneCol = fromMaybe inc $ widthHint sh_resize_inc base = fromMaybe 0 $ widthHint sh_base_size return $ 2 * bw + base + n * oneCol