diff --git a/README.md b/README.md index 68873af..86271ca 100644 --- a/README.md +++ b/README.md @@ -269,6 +269,8 @@ The geometry of the window is from the upper-left corner of the UL to the bottom This is suppose to work with areas 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`. +__New in machi-ng:__ draft mode can be overrided by per-window settings. Use `f` or `.` key in switcher UI, or change the `c.machi_draft` boolean for window `c`. + ### Nested layouts __This feature is a toy. It may come with performance and usability issues - you have been warned.__ @@ -279,7 +281,7 @@ Known caveats include: 2. `client.*wfact` and other layout related operations don't work as machi fakes tag data to the nested layout engine. But it hopefully works if one changes the fields in the faked tag data. -__This feature is not available in draft mode.__ +__This feature is not available for windows 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 area to the mapped one. @@ -302,8 +304,9 @@ Calling `machi.switcher.start()` will create a switcher supporting the following - `Shift` + arrow keys: move the focused window to other areas by the direction. In draft mode, move the window while preserving its size. - `Control`[ + `Shift`] + arrow keys: move the bottom-right (or top-left window if `Shift` is pressed) area of the focused window by direction. Only works in draft mode. - `Tab`: switch beteen windows covering the current areas. - - `u` or `PageUp` (`Prior`): In non-draft mode, you can select the parent of the current area. - - `/`: In non-draft mode, this opens the editor to edit the selected area using the same command interpretation. + - `u` or `PageUp` (`Prior`): select the parent of the current area. + - `f` or `.`: toggle the per-window setting of draft mode. + - `/`: open the editor to edit the selected area using the same command interpretation. Note the final command may be transcoded to be embeddable, but the areas shall be the same. So far, the key binding is not configurable. One has to modify the source code to change it. diff --git a/layout.lua b/layout.lua index 307c185..bcdaff3 100644 --- a/layout.lua +++ b/layout.lua @@ -212,12 +212,15 @@ function module.create(args_or_name, editor, default_cmd) end end - if draft_mode then - for i, c in ipairs(cls) do - if c.floating or c.immobilized then - log(DEBUG, "Ignore client " .. tostring(c)) - else - local skip = false + for i, c in ipairs(cls) do + if c.floating or c.immobilized then + log(DEBUG, "Ignore client " .. tostring(c)) + else + local in_draft = c.machi_draft + if in_draft == nil then in_draft = draft_mode end + local skip = false + + if in_draft then if c.machi.lu ~= nil and c.machi.rd ~= nil and c.machi.lu <= #areas and c.machi.rd <= #areas and not areas[c.machi.lu].inhabitable and not areas[c.machi.rd].inhabitable @@ -249,12 +252,6 @@ function module.create(args_or_name, editor, default_cmd) p.geometries[c] = {} module.set_geometry(p.geometries[c], areas[lu], areas[rd], useless_gap, 0) end - end - end - else - for i, c in ipairs(cls) do - if c.floating or c.immobilized then - log(DEBUG, "Ignore client " .. tostring(c)) else if c.machi.area ~= nil and c.machi.area < #areas and @@ -281,62 +278,64 @@ function module.create(args_or_name, editor, default_cmd) end end end + end - for area, clients in pairs(nested_clients) do - if instance.tag_data[area] == nil then - -- TODO: Make the default more flexible. - instance.tag_data[area] = { - column_count = 1, - master_count = 1, - master_fill_policy = "expand", - gap = 0, - master_width_factor = 0.5, - _private = { - awful_tag_properties = { - }, + for area, clients in pairs(nested_clients) do + if instance.tag_data[area] == nil then + -- TODO: Make the default more flexible. + instance.tag_data[area] = { + column_count = 1, + master_count = 1, + master_fill_policy = "expand", + gap = 0, + master_width_factor = 0.5, + _private = { + awful_tag_properties = { }, - } - end - local nested_params = { - tag = instance.tag_data[area], - screen = p.screen, - clients = clients, - padding = 0, - geometry = { - x = areas[area].x, - y = areas[area].y, - width = areas[area].width, - height = areas[area].height, }, - -- Not sure how useless_gap adjustment works here. It seems to work anyway. - workarea = { - x = areas[area].x - useless_gap, - y = areas[area].y - useless_gap, - width = areas[area].width + useless_gap * 2, - height = areas[area].height + useless_gap * 2, - }, - useless_gap = useless_gap, - geometries = {}, } - machi_editor.nested_layouts[areas[area].layout].arrange(nested_params) - for _, c in ipairs(clients) do - p.geometries[c] = { - x = nested_params.geometries[c].x, - y = nested_params.geometries[c].y, - width = nested_params.geometries[c].width, - height = nested_params.geometries[c].height, - } - end + end + local nested_params = { + tag = instance.tag_data[area], + screen = p.screen, + clients = clients, + padding = 0, + geometry = { + x = areas[area].x, + y = areas[area].y, + width = areas[area].width, + height = areas[area].height, + }, + -- Not sure how useless_gap adjustment works here. It seems to work anyway. + workarea = { + x = areas[area].x - useless_gap, + y = areas[area].y - useless_gap, + width = areas[area].width + useless_gap * 2, + height = areas[area].height + useless_gap * 2, + }, + useless_gap = useless_gap, + geometries = {}, + } + machi_editor.nested_layouts[areas[area].layout].arrange(nested_params) + for _, c in ipairs(clients) do + p.geometries[c] = { + x = nested_params.geometries[c].x, + y = nested_params.geometries[c].y, + width = nested_params.geometries[c].width, + height = nested_params.geometries[c].height, + } end end end local function resize_handler (c, context, h) local areas, draft_mode = get_areas(c.screen, c.screen.selected_tag) + if areas == nil then return end - if #areas == 0 then return end + local in_draft = c.machi_draft + if in_draft == nil then in_draft = draft_mode end - if draft_mode then + if in_draft then local lu = find_lu(h, areas) local rd = nil if lu ~= nil then @@ -375,25 +374,25 @@ function module.create(args_or_name, editor, default_cmd) else if context ~= "mouse.move" then return end - if #areas == 0 then return end - local center_x = h.x + h.width / 2 local center_y = h.y + h.height / 2 - local choice = 1 + local choice = nil local choice_value = nil - for i, r in ipairs(areas) 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) - if choice_value == nil or choice_value > dis then - choice = i - choice_value = dis + for i, a in ipairs(areas) do + if not a.inhabitable then + local ac_x = a.x + a.width / 2 + local ac_y = a.y + a.height / 2 + local dis = (ac_x - center_x) * (ac_x - center_x) + (ac_y - center_y) * (ac_y - center_y) + if choice_value == nil or choice_value > dis then + choice = i + choice_value = dis + end end end - if c.machi.area ~= choice then + if choice and c.machi.area ~= choice then c.machi.area = choice module.set_geometry(c, areas[choice], areas[choice], 0, c.border_width) end diff --git a/switcher.lua b/switcher.lua index a64971c..9b072b6 100644 --- a/switcher.lua +++ b/switcher.lua @@ -430,74 +430,78 @@ function module.start(c, exit_keys) tablist = nil set_selected_area(nil) - if c and ctrl and draft_mode then - local lu = c.machi.lu - local rd = c.machi.rd + if c then + local in_draft = c and c.machi_draft + if in_draft == nil then in_draft = draft_mode end + if ctrl and in_draft then + local lu = c.machi.lu + local rd = c.machi.rd - if shift then - lu = choice - if areas[rd].x + areas[rd].width <= areas[lu].x or - areas[rd].y + areas[rd].height <= areas[lu].y - then - rd = nil - end - else - rd = choice - if areas[rd].x + areas[rd].width <= areas[lu].x or - areas[rd].y + areas[rd].height <= areas[lu].y - then - lu = nil - end - end + if shift then + lu = choice + if areas[rd].x + areas[rd].width <= areas[lu].x or + areas[rd].y + areas[rd].height <= areas[lu].y + then + rd = nil + end + else + rd = choice + if areas[rd].x + areas[rd].width <= areas[lu].x or + areas[rd].y + areas[rd].height <= areas[lu].y + then + lu = nil + end + end - if lu ~= nil and rd ~= nil then - machi.layout.set_geometry(c, areas[lu], areas[rd], 0, c.border_width) - elseif lu ~= nil then - machi.layout.set_geometry(c, areas[lu], nil, 0, c.border_width) - elseif rd ~= nil then - c.x = min(c.x, areas[rd].x) - c.y = min(c.y, areas[rd].y) - machi.layout.set_geometry(c, nil, areas[rd], 0, c.border_width) - end - c.machi.lu = lu - c.machi.rd = rd + if lu ~= nil and rd ~= nil then + machi.layout.set_geometry(c, areas[lu], areas[rd], 0, c.border_width) + elseif lu ~= nil then + machi.layout.set_geometry(c, areas[lu], nil, 0, c.border_width) + elseif rd ~= nil then + c.x = min(c.x, areas[rd].x) + c.y = min(c.y, areas[rd].y) + machi.layout.set_geometry(c, nil, areas[rd], 0, c.border_width) + end + c.machi.lu = lu + c.machi.rd = rd - c:emit_signal("request::activate", "mouse.move", {raise=false}) - c:raise() - api.layout.arrange(screen) - elseif c and shift then - -- move the window - if draft_mode then - c.x = areas[choice].x - c.y = areas[choice].y - else - machi.layout.set_geometry(c, areas[choice], areas[choice], 0, c.border_width) - c.machi.area = choice - end - c:emit_signal("request::activate", "mouse.move", {raise=false}) - c:raise() - api.layout.arrange(screen) + c:emit_signal("request::activate", "mouse.move", {raise=false}) + c:raise() + api.layout.arrange(screen) + elseif shift then + -- move the window + if in_draft then + c.x = areas[choice].x + c.y = areas[choice].y + else + machi.layout.set_geometry(c, areas[choice], areas[choice], 0, c.border_width) + c.machi.area = choice + end + c:emit_signal("request::activate", "mouse.move", {raise=false}) + c:raise() + api.layout.arrange(screen) - tablist = nil + tablist = nil + end else - maintain_tablist() - -- move the focus - if #tablist > 0 and tablist[1] ~= c then - c = tablist[1] - api.client.focus = c - end + maintain_tablist() + -- move the focus + if #tablist > 0 and tablist[1] ~= c then + c = tablist[1] + api.client.focus = c + end end infobox.bgimage = draw_info end - elseif (key == "u" or key == "Prior") and not draft_mode then + elseif (key == "u" or key == "Prior") then local current_area = selected_area() if areas[current_area].parent_id then tablist = nil set_selected_area(areas[current_area].parent_id) infobox.bgimage = draw_info end - elseif key == "/" and not draft_mode then + elseif key == "/" then local current_area = selected_area() local original_cmd = machi.engine.areas_to_command(areas, true, current_area) areas[current_area].hole = true @@ -526,6 +530,13 @@ function module.start(c, exit_keys) end ) exit() + elseif (key == "f" or key == ".") and c then + if c.machi_draft == nil then + c.machi_draft = not draft_mode + else + c.machi_draft = not c.machi_draft + end + api.layout.arrange(screen) elseif key == "Escape" or key == "Return" then exit() else