mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 11:30:22 -07:00
133 lines
4.8 KiB
Haskell
133 lines
4.8 KiB
Haskell
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
|
|
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Layout.OneBig
|
|
-- Description : Place one window at top left corner, and other windows at the top.
|
|
-- Copyright : (c) 2009 Ilya Portnov
|
|
-- License : BSD3-style (see LICENSE)
|
|
--
|
|
-- Maintainer : Ilya Portnov <portnov84@rambler.ru>
|
|
-- Stability : unstable
|
|
-- Portability : unportable
|
|
--
|
|
-- Provides layout named OneBig. It places one (master) window at top left corner of screen, and other (slave) windows at top
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
module XMonad.Layout.OneBig (
|
|
-- * Usage
|
|
-- $usage
|
|
OneBig (..)
|
|
) where
|
|
import XMonad
|
|
import qualified XMonad.StackSet as W
|
|
|
|
-- $usage
|
|
-- This module defines layout named OneBig. It places one (master)
|
|
-- window at top left, and other (slave) windows at right and at
|
|
-- bottom of master. It tries to give equal space for each slave
|
|
-- window.
|
|
--
|
|
-- You can use this module by adding following in your @xmonad.hs@:
|
|
--
|
|
-- > import XMonad.Layout.OneBig
|
|
--
|
|
-- Then add layouts to your layoutHook:
|
|
--
|
|
-- > myLayoutHook = OneBig (3/4) (3/4) ||| ...
|
|
--
|
|
-- In this example, master window will occupy 3/4 of screen width and
|
|
-- 3/4 of screen height.
|
|
|
|
-- | Data type for layout
|
|
data OneBig a = OneBig Float Float deriving (Read,Show)
|
|
|
|
instance LayoutClass OneBig a where
|
|
pureLayout = oneBigLayout
|
|
pureMessage = oneBigMessage
|
|
|
|
-- | Processes Shrink/Expand messages
|
|
oneBigMessage :: OneBig a -> SomeMessage -> Maybe (OneBig a)
|
|
oneBigMessage (OneBig cx cy) m = fmap resize (fromMessage m)
|
|
where resize Shrink = OneBig (cx-delta) (cy-delta)
|
|
resize Expand = OneBig (cx+delta) (cy+delta)
|
|
delta = 3/100
|
|
|
|
-- | Main layout function
|
|
oneBigLayout :: OneBig a -> Rectangle -> W.Stack a -> [(a, Rectangle)]
|
|
oneBigLayout (OneBig cx cy) rect stack = [(master,masterRect)]
|
|
++ divideBottom bottomRect bottomWs
|
|
++ divideRight rightRect rightWs
|
|
where ws = W.integrate stack
|
|
n = length ws
|
|
ht (Rectangle _ _ _ hh) = hh
|
|
wd (Rectangle _ _ ww _) = ww
|
|
h' = round (fromIntegral (ht rect)*cy)
|
|
w = wd rect
|
|
m = calcBottomWs n w h'
|
|
master = head ws
|
|
other = tail ws
|
|
bottomWs = take m other
|
|
rightWs = drop m other
|
|
masterRect = cmaster n m cx cy rect
|
|
bottomRect = cbottom cy rect
|
|
rightRect = cright cx cy rect
|
|
|
|
-- | Calculate how many windows must be placed at bottom
|
|
calcBottomWs :: Int -> Dimension -> Dimension -> Int
|
|
calcBottomWs n w h' = case n of
|
|
1 -> 0
|
|
2 -> 1
|
|
3 -> 2
|
|
4 -> 2
|
|
_ -> fromIntegral w*(n-1) `div` fromIntegral (h'+fromIntegral w)
|
|
|
|
-- | Calculate rectangle for master window
|
|
cmaster:: Int -> Int -> Float -> Float -> Rectangle -> Rectangle
|
|
cmaster n m cx cy (Rectangle x y sw sh) = Rectangle x y w h
|
|
where w = if n > m+1 then
|
|
round (fromIntegral sw*cx)
|
|
else
|
|
sw
|
|
h = if n > 1 then
|
|
round (fromIntegral sh*cy)
|
|
else
|
|
sh
|
|
|
|
-- | Calculate rectangle for bottom windows
|
|
cbottom:: Float -> Rectangle -> Rectangle
|
|
cbottom cy (Rectangle sx sy sw sh) = Rectangle sx y sw h
|
|
where h = round (fromIntegral sh*(1-cy))
|
|
y = round (fromIntegral sh*cy+fromIntegral sy)
|
|
|
|
-- | Calculate rectangle for right windows
|
|
cright:: Float -> Float -> Rectangle -> Rectangle
|
|
cright cx cy (Rectangle sx sy sw sh) = Rectangle x sy w h
|
|
where w = round (fromIntegral sw*(1-cx))
|
|
x = round (fromIntegral sw*cx+fromIntegral sx)
|
|
h = round (fromIntegral sh*cy)
|
|
|
|
-- | Divide bottom rectangle between windows
|
|
divideBottom :: Rectangle -> [a] -> [(a, Rectangle)]
|
|
divideBottom (Rectangle x y w h) ws = zip ws rects
|
|
where n = length ws
|
|
oneW = fromIntegral w `div` n
|
|
oneRect = Rectangle x y (fromIntegral oneW) h
|
|
rects = take n $ iterate (shiftR (fromIntegral oneW)) oneRect
|
|
|
|
-- | Divide right rectangle between windows
|
|
divideRight :: Rectangle -> [a] -> [(a, Rectangle)]
|
|
divideRight (Rectangle x y w h) ws = if n==0 then [] else zip ws rects
|
|
where n = length ws
|
|
oneH = fromIntegral h `div` n
|
|
oneRect = Rectangle x y w (fromIntegral oneH)
|
|
rects = take n $ iterate (shiftB (fromIntegral oneH)) oneRect
|
|
|
|
-- | Shift rectangle right
|
|
shiftR :: Position -> Rectangle -> Rectangle
|
|
shiftR s (Rectangle x y w h) = Rectangle (x+s) y w h
|
|
|
|
-- | Shift rectangle bottom
|
|
shiftB :: Position -> Rectangle -> Rectangle
|
|
shiftB s (Rectangle x y w h) = Rectangle x (y+s) w h
|