summaryrefslogtreecommitdiff
path: root/lain/layout/cascadetile.lua
blob: e9b942560cc6a32333d4de128b413d45cd8c7840 (plain)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

--[[
                                                  
     Licensed under GNU General Public License v2 
      * (c) 2014,      projektile                 
      * (c) 2013,      Luke Bonham                
      * (c) 2010-2012, Peter Hofmann              
                                                  
--]]

local tag       = require("awful.tag")
local beautiful = require("beautiful")
local tonumber  = tonumber

local cascadetile =
{
    name          = "cascadetile",
    nmaster       = 0,
    ncol          = 0,
    mwfact        = 0,
    offset_x      = 5,
    offset_y      = 32,
    extra_padding = 0
}

function cascadetile.arrange(p)

    -- Layout with one fixed column meant for a master window. Its
    -- width is calculated according to mwfact. Other clients are
    -- cascaded or "tabbed" in a slave column on the right.

    -- It's a bit hard to demonstrate the behaviour with ASCII-images...
    --
    --         (1)                 (2)                 (3)                 (4)
    --   +----------+---+    +----------+---+    +----------+---+    +----------+---+
    --   |          |   |    |          | 3 |    |          | 4 |    |         +---+|
    --   |          |   | -> |          |   | -> |         +---++ -> |        +---+|+
    --   |  1       | 2 |    |  1      +---++    |  1      | 3 ||    |  1    +---+|+|
    --   |          |   |    |         | 2 ||    |        +---++|    |      +---+|+ |
    --   |          |   |    |         |   ||    |        | 2 | |    |      | 2 |+  |
    --   +----------+---+    +---------+---++    +--------+---+-+    +------+---+---+

    -- A useless gap (like the dwm patch) can be defined with
    -- beautiful.useless_gap_width.
    local useless_gap = tonumber(beautiful.useless_gap_width) or 0
    if useless_gap < 0 then useless_gap = 0 end

    -- A global border can be defined with
    -- beautiful.global_border_width
    local global_border = tonumber(beautiful.global_border_width) or 0
    if global_border < 0 then global_border = 0 end

    -- Themes border width requires an offset
    local bw = tonumber(beautiful.border_width) or 0

    -- Screen.
    local wa = p.workarea
    local cls = p.clients

    -- Borders are factored in.
    wa.height = wa.height - ((global_border * 2) + (bw * 2))
    wa.width = wa.width - ((global_border * 2) + (bw * 2))

    -- Width of main column?
    local t = tag.selected(p.screen)
    local mwfact
    if cascadetile.mwfact > 0
    then
        mwfact = cascadetile.mwfact
    else
        mwfact = tag.getmwfact(t)
    end

    -- Make slave windows overlap main window? Do this if ncol is 1.
    local overlap_main
    if cascadetile.ncol > 0
    then
        overlap_main = cascadetile.ncol
    else
        overlap_main = tag.getncol(t)
    end

    -- Minimum space for slave windows? See cascade.lua.
    local num_c
    if cascadetile.nmaster > 0
    then
        num_c = cascadetile.nmaster
    else
        num_c = tag.getnmaster(t)
    end

    local how_many = #cls - 1
    if how_many < num_c
    then
        how_many = num_c
    end
    local current_offset_x = cascadetile.offset_x * (how_many - 1)
    local current_offset_y = cascadetile.offset_y * (how_many - 1)

    if #cls > 0
    then
        -- Main column, fixed width and height.
        local c = cls[#cls]
        local g = {}
        local mainwid = wa.width * mwfact
        local slavewid = wa.width - mainwid

        if overlap_main == 1
        then
            g.width = wa.width

            -- The size of the main window may be reduced a little bit.
            -- This allows you to see if there are any windows below the
            -- main window.
            -- This only makes sense, though, if the main window is
            -- overlapping everything else.
            g.width = g.width - cascadetile.extra_padding
        else
            g.width = mainwid
        end

        g.height = wa.height
        g.x = wa.x + global_border
        g.y = wa.y + global_border
        if useless_gap > 0
        then
            -- Reduce width once and move window to the right. Reduce
            -- height twice, however.
            g.width = g.width - useless_gap
            g.height = g.height - 2 * useless_gap
            g.x = g.x + useless_gap
            g.y = g.y + useless_gap

            -- When there's no window to the right, add an additional
            -- gap.
            if overlap_main == 1
            then
                g.width = g.width - useless_gap
            end
        end
        c:geometry(g)

        -- Remaining clients stacked in slave column, new ones on top.
        if #cls > 1
        then
            for i = (#cls - 1),1,-1
            do
                c = cls[i]
                g = {}
                g.width = slavewid - current_offset_x
                g.height = wa.height - current_offset_y
                g.x = wa.x + mainwid + (how_many - i) * cascadetile.offset_x
                g.y = wa.y + (i - 1) * cascadetile.offset_y + global_border
                if useless_gap > 0
                then
                    g.width = g.width - 2 * useless_gap
                    g.height = g.height - 2 * useless_gap
                    g.x = g.x + useless_gap
                    g.y = g.y + useless_gap
                end
                c:geometry(g)
            end
        end
    end
end

return cascadetile