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

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