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

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