123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- --[[
- Licensed under GNU General Public License v2
- * (c) 2018, Eugene Pakhomov
- * (c) 2016, Henrik Antonsson
- * (c) 2015, Joerg Jaspert
- * (c) 2014, projektile
- * (c) 2013, Luca CPZ
- * (c) 2010-2012, Peter Hofmann
- --]]
- local floor, max, mouse, mousegrabber, screen = math.floor, math.max, mouse, mousegrabber, screen
- local centerwork = {
- name = "centerwork",
- horizontal = { name = "centerworkh" }
- }
- local function arrange(p, layout)
- local t = p.tag or screen[p.screen].selected_tag
- local wa = p.workarea
- local cls = p.clients
- if #cls == 0 then return end
- local g = {}
- -- Main column, fixed width and height
- local mwfact = t.master_width_factor
- local mainhei = floor(wa.height * mwfact)
- local mainwid = floor(wa.width * mwfact)
- local slavewid = wa.width - mainwid
- local slaveLwid = floor(slavewid / 2)
- local slaveRwid = slavewid - slaveLwid
- local slavehei = wa.height - mainhei
- local slaveThei = floor(slavehei / 2)
- local slaveBhei = slavehei - slaveThei
- local nbrFirstSlaves = floor(#cls / 2)
- local nbrSecondSlaves = floor((#cls - 1) / 2)
- local slaveFirstDim, slaveSecondDim = 0, 0
- if layout.name == "centerwork" then -- vertical
- if nbrFirstSlaves > 0 then slaveFirstDim = floor(wa.height / nbrFirstSlaves) end
- if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.height / nbrSecondSlaves) end
- g.height = wa.height
- g.width = mainwid
- g.x = wa.x + slaveLwid
- g.y = wa.y
- else -- horizontal
- if nbrFirstSlaves > 0 then slaveFirstDim = floor(wa.width / nbrFirstSlaves) end
- if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.width / nbrSecondSlaves) end
- g.height = mainhei
- g.width = wa.width
- g.x = wa.x
- g.y = wa.y + slaveThei
- end
- g.width = max(g.width, 1)
- g.height = max(g.height, 1)
- p.geometries[cls[1]] = g
- -- Auxiliary clients
- if #cls <= 1 then return end
- for i = 2, #cls do
- g = {}
- local idxChecker, dimToAssign
- local rowIndex = floor(i/2)
- if layout.name == "centerwork" then
- if i % 2 == 0 then -- left slave
- g.x = wa.x
- g.y = wa.y + (rowIndex - 1) * slaveFirstDim
- g.width = slaveLwid
- idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim
- else -- right slave
- g.x = wa.x + slaveLwid + mainwid
- g.y = wa.y + (rowIndex - 1) * slaveSecondDim
- g.width = slaveRwid
- idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim
- end
- -- if last slave in row, use remaining space for it
- if rowIndex == idxChecker then
- g.height = wa.y + wa.height - g.y
- else
- g.height = dimToAssign
- end
- else
- if i % 2 == 0 then -- top slave
- g.x = wa.x + (rowIndex - 1) * slaveFirstDim
- g.y = wa.y
- g.height = slaveThei
- idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim
- else -- bottom slave
- g.x = wa.x + (rowIndex - 1) * slaveSecondDim
- g.y = wa.y + slaveThei + mainhei
- g.height = slaveBhei
- idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim
- end
- -- if last slave in row, use remaining space for it
- if rowIndex == idxChecker then
- g.width = wa.x + wa.width - g.x
- else
- g.width = dimToAssign
- end
- end
- g.width = max(g.width, 1)
- g.height = max(g.height, 1)
- p.geometries[cls[i]] = g
- end
- end
- local function mouse_resize_handler(c, _, _, _, orientation)
- local wa = c.screen.workarea
- local mwfact = c.screen.selected_tag.master_width_factor
- local g = c:geometry()
- local offset = 0
- local cursor = "cross"
- local corner_coords
- if orientation == 'vertical' then
- if g.height + 15 >= wa.height then
- offset = g.height * .5
- cursor = "sb_h_double_arrow"
- elseif not (g.y + g.height + 15 > wa.y + wa.height) then
- offset = g.height
- end
- corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset }
- else
- if g.width + 15 >= wa.width then
- offset = g.width * .5
- cursor = "sb_v_double_arrow"
- elseif not (g.x + g.width + 15 > wa.x + wa.width) then
- offset = g.width
- end
- corner_coords = { y = wa.y + wa.height * (1 - mwfact) / 2, x = g.x + offset }
- end
- mouse.coords(corner_coords)
- local prev_coords = {}
- mousegrabber.run(function(_mouse)
- if not c.valid then return false end
- for _, v in ipairs(_mouse.buttons) do
- if v then
- prev_coords = { x = _mouse.x, y = _mouse.y }
- local new_mwfact
- if orientation == 'vertical' then
- new_mwfact = 1 - (_mouse.x - wa.x) / wa.width * 2
- else
- new_mwfact = 1 - (_mouse.y - wa.y) / wa.height * 2
- end
- c.screen.selected_tag.master_width_factor = math.min(math.max(new_mwfact, 0.01), 0.99)
- return true
- end
- end
- return prev_coords.x == _mouse.x and prev_coords.y == _mouse.y
- end, cursor)
- end
- function centerwork.arrange(p)
- return arrange(p, centerwork)
- end
- function centerwork.horizontal.arrange(p)
- return arrange(p, centerwork.horizontal)
- end
- function centerwork.mouse_resize_handler(c, corner, x, y)
- return mouse_resize_handler(c, corner, x, y, 'vertical')
- end
- function centerwork.horizontal.mouse_resize_handler(c, corner, x, y)
- return mouse_resize_handler(c, corner, x, y, 'horizontal')
- end
- -------------------------------------------------------------------------------
- -- make focus.byidx and swap.byidx behave more consistently with other layouts
- local awful = require("awful")
- local gears = require("gears")
- local function compare_position(a, b)
- if a.x == b.x then
- return a.y < b.y
- else
- return a.x < b.x
- end
- end
- local function clients_by_position()
- local this = client.focus
- if this then
- local sorted = client.focus.first_tag:clients()
- table.sort(sorted, compare_position)
- local idx = 0
- for i, that in ipairs(sorted) do
- if this.window == that.window then
- idx = i
- end
- end
- if idx > 0 then
- return { sorted = sorted, idx = idx }
- end
- end
- return {}
- end
- local function in_centerwork()
- return client.focus and client.focus.first_tag.layout.name == "centerwork"
- end
- centerwork.focus = {}
- --[[
- Drop in replacements for awful.client.focus.byidx and awful.client.swap.byidx
- that behaves consistently with other layouts
- --]]
- function centerwork.focus.byidx(i)
- if in_centerwork() then
- local cls = clients_by_position()
- if cls.idx then
- local target = cls.sorted[gears.math.cycle(#cls.sorted, cls.idx + i)]
- awful.client.focus.byidx(0, target)
- end
- else
- awful.client.focus.byidx(i)
- end
- end
- centerwork.swap = {}
- function centerwork.swap.byidx(i)
- if in_centerwork() then
- local cls = clients_by_position()
- if cls.idx then
- local target = cls.sorted[gears.math.cycle(#cls.sorted, cls.idx + i)]
- client.focus:swap(target)
- end
- else
- awful.client.swap.byidx(i)
- end
- end
- return centerwork
|