{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances, FlexibleContexts, PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : XMonad.Layout.Master -- Copyright : (c) Ismael Carnales, Lukas Mai -- License : BSD-style (see LICENSE) -- -- Maintainer : Ismael Carnales -- Stability : unstable -- Portability : unportable -- -- Layout modfier that adds a master window to another layout. ----------------------------------------------------------------------------- module XMonad.Layout.Master ( -- * Usage -- $usage mastered, multimastered, AddMaster, ) where import XMonad import qualified XMonad.StackSet as S import XMonad.Layout.LayoutModifier -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Layout.Master -- -- Then edit your @layoutHook@ and add the Master modifier to the layout that -- you prefer. -- -- > mastered (1/100) (1/2) $ Grid -- -- Or if you want multiple (here two) master windows from the beginning: -- -- > multimastered 2 (1/100) (1/2) $ Grid -- -- This will use the left half of your screen for a master window and let -- Grid manage the right half. -- -- For more detailed instructions on editing the layoutHook see -- "XMonad.Doc.Extending#Editing_the_layout_hook". -- -- Like 'XMonad.Layout.Tall', 'withMaster' supports the -- 'XMonad.Layout.Shrink' and XMonad.Layout.Expand' messages. -- | Data type for LayoutModifier which converts given layout to a mastered -- layout data AddMaster a = AddMaster Int Rational Rational deriving (Show, Read) -- | Modifier which converts given layout to a mastered one multimastered :: (LayoutClass l a) => Int -- ^ @k@, number of master windows -> Rational -- ^ @delta@, the ratio of the screen to resize by -> Rational -- ^ @frac@, what portion of the screen to use for the master window -> l a -- ^ the layout to be modified -> ModifiedLayout AddMaster l a multimastered k delta frac = ModifiedLayout $ AddMaster k delta frac mastered :: (LayoutClass l a) => Rational -- ^ @delta@, the ratio of the screen to resize by -> Rational -- ^ @frac@, what portion of the screen to use for the master window -> l a -- ^ the layout to be modified -> ModifiedLayout AddMaster l a mastered delta frac = multimastered 1 delta frac instance LayoutModifier AddMaster Window where modifyLayout (AddMaster k delta frac) = applyMaster k delta frac modifierDescription _ = "Mastered" pureMess (AddMaster k delta frac) m | Just Shrink <- fromMessage m = Just $ AddMaster k delta (frac-delta) | Just Expand <- fromMessage m = Just $ AddMaster k delta (frac+delta) | Just (IncMasterN d) <- fromMessage m = Just $ AddMaster (max 1 (k+d)) delta frac pureMess _ _ = Nothing -- | Internal function for adding a master window and let the modified -- layout handle the rest of the windows applyMaster :: (LayoutClass l Window) => Int -> Rational -> Rational -> S.Workspace WorkspaceId (l Window) Window -> Rectangle -> X ([(Window, Rectangle)], Maybe (l Window)) applyMaster k _ frac wksp rect = do let st= S.stack wksp let ws = S.integrate' $ st let n = length ws if n > 1 then do if(n<=k) then return ((divideCol rect ws), Nothing) else do let m = take k ws let (mr, sr) = splitHorizontallyBy frac rect let nst = st>>= S.filter (\w -> not (w `elem` m)) wrs <- runLayout (wksp {S.stack = nst}) sr return ((divideCol mr m) ++ (fst wrs), snd wrs) else runLayout wksp rect -- | Shift rectangle down shiftD :: Position -> Rectangle -> Rectangle shiftD s (Rectangle x y w h) = Rectangle x (y+s) w h -- | Divide rectangle between windows divideCol :: Rectangle -> [a] -> [(a, Rectangle)] divideCol (Rectangle x y w h) ws = zip ws rects where n = length ws oneH = fromIntegral h `div` n oneRect = Rectangle x y w (fromIntegral oneH) rects = take n $ iterate (shiftD (fromIntegral oneH)) oneRect