From dfb3e8f365ed46ec4ffcdeae2c4bf3776c733eee Mon Sep 17 00:00:00 2001 From: Xinhao Yuan Date: Thu, 11 Jul 2019 11:25:20 -0400 Subject: [PATCH] move region calculation to arrangement --- README.md | 6 +-- editor.lua | 52 ++++++++++++++++--------- layout.lua | 108 ++++++++++++++++++++++++++++++--------------------- switcher.lua | 2 +- 4 files changed, 99 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 4523b46..3748809 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ TL;DR --- I want the control of my layout. ## Use the layout -Use `layout = layout_machi.layout.create(name)` to instantiate the layout. -It is advised to instantiate layouts of unique names for each tag (and for each screen), since the editor will restore the last regions of the layout based on the names. +Use `layout = layout_machi.layout.create(name, editor)` to instantiate the layout with an editor object (see below on creating the editor). +The editor will restore the last regions of the layouts based on their names. ## Editor @@ -101,8 +101,6 @@ So far, the key binding is not configurable. One has to modify the source code t `layout_machi.editor.fit_region(c, cycle = false)` will fit a floating client into the closest region. If `cycle` is true, it then moves the window by cycling all regions. -`layout_machi.editor.refresh_layout(layout, screen)` will recalculate the regions of the layout based on the workarea of the `screen` and the last editing command performed on `layout`. - ## Caveats `beautiful.useless_gap` is handled differently in layout-machi and it doesn't cooperate well with the standard way. diff --git a/editor.lua b/editor.lua index 911cab6..2fa1b6c 100644 --- a/editor.lua +++ b/editor.lua @@ -70,7 +70,7 @@ end -- @return whether any actions have been taken on the client local function fit_region(c, cycle) layout = api.layout.get(c.screen) - regions = layout.get_regions and layout.get_regions() + regions = layout.get_regions and layout.get_regions(c.screen.workarea) if type(regions) ~= "table" or #regions < 1 then return false end @@ -102,6 +102,28 @@ local function shrink_area_with_gap(a, gap) height = a.height - (a.bu and 0 or gap / 2) - (a.bd and 0 or gap / 2) } end +-- local function parse(cmd) +-- root = {} +-- args = "" + +-- open_areas = { root } + +-- for c = 1, #cmd do +-- char = cmd:sub(c, c) + +-- if char == "w" then +-- local a = open_areas[#open_areas] +-- table.remove(open_areas, #open_areas) + +-- root.type = "w" +-- root. + +-- else if tonumber(char) ~= nil then +-- args = args .. char +-- end +-- end +-- end + local function restore_data(data) if data.history_file then local file, err = io.open(data.history_file, "r") @@ -268,7 +290,7 @@ local function create(data) depth = a.depth + 1, group_id = split_count, bl = i == 1 and a.bl or false, - br = i == #offset and a.br or false, + br = i == #offset - 1 and a.br or false, bu = a.bu, bd = a.bd, } @@ -313,7 +335,7 @@ local function create(data) bl = a.bl, br = a.br, bu = i == 1 and a.bu or false, - bd = i == #offset and a.bd or false, + bd = i == #offset - 1 and a.bd or false, } children[#children + 1] = child end @@ -678,8 +700,8 @@ local function create(data) ) end - local function set_by_cmd(layout, screen, cmd) - init(screen.workarea) + local function run_cmd(init_area, cmd) + init(init_area) push_history() for i = 1, #cmd do @@ -702,26 +724,18 @@ local function create(data) end end ) - layout.cmd = cmd - data.last_cmd[layout.name] = cmd - layout.set_regions(areas_with_gap) - api.layout.arrange(screen) + + return areas_with_gap end - local function refresh_layout(layout, screen) - if layout.cmd == nil then return end - set_by_cmd(layout, screen, layout.cmd) - end - - local function try_restore_last(layout, screen) - if data.last_cmd[layout.name] == nil then return end - set_by_cmd(layout, screen, data.last_cmd[layout.name]) + local function get_last_cmd(name) + return data.last_cmd[name] end return { start_interactive = start_interactive, - refresh_layout = refresh_layout, - try_restore_last = try_restore_last, + run_cmd = run_cmd, + get_last_cmd = get_last_cmd } end diff --git a/layout.lua b/layout.lua index 3cd0a28..7ce3eee 100644 --- a/layout.lua +++ b/layout.lua @@ -36,53 +36,71 @@ local function find_region(c, regions) return choice end -function do_arrange(p, priv) - local wa = p.workarea - local cls = p.clients - local regions = priv.regions +function create(name, editor) + local priv = { + name = name, + editor = editor, + cmd = editor.get_last_cmd(name), + regions_cache = {} + } - if #regions == 0 then return end + local function get_regions(workarea) + if priv.cmd == nil then return {} end + local key = tostring(workarea.width) .. "x" .. tostring(workarea.height) .. "+" .. tostring(workarea.x) .. "+" .. tostring(workarea.y) + if priv.regions_cache[key] == nil then + priv.regions_cache[key] = priv.editor.run_cmd(workarea, priv.cmd) + end + return priv.regions_cache[key] + end + + function arrange(p) + local wa = p.workarea + local cls = p.clients + local regions = get_regions(wa) + + + if #regions == 0 then return end + + for i, c in ipairs(cls) do + if c.floating then + print("Ignore client " .. tostring(c)) + else + if c.machi_region == nil then + c.machi_region = find_region(c, regions) + elseif c.machi_region > #regions then + c.machi_region = #regions + elseif c.machi_region <= 1 then + c.machi_region = 1 + end + local region = c.machi_region + + p.geometries[c] = { + x = regions[region].x, + y = regions[region].y, + width = regions[region].width, + height = regions[region].height, + } + + print("Put client " .. tostring(c) .. " to region " .. region) - for i, c in ipairs(cls) do - if c.floating then - print("Ignore client " .. tostring(c)) - else - if c.machi_region == nil then - c.machi_region = find_region(c, regions) - elseif c.machi_region > #regions then - c.machi_region = #regions - elseif c.machi_region <= 1 then - c.machi_region = 1 end - local region = c.machi_region - - p.geometries[c] = { - x = regions[region].x, - y = regions[region].y, - width = regions[region].width, - height = regions[region].height, - } - - print("Put client " .. tostring(c) .. " to region " .. region) - end end -end -function create(name) - local priv = { regions = {} } - - local function set_regions(regions) - priv.regions = regions - end - - local function get_regions() - return priv.regions + function set_cmd(cmd) + if priv.cmd ~= cmd then + priv.cmd = cmd + priv.regions_cache = {} + end end -- move the closest region regardingly to the center distance local function resize_handler(c, context, h) if context ~= "mouse.move" then return end + + local workarea = c.screen.workarea + local regions = get_regions(workarea) + if #priv.regions == 0 then return end local center_x = h.x + h.width / 2 @@ -90,7 +108,8 @@ function create(name) local choice = 1 local choice_value = nil - for i, r in ipairs(priv.regions) do + + for i, r in ipairs(regions) do local r_x = r.x + r.width / 2 local r_y = r.y + r.height / 2 local dis = (r_x - center_x) * (r_x - center_x) + (r_y - center_y) * (r_y - center_y) @@ -102,24 +121,23 @@ function create(name) if c.machi_region ~= choice then c.machi_region = choice - c.x = priv.regions[choice].x - c.y = priv.regions[choice].y - c.width = priv.regions[choice].width - c.height = priv.regions[choice].height + c.x = regions[choice].x + c.y = regions[choice].y + c.width = regions[choice].width + c.height = regions[choice].height end end return { name = name, - arrange = function (p) do_arrange(p, priv) end, - get_region_count = function () return #priv.regions end, - set_regions = set_regions, + arrange = arrange, + set_cmd = set_cmd, get_regions = get_regions, resize_handler = resize_handler, } end -return { +return { create = create, find_region = find_region, } diff --git a/switcher.lua b/switcher.lua index 6c67bc5..9a1227f 100644 --- a/switcher.lua +++ b/switcher.lua @@ -58,7 +58,7 @@ local function start(c) local layout = api.layout.get(screen) if c.floating or layout.get_regions == nil then return end - local regions = layout.get_regions() + local regions = layout.get_regions(c.screen.workarea) local infobox = api.wibox({ screen = screen,