]> git.madduck.net Git - etc/awesome.git/blob - layout/cascade.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge branch 'Veratil-awesome-v4-layout-fix'
[etc/awesome.git] / layout / cascade.lua
1
2 --[[
3                                                   
4      Licensed under GNU General Public License v2 
5       * (c) 2014,      projektile                 
6       * (c) 2013,      Luke Bonham                
7       * (c) 2010-2012, Peter Hofmann              
8                                                   
9 --]]
10
11 local scr      = require("awful.screen")
12 local tonumber = tonumber
13
14 local cascade = {
15     name     = "cascade",
16     nmaster  = 0,
17     offset_x = 32,
18     offset_y = 8,
19     tile     = {
20         name          = "cascadetile",
21         nmaster       = 0,
22         ncol          = 0,
23         mwfact        = 0,
24         offset_x      = 5,
25         offset_y      = 32,
26         extra_padding = 0
27     }
28 }
29
30 local function do_cascade(p, tiling)
31     -- Screen.
32     local wa  = p.workarea
33     local cls = p.clients
34     local ta = scr.focused().selected_tag
35
36     if not ta then return end
37
38     if #cls <= 0 then return end
39
40     -- Useless gaps.
41     local useless_gap = p.useless_gap or 0
42
43     if not tiling then
44         -- Cascade windows.
45
46         local num_c
47         if cascade.nmaster > 0 then
48             num_c = cascade.nmaster
49         else
50             num_c = ta.master_count
51         end
52
53         -- Opening a new window will usually force all existing windows to
54         -- get resized. This wastes a lot of CPU time. So let's set a lower
55         -- bound to "how_many": This wastes a little screen space but you'll
56         -- get a much better user experience.
57         local how_many = (#cls >= num_c and #cls) or num_c
58
59         local current_offset_x = cascade.offset_x * (how_many - 1)
60         local current_offset_y = cascade.offset_y * (how_many - 1)
61
62         -- Iterate.
63         for i = 1,#cls,1 do
64             local c = cls[i]
65             local g = {}
66
67             g.x      = wa.x + (how_many - i) * cascade.offset_x
68             g.y      = wa.y + (i - 1) * cascade.offset_y
69             g.width  = wa.width - current_offset_x - 2*c.border_width
70             g.height = wa.height - current_offset_y - 2*c.border_width
71
72             if g.width  < 1 then g.width  = 1 end
73             if g.height < 1 then g.height = 1 end
74
75             c:geometry(g)
76         end
77     else
78         -- Layout with one fixed column meant for a master window. Its
79         -- width is calculated according to mwfact. Other clients are
80         -- cascaded or "tabbed" in a slave column on the right.
81
82         --         (1)                 (2)                 (3)                 (4)
83         --   +----------+---+    +----------+---+    +----------+---+    +----------+---+
84         --   |          |   |    |          | 3 |    |          | 4 |    |         +---+|
85         --   |          |   | -> |          |   | -> |         +---++ -> |        +---+|+
86         --   |  1       | 2 |    |  1      +---++    |  1      | 3 ||    |  1    +---+|+|
87         --   |          |   |    |         | 2 ||    |        +---++|    |      +---+|+ |
88         --   |          |   |    |         |   ||    |        | 2 | |    |      | 2 |+  |
89         --   +----------+---+    +---------+---++    +--------+---+-+    +------+---+---+
90
91         local mwfact
92         if cascade.tile.mwfact > 0 then
93             mwfact = cascade.tile.mwfact
94         else
95             mwfact = ta.master_width_factor
96         end
97
98         -- Make slave windows overlap main window? Do this if ncol is 1.
99         local overlap_main
100         if cascade.tile.ncol > 0 then
101             overlap_main = cascade.tile.ncol
102         else
103             overlap_main = ta.column_count
104         end
105
106         -- Minimum space for slave windows? See cascade.tile.lua.
107         local num_c
108         if cascade.tile.nmaster > 0 then
109             num_c = cascade.tile.nmaster
110         else
111             num_c = ta.master_count
112         end
113
114         local how_many = (#cls - 1 >= num_c and (#cls - 1)) or num_c
115
116         local current_offset_x = cascade.tile.offset_x * (how_many - 1)
117         local current_offset_y = cascade.tile.offset_y * (how_many - 1)
118
119         if #cls <= 0 then return end
120
121         -- Main column, fixed width and height.
122         local c = cls[1]
123         local g = {}
124         -- Subtracting the useless_gap width from the work area width here
125         -- makes this mwfact calculation work the same as in uselesstile.
126         -- Rounding is necessary to prevent the rendered size of slavewid
127         -- from being 1 pixel off when the result is not an integer.
128         local mainwid = math.floor((wa.width - useless_gap) * mwfact)
129         local slavewid = wa.width - mainwid
130
131         if overlap_main == 1 then
132             g.width = wa.width - 2*c.border_width
133
134             -- The size of the main window may be reduced a little bit.
135             -- This allows you to see if there are any windows below the
136             -- main window.
137             -- This only makes sense, though, if the main window is
138             -- overlapping everything else.
139             g.width = g.width - cascade.tile.extra_padding
140         else
141             g.width = mainwid - 2*c.border_width
142         end
143
144         g.height = wa.height - 2*c.border_width
145         g.x = wa.x
146         g.y = wa.y
147         if useless_gap > 0 then
148             -- Reduce width once and move window to the right.
149             -- Reduce height twice, however.
150             g.width = g.width - useless_gap
151             g.height = g.height - 2 * useless_gap
152             g.x = g.x + useless_gap
153             g.y = g.y + useless_gap
154
155             -- When there's no window to the right, add an additional gap.
156             if overlap_main == 1 then g.width = g.width - useless_gap end
157         end
158         if g.width < 1 then g.width = 1 end
159         if g.height < 1 then g.height = 1 end
160         c:geometry(g)
161
162         -- Remaining clients stacked in slave column, new ones on top.
163         if #cls > 1 then
164             for i = 2,#cls do
165                 c = cls[i]
166                 g = {}
167                 g.width = slavewid - current_offset_x - 2*c.border_width
168                 g.height = wa.height - current_offset_y - 2*c.border_width
169                 g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x
170                 g.y = wa.y + (i - 2) * cascade.tile.offset_y
171
172                 if useless_gap > 0 then
173                     g.width = g.width - 2 * useless_gap
174                     g.height = g.height - 2 * useless_gap
175                     g.x = g.x + useless_gap
176                     g.y = g.y + useless_gap
177                 end
178
179                 if g.width < 1 then g.width = 1 end
180                 if g.height < 1 then g.height = 1 end
181
182                 c:geometry(g)
183             end
184         end
185     end
186 end
187
188 function cascade.tile.arrange(p)
189     return do_cascade(p, true)
190 end
191
192 function cascade.arrange(p)
193     return do_cascade(p, false)
194 end
195
196 return cascade