Per-window setting of draft mode.

This commit is contained in:
Xinhao Yuan 2021-02-26 20:21:21 -05:00
parent b8a08279cf
commit ee08eecb49
3 changed files with 136 additions and 123 deletions

View File

@ -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. 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`. 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 ### Nested layouts
__This feature is a toy. It may come with performance and usability issues - you have been warned.__ __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. 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. 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. 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. 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. - `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. - `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. - `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. - `u` or `PageUp` (`Prior`): 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. - `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. 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. So far, the key binding is not configurable. One has to modify the source code to change it.

View File

@ -212,12 +212,15 @@ function module.create(args_or_name, editor, default_cmd)
end end
end end
if draft_mode then for i, c in ipairs(cls) do
for i, c in ipairs(cls) do if c.floating or c.immobilized then
if c.floating or c.immobilized then log(DEBUG, "Ignore client " .. tostring(c))
log(DEBUG, "Ignore client " .. tostring(c)) else
else local in_draft = c.machi_draft
local skip = false 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 if c.machi.lu ~= nil and c.machi.rd ~= nil and
c.machi.lu <= #areas and c.machi.rd <= #areas and c.machi.lu <= #areas and c.machi.rd <= #areas and
not areas[c.machi.lu].inhabitable and not areas[c.machi.rd].inhabitable 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] = {} p.geometries[c] = {}
module.set_geometry(p.geometries[c], areas[lu], areas[rd], useless_gap, 0) module.set_geometry(p.geometries[c], areas[lu], areas[rd], useless_gap, 0)
end 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 else
if c.machi.area ~= nil and if c.machi.area ~= nil and
c.machi.area < #areas and c.machi.area < #areas and
@ -281,62 +278,64 @@ function module.create(args_or_name, editor, default_cmd)
end end
end end
end end
end
for area, clients in pairs(nested_clients) do for area, clients in pairs(nested_clients) do
if instance.tag_data[area] == nil then if instance.tag_data[area] == nil then
-- TODO: Make the default more flexible. -- TODO: Make the default more flexible.
instance.tag_data[area] = { instance.tag_data[area] = {
column_count = 1, column_count = 1,
master_count = 1, master_count = 1,
master_fill_policy = "expand", master_fill_policy = "expand",
gap = 0, gap = 0,
master_width_factor = 0.5, master_width_factor = 0.5,
_private = { _private = {
awful_tag_properties = { 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) end
for _, c in ipairs(clients) do local nested_params = {
p.geometries[c] = { tag = instance.tag_data[area],
x = nested_params.geometries[c].x, screen = p.screen,
y = nested_params.geometries[c].y, clients = clients,
width = nested_params.geometries[c].width, padding = 0,
height = nested_params.geometries[c].height, geometry = {
} x = areas[area].x,
end 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 end
end end
local function resize_handler (c, context, h) local function resize_handler (c, context, h)
local areas, draft_mode = get_areas(c.screen, c.screen.selected_tag) 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 lu = find_lu(h, areas)
local rd = nil local rd = nil
if lu ~= nil then if lu ~= nil then
@ -375,25 +374,25 @@ function module.create(args_or_name, editor, default_cmd)
else else
if context ~= "mouse.move" then return end if context ~= "mouse.move" then return end
if #areas == 0 then return end
local center_x = h.x + h.width / 2 local center_x = h.x + h.width / 2
local center_y = h.y + h.height / 2 local center_y = h.y + h.height / 2
local choice = 1 local choice = nil
local choice_value = nil local choice_value = nil
for i, r in ipairs(areas) do for i, a in ipairs(areas) do
local r_x = r.x + r.width / 2 if not a.inhabitable then
local r_y = r.y + r.height / 2 local ac_x = a.x + a.width / 2
local dis = (r_x - center_x) * (r_x - center_x) + (r_y - center_y) * (r_y - center_y) local ac_y = a.y + a.height / 2
if choice_value == nil or choice_value > dis then local dis = (ac_x - center_x) * (ac_x - center_x) + (ac_y - center_y) * (ac_y - center_y)
choice = i if choice_value == nil or choice_value > dis then
choice_value = dis choice = i
choice_value = dis
end
end end
end end
if c.machi.area ~= choice then if choice and c.machi.area ~= choice then
c.machi.area = choice c.machi.area = choice
module.set_geometry(c, areas[choice], areas[choice], 0, c.border_width) module.set_geometry(c, areas[choice], areas[choice], 0, c.border_width)
end end

View File

@ -430,74 +430,78 @@ function module.start(c, exit_keys)
tablist = nil tablist = nil
set_selected_area(nil) set_selected_area(nil)
if c and ctrl and draft_mode then if c then
local lu = c.machi.lu local in_draft = c and c.machi_draft
local rd = c.machi.rd 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 if shift then
lu = choice lu = choice
if areas[rd].x + areas[rd].width <= areas[lu].x or if areas[rd].x + areas[rd].width <= areas[lu].x or
areas[rd].y + areas[rd].height <= areas[lu].y areas[rd].y + areas[rd].height <= areas[lu].y
then then
rd = nil rd = nil
end end
else else
rd = choice rd = choice
if areas[rd].x + areas[rd].width <= areas[lu].x or if areas[rd].x + areas[rd].width <= areas[lu].x or
areas[rd].y + areas[rd].height <= areas[lu].y areas[rd].y + areas[rd].height <= areas[lu].y
then then
lu = nil lu = nil
end end
end end
if lu ~= nil and rd ~= nil then if lu ~= nil and rd ~= nil then
machi.layout.set_geometry(c, areas[lu], areas[rd], 0, c.border_width) machi.layout.set_geometry(c, areas[lu], areas[rd], 0, c.border_width)
elseif lu ~= nil then elseif lu ~= nil then
machi.layout.set_geometry(c, areas[lu], nil, 0, c.border_width) machi.layout.set_geometry(c, areas[lu], nil, 0, c.border_width)
elseif rd ~= nil then elseif rd ~= nil then
c.x = min(c.x, areas[rd].x) c.x = min(c.x, areas[rd].x)
c.y = min(c.y, areas[rd].y) c.y = min(c.y, areas[rd].y)
machi.layout.set_geometry(c, nil, areas[rd], 0, c.border_width) machi.layout.set_geometry(c, nil, areas[rd], 0, c.border_width)
end end
c.machi.lu = lu c.machi.lu = lu
c.machi.rd = rd c.machi.rd = rd
c:emit_signal("request::activate", "mouse.move", {raise=false}) c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise() c:raise()
api.layout.arrange(screen) api.layout.arrange(screen)
elseif c and shift then elseif shift then
-- move the window -- move the window
if draft_mode then if in_draft then
c.x = areas[choice].x c.x = areas[choice].x
c.y = areas[choice].y c.y = areas[choice].y
else else
machi.layout.set_geometry(c, areas[choice], areas[choice], 0, c.border_width) machi.layout.set_geometry(c, areas[choice], areas[choice], 0, c.border_width)
c.machi.area = choice c.machi.area = choice
end end
c:emit_signal("request::activate", "mouse.move", {raise=false}) c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise() c:raise()
api.layout.arrange(screen) api.layout.arrange(screen)
tablist = nil tablist = nil
end
else else
maintain_tablist() maintain_tablist()
-- move the focus -- move the focus
if #tablist > 0 and tablist[1] ~= c then if #tablist > 0 and tablist[1] ~= c then
c = tablist[1] c = tablist[1]
api.client.focus = c api.client.focus = c
end end
end end
infobox.bgimage = draw_info infobox.bgimage = draw_info
end end
elseif (key == "u" or key == "Prior") and not draft_mode then elseif (key == "u" or key == "Prior") then
local current_area = selected_area() local current_area = selected_area()
if areas[current_area].parent_id then if areas[current_area].parent_id then
tablist = nil tablist = nil
set_selected_area(areas[current_area].parent_id) set_selected_area(areas[current_area].parent_id)
infobox.bgimage = draw_info infobox.bgimage = draw_info
end end
elseif key == "/" and not draft_mode then elseif key == "/" then
local current_area = selected_area() local current_area = selected_area()
local original_cmd = machi.engine.areas_to_command(areas, true, current_area) local original_cmd = machi.engine.areas_to_command(areas, true, current_area)
areas[current_area].hole = true areas[current_area].hole = true
@ -526,6 +530,13 @@ function module.start(c, exit_keys)
end end
) )
exit() 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 elseif key == "Escape" or key == "Return" then
exit() exit()
else else