{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} ----------------------------------------------------------------------------- -- | -- Module : XMonad.Layout.CenterMainFluid -- Description : Three column layout with master in center and unoccupied spaces reserved. -- Copyright : (c) 2023 Mahdi Seyedan -- License : BSD-style (see xmonad/LICENSE) -- -- Maintainer : Mahdi Seyedan. -- Stability : unstable -- Portability : unportable -- -- A three column layout with main column in the center and -- two stack columns surrounding it. There will be always -- a pane in the center column and unoccupied spaces on the -- sides are reserved. -- It's best suited for ultrawide montiors, where a single -- stretched window might be annoying. ----------------------------------------------------------------------------- module XMonad.Layout.CenterMainFluid ( -- * Usage -- $usage CenterMainFluid (..) ) where import XMonad import qualified XMonad.StackSet as W import Control.Monad (msum) -- $usage -- You can use this module by adding following in your @xmonad.hs@: -- -- > import XMonad.Layout.CenterMainFluid -- -- Then edit your @layoutHook@ by adding the CenterMainFluid layout: -- -- > myLayoutHook = CenterMainFluid 1 (3/100) (70/100) ||| ... -- > main = xmonad def { layoutHook = myLayout } -- -- The first argument specifies how many windows initially appear in the center -- column. The second argument specifies the amount to resize while resizing -- and the third argument specifies the initial size of the center column. -- -- For more detailed instructions on editing the layoutHook see -- and -- "XMonad.Doc.Extending#Editing_the_layout_hook". -- | Arguments are nmaster, delta, fraction. Supports 'Shrink', 'Expand' and -- 'IncMasterN' data CenterMainFluid a = CenterMainFluid { cmfNMaster :: !Int -- ^ The default number of windows in the center pane (default: 1) , cmfRatioIncrement :: !Rational -- ^ Percent of screen to increment by when resizing panes (default: 3/100) , cmfRatio :: !Rational -- ^ Default proportion of screen occupied by the center pane (default: 70/100) } deriving (Show,Read) instance LayoutClass CenterMainFluid a where pureLayout (CenterMainFluid nmaster _ frac) r s | frac == 0 = drop nmaster layout | frac == 1 = take nmaster layout | otherwise = layout where layout = zip ws rs ws = W.integrate s rs = tile3 frac r nmaster (length ws) pureMessage (CenterMainFluid nmaster delta frac) m = msum [fmap resize (fromMessage m) ,fmap incmastern (fromMessage m)] where resize Shrink = CenterMainFluid nmaster delta (max 0 $ frac-delta) resize Expand = CenterMainFluid nmaster delta (min 1 $ frac+delta) incmastern (IncMasterN d) = CenterMainFluid (max 0 (nmaster+d)) delta frac description _ = "CenterMainFluid" tile3 :: Rational -> Rectangle -> Int -> Int -> [Rectangle] tile3 f r nmaster n | nmaster <= 0 || n <= nmaster = splitVertically n middleR | otherwise = masters ++ rights ++ lefts where (leftR, middleR, rightR) = split3HorizontallyBy f r (halfN, remaining) = (n - nmaster) `divMod` 2 masters = splitVertically nmaster middleR lefts = splitVertically halfN leftR rights = splitVertically (halfN + remaining) rightR -- | Divide the screen into three rectangles, using a rational to specify the ratio of center one split3HorizontallyBy :: RealFrac r => r -> Rectangle -> (Rectangle, Rectangle, Rectangle) split3HorizontallyBy f (Rectangle sx sy sw sh) = ( Rectangle sx sy sidew sh , Rectangle (sx + fromIntegral sidew) sy middlew sh , Rectangle (sx + fromIntegral sidew + fromIntegral middlew) sy sidew sh ) where middlew = floor $ fromIntegral sw * f sidew = (sw - fromIntegral middlew) `div` 2