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

bd365a893f40cdbf70862649b14347a334449461
[etc/awesome.git] / layout / uselesstile.lua
1
2 --[[
3
4      Licensed under GNU General Public License v2
5       * (c) 2014       projektile, worron
6       * (c) 2013       Luke Bonham
7       * (c) 2009       Donald Ephraim Curtis
8       * (c) 2008       Julien Danjolu
9
10 --]]
11
12 local tag       = require("awful.tag")
13 local beautiful = require("beautiful")
14 local ipairs    = ipairs
15 local math      = { floor = math.floor,
16                     ceil  = math.ceil,
17                     max   = math.max,
18                     min   = math.min }
19 local tonumber  = tonumber
20
21 local uselesstile = {}
22
23 -- Transformation functions
24 local function flip(canvas, geometry)
25     return {
26         -- vertical only
27         x = 2 * canvas.x + canvas.width - geometry.x - geometry.width,
28         y = geometry.y,
29         width = geometry.width,
30         height = geometry.height
31     }
32 end
33
34 local function swap(geometry)
35     return { x = geometry.y, y = geometry.x, width = geometry.height, height = geometry.width }
36 end
37
38 -- Find geometry for secondary windows column
39 local function cut_column(wa, n, index)
40     local width = wa.width / n
41     local area = { x = wa.x + (index - 1) * width, y = wa.y, width = width, height = wa.height }
42
43     return area
44 end
45
46 -- Find geometry for certain window in column
47 local function cut_row(wa, factor, index, used)
48     local height = wa.height * factor.window[index] / factor.total
49     local area = { x = wa.x, y = wa.y + used, width = wa.width, height = height }
50
51     return area
52 end
53
54 -- Client geometry correction depending on useless gap and window border
55 local function size_correction(c, geometry, useless_gap)
56     geometry.width  = math.max(geometry.width  - 2 * c.border_width - useless_gap, 1)
57     geometry.height = math.max(geometry.height - 2 * c.border_width - useless_gap, 1)
58     geometry.x = geometry.x + useless_gap / 2
59     geometry.y = geometry.y + useless_gap / 2
60 end
61
62 -- Check size factor for group of clients and calculate total
63 local function calc_factor(n, winfactors)
64     local factor = { window = winfactors, total = 0, min = 1 }
65
66     for i = 1, n do
67         if not factor.window[i] then
68             factor.window[i] = factor.min
69         else
70             factor.min = math.min(factor.window[i], factor.min)
71             if factor.window[i] < 0.05 then factor.window[i] = 0.05 end
72         end
73         factor.total = factor.total + factor.window[i]
74     end
75
76     return factor
77 end
78
79 -- Tile group of clients in given area
80 -- @canvas need for proper transformation only
81 -- @winfactors table with clients size factors
82 local function tile_column(canvas, area, list, useless_gap, transformation, winfactors)
83     local used = 0
84     local factor = calc_factor(#list, winfactors)
85
86     for i, c in ipairs(list) do
87         local g = cut_row(area, factor, i, used)
88         used = used + g.height
89
90         -- swap workarea dimensions
91         if transformation.flip then g = flip(canvas, g) end
92         if transformation.swap then g = swap(g) end
93
94         -- useless gap and border correction
95         size_correction(c, g, useless_gap)
96
97         c:geometry(g)
98     end
99 end
100
101 --Main tile function
102 local function tile(p, orientation)
103
104     -- Theme vars
105     local useless_gap = beautiful.useless_gap_width or 0
106     local global_border = beautiful.global_border_width or 0
107
108     -- Aliases
109     local wa = p.workarea
110     local cls = p.clients
111     local t = tag.selected(p.screen)
112
113     -- Nothing to tile here
114     if #cls == 0 then return end
115
116     -- Get tag prop
117     local nmaster = math.min(tag.getnmaster(t), #cls)
118     local mwfact = tag.getmwfact(t)
119
120     if nmaster == 0 then
121         mwfact = 0
122     elseif nmaster == #cls then
123         mwfact = 1
124     end
125
126     -- clients size factor
127     local data = tag.getdata(t).windowfact
128
129     if not data then
130         data = {}
131         tag.getdata(t).windowfact = data
132     end
133
134     -- Workarea size correction depending on useless gap and global border
135     wa.height = wa.height - 2 * global_border - useless_gap
136     wa.width  = wa.width -  2 * global_border - useless_gap
137     wa.x = wa.x + useless_gap / 2 + global_border
138     wa.y = wa.y + useless_gap / 2 + global_border
139
140     -- Find which transformation we need for given orientation
141     local transformation = {
142         swap = orientation == 'top' or orientation == 'bottom',
143         flip = orientation == 'left' or orientation == 'top'
144     }
145
146     -- Swap workarea dimensions if orientation vertical
147     if transformation.swap then wa = swap(wa) end
148
149     -- Split master and other windows
150     local cls_master, cls_other = {}, {}
151
152     for i, c in ipairs(cls) do
153         if i <= nmaster then
154             table.insert(cls_master, c)
155         else
156             table.insert(cls_other, c)
157         end
158     end
159
160     -- Tile master windows
161     local master_area = {
162         x = wa.x,
163         y = wa.y,
164         width  = nmaster > 0 and wa.width * mwfact or 0,
165         height = wa.height
166     }
167
168     if not data[0] then data[0] = {} end
169     tile_column(wa, master_area, cls_master, useless_gap, transformation, data[0])
170
171     -- Tile other windows
172     local other_area = {
173         x = wa.x + master_area.width,
174         y = wa.y,
175         width  = wa.width - master_area.width,
176         height = wa.height
177     }
178
179     -- get column number for other windows
180     local ncol = math.min(tag.getncol(t), #cls_other)
181
182     -- split other windows to column groups
183     local last_small_column = ncol - #cls_other % ncol
184     local rows_min = math.floor(#cls_other / ncol)
185
186     local client_index = 1
187     for i = 1, ncol do
188         local position = transformation.flip and ncol - i + 1 or i
189         local rows = i <= last_small_column and rows_min or rows_min + 1
190         local column = {}
191
192         for j = 1, rows do
193             table.insert(column, cls_other[client_index])
194             client_index = client_index + 1
195         end
196
197         -- and tile
198         local column_area = cut_column(other_area, ncol, position)
199
200         if not data[i] then data[i] = {} end
201         tile_column(wa, column_area, column, useless_gap, transformation, data[i])
202     end
203 end
204
205 -- Layout constructor
206 local function construct_layout(name, orientation)
207     return {
208         name = name,
209         -- @p screen number to tile
210         arrange = function(p) return tile(p, orientation) end
211     }
212 end
213
214 -- Build layouts with different tile direction
215 uselesstile.right  = construct_layout("uselesstile", "right")
216 uselesstile.left   = construct_layout("uselesstileleft", "left")
217 uselesstile.bottom = construct_layout("uselesstilebottom", "bottom")
218 uselesstile.top    = construct_layout("uselesstiletop", "top")
219
220 -- Module aliase
221 uselesstile.arrange = uselesstile.right.arrange
222 uselesstile.name = uselesstile.right.name
223
224 return uselesstile