----------------------------------------------------------------------------- -- | -- Module : XMonad.Layout.IfMax -- Copyright : (c) 2013 Ilya Portnov -- License : BSD3-style (see LICENSE) -- -- Maintainer : Ilya Portnov -- Stability : unstable -- Portability : unportable -- -- Provides IfMax layout, which will run one layout if there are maximum N -- windows on workspace, and another layout, when number of windows is greater -- than N. -- ----------------------------------------------------------------------------- {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, PatternGuards #-} module XMonad.Layout.IfMax ( -- * Usage -- $usage IfMax (..) , ifMax ) where import Control.Applicative((<$>)) import Control.Arrow import qualified Data.List as L import qualified Data.Map as M import Data.Maybe import XMonad import qualified XMonad.StackSet as W -- $usage -- IfMax layout will run one layout if number of windows on workspace is as -- maximum N, and else will run another layout. -- -- You can use this module by adding folowing in your @xmonad.hs@: -- -- > import XMonad.Layout.IfMax -- -- Then add layouts to your layoutHook: -- -- > myLayoutHook = IfMax 2 Full (Tall ...) ||| ... -- -- In this example, if there are 1 or 2 windows, Full layout will be used; -- otherwise, Tall layout will be used. -- data IfMax l1 l2 w = IfMax Int (l1 w) (l2 w) deriving (Read, Show) instance (LayoutClass l1 Window, LayoutClass l2 Window) => LayoutClass (IfMax l1 l2) Window where runLayout (W.Workspace wname (IfMax n l1 l2) s) rect = withWindowSet $ \ws -> arrange (W.integrate' s) (M.keys . W.floating $ ws) where arrange ws fw | length (ws L.\\ fw) <= n = do (wrs, ml1') <- runLayout (W.Workspace wname l1 s) rect let l1' = fromMaybe l1 ml1' l2' <- fromMaybe l2 <$> handleMessage l2 (SomeMessage Hide) return (wrs, Just $ IfMax n l1' l2') | otherwise = do (wrs, ml2') <- runLayout (W.Workspace wname l2 s) rect l1' <- fromMaybe l1 <$> handleMessage l1 (SomeMessage Hide) let l2' = fromMaybe l2 ml2' return (wrs, Just $ IfMax n l1' l2') handleMessage (IfMax n l1 l2) m | Just ReleaseResources <- fromMessage m = do l1' <- handleMessage l1 (SomeMessage ReleaseResources) l2' <- handleMessage l2 (SomeMessage ReleaseResources) if isNothing l1' && isNothing l2' then return Nothing else return $ Just $ IfMax n (fromMaybe l1 l1') (fromMaybe l2 l2') handleMessage (IfMax n l1 l2) m = do (allWindows, floatingWindows) <- gets ((W.integrate' . W.stack . W.workspace . W.current &&& M.keys . W.floating) . windowset) if length (allWindows L.\\ floatingWindows) <= n then do l1' <- handleMessage l1 m return $ flip (IfMax n) l2 <$> l1' else do l2' <- handleMessage l2 m return $ IfMax n l1 <$> l2' description (IfMax n l1 l2) = "If number of windows is <= " ++ show n ++ ", then " ++ description l1 ++ ", else " ++ description l2 -- | Layout itself ifMax :: (LayoutClass l1 w, LayoutClass l2 w) => Int -- ^ Maximum number of windows for the first layout -> l1 w -- ^ First layout -> l2 w -- ^ Second layout -> IfMax l1 l2 w ifMax n l1 l2 = IfMax n l1 l2