]> 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:

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