Tony Zorman 3d65a6bf72 Refer to the tutorial instead of X.D.Extending more often
Essentially, whenever the tutorial actually has decent material on the
subject matter.  The replacement is roughly done as follows:

  - logHook → tutorial
  - keybindings → tutorial, as this is thoroughly covered
  - manageHook → tutorial + X.D.Extending, as the manageHook stuff the
    tutorial talks about is a little bit of an afterthought.
  - X.D.Extending (on its own) → tutorial + X.D.Extending
  - layoutHook → tutorial + X.D.Extending, as the tutorial, while
    talking about layouts, doesn't necessarily have a huge focus there.
  - mouse bindings → leave this alone, as the tutorial does not at all
    talk about them.
2022-10-21 09:17:43 +02:00

141 lines
5.1 KiB
Haskell

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, PatternGuards #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.Master
-- Description : Layout modfier that adds a master window to another layout.
-- Copyright : (c) Ismael Carnales, Lukas Mai
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Ismael Carnales <icarnales@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- Layout modfier that adds a master window to another layout.
-----------------------------------------------------------------------------
module XMonad.Layout.Master (
-- * Usage
-- $usage
mastered,
fixMastered,
multimastered,
AddMaster,
) where
import XMonad
import qualified XMonad.StackSet as S
import XMonad.Layout.LayoutModifier
import Control.Arrow (first)
-- $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 prefer to have a master with fixed width:
--
-- > fixMastered (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
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial> and
-- "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)
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 = multimastered 1
instance LayoutModifier AddMaster Window where
modifyLayout (AddMaster k delta frac) = applyMaster False 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
newtype FixMaster a = FixMaster (AddMaster a) deriving (Show, Read)
instance LayoutModifier FixMaster Window where
modifyLayout (FixMaster (AddMaster k d f)) = applyMaster True k d f
modifierDescription (FixMaster a) = "Fix" ++ modifierDescription a
pureMess (FixMaster a) m = fmap FixMaster (pureMess a m)
fixMastered :: (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 FixMaster l a
fixMastered delta frac = ModifiedLayout . FixMaster $ AddMaster 1 delta frac
-- | Internal function for adding a master window and let the modified
-- layout handle the rest of the windows
applyMaster :: (LayoutClass l Window) =>
Bool
-> Int
-> Rational
-> Rational
-> S.Workspace WorkspaceId (l Window) Window
-> Rectangle
-> X ([(Window, Rectangle)], Maybe (l Window))
applyMaster f k _ frac wksp rect = do
let st= S.stack wksp
let ws = S.integrate' st
let n = length ws + fromEnum f
if n > 1 then
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 (`notElem` m)
wrs <- runLayout (wksp {S.stack = nst}) sr
return (first (divideCol mr m ++) 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