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

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