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

Change io.popen to io.open so we don't execute image files.
[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             gap_factor = (useless_gap / 100) * 2
92
93             if geom[y] == wa[y] then
94                 top = true
95             end
96
97             if geom[x] == 0 or geom[x] == wa[x] then
98                 left = true
99             end
100
101             if top then
102                 geom[height] = geom[height] - (2 + gap_factor) * useless_gap
103                 geom[y] = geom[y] + useless_gap
104             else
105                 geom[height] = geom[height] - (1 + gap_factor) * useless_gap 
106             end
107
108             if left then
109                 geom[width] = geom[width] - (2 + gap_factor) * useless_gap
110                 geom[x] = geom[x] + useless_gap
111             else
112                 geom[width] = geom[width] - (1 + gap_factor) * useless_gap
113             end
114         end
115         -- End of useless gap.
116
117         geom = cls[c]:geometry(geom)
118     end
119
120     return used_size
121 end
122
123 local function tile(param, orientation)
124     local t = tag.selected(param.screen)
125     orientation = orientation or "right"
126
127     -- this handles are different orientations
128     local height = "height"
129     local width = "width"
130     local x = "x"
131     local y = "y"
132     if orientation == "top" or orientation == "bottom" then
133         height = "width"
134         width = "height"
135         x = "y"
136         y = "x"
137     end
138
139     local cls = param.clients
140     local nmaster = math.min(tag.getnmaster(t), #cls)
141     local nother = math.max(#cls - nmaster,0)
142
143     local mwfact = tag.getmwfact(t)
144     local wa = param.workarea
145     local ncol = tag.getncol(t)
146
147     local data = tag.getdata(t).windowfact
148
149     if not data then
150         data = {}
151         tag.getdata(t).windowfact = data
152     end
153
154     local coord = wa[x]
155     local place_master = true
156     if orientation == "left" or orientation == "top" then
157         -- if we are on the left or top we need to render the other windows first
158         place_master = false
159     end
160
161     -- this was easier than writing functions because there is a lot of data we need
162     for d = 1,2 do
163         if place_master and nmaster > 0 then
164             local size = wa[width]
165             if nother > 0 then
166                 size = math.min(wa[width] * mwfact, wa[width] - (coord - wa[x]))
167             end
168             if not data[0] then
169                 data[0] = {}
170             end
171             coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size})
172         end
173
174         if not place_master and nother > 0 then
175             local last = nmaster
176
177             -- we have to modify the work area size to consider left and top views
178             local wasize = wa[width]
179             if nmaster > 0 and (orientation == "left" or orientation == "top") then
180                 wasize = wa[width] - wa[width]*mwfact
181             end
182             for i = 1,ncol do
183                 -- Try to get equal width among remaining columns
184                 local size = math.min( (wasize - (coord - wa[x])) / (ncol - i + 1) )
185                 local first = last + 1
186                 last = last + math.floor((#cls - last)/(ncol - i + 1))
187                 -- tile the column and update our current x coordinate
188                 if not data[i] then
189                     data[i] = {}
190                 end
191                 coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size })
192             end
193         end
194         place_master = not place_master
195     end
196
197 end
198
199 uselesstile.right = {}
200 uselesstile.right.name = "uselesstile"
201 uselesstile.right.arrange = tile
202
203 --- The main tile algo, on left.
204 -- @param screen The screen number to tile.
205 uselesstile.left = {}
206 uselesstile.left.name = "uselesstileleft"
207 function uselesstile.left.arrange(p)
208     return tile(p, "left")
209 end
210
211 --- The main tile algo, on bottom.
212 -- @param screen The screen number to tile.
213 uselesstile.bottom = {}
214 uselesstile.bottom.name = "uselesstilebottom"
215 function uselesstile.bottom.arrange(p)
216     return tile(p, "bottom")
217 end
218
219 --- The main tile algo, on top.
220 -- @param screen The screen number to tile.
221 uselesstile.top = {}
222 uselesstile.top.name = "uselesstiletop"
223 function uselesstile.top.arrange(p)
224     return tile(p, "top")
225 end
226
227 uselesstile.arrange = uselesstile.right.arrange
228 uselesstile.name = uselesstile.right.name
229
230 return uselesstile