From cf00d2d2371a40368cda870d6f9aa0a4e71f13e6 Mon Sep 17 00:00:00 2001 From: Mahdi Seyedan Date: Fri, 21 Apr 2023 02:27:46 +0330 Subject: [PATCH] Add CenterMainFluid layout --- CHANGES.md | 5 ++ XMonad/Layout/CenterMainFluid.hs | 98 ++++++++++++++++++++++++++++++++ xmonad-contrib.cabal | 1 + 3 files changed, 104 insertions(+) create mode 100644 XMonad/Layout/CenterMainFluid.hs diff --git a/CHANGES.md b/CHANGES.md index a685d371..0e37ef17 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -81,6 +81,11 @@ ### New Modules + * `XMonad.Layout.CenterMainFluid` + - A three column layout with main column in the center and two stack + column surrounding it. Master window will be on center column and + spaces on the sides are reserved. + * `XMonad.Layout.FocusTracking`. - Replaces `X.L.StateFull` and half of `X.L.TrackFloating`. diff --git a/XMonad/Layout/CenterMainFluid.hs b/XMonad/Layout/CenterMainFluid.hs new file mode 100644 index 00000000..396748e8 --- /dev/null +++ b/XMonad/Layout/CenterMainFluid.hs @@ -0,0 +1,98 @@ +{-# 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 diff --git a/xmonad-contrib.cabal b/xmonad-contrib.cabal index 72a9b6da..e061fcb8 100644 --- a/xmonad-contrib.cabal +++ b/xmonad-contrib.cabal @@ -228,6 +228,7 @@ library XMonad.Layout.BorderResize XMonad.Layout.BoringWindows XMonad.Layout.ButtonDecoration + XMonad.Layout.CenterMainFluid XMonad.Layout.CenteredIfSingle XMonad.Layout.CenteredMaster XMonad.Layout.Circle