]> git.madduck.net Git - etc/awesome.git/blob - layout/termfair.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:

centerwork: mouse_resize_handler added; #395
[etc/awesome.git] / layout / termfair.lua
1 --[[
2
3      Licensed under GNU General Public License v2
4       * (c) 2014,      projektile
5       * (c) 2013,      Luca CPZ
6       * (c) 2010,      Nicolas Estibals
7       * (c) 2010-2012, Peter Hofmann
8
9 --]]
10
11 local math     = { ceil  = math.ceil,
12                    floor = math.floor,
13                    max   = math.max }
14 local screen   = screen
15 local tonumber = tonumber
16
17 local termfair  = { name = "termfair" }
18 termfair.center = { name = "centerfair" }
19
20 local function do_fair(p, orientation)
21     local t = p.tag or screen[p.screen].selected_tag
22     local wa = p.workarea
23     local cls = p.clients
24
25     if #cls == 0 then return end
26
27     if orientation == "west" then
28         -- Layout with fixed number of vertical columns (read from nmaster).
29         -- New windows align from left to right. When a row is full, a now
30         -- one above it is created. Like this:
31
32         --        (1)                (2)                (3)
33         --   +---+---+---+      +---+---+---+      +---+---+---+
34         --   |   |   |   |      |   |   |   |      |   |   |   |
35         --   | 1 |   |   |  ->  | 2 | 1 |   |  ->  | 3 | 2 | 1 |  ->
36         --   |   |   |   |      |   |   |   |      |   |   |   |
37         --   +---+---+---+      +---+---+---+      +---+---+---+
38
39         --        (4)                (5)                (6)
40         --   +---+---+---+      +---+---+---+      +---+---+---+
41         --   | 4 |   |   |      | 5 | 4 |   |      | 6 | 5 | 4 |
42         --   +---+---+---+  ->  +---+---+---+  ->  +---+---+---+
43         --   | 3 | 2 | 1 |      | 3 | 2 | 1 |      | 3 | 2 | 1 |
44         --   +---+---+---+      +---+---+---+      +---+---+---+
45
46         -- How many vertical columns? Read from nmaster on the tag.
47         local num_x = tonumber(termfair.nmaster) or t.master_count
48         local ncol  = tonumber(termfair.ncol) or t.column_count
49
50         if num_x <= 2 then num_x = 2 end
51         if ncol  <= 1 then ncol  = 1 end
52         local width = math.floor(wa.width/num_x)
53
54         local num_y     = math.max(math.ceil(#cls / num_x), ncol)
55         local height    = math.floor(wa.height/num_y)
56         local cur_num_x = num_x
57         local at_x      = 0
58         local at_y      = 0
59
60         local remaining_clients = #cls
61
62         -- We start the first row. Left-align by limiting the number of
63         -- available slots.
64         if remaining_clients < num_x then
65             cur_num_x = remaining_clients
66         end
67
68         -- Iterate in reversed order.
69         for i = #cls,1,-1 do
70             -- Get x and y position.
71             local c = cls[i]
72             local this_x = cur_num_x - at_x - 1
73             local this_y = num_y - at_y - 1
74
75             -- Calculate geometry.
76             local g = {}
77             if this_x == (num_x - 1) then
78                 g.width = wa.width - (num_x - 1)*width
79             else
80                 g.width = width
81             end
82
83             if this_y == (num_y - 1) then
84                 g.height = wa.height - (num_y - 1)*height
85             else
86                 g.height = height
87             end
88
89             g.x = wa.x + this_x*width
90             g.y = wa.y + this_y*height
91
92             if g.width  < 1 then g.width  = 1 end
93             if g.height < 1 then g.height = 1 end
94
95             p.geometries[c] = g
96
97             remaining_clients = remaining_clients - 1
98
99             -- Next grid position.
100             at_x = at_x + 1
101             if at_x == num_x then
102                 -- Row full, create a new one above it.
103                 at_x = 0
104                 at_y = at_y + 1
105
106                 -- We start a new row. Left-align.
107                 if remaining_clients < num_x then
108                     cur_num_x = remaining_clients
109                 end
110             end
111         end
112     elseif orientation == "center" then
113         -- Layout with fixed number of vertical columns (read from nmaster).
114         -- Cols are centerded until there is nmaster columns, then windows
115         -- are stacked in the slave columns, with at most ncol clients per
116         -- column if possible.
117
118         -- with nmaster=3 and ncol=1 you'll have
119         --        (1)                (2)                (3)
120         --   +---+---+---+      +-+---+---+-+      +---+---+---+
121         --   |   |   |   |      | |   |   | |      |   |   |   |
122         --   |   | 1 |   |  ->  | | 1 | 2 | | ->   | 1 | 2 | 3 |  ->
123         --   |   |   |   |      | |   |   | |      |   |   |   |
124         --   +---+---+---+      +-+---+---+-+      +---+---+---+
125
126         --        (4)                (5)
127         --   +---+---+---+      +---+---+---+
128         --   |   |   | 3 |      |   | 2 | 4 |
129         --   + 1 + 2 +---+  ->  + 1 +---+---+
130         --   |   |   | 4 |      |   | 3 | 5 |
131         --   +---+---+---+      +---+---+---+
132
133         -- How many vertical columns? Read from nmaster on the tag.
134         local num_x = tonumber(termfair.center.nmaster) or t.master_count
135         local ncol  = tonumber(termfair.center.ncol) or t.column_count
136
137         if num_x <= 2 then num_x = 2 end
138         if ncol  <= 1 then ncol  = 1 end
139
140         local width = math.floor(wa.width / num_x)
141
142         if #cls < num_x then
143             -- Less clients than the number of columns, let's center it!
144             local offset_x = wa.x + (wa.width - #cls*width) / 2
145             for i = 1, #cls do
146                 local g = { y = wa.y }
147                 g.width  = width
148                 g.height = wa.height
149                 if g.width < 1 then g.width = 1 end
150                 if g.height < 1 then g.height = 1 end
151                 g.x = offset_x + (i - 1) * width
152                 p.geometries[cls[i]] = g
153             end
154         else
155             -- More clients than the number of columns, let's arrange it!
156             -- Master client deserves a special treatement
157             local g = {}
158             g.width = wa.width - (num_x - 1)*width
159             g.height = wa.height
160             if g.width < 1 then g.width = 1 end
161             if g.height < 1 then g.height = 1 end
162             g.x = wa.x
163             g.y = wa.y
164             p.geometries[cls[1]] = g
165
166             -- Treat the other clients
167
168             -- Compute distribution of clients among columns
169             local num_y = {}
170             local remaining_clients = #cls-1
171             local ncol_min = math.ceil(remaining_clients/(num_x-1))
172
173             if ncol >= ncol_min then
174                 for i = (num_x-1), 1, -1 do
175                     if (remaining_clients-i+1) < ncol then
176                         num_y[i] = remaining_clients-i + 1
177                     else
178                         num_y[i] = ncol
179                     end
180                     remaining_clients = remaining_clients - num_y[i]
181                 end
182             else
183                 local rem = remaining_clients % (num_x-1)
184                 if rem == 0 then
185                     for i = 1, num_x-1 do
186                         num_y[i] = ncol_min
187                     end
188                 else
189                     for i = 1, num_x-1 do
190                         num_y[i] = ncol_min - 1
191                     end
192                     for i = 0, rem-1 do
193                         num_y[num_x-1-i] = num_y[num_x-1-i] + 1
194                     end
195                 end
196             end
197
198             -- Compute geometry of the other clients
199             local nclient = 2 -- we start with the 2nd client
200             local wx = g.x + g.width
201             for i = 1, (num_x-1) do
202                 local height = math.floor(wa.height / num_y[i])
203                 local wy = wa.y
204                 for j = 0, (num_y[i]-2) do
205                     local g = {}
206                     g.x = wx
207                     g.y = wy
208                     g.height = height
209                     g.width = width
210                     if g.width < 1 then g.width = 1 end
211                     if g.height < 1 then g.height = 1 end
212                     p.geometries[cls[nclient]] = g
213                     nclient = nclient + 1
214                     wy = wy + height
215                 end
216                 local g = {}
217                 g.x = wx
218                 g.y = wy
219                 g.height = wa.height - (num_y[i] - 1)*height
220                 g.width = width
221                 if g.width < 1 then g.width = 1 end
222                 if g.height < 1 then g.height = 1 end
223                 p.geometries[cls[nclient]] = g
224                 nclient = nclient + 1
225                 wx = wx + width
226             end
227         end
228     end
229 end
230
231 function termfair.center.arrange(p)
232     return do_fair(p, "center")
233 end
234
235 function termfair.arrange(p)
236     return do_fair(p, "west")
237 end
238
239 return termfair