From 1dc5889cc9dfec1d891a7f40c3cb3edaddf91bce Mon Sep 17 00:00:00 2001 From: Andrea Rossato Date: Wed, 21 Nov 2007 12:23:31 +0100 Subject: HintedTile: ported to the LayoutClass darcs-hash:20071121112331-32816-9cf35d9f7f439bc133959483859923be8735599f.gz --- XMonad/Layout/HintedTile.hs | 115 +++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 49 deletions(-) (limited to 'XMonad') diff --git a/XMonad/Layout/HintedTile.hs b/XMonad/Layout/HintedTile.hs index 2ec9d3c..70c9c82 100644 --- a/XMonad/Layout/HintedTile.hs +++ b/XMonad/Layout/HintedTile.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-} + ----------------------------------------------------------------------------- -- | -- Module : XMonad.Layout.HintedTile @@ -5,10 +7,11 @@ -- License : BSD3-style (see LICENSE) -- -- Maintainer : Peter De Wachter +-- Andrea Rossato -- Stability : unstable -- Portability : unportable -- --- A gapless tiled layout that attempts to obey window size hints, +-- A gapless tiled layout that attempts to obey window size hints, -- rather than simply ignoring them. -- ----------------------------------------------------------------------------- @@ -16,73 +19,87 @@ module XMonad.Layout.HintedTile ( -- * Usage -- $usage - tall, wide) where + tall, wide ) where import XMonad -import XMonad.Operations (Resize(..), IncMasterN(..), applySizeHints) +import XMonad.Layouts ( Resize(..), IncMasterN(..) ) +import XMonad.Operations ( applySizeHints ) import qualified XMonad.StackSet as W -import {-# SOURCE #-} Config (borderWidth) import Graphics.X11.Xlib import Graphics.X11.Xlib.Extras -import Control.Monad +import Control.Monad.Reader -- $usage --- You can use this module with the following in your Config.hs file: +-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- --- > import qualified XMonad.Layout.HintedTile +-- > import XMonad.Layout.HintedTile -- --- > layouts = [ XMonad.Layout.HintedTile.tall nmaster delta ratio, ... ] - --- %import qualified XMonad.Layout.HintedTile +-- The edit your @layoutHook@ by adding the HintedTile layout: -- --- %layout , XMonad.Layout.HintedTile.tall nmaster delta ratio - --- this sucks -addBorder, substractBorder :: (Dimension, Dimension) -> (Dimension, Dimension) -addBorder (w, h) = (w + 2 * borderWidth, h + 2 * borderWidth) -substractBorder (w, h) = (w - 2 * borderWidth, h - 2 * borderWidth) - - -tall, wide :: Int -> Rational -> Rational -> Layout Window -wide = tile splitVertically divideHorizontally -tall = tile splitHorizontally divideVertically - -tile split divide nmaster delta frac = - Layout { doLayout = \r w' -> let w = W.integrate w' - in do { hints <- sequence (map getHints w) - ; return (zip w (tiler frac r `uncurry` splitAt nmaster hints) - , Nothing) } - , modifyLayout = \m -> return $ fmap resize (fromMessage m) `mplus` - fmap incmastern (fromMessage m) } - - where resize Shrink = tile split divide nmaster delta (frac-delta) - resize Expand = tile split divide nmaster delta (frac+delta) - incmastern (IncMasterN d) = tile split divide (max 0 (nmaster+d)) delta frac - - tiler f r masters slaves = if null masters || null slaves - then divide (masters ++ slaves) r - else split f r (divide masters) (divide slaves) +-- > mylayout = tall 1 0.1 0.5 ||| Full ||| etc.. +-- > main = xmonad dafaultConfig { layoutHook = mylayouts } +-- +-- For more detailed instructions on editing the layoutHook see: +-- "XMonad.Doc.Extending#Editing_the_layout_hook" + +data HintedTile a = + HT { nmaster :: Int + , delta, frac :: Rational + , orientation :: Orientation + } deriving ( Show, Read ) + +data Orientation = Wide | Tall deriving ( Show, Read ) + +tall, wide :: Int -> Rational -> Rational -> HintedTile Window +wide n d f = HT {nmaster = n, delta = d, frac = f, orientation = Tall } +tall n d f = HT {nmaster = n, delta = d, frac = f, orientation = Wide } + +instance LayoutClass HintedTile Window where + doLayout c rect w' = let w = W.integrate w' + in do { hints <- sequence (map getHints w) + ; b <- asks (borderWidth . config) + ; return (zip w (tiler b (frac c) rect `uncurry` splitAt (nmaster c) hints) + , Nothing) } + where + (split, divide) = + case orientation c of + Wide -> (splitHorizontally, divideHorizontally) + Tall -> (splitVertically, divideVertically ) + tiler b f r masters slaves = + if null masters || null slaves + then divide b (masters ++ slaves) r + else split f r (divide b masters) (divide b slaves) + + pureMessage c m = fmap resize (fromMessage m) `mplus` + fmap incmastern (fromMessage m) + where + resize Shrink = c { frac = max 0 $ frac c - delta c } + resize Expand = c { frac = min 1 $ frac c + delta c } + incmastern (IncMasterN d) = c { nmaster = max 0 $ nmaster c + d } + + description l = "HintedTile " ++ show (orientation l) + +addBorder, substractBorder :: Dimension -> (Dimension, Dimension) -> (Dimension, Dimension) +addBorder b (w, h) = (w + 2 * b, h + 2 * b) +substractBorder b (w, h) = (w - 2 * b, h - 2 * b) getHints :: Window -> X SizeHints getHints w = withDisplay $ \d -> io $ getWMNormalHints d w --- -- Divide the screen vertically (horizontally) into n subrectangles --- -divideVertically, divideHorizontally :: [SizeHints] -> Rectangle -> [Rectangle] -divideVertically [] _ = [] -- there's a fold here, struggling to get out -divideVertically (hints:rest) (Rectangle sx sy sw sh) = (Rectangle sx sy w h) : - (divideVertically rest (Rectangle sx (sy + fromIntegral h) sw (sh - h))) - where (w, h) = addBorder $ applySizeHints hints $ substractBorder +divideVertically, divideHorizontally :: Dimension -> [SizeHints] -> Rectangle -> [Rectangle] +divideVertically _ [] _ = [] -- there's a fold here, struggling to get out +divideVertically b (hints:rest) (Rectangle sx sy sw sh) = (Rectangle sx sy w h) : + (divideVertically b rest (Rectangle sx (sy + fromIntegral h) sw (sh - h))) + where (w, h) = addBorder b $ applySizeHints hints $ substractBorder b (sw, sh `div` fromIntegral (1 + (length rest))) -divideHorizontally [] _ = [] -divideHorizontally (hints:rest) (Rectangle sx sy sw sh) = (Rectangle sx sy w h) : - (divideHorizontally rest (Rectangle (sx + fromIntegral w) sy (sw - w) sh)) - where (w, h) = addBorder $ applySizeHints hints $ substractBorder +divideHorizontally _ [] _ = [] +divideHorizontally b (hints:rest) (Rectangle sx sy sw sh) = (Rectangle sx sy w h) : + (divideHorizontally b rest (Rectangle (sx + fromIntegral w) sy (sw - w) sh)) + where (w, h) = addBorder b $ applySizeHints hints $ substractBorder b (sw `div` fromIntegral (1 + (length rest)), sh) - -- Split the screen into two rectangles, using a rational to specify the ratio splitHorizontally, splitVertically :: Rational -> Rectangle -> (Rectangle -> [Rectangle]) -> (Rectangle -> [Rectangle]) -> [Rectangle] splitHorizontally f (Rectangle sx sy sw sh) left right = leftRects ++ rightRects -- cgit v1.2.3