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

Merge pull request #90 from jepugs/master
[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 column/row tiling
39 local function cut_area(wa, total, index, is_horizontal)
40     local wa = is_horizontal and swap(wa) or wa
41     local height = wa.height / total
42
43     local area = {
44         x = wa.x,
45         y = wa.y + (index - 1) * height,
46         width = wa.width,
47         height = height
48     }
49
50     if is_horizontal then area = swap(area) end
51
52     return area
53 end
54
55 -- Client geometry correction depending on useless gap and window border
56 local function size_correction(c, geometry, useless_gap)
57     geometry.width  = math.max(geometry.width  - 2 * c.border_width - useless_gap, 1)
58     geometry.height = math.max(geometry.height - 2 * c.border_width - useless_gap, 1)
59     geometry.x = geometry.x + useless_gap / 2
60     geometry.y = geometry.y + useless_gap / 2
61 end
62
63 -- Tile group of clients in given area
64 -- @canvas need for proper transformation only
65 local function tile_column(canvas, area, list, useless_gap, transformation)
66     for i, c in ipairs(list) do
67         local g = cut_area(area, #list, i)
68
69         -- swap workarea dimensions
70         if transformation.flip then g = flip(canvas, g) end
71         if transformation.swap then g = swap(g) end
72
73         -- useless gap and border correction
74         size_correction(c, g, useless_gap)
75
76         c:geometry(g)
77     end
78 end
79
80 --Main tile function
81 local function tile(p, orientation)
82
83     -- Theme vars
84     local useless_gap = beautiful.useless_gap_width or 0
85     local global_border = beautiful.global_border_width or 0
86
87     -- Aliases
88     local wa = p.workarea
89     local cls = p.clients
90     local t = tag.selected(p.screen)
91
92     -- Nothing to tile here
93     if #cls == 0 then return end
94
95     -- Get tag prop
96     local nmaster = math.min(tag.getnmaster(t), #cls)
97     local mwfact = tag.getmwfact(t)
98
99     if nmaster == 0 then
100         mwfact = 0
101     elseif nmaster == #cls then
102         mwfact = 1
103     end
104
105     -- Workarea size correction depending on useless gap and global border
106     wa.height = wa.height - 2 * global_border - useless_gap
107     wa.width  = wa.width -  2 * global_border - useless_gap
108     wa.x = wa.x + useless_gap / 2 + global_border
109     wa.y = wa.y + useless_gap / 2 + global_border
110
111     -- Find which transformation we need for given orientation
112     local transformation = {
113         swap = orientation == 'top' or orientation == 'bottom',
114         flip = orientation == 'left' or orientation == 'top'
115     }
116
117     -- Swap workarea dimensions if orientation vertical
118     if transformation.swap then wa = swap(wa) end
119
120     -- Split master and other windows
121     local cls_master, cls_other = {}, {}
122
123     for i, c in ipairs(cls) do
124         if i <= nmaster then
125             table.insert(cls_master, c)
126         else
127             table.insert(cls_other, c)
128         end
129     end
130
131     -- Tile master windows
132     local master_area = {
133         x = wa.x,
134         y = wa.y,
135         width  = nmaster > 0 and wa.width * mwfact or 0,
136         height = wa.height
137     }
138
139     tile_column(wa, master_area, cls_master, useless_gap, transformation)
140
141     -- Tile other windows
142     local other_area = {
143         x = wa.x + master_area.width,
144         y = wa.y,
145         width  = wa.width - master_area.width,
146         height = wa.height
147     }
148
149     -- get column number for other windows
150     local ncol = math.min(tag.getncol(t), #cls_other)
151
152     -- split other windows to column groups
153     local last_small_column = ncol - #cls_other % ncol
154     local rows_min = math.floor(#cls_other / ncol)
155
156     local client_index = 1
157     for i = 1, ncol do
158         local position = transformation.flip and ncol - i + 1 or i
159         local rows = i <= last_small_column and rows_min or rows_min + 1
160         local column = {}
161
162         for j = 1, rows do
163             table.insert(column, cls_other[client_index])
164             client_index = client_index + 1
165         end
166
167                 -- and tile
168                 local column_area = cut_area(other_area, ncol, position, true)
169         tile_column(wa, column_area, column, useless_gap, transformation)
170     end
171 end
172
173 -- Layout constructor
174 local function construct_layout(name, orientation)
175     return {
176         name = name,
177         -- @p screen number to tile
178         arrange = function(p) return tile(p, orientation) end
179     }
180 end
181
182 -- Build layouts with different tile direction
183 uselesstile.right  = construct_layout("uselesstile", "right")
184 uselesstile.left   = construct_layout("uselesstileleft", "left")
185 uselesstile.bottom = construct_layout("uselesstilebottom", "bottom")
186 uselesstile.top    = construct_layout("uselesstiletop", "top")
187
188 -- Module aliase
189 uselesstile.arrange = uselesstile.right.arrange
190 uselesstile.name = uselesstile.right.name
191
192 return uselesstile