massive update, probably broken
[dotfiles/.git] / .config / awesome / lain / layout / centerwork.lua
1 --[[
2
3      Licensed under GNU General Public License v2
4       * (c) 2018,      Eugene Pakhomov
5       * (c) 2016,      Henrik Antonsson
6       * (c) 2015,      Joerg Jaspert
7       * (c) 2014,      projektile
8       * (c) 2013,      Luca CPZ
9       * (c) 2010-2012, Peter Hofmann
10
11 --]]
12
13 local floor, max, mouse, mousegrabber, screen = math.floor, math.max, mouse, mousegrabber, screen
14
15 local centerwork = {
16     name       = "centerwork",
17     horizontal = { name = "centerworkh" }
18 }
19
20 local function arrange(p, layout)
21     local t   = p.tag or screen[p.screen].selected_tag
22     local wa  = p.workarea
23     local cls = p.clients
24
25     if #cls == 0 then return end
26
27     local c, g = cls[1], {}
28
29     -- Main column, fixed width and height
30     local mwfact          = t.master_width_factor
31     local mainhei         = floor(wa.height * mwfact)
32     local mainwid         = floor(wa.width * mwfact)
33     local slavewid        = wa.width - mainwid
34     local slaveLwid       = floor(slavewid / 2)
35     local slaveRwid       = slavewid - slaveLwid
36     local slavehei        = wa.height - mainhei
37     local slaveThei       = floor(slavehei / 2)
38     local slaveBhei       = slavehei - slaveThei
39     local nbrFirstSlaves  = floor(#cls / 2)
40     local nbrSecondSlaves = floor((#cls - 1) / 2)
41
42     local slaveFirstDim, slaveSecondDim = 0, 0
43
44     if layout.name == "centerwork" then -- vertical
45         if nbrFirstSlaves  > 0 then slaveFirstDim  = floor(wa.height / nbrFirstSlaves) end
46         if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.height / nbrSecondSlaves) end
47
48         g.height = wa.height
49         g.width  = mainwid
50
51         g.x = wa.x + slaveLwid
52         g.y = wa.y
53     else -- horizontal
54         if nbrFirstSlaves  > 0 then slaveFirstDim  = floor(wa.width / nbrFirstSlaves) end
55         if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.width / nbrSecondSlaves) end
56
57         g.height  = mainhei
58         g.width = wa.width
59
60         g.x = wa.x
61         g.y = wa.y + slaveThei
62     end
63
64     g.width  = max(g.width, 1)
65     g.height = max(g.height, 1)
66
67     p.geometries[c] = g
68
69     -- Auxiliary clients
70     if #cls <= 1 then return end
71     for i = 2, #cls do
72         local c, g = cls[i], {}
73         local idxChecker, dimToAssign
74
75         local rowIndex = floor(i/2)
76
77         if layout.name == "centerwork" then
78             if i % 2 == 0 then -- left slave
79                 g.x     = wa.x
80                 g.y     = wa.y + (rowIndex - 1) * slaveFirstDim
81                 g.width = slaveLwid
82
83                 idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim
84             else -- right slave
85                 g.x     = wa.x + slaveLwid + mainwid
86                 g.y     = wa.y + (rowIndex - 1) * slaveSecondDim
87                 g.width = slaveRwid
88
89                 idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim
90             end
91
92             -- if last slave in row, use remaining space for it
93             if rowIndex == idxChecker then
94                 g.height = wa.y + wa.height - g.y
95             else
96                 g.height = dimToAssign
97             end
98         else
99             if i % 2 == 0 then -- top slave
100                 g.x      = wa.x + (rowIndex - 1) * slaveFirstDim
101                 g.y      = wa.y
102                 g.height = slaveThei
103
104                 idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim
105             else -- bottom slave
106                 g.x      = wa.x + (rowIndex - 1) * slaveSecondDim
107                 g.y      = wa.y + slaveThei + mainhei
108                 g.height = slaveBhei
109
110                 idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim
111             end
112
113             -- if last slave in row, use remaining space for it
114             if rowIndex == idxChecker then
115                 g.width = wa.x + wa.width - g.x
116             else
117                 g.width = dimToAssign
118             end
119         end
120
121         g.width  = max(g.width, 1)
122         g.height = max(g.height, 1)
123
124         p.geometries[c] = g
125     end
126 end
127
128 local function mouse_resize_handler(c, corner, x, y, orientation)
129     local wa     = c.screen.workarea
130     local mwfact = c.screen.selected_tag.master_width_factor
131     local g      = c:geometry()
132     local offset = 0
133     local cursor = "cross"
134
135     local corner_coords
136
137     if orientation == 'vertical' then
138         if g.height + 15 >= wa.height then
139             offset = g.height * .5
140             cursor = "sb_h_double_arrow"
141         elseif not (g.y + g.height + 15 > wa.y + wa.height) then
142             offset = g.height
143         end
144         corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset }
145     else
146         if g.width + 15 >= wa.width then
147             offset = g.width * .5
148             cursor = "sb_v_double_arrow"
149         elseif not (g.x + g.width + 15 > wa.x + wa.width) then
150             offset = g.width
151         end
152         corner_coords = { y = wa.y + wa.height * (1 - mwfact) / 2, x = g.x + offset }
153     end
154
155     mouse.coords(corner_coords)
156
157     local prev_coords = {}
158
159     mousegrabber.run(function(_mouse)
160         if not c.valid then return false end
161         for _, v in ipairs(_mouse.buttons) do
162             if v then
163                 prev_coords = { x = _mouse.x, y = _mouse.y }
164                 local new_mwfact
165                 if orientation == 'vertical' then
166                     new_mwfact = 1 - (_mouse.x - wa.x) / wa.width * 2
167                 else
168                     new_mwfact = 1 - (_mouse.y - wa.y) / wa.height * 2
169                 end
170                 c.screen.selected_tag.master_width_factor = math.min(math.max(new_mwfact, 0.01), 0.99)
171                 return true
172             end
173         end
174         return prev_coords.x == _mouse.x and prev_coords.y == _mouse.y
175     end, cursor)
176 end
177
178 function centerwork.arrange(p)
179     return arrange(p, centerwork)
180 end
181
182 function centerwork.horizontal.arrange(p)
183     return arrange(p, centerwork.horizontal)
184 end
185
186 function centerwork.mouse_resize_handler(c, corner, x, y)
187     return mouse_resize_handler(c, corner, x, y, 'vertical')
188 end
189
190 function centerwork.horizontal.mouse_resize_handler(c, corner, x, y)
191     return mouse_resize_handler(c, corner, x, y, 'horizontal')
192 end
193
194 return centerwork