]> 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 #75 from osleg/master
[etc/awesome.git] / layout / uselesstile.lua
1
2 --[[
3                                                   
4      Licensed under GNU General Public License v2 
5       * (c) 2014       projektile                 
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                     max   = math.max,
17                     min   = math.min }
18 local tonumber  = tonumber
19
20 local uselesstile = {}
21
22 local function tile_group(cls, wa, orientation, fact, group)
23     -- A useless gap (like the dwm patch) can be defined with
24     -- beautiful.useless_gap_width .
25     local useless_gap = tonumber(beautiful.useless_gap_width) or 0
26     if useless_gap < 0 then useless_gap = 0 end
27
28     -- A global border can be defined with
29     -- beautiful.global_border_width
30     local global_border = tonumber(beautiful.global_border_width) or 0
31     if global_border < 0 then global_border = 0 end
32
33     -- Themes border width requires an offset
34     local bw = tonumber(beautiful.border_width) or 0
35
36     -- get our orientation right
37     local height = "height"
38     local width = "width"
39     local x = "x"
40     local y = "y"
41     if orientation == "top" or orientation == "bottom" then
42         height = "width"
43         width = "height"
44         x = "y"
45         y = "x"
46     end
47
48     -- make this more generic (not just width)
49     --if for top
50     available = wa[width] - (group.coord - wa[x]) -- it's truly not here
51
52     -- find our total values
53     local total_fact = 0
54     local min_fact = 1
55     local size = group.size
56     for c = group.first,group.last do
57         -- determine the width/height based on the size_hint
58         local i = c - group.first +1
59         local size_hints = cls[c].size_hints
60         local size_hint = size_hints["min_"..width] or size_hints["base_"..width] or 0
61         size_hint = size_hint + cls[c].border_width*2
62         size = math.max(size_hint, size)
63
64         -- calculate the height
65         if not fact[i] then
66             fact[i] = min_fact
67         else
68             min_fact = math.min(fact[i],min_fact)
69         end
70         total_fact = total_fact + fact[i]
71     end
72     size = math.min(size, (available - global_border))
73     local coord = wa[y]
74     local geom = {}
75     local used_size = 0
76     local unused = wa[height] - (global_border * 2)
77     local stat_coord = wa[x]
78     --stat_coord = size
79     for c = group.first,group.last do
80         local i = c - group.first +1
81         geom[width] = size - global_border - (bw * 2)
82         geom[height] = math.floor(unused * fact[i] / total_fact) - (bw * 2)
83         geom[x] = group.coord + global_border + (useless_gap / 2)
84         geom[y] = coord + global_border + (useless_gap / 2)
85
86         coord = coord + geom[height]
87         unused = unused - geom[height]
88         total_fact = total_fact - fact[i]
89         used_size = math.max(used_size, geom[width])
90
91         -- Useless gap
92         if useless_gap > 0
93         then
94             -- Top and left clients are shrinked by two steps and
95             -- get moved away from the border. Other clients just
96             -- get shrinked in one direction.
97
98             top = false
99             left = false
100
101             if geom[y] == wa[y] then
102                 top = true
103             end
104
105             if geom[x] == 0 or geom[x] == wa[x] then
106                 left = true
107             end
108
109             if top then
110                 geom[height] = geom[height] - (2 * useless_gap)
111                 geom[y] = geom[y] + useless_gap
112             else
113                 geom[height] = geom[height] - useless_gap
114             end
115
116             if left then
117                 geom[width] = geom[width] - (2 * useless_gap)
118                 geom[x] = geom[x] + useless_gap
119             else
120                 geom[width] = geom[width] - useless_gap
121             end
122         end
123         -- End of useless gap.
124
125         geom = cls[c]:geometry(geom)
126     end
127
128     return used_size
129 end
130
131 local function tile(param, orientation)
132     local t = tag.selected(param.screen)
133     orientation = orientation or "right"
134
135     -- this handles are different orientations
136     local height = "height"
137     local width = "width"
138     local x = "x"
139     local y = "y"
140     if orientation == "top" or orientation == "bottom" then
141         height = "width"
142         width = "height"
143         x = "y"
144         y = "x"
145     end
146
147     local cls = param.clients
148     local nmaster = math.min(tag.getnmaster(t), #cls)
149     local nother = math.max(#cls - nmaster,0)
150
151     local mwfact = tag.getmwfact(t)
152     local wa = param.workarea
153     local ncol = tag.getncol(t)
154
155     local data = tag.getdata(t).windowfact
156
157     if not data then
158         data = {}
159         tag.getdata(t).windowfact = data
160     end
161
162     local coord = wa[x]
163     local place_master = true
164     if orientation == "left" or orientation == "top" then
165         -- if we are on the left or top we need to render the other windows first
166         place_master = false
167     end
168
169     -- this was easier than writing functions because there is a lot of data we need
170     for d = 1,2 do
171         if place_master and nmaster > 0 then
172             local size = wa[width]
173             if nother > 0 then
174                 size = math.min(wa[width] * mwfact, wa[width] - (coord - wa[x]))
175             end
176             if not data[0] then
177                 data[0] = {}
178             end
179             coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size})
180         end
181
182         if not place_master and nother > 0 then
183             local last = nmaster
184
185             -- we have to modify the work area size to consider left and top views
186             local wasize = wa[width]
187             if nmaster > 0 and (orientation == "left" or orientation == "top") then
188                 wasize = wa[width] - wa[width]*mwfact
189             end
190             for i = 1,ncol do
191                 -- Try to get equal width among remaining columns
192                 local size = math.min((wasize - (coord - wa[x]))  / (ncol - i + 1)) --+ (global_border/(ncol))/(ncol+i^2)
193                 local first = last + 1
194                 last = last + math.floor((#cls - last)/(ncol - i + 1))
195                 -- tile the column and update our current x coordinate
196                 if not data[i] then
197                     data[i] = {}
198                 end
199                 coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size })
200             end
201         end
202         place_master = not place_master
203     end
204
205 end
206
207 uselesstile.right = {}
208 uselesstile.right.name = "uselesstile"
209 uselesstile.right.arrange = tile
210
211 --- The main tile algo, on left.
212 -- @param screen The screen number to tile.
213 uselesstile.left = {}
214 uselesstile.left.name = "uselesstileleft"
215 function uselesstile.left.arrange(p)
216     return tile(p, "left")
217 end
218
219 --- The main tile algo, on bottom.
220 -- @param screen The screen number to tile.
221 uselesstile.bottom = {}
222 uselesstile.bottom.name = "uselesstilebottom"
223 function uselesstile.bottom.arrange(p)
224     return tile(p, "bottom")
225 end
226
227 --- The main tile algo, on top.
228 -- @param screen The screen number to tile.
229 uselesstile.top = {}
230 uselesstile.top.name = "uselesstiletop"
231 function uselesstile.top.arrange(p)
232     return tile(p, "top")
233 end
234
235 uselesstile.arrange = uselesstile.right.arrange
236 uselesstile.name = uselesstile.right.name
237
238 return uselesstile
239