1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.CenteredMaster
-- Copyright : (c) 2009 Ilya Portnov
-- License : BSD-style (see xmonad/LICENSE)
--
-- Maintainer : Ilya Portnov <portnov84@rambler.ru>
-- Stability : unstable
-- Portability : unportable
--
-- Two layout modifiers. centerMaster places master window at center,
-- on top of all other windows, which are managed by base layout.
-- topRightMaster is similar, but places master window in top right corner
-- instead of center.
--
-----------------------------------------------------------------------------
module XMonad.Layout.CenteredMaster (
-- * Usage
-- $usage
centerMaster,
topRightMaster,
CenteredMaster, TopRightMaster,
) where
import XMonad
import XMonad.Layout.LayoutModifier
import qualified XMonad.StackSet as W
-- $usage
-- This module defines two new layout modifiers: centerMaster and topRightMaster.
-- centerMaster places master window at center of screen, on top of others.
-- All other windows in background are managed by base layout.
-- topRightMaster is like centerMaster, but places master window in top right corner instead of center.
--
-- Yo can use this module by adding folowing in your @xmonad.hs@:
--
-- > import XMonad.Layout.CenteredMaster
--
-- Then add layouts to your layoutHook:
--
-- > myLayoutHook = centerMaster Grid ||| ...
-- | Function that decides where master window should be placed
type Positioner = Rectangle -> Rectangle
-- | Data type for LayoutModifier
data CenteredMaster a = CenteredMaster deriving (Read,Show)
instance LayoutModifier CenteredMaster Window where
modifyLayout CenteredMaster = applyPosition (center (5/7) (5/7))
data TopRightMaster a = TopRightMaster deriving (Read,Show)
instance LayoutModifier TopRightMaster Window where
modifyLayout TopRightMaster = applyPosition (topRight (3/7) (1/2))
-- | Modifier that puts master window in center, other windows in background
-- are managed by given layout
centerMaster :: LayoutClass l a => l a -> ModifiedLayout CenteredMaster l a
centerMaster = ModifiedLayout CenteredMaster
-- | Modifier that puts master window in top right corner, other windows in background
-- are managed by given layout
topRightMaster :: LayoutClass l a => l a -> ModifiedLayout TopRightMaster l a
topRightMaster = ModifiedLayout TopRightMaster
-- | Internal function, doing main job
applyPosition :: (LayoutClass l a, Eq a) =>
Positioner
-> W.Workspace WorkspaceId (l a) a
-> Rectangle
-> X ([(a, Rectangle)], Maybe (l a))
applyPosition pos wksp rect = do
let stack = W.stack wksp
let ws = W.integrate' $ stack
if null ws then
runLayout wksp rect
else do
let first = head ws
let other = tail ws
let filtStack = stack >>= W.filter (first /=)
wrs <- runLayout (wksp {W.stack = filtStack}) rect
return ((first, place pos other rect) : fst wrs, snd wrs)
-- | Place master window (it's Rectangle is given), using the given Positioner.
-- If second argument is empty (that is, there is only one window on workspace),
-- place that window fullscreen.
place :: Positioner -> [a] -> Rectangle -> Rectangle
place _ [] rect = rect
place pos _ rect = pos rect
-- | Function that calculates Rectangle at top right corner of given Rectangle
topRight :: Float -> Float -> Rectangle -> Rectangle
topRight rx ry (Rectangle sx sy sw sh) = Rectangle x sy w h
where w = round (fromIntegral sw * rx)
h = round (fromIntegral sh * ry)
x = sx + fromIntegral (sw-w)
-- | Function that calculates Rectangle at center of given Rectangle.
center :: Float -> Float -> Rectangle -> Rectangle
center rx ry (Rectangle sx sy sw sh) = Rectangle x y w h
where w = round (fromIntegral sw * rx)
h = round (fromIntegral sh * ry)
x = sx + fromIntegral (sw-w) `div` 2
y = sy + fromIntegral (sh-h) `div` 2
|