2021-02-23 06:32:58 +01:00
|
|
|
local this_package = ... and (...):match("(.-)[^%.]+$") or ""
|
|
|
|
local machi_editor = require(this_package.."editor")
|
|
|
|
local awful = require("awful")
|
|
|
|
local capi = {
|
|
|
|
screen = screen
|
2019-07-12 22:17:34 +02:00
|
|
|
}
|
|
|
|
|
2019-08-20 05:46:49 +02:00
|
|
|
local ERROR = 2
|
|
|
|
local WARNING = 1
|
|
|
|
local INFO = 0
|
|
|
|
local DEBUG = -1
|
|
|
|
|
|
|
|
local module = {
|
2021-02-27 02:39:59 +01:00
|
|
|
log_level = WARNING,
|
2021-02-27 17:11:54 +01:00
|
|
|
global_default_cmd = "w66.",
|
2021-02-27 02:39:59 +01:00
|
|
|
allow_shrinking_by_mouse_moving = false,
|
2019-08-20 05:46:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
local function log(level, msg)
|
2021-02-23 06:32:58 +01:00
|
|
|
if level > module.log_level then
|
|
|
|
print(msg)
|
|
|
|
end
|
2019-08-20 05:46:49 +02:00
|
|
|
end
|
|
|
|
|
2019-07-07 22:43:54 +02:00
|
|
|
local function min(a, b)
|
2021-02-23 06:32:58 +01:00
|
|
|
if a < b then return a else return b end
|
2019-07-07 22:43:54 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function max(a, b)
|
2021-02-23 06:32:58 +01:00
|
|
|
if a < b then return b else return a end
|
2019-07-07 22:43:54 +02:00
|
|
|
end
|
|
|
|
|
2019-07-12 22:17:34 +02:00
|
|
|
local function get_screen(s)
|
2021-02-23 06:32:58 +01:00
|
|
|
return s and capi.screen[s]
|
2019-07-12 22:17:34 +02:00
|
|
|
end
|
|
|
|
|
2021-02-23 06:32:58 +01:00
|
|
|
awful.mouse.resize.add_enter_callback(
|
|
|
|
function (c)
|
|
|
|
c.full_width_before_move = c.width + c.border_width * 2
|
|
|
|
c.full_height_before_move = c.height + c.border_width * 2
|
|
|
|
end, 'mouse.move')
|
2019-08-02 23:45:21 +02:00
|
|
|
|
2021-02-23 06:32:58 +01:00
|
|
|
--- find the best area for the area-like object
|
2019-07-07 22:19:18 +02:00
|
|
|
-- @param c area-like object - table with properties x, y, width, and height
|
2021-02-23 06:32:58 +01:00
|
|
|
-- @param areas array of area objects
|
|
|
|
-- @return the index of the best area
|
|
|
|
local function find_area(c, areas)
|
|
|
|
local choice = 1
|
|
|
|
local choice_value = nil
|
|
|
|
local c_area = c.width * c.height
|
|
|
|
for i, a in ipairs(areas) do
|
|
|
|
if not a.inhabitable then
|
|
|
|
local x_cap = max(0, min(c.x + c.width, a.x + a.width) - max(c.x, a.x))
|
|
|
|
local y_cap = max(0, min(c.y + c.height, a.y + a.height) - max(c.y, a.y))
|
|
|
|
local cap = x_cap * y_cap
|
|
|
|
-- -- a cap b / a cup b
|
|
|
|
-- local cup = c_area + a.width * a.height - cap
|
|
|
|
-- if cup > 0 then
|
|
|
|
-- local itx_ratio = cap / cup
|
|
|
|
-- if choice_value == nil or choice_value < itx_ratio then
|
|
|
|
-- choice_value = itx_ratio
|
|
|
|
-- choice = i
|
|
|
|
-- end
|
|
|
|
-- end
|
|
|
|
-- a cap b
|
|
|
|
if choice_value == nil or choice_value < cap then
|
|
|
|
choice = i
|
|
|
|
choice_value = cap
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return choice
|
2019-07-07 22:19:18 +02:00
|
|
|
end
|
|
|
|
|
2019-08-01 03:00:38 +02:00
|
|
|
local function distance(x1, y1, x2, y2)
|
2021-02-23 06:32:58 +01:00
|
|
|
-- use d1
|
|
|
|
return math.abs(x1 - x2) + math.abs(y1 - y2)
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
|
|
|
|
2021-02-23 06:32:58 +01:00
|
|
|
local function find_lu(c, areas, rd)
|
|
|
|
local lu = nil
|
|
|
|
for i, a in ipairs(areas) do
|
|
|
|
if not a.inhabitable then
|
|
|
|
if rd == nil or (a.x < areas[rd].x + areas[rd].width and a.y < areas[rd].y + areas[rd].height) then
|
|
|
|
if lu == nil or distance(c.x, c.y, a.x, a.y) < distance(c.x, c.y, areas[lu].x, areas[lu].y) then
|
|
|
|
lu = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return lu
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
|
|
|
|
2021-02-28 15:32:19 +01:00
|
|
|
local function find_rd(c, border_width, areas, lu)
|
2021-02-23 06:32:58 +01:00
|
|
|
local x, y
|
2021-02-28 15:32:19 +01:00
|
|
|
x = c.x + c.width + (border_width or 0) * 2
|
|
|
|
y = c.y + c.height + (border_width or 0) * 2
|
2021-02-23 06:32:58 +01:00
|
|
|
local rd = nil
|
|
|
|
for i, a in ipairs(areas) do
|
|
|
|
if not a.inhabitable then
|
|
|
|
if lu == nil or (a.x + a.width > areas[lu].x and a.y + a.height > areas[lu].y) then
|
|
|
|
if rd == nil or distance(x, y, a.x + a.width, a.y + a.height) < distance(x, y, areas[rd].x + areas[rd].width, areas[rd].y + areas[rd].height) then
|
|
|
|
rd = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return rd
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
|
|
|
|
2021-02-23 06:32:58 +01:00
|
|
|
function module.set_geometry(c, area_lu, area_rd, useless_gap, border_width)
|
|
|
|
-- We try to negate the gap of outer layer
|
|
|
|
if area_lu ~= nil then
|
|
|
|
c.x = area_lu.x - useless_gap
|
|
|
|
c.y = area_lu.y - useless_gap
|
|
|
|
end
|
|
|
|
|
|
|
|
if area_rd ~= nil then
|
|
|
|
c.width = area_rd.x + area_rd.width - c.x + useless_gap - border_width * 2
|
|
|
|
c.height = area_rd.y + area_rd.height - c.y + useless_gap - border_width * 2
|
|
|
|
end
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
|
|
|
|
2021-02-28 15:32:19 +01:00
|
|
|
function module.default_name_func(tag)
|
|
|
|
if tag.machi_name_cache == nil then
|
|
|
|
tag.machi_name_cache =
|
|
|
|
tostring(tag.screen.geometry.width) .. "x" .. tostring(tag.screen.geometry.height) .. "+" ..
|
|
|
|
tostring(tag.screen.geometry.x) .. "+" .. tostring(tag.screen.geometry.y) .. '+' .. tag.name
|
|
|
|
end
|
|
|
|
return tag.machi_name_cache
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2020-03-21 21:49:20 +01:00
|
|
|
function module.create(args_or_name, editor, default_cmd)
|
|
|
|
local args
|
|
|
|
if type(args_or_name) == "string" then
|
|
|
|
args = {
|
|
|
|
name = args_or_name
|
|
|
|
}
|
|
|
|
elseif type(args_or_name) == "function" then
|
|
|
|
args = {
|
|
|
|
name_func = args_or_name
|
|
|
|
}
|
|
|
|
elseif type(args_or_name) == "table" then
|
|
|
|
args = args_or_name
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
2021-02-28 15:32:19 +01:00
|
|
|
if args.name == nil and args.name_func == nil then
|
|
|
|
args.name_func = module.default_name_func
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
args.editor = args.editor or editor or machi_editor.default_editor
|
2020-03-21 21:49:20 +01:00
|
|
|
args.default_cmd = args.default_cmd or default_cmd or global_default_cmd
|
|
|
|
args.persistent = args.persistent == nil or args.persistent
|
|
|
|
|
2021-02-15 16:29:24 +01:00
|
|
|
local layout = {}
|
2020-03-21 21:49:20 +01:00
|
|
|
local instances = {}
|
|
|
|
|
|
|
|
local function get_instance_info(tag)
|
|
|
|
return (args.name_func and args.name_func(tag) or args.name), args.persistent
|
|
|
|
end
|
2019-07-12 22:21:35 +02:00
|
|
|
|
2021-02-23 06:32:58 +01:00
|
|
|
local function get_instance_(tag)
|
|
|
|
local name, persistent = get_instance_info(tag)
|
|
|
|
if instances[name] == nil then
|
|
|
|
instances[name] = {
|
|
|
|
layout = layout,
|
|
|
|
cmd = persistent and args.editor.get_last_cmd(name) or nil,
|
|
|
|
areas_cache = {},
|
|
|
|
tag_data = {},
|
2021-02-27 06:16:32 +01:00
|
|
|
client_data = setmetatable({}, {__mode="k"}),
|
2021-02-23 06:32:58 +01:00
|
|
|
}
|
|
|
|
if instances[name].cmd == nil then
|
|
|
|
instances[name].cmd = args.default_cmd
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
return instances[name]
|
|
|
|
end
|
|
|
|
|
2021-02-27 06:16:32 +01:00
|
|
|
local function get_instance_data(screen, tag)
|
2021-02-23 06:32:58 +01:00
|
|
|
local workarea = screen.workarea
|
|
|
|
local instance = get_instance_(tag)
|
|
|
|
local cmd = instance.cmd or module.global_default_cmd
|
2021-02-27 17:11:54 +01:00
|
|
|
if cmd == nil then return end
|
2021-02-23 06:32:58 +01:00
|
|
|
|
|
|
|
local key = tostring(workarea.width) .. "x" .. tostring(workarea.height) .. "+" .. tostring(workarea.x) .. "+" .. tostring(workarea.y)
|
|
|
|
if instance.areas_cache[key] == nil then
|
|
|
|
instance.areas_cache[key] = args.editor.run_cmd(cmd, screen, tag)
|
2021-02-27 17:11:54 +01:00
|
|
|
if instance.areas_cache[key] == nil then
|
|
|
|
return
|
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
2021-02-27 17:11:54 +01:00
|
|
|
return instance.client_data, instance.tag_data, instance.areas_cache[key], instance, args.new_placement_cb
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
local function set_cmd(cmd, tag)
|
|
|
|
local instance = get_instance_(tag)
|
|
|
|
if instance.cmd ~= cmd then
|
|
|
|
instance.cmd = cmd
|
|
|
|
instance.areas_cache = {}
|
|
|
|
instance.tag_data = {}
|
2021-02-27 06:16:32 +01:00
|
|
|
instance.client_data = setmetatable({}, {__mode="k"})
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function arrange(p)
|
|
|
|
local useless_gap = p.useless_gap
|
|
|
|
local screen = get_screen(p.screen)
|
|
|
|
local wa = screen.workarea -- get the real workarea without the gap (instead of p.workarea)
|
|
|
|
local cls = p.clients
|
|
|
|
local tag = screen.selected_tag
|
2021-02-27 17:11:54 +01:00
|
|
|
local cd, td, areas, instance, new_placement_cb = get_instance_data(screen, tag)
|
2021-02-23 06:32:58 +01:00
|
|
|
|
2021-02-26 05:50:35 +01:00
|
|
|
if areas == nil then return end
|
2021-02-23 06:32:58 +01:00
|
|
|
local nested_clients = {}
|
|
|
|
|
2021-02-27 17:43:25 +01:00
|
|
|
local function place_client_in_area(c, area)
|
|
|
|
if machi_editor.nested_layouts[areas[area].layout] ~= nil then
|
|
|
|
local clients = nested_clients[area]
|
|
|
|
if clients == nil then clients = {}; nested_clients[area] = clients end
|
|
|
|
clients[#clients + 1] = c
|
|
|
|
else
|
2021-02-28 15:32:19 +01:00
|
|
|
p.geometries[c] = {}
|
2021-02-27 17:43:25 +01:00
|
|
|
module.set_geometry(p.geometries[c], areas[area], areas[area], useless_gap, 0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-28 15:32:19 +01:00
|
|
|
-- Make clients calling new_placement_cb appear in the end.
|
2021-02-28 06:14:54 +01:00
|
|
|
local j = 0
|
|
|
|
for i = 1, #cls do
|
2021-02-28 15:32:19 +01:00
|
|
|
cd[cls[i]] = cd[cls[i]] or {}
|
|
|
|
if cd[cls[i]].placement then
|
2021-02-28 06:14:54 +01:00
|
|
|
j = j + 1
|
|
|
|
cls[j], cls[i] = cls[i], cls[j]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-27 02:21:21 +01:00
|
|
|
for i, c in ipairs(cls) do
|
|
|
|
if c.floating or c.immobilized then
|
|
|
|
log(DEBUG, "Ignore client " .. tostring(c))
|
|
|
|
else
|
2021-02-28 15:32:19 +01:00
|
|
|
local geo = {
|
|
|
|
x = c.x,
|
|
|
|
y = c.y,
|
|
|
|
width = c.width + c.border_width * 2,
|
|
|
|
height = c.height + c.border_width * 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
if not cd[c].placement and new_placement_cb then
|
|
|
|
cd[c].placement = true
|
|
|
|
new_placement_cb(c, instance, areas, geo)
|
|
|
|
end
|
2021-02-27 06:16:32 +01:00
|
|
|
|
|
|
|
local in_draft = cd[c].draft
|
|
|
|
if cd[c].draft ~= nil then
|
|
|
|
in_draft = cd[c].draft
|
|
|
|
elseif cd[c].lu then
|
|
|
|
in_draft = true
|
|
|
|
elseif cd[c].area then
|
|
|
|
in_draft = false
|
|
|
|
else
|
2021-02-27 17:11:54 +01:00
|
|
|
in_draft = nil
|
2021-02-27 06:16:32 +01:00
|
|
|
end
|
2021-02-28 06:14:54 +01:00
|
|
|
|
2021-02-27 02:21:21 +01:00
|
|
|
local skip = false
|
|
|
|
|
2021-02-27 17:11:54 +01:00
|
|
|
if in_draft ~= false then
|
2021-02-27 06:16:32 +01:00
|
|
|
if cd[c].lu ~= nil and cd[c].rd ~= nil and
|
|
|
|
cd[c].lu <= #areas and cd[c].rd <= #areas and
|
|
|
|
not areas[cd[c].lu].inhabitable and not areas[cd[c].rd].inhabitable
|
2021-02-23 06:32:58 +01:00
|
|
|
then
|
2021-02-28 15:32:19 +01:00
|
|
|
if areas[cd[c].lu].x == geo.x and
|
|
|
|
areas[cd[c].lu].y == geo.y and
|
|
|
|
areas[cd[c].rd].x + areas[cd[c].rd].width == geo.x + geo.width and
|
|
|
|
areas[cd[c].rd].y + areas[cd[c].rd].height == geo.y + geo.height
|
2021-02-23 06:32:58 +01:00
|
|
|
then
|
|
|
|
skip = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local lu = nil
|
|
|
|
local rd = nil
|
|
|
|
if not skip then
|
|
|
|
log(DEBUG, "Compute areas for " .. (c.name or ("<untitled:" .. tostring(c) .. ">")))
|
2021-02-28 15:32:19 +01:00
|
|
|
lu = find_lu(geo, areas)
|
2021-02-23 06:32:58 +01:00
|
|
|
if lu ~= nil then
|
2021-02-28 15:32:19 +01:00
|
|
|
geo.x = areas[lu].x
|
|
|
|
geo.y = areas[lu].y
|
|
|
|
rd = find_rd(geo, 0, areas, lu)
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if lu ~= nil and rd ~= nil then
|
2021-02-27 17:43:25 +01:00
|
|
|
if lu == rd and cd[c].lu == nil then
|
2021-02-27 17:11:54 +01:00
|
|
|
cd[c].area = lu
|
2021-02-27 17:43:25 +01:00
|
|
|
place_client_in_area(c, lu)
|
2021-02-27 17:11:54 +01:00
|
|
|
else
|
|
|
|
cd[c].lu = lu
|
|
|
|
cd[c].rd = rd
|
|
|
|
cd[c].area = nil
|
2021-02-28 15:32:19 +01:00
|
|
|
p.geometries[c] = {}
|
2021-02-27 17:43:25 +01:00
|
|
|
module.set_geometry(p.geometries[c], areas[lu], areas[rd], useless_gap, 0)
|
2021-02-27 17:11:54 +01:00
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
else
|
2021-02-27 06:16:32 +01:00
|
|
|
if cd[c].area ~= nil and
|
2021-02-28 15:32:19 +01:00
|
|
|
cd[c].area <= #areas and
|
2021-02-27 06:16:32 +01:00
|
|
|
not areas[cd[c].area].inhabitable and
|
|
|
|
areas[cd[c].area].layout == nil and
|
2021-02-28 15:32:19 +01:00
|
|
|
areas[cd[c].area].x == geo.x and
|
|
|
|
areas[cd[c].area].y == geo.y and
|
|
|
|
areas[cd[c].area].width == geo.width and
|
|
|
|
areas[cd[c].area].height == geo.height
|
2021-02-23 06:32:58 +01:00
|
|
|
then
|
2021-02-28 15:32:19 +01:00
|
|
|
skip = true
|
2021-02-23 06:32:58 +01:00
|
|
|
else
|
|
|
|
log(DEBUG, "Compute areas for " .. (c.name or ("<untitled:" .. tostring(c) .. ">")))
|
2021-02-28 15:32:19 +01:00
|
|
|
local area = find_area(geo, areas)
|
2021-02-27 06:16:32 +01:00
|
|
|
cd[c].area, cd[c].lu, cd[c].rd = area, nil, nil
|
2021-02-27 17:43:25 +01:00
|
|
|
place_client_in_area(c, area)
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
end
|
2021-02-28 15:32:19 +01:00
|
|
|
|
|
|
|
if skip then
|
|
|
|
if geo.x ~= c.x or geo.y ~= c.y or
|
|
|
|
geo.width ~= c.width + c.border_width * 2 or
|
|
|
|
geo.height ~= c.height + c.border_width * 2 then
|
|
|
|
p.geometries[c] = {}
|
|
|
|
module.set_geometry(p.geometries[c], geo, geo, useless_gap, 0)
|
|
|
|
end
|
|
|
|
end
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
2021-02-27 02:21:21 +01:00
|
|
|
end
|
2019-07-05 23:04:18 +02:00
|
|
|
|
2021-02-27 02:21:21 +01:00
|
|
|
for area, clients in pairs(nested_clients) do
|
2021-02-27 06:16:32 +01:00
|
|
|
if td[area] == nil then
|
2021-02-27 02:21:21 +01:00
|
|
|
-- TODO: Make the default more flexible.
|
2021-02-27 06:16:32 +01:00
|
|
|
td[area] = {
|
2021-02-27 02:21:21 +01:00
|
|
|
column_count = 1,
|
|
|
|
master_count = 1,
|
|
|
|
master_fill_policy = "expand",
|
|
|
|
gap = 0,
|
|
|
|
master_width_factor = 0.5,
|
|
|
|
_private = {
|
|
|
|
awful_tag_properties = {
|
2021-02-23 06:32:58 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2021-02-27 02:21:21 +01:00
|
|
|
end
|
|
|
|
local nested_params = {
|
2021-02-27 06:16:32 +01:00
|
|
|
tag = td[area],
|
2021-02-27 02:21:21 +01:00
|
|
|
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,
|
|
|
|
}
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
end
|
2019-07-11 17:25:20 +02:00
|
|
|
|
2021-02-23 06:32:58 +01:00
|
|
|
local function resize_handler (c, context, h)
|
2021-02-27 06:16:32 +01:00
|
|
|
local tag = c.screen.selected_tag
|
|
|
|
local instance = get_instance_(tag)
|
|
|
|
local cd = instance.client_data
|
2021-02-27 17:11:54 +01:00
|
|
|
local cd, td, areas, _placement_cb = get_instance_data(c.screen, tag)
|
2021-02-23 06:32:58 +01:00
|
|
|
|
2021-02-27 06:16:32 +01:00
|
|
|
if areas == nil then return end
|
2021-02-23 06:32:58 +01:00
|
|
|
|
2021-02-27 06:16:32 +01:00
|
|
|
if context == "mouse.move" then
|
|
|
|
local in_draft = cd[c].draft
|
|
|
|
if cd[c].draft ~= nil then
|
|
|
|
in_draft = cd[c].draft
|
|
|
|
elseif cd[c].lu then
|
|
|
|
in_draft = true
|
|
|
|
elseif cd[c].area then
|
|
|
|
in_draft = false
|
|
|
|
else
|
2021-02-27 17:11:54 +01:00
|
|
|
log(ERROR, "Assuming in_draft for unhandled client "..tostring(c))
|
|
|
|
in_draft = true
|
2021-02-27 06:16:32 +01:00
|
|
|
end
|
|
|
|
if in_draft then
|
|
|
|
local lu = find_lu(h, areas)
|
|
|
|
local rd = nil
|
|
|
|
if lu ~= nil then
|
2021-02-23 06:32:58 +01:00
|
|
|
-- Use the initial width and height since it may change in undesired way.
|
|
|
|
local hh = {}
|
|
|
|
hh.x = areas[lu].x
|
|
|
|
hh.y = areas[lu].y
|
|
|
|
hh.width = c.full_width_before_move
|
|
|
|
hh.height = c.full_height_before_move
|
2021-02-28 15:32:19 +01:00
|
|
|
rd = find_rd(hh, 0, areas, lu)
|
2021-02-23 06:32:58 +01:00
|
|
|
|
|
|
|
if rd ~= nil and not module.allowing_shrinking_by_mouse_moving and
|
|
|
|
(areas[rd].x + areas[rd].width - areas[lu].x < c.full_width_before_move or
|
|
|
|
areas[rd].y + areas[rd].height - areas[lu].y < c.full_height_before_move) then
|
|
|
|
hh.x = areas[rd].x + areas[rd].width - c.full_width_before_move
|
|
|
|
hh.y = areas[rd].y + areas[rd].height - c.full_height_before_move
|
|
|
|
lu = find_lu(hh, areas, rd)
|
|
|
|
end
|
|
|
|
|
2021-02-27 06:16:32 +01:00
|
|
|
if lu ~= nil and rd ~= nil then
|
|
|
|
cd[c].lu = lu
|
|
|
|
cd[c].rd = rd
|
|
|
|
cd[c].area = nil
|
|
|
|
module.set_geometry(c, areas[lu], areas[rd], 0, c.border_width)
|
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
2021-02-27 06:16:32 +01:00
|
|
|
else
|
|
|
|
local center_x = h.x + h.width / 2
|
|
|
|
local center_y = h.y + h.height / 2
|
|
|
|
|
|
|
|
local choice = nil
|
|
|
|
local choice_value = nil
|
|
|
|
|
|
|
|
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
|
2021-02-27 02:21:21 +01:00
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
2021-02-27 06:16:32 +01:00
|
|
|
|
|
|
|
if choice and cd[c].area ~= choice then
|
|
|
|
cd[c].lu = nil
|
|
|
|
cd[c].rd = nil
|
|
|
|
cd[c].area = choice
|
|
|
|
module.set_geometry(c, areas[choice], areas[choice], 0, c.border_width)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif cd[c].draft ~= false then
|
|
|
|
local lu = find_lu(h, areas)
|
|
|
|
local rd = nil
|
|
|
|
if lu ~= nil then
|
|
|
|
local hh = {}
|
|
|
|
hh.x = h.x
|
|
|
|
hh.y = h.y
|
|
|
|
hh.width = h.width
|
|
|
|
hh.height = h.height
|
2021-02-28 15:32:19 +01:00
|
|
|
rd = find_rd(hh, c.border_width, areas, lu)
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
2019-08-01 03:00:38 +02:00
|
|
|
|
2021-02-27 06:16:32 +01:00
|
|
|
if lu ~= nil and rd ~= nil then
|
|
|
|
if lu == rd and cd[c].draft ~= true then
|
|
|
|
cd[c].lu = nil
|
|
|
|
cd[c].rd = nil
|
|
|
|
cd[c].area = lu
|
2021-02-27 17:43:25 +01:00
|
|
|
awful.layout.arrange(c.screen)
|
2021-02-27 06:16:32 +01:00
|
|
|
else
|
|
|
|
cd[c].lu = lu
|
|
|
|
cd[c].rd = rd
|
|
|
|
cd[c].area = nil
|
2021-02-27 17:43:25 +01:00
|
|
|
module.set_geometry(c, areas[lu], areas[rd], 0, c.border_width)
|
2021-02-27 06:16:32 +01:00
|
|
|
end
|
2019-08-01 03:00:38 +02:00
|
|
|
end
|
2021-02-23 06:32:58 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
layout.name = args.icon_name or "machi"
|
|
|
|
layout.arrange = arrange
|
|
|
|
layout.resize_handler = resize_handler
|
2021-02-28 15:32:19 +01:00
|
|
|
layout.machi_editor = args.editor
|
2021-02-23 06:32:58 +01:00
|
|
|
layout.machi_get_instance_info = get_instance_info
|
2021-02-27 06:16:32 +01:00
|
|
|
layout.machi_get_instance_data = get_instance_data
|
2021-02-23 06:32:58 +01:00
|
|
|
layout.machi_set_cmd = set_cmd
|
|
|
|
return layout
|
2019-07-04 23:32:05 +02:00
|
|
|
end
|
|
|
|
|
2021-02-28 15:32:19 +01:00
|
|
|
module.placement = {}
|
|
|
|
|
|
|
|
function module.placement.fair(c, instance, areas, geometry)
|
|
|
|
local area_client_count = {}
|
|
|
|
for _, oc in ipairs(c.screen.tiled_clients) do
|
|
|
|
local cd = instance.client_data[oc]
|
|
|
|
if cd and cd.placement and cd.area then
|
|
|
|
area_client_count[cd.area] = (area_client_count[cd.area] or 0) + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local emptyness_max = nil
|
|
|
|
local choice = nil
|
|
|
|
for i = 1, #areas do
|
|
|
|
local a = areas[i]
|
|
|
|
if not a.inhabitable then
|
|
|
|
local emptyness = a.width * a.height / ((area_client_count[i] or 0) + 1)
|
|
|
|
if emptyness_max == nil or emptyness > emptyness_max then
|
|
|
|
emptyness_max = emptyness
|
|
|
|
choice = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
instance.client_data[c].area = choice
|
|
|
|
geometry.x = areas[choice].x
|
|
|
|
geometry.y = areas[choice].y
|
|
|
|
geometry.width = areas[choice].width
|
|
|
|
geometry.height = areas[choice].height
|
|
|
|
end
|
|
|
|
|
2019-08-20 05:46:49 +02:00
|
|
|
return module
|