diff --git a/README.md b/README.md index 0f214d6..012fab0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ![](icon.png) layout-machi +# ![machi icon](icon.png) layout-machi A manual layout for Awesome with a rapid interactive editor. @@ -8,16 +8,16 @@ Draft mode: https://imgur.com/a/BOvMeQL ## Why? -TL;DR --- I want the control of my layout. +TL;DR --- To bring back control the window layout. -1. Dynamic tiling is an overkill, since tiling is only useful for persistent windows, and people extensively use hibernate/sleep these days. -2. I don't want to have all windows moving around whenever a new window shows up. -3. I want to have a flexible layout such that I can quickly adjust to whatever I need. +1. Dynamic tiling can be an overkill, since tiling is only useful for persistent windows, and people extensively use hibernate/sleep these days. +2. Having window moving around can be annoying whenever a new window shows up. +3. I want a flexible layout such that I can quickly adjust to whatever I need. ## Compatibilities -I developed it with Awesome 4.3. -Please let me know if it does not work in other versions. +I developed it with Awesome git version. Hopefully it works with 4.3 stable. +Please let me know if it does not work in 4.3 or older versions. ## Really quick usage @@ -228,7 +228,7 @@ Final merge, size 3x1, `w443113132231`: ### Draft mode -__This mode is experimental. Its usage may change fast.__ +__This mode is somewhat usable, yet it may change in the future.__ Unlike the original machi layout, where a window fits in a single region, draft mode allows window to span across multiple regions. Each tiled window is associated with a upper-left region (ULR) and a bottom-right region (BRR). @@ -237,6 +237,20 @@ The geometry of the window is from the upper-left corner of the ULR to the botto This is suppose to work with regions produced with `d` or `w` operation. To enable draft mode in a layout, configure the layout with a command with a leading `d`, for example, `d12210121`, or `dw66`. +### Nested layouts + +__This feature is a toy. It may come with performance and usability issues - you have been warned.__ + +__This feature is not available in draft mode.__ + +To set up nested layouts, you first need to check/modify `machi.editor.nested_layouts` array, which maps an argument string (`[0-9,]+`) to a layout object. +In machi command, use the argument string with command `x` will set up the nested layout of the region to the mapped one. + +For example, since by default `machi.editor.nested_layouts["0"]` is `awful.layout.suit.tile` and `machi.editor.nested_layouts["1"]` is `awful.layout.suit.spiral`, +the command `11h0x1x` will split the screen horizontally apply the layouts accordingly - see the figure below. + +![nested layout screenshot](nested_layout_screenshot.png) + ### Persistent history By default, the last 100 command sequences are stored in `.cache/awesome/history_machi`. diff --git a/editor.lua b/editor.lua index 89d738e..918a1d0 100644 --- a/editor.lua +++ b/editor.lua @@ -18,6 +18,12 @@ local DEBUG = -1 local module = { log_level = WARNING, + nested_layouts = { + ["0"] = api.layout.suit.tile, + ["1"] = api.layout.suit.spiral, + ["2"] = api.layout.suit.fair, + ["3"] = api.layout.suit.fair.horizontal, + }, } local function log(level, msg) @@ -131,7 +137,8 @@ end local function shrink_area_with_gap(a, inner_gap, outer_gap) return { x = a.x + (a.bl and outer_gap or inner_gap / 2), y = a.y + (a.bu and outer_gap or inner_gap / 2), width = a.width - (a.bl and outer_gap or inner_gap / 2) - (a.br and outer_gap or inner_gap / 2), - height = a.height - (a.bu and outer_gap or inner_gap / 2) - (a.bd and outer_gap or inner_gap / 2) } + height = a.height - (a.bu and outer_gap or inner_gap / 2) - (a.bd and outer_gap or inner_gap / 2), + layout = a.layout } end function module.restore_data(data) @@ -553,6 +560,11 @@ function module.create(data) max_depth = n end + elseif method == "x" then + + push_area() + closed_areas[#closed_areas].layout = module.nested_layouts[arg_str] + elseif method == "-" then push_area() @@ -596,6 +608,7 @@ function module.create(data) ["d"] = 3, ["D"] = 3, ["s"] = 3, ["S"] = 3, ["t"] = 3, ["T"] = 3, + ["x"] = 3, ["-"] = 2, ["/"] = 2, ["."] = 1, diff --git a/layout.lua b/layout.lua index c0c0269..e0a600f 100644 --- a/layout.lua +++ b/layout.lua @@ -183,6 +183,7 @@ function module.create(args_or_name, editor, default_cmd) local regions, draft_mode = get_regions(wa, get_screen(p.screen).selected_tag) if #regions == 0 then return end + local nested_clients = {} if draft_mode then for i, c in ipairs(cls) do @@ -227,6 +228,7 @@ function module.create(args_or_name, editor, default_cmd) log(DEBUG, "Ignore client " .. tostring(c)) else if c.machi_region ~= nil and + regions[c.machi_region].layout == nil and regions[c.machi_region].x == c.x and regions[c.machi_region].y == c.y and regions[c.machi_region].width - c.border_width * 2 == c.width and @@ -237,10 +239,52 @@ function module.create(args_or_name, editor, default_cmd) local region = find_region(c, regions) c.machi_region = region p.geometries[c] = {} - module.set_geometry(p.geometries[c], regions[region], regions[region], useless_gap, 0) + if regions[region].layout ~= nil then + local clients = nested_clients[region] + if clients == nil then clients = {}; nested_clients[region] = clients end + clients[#clients + 1] = c + else + module.set_geometry(p.geometries[c], regions[region], regions[region], useless_gap, 0) + end end end end + + for region, clients in pairs(nested_clients) do + local nested_params = { + tags = { + -- Any tag properties to fake? + useless_gap = 0, + }, + screen = p.screen, + clients = clients, + padding = 0, + geometry = { + x = regions[region].x, + y = regions[region].y, + width = regions[region].width, + height = regions[region].height, + }, + -- Not sure how useless_gap adjustment works here. It seems to work anyway. + workarea = { + x = regions[region].x - useless_gap / 2, + y = regions[region].y - useless_gap / 2, + width = regions[region].width + useless_gap, + height = regions[region].height + useless_gap, + }, + useless_gap = 0, + geometries = {}, + } + regions[region].layout.arrange(nested_params) + for _, c in ipairs(clients) do + p.geometries[c] = { + x = nested_params.geometries[c].x - useless_gap / 2, + y = nested_params.geometries[c].y - useless_gap / 2, + width = nested_params.geometries[c].width + useless_gap, + height = nested_params.geometries[c].height + useless_gap, + } + end + end end end @@ -289,9 +333,6 @@ function module.create(args_or_name, editor, default_cmd) else if context ~= "mouse.move" then return end - local workarea = c.screen.workarea - local regions = get_regions(workarea, c.screen.selected_tag) - if #regions == 0 then return end local center_x = h.x + h.width / 2 diff --git a/nested_layout_screenshot.png b/nested_layout_screenshot.png new file mode 100644 index 0000000..6ca121a Binary files /dev/null and b/nested_layout_screenshot.png differ