initial
This commit is contained in:
commit
c1c6a759f4
|
@ -0,0 +1,13 @@
|
|||
Copyright 2019 Xinhao Yuan
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,84 @@
|
|||
# layout-machi
|
||||
|
||||
A simple and static layout for Awesome with a rapid interactive layout editor.
|
||||
|
||||
## Why?
|
||||
|
||||
1. Dynamic tiling is an overkill, since tiling is only useful for persistent windows, and people extensively use hibernate/sleep these days.
|
||||
2. I want to have a flexible layout such that I can quickly adjust to whatever I need.
|
||||
|
||||
## Use the layout
|
||||
|
||||
Use `layout-machi.layout.create_layout([LAYOUT_NAME}, [DEFAULT_REGIONS])` to instantiate the layout.
|
||||
For example:
|
||||
|
||||
```
|
||||
layout-machi.layout.create_layout("default", {})
|
||||
```
|
||||
|
||||
Creates a layout with no regions
|
||||
|
||||
## Use the editor
|
||||
|
||||
Call `layout-machi.editor.start_editor(data)` to enter the editor for the current layout (given it is a machi instance).
|
||||
`data` is am object for storing the history of the editing, initially `{}`.
|
||||
The editor starts with the open area of the entire workarea, taking command to split the current area into multiple sub-areas, then editing each of them.
|
||||
The editor is keyboard driven, accepting a number of command keys.
|
||||
Before each command, you can optionally provide at most 2 digits for parameters (A, B) of the command.
|
||||
By default A = B = 1.
|
||||
|
||||
1. `Up`/`Down`: restore to the history command sequence
|
||||
2. `h`/`v`: split the current region horizontally/vertically into 2 regions. The split will respect the ratio A:B.
|
||||
3. `w`: Take two parameters (A, B), and split the current region equally into A columns and B rows. If both A and B is 1, behave the same as `Space` without parameters.
|
||||
4. `s`: shift the current editing region with other open sibling regions.
|
||||
5. `Space` or `-`: Without parameters, close the current region and move to the next open region. With parameters, set the maximum depth of splitting (default is 2).
|
||||
6. `Enter`/`.`: close all open regions. When all regions are closed, press `Enter` will save the layout and exit the editor.
|
||||
7. `Backspace`: undo the last command.
|
||||
8. `Escape`: exit the editor without saving the layout.
|
||||
|
||||
## Other functions
|
||||
|
||||
`layout-machi.editor.cycle_region(c)` will fit a floating client into the closest region, then cycle through all regions.
|
||||
|
||||
## Demos:
|
||||
|
||||
I used `Super + /` for editor and `Super + Tab` for fitting the windows.
|
||||
|
||||
|
||||
h-v
|
||||
|
||||
```
|
||||
11 22
|
||||
11 22
|
||||
11
|
||||
11 33
|
||||
11 33
|
||||
```
|
||||
|
||||
![][https://i.imgur.com/QbvMRTW.gif]
|
||||
|
||||
|
||||
hvv (or 22w)
|
||||
|
||||
```
|
||||
11 33
|
||||
11 33
|
||||
|
||||
22 44
|
||||
22 44
|
||||
```
|
||||
|
||||
![][https://i.imgur.com/xJebxcF.gif]
|
||||
|
||||
|
||||
history
|
||||
|
||||
![][https://i.imgur.com/gzFr48V.gif]
|
||||
|
||||
## TODO
|
||||
|
||||
- Make history persistent
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0 --- See LICENSE
|
|
@ -0,0 +1,537 @@
|
|||
local api = {
|
||||
beautiful = require("beautiful"),
|
||||
wibox = require("wibox"),
|
||||
awful = require("awful"),
|
||||
screen = require("awful.screen"),
|
||||
layout = require("awful.layout"),
|
||||
keygrabber = require("awful.keygrabber"),
|
||||
naughty = require("naughty"),
|
||||
gears = require("gears"),
|
||||
dpi = require("beautiful.xresources").apply_dpi,
|
||||
}
|
||||
|
||||
local gap = api.beautiful.useless_gap or 0
|
||||
local label_font_family = api.beautiful.get_font(
|
||||
api.beautiful.mono_font or api.beautiful.font):get_family()
|
||||
local label_size = api.dpi(30)
|
||||
local info_size = api.dpi(60)
|
||||
-- colors are in rgba
|
||||
local border_color = "#ffffffc0"
|
||||
local active_color = "#6c7ea780"
|
||||
local open_color = "#00000080"
|
||||
local closed_color = "#00000080"
|
||||
local init_max_depth = 2
|
||||
|
||||
function is_tiling(c)
|
||||
return
|
||||
not (c.tomb_floating or c.floating or c.maximized_horizontal or c.maximized_vertical or c.maximized or c.fullscreen)
|
||||
end
|
||||
|
||||
function set_tiling(c)
|
||||
c.floating = false
|
||||
c.maximized = false
|
||||
c.maximized_vertical = false
|
||||
c.maximized_horizontal = false
|
||||
c.fullscreen = false
|
||||
end
|
||||
|
||||
function min(a, b)
|
||||
if a < b then return a else return b end
|
||||
end
|
||||
|
||||
function max(a, b)
|
||||
if a < b then return b else return a end
|
||||
end
|
||||
|
||||
function set_region(c, r)
|
||||
c.floating = false
|
||||
c.maximized = false
|
||||
c.fullscreen = false
|
||||
c.machi_region = r
|
||||
api.layout.arrange(c.screen)
|
||||
end
|
||||
|
||||
-- find the best region for the area
|
||||
function fit_region(c, regions)
|
||||
local choice = 1
|
||||
local choice_value = nil
|
||||
local c_area = c.width * c.height
|
||||
for i, a in ipairs(regions) do
|
||||
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
|
||||
return choice
|
||||
end
|
||||
|
||||
function cycle_region(c)
|
||||
layout = api.layout.get(c.screen)
|
||||
regions = layout.get_regions and layout.get_regions()
|
||||
if type(regions) ~= "table" or #regions < 1 then
|
||||
c.float = true
|
||||
return
|
||||
end
|
||||
current_region = c.machi_region or 1
|
||||
if not is_tiling(c) then
|
||||
-- find out which region has the most intersection, calculated by a cap b / a cup b
|
||||
c.machi_region = fit_region(c, regions)
|
||||
set_tiling(c)
|
||||
elseif current_region >= #regions then
|
||||
c.machi_region = 1
|
||||
else
|
||||
c.machi_region = current_region + 1
|
||||
end
|
||||
api.layout.arrange(c.screen)
|
||||
end
|
||||
|
||||
function _area_tostring(wa)
|
||||
return "{x:" .. tostring(wa.x) .. ",y:" .. tostring(wa.y) .. ",w:" .. tostring(wa.width) .. ",h:" .. tostring(wa.height) .. "}"
|
||||
end
|
||||
|
||||
function shrink_area_with_gap(a, gap)
|
||||
return { x = a.x + (a.bl and 0 or gap / 2), y = a.y + (a.bu and 0 or gap / 2),
|
||||
width = a.width - (a.bl and 0 or gap / 2) - (a.br and 0 or gap / 2),
|
||||
height = a.height - (a.bu and 0 or gap / 2) - (a.bd and 0 or gap / 2) }
|
||||
end
|
||||
|
||||
function start_editor(data)
|
||||
if data.cmds == nil then
|
||||
data.cmds = {}
|
||||
end
|
||||
|
||||
local cmd_index = #data.cmds + 1
|
||||
data.cmds[cmd_index] = ""
|
||||
|
||||
local screen = api.screen.focused()
|
||||
local init_area = {
|
||||
x = screen.workarea.x,
|
||||
y = screen.workarea.y,
|
||||
width = screen.workarea.width,
|
||||
height = screen.workarea.height,
|
||||
border = 15,
|
||||
depth = 0,
|
||||
-- we do not want to rely on bitop
|
||||
bl = true, br = true, bu = true, bd = true,
|
||||
}
|
||||
local kg
|
||||
local infobox = api.wibox({
|
||||
x = screen.workarea.x,
|
||||
y = screen.workarea.y,
|
||||
width = screen.workarea.width,
|
||||
height = screen.workarea.height,
|
||||
bg = "#ffffff00",
|
||||
opacity = 1,
|
||||
ontop = true
|
||||
})
|
||||
infobox.visible = true
|
||||
|
||||
local closed_areas
|
||||
local open_areas
|
||||
local history
|
||||
local num_1
|
||||
local num_2
|
||||
local max_depth
|
||||
local current_info
|
||||
local current_cmd
|
||||
local to_exit
|
||||
local to_apply
|
||||
|
||||
local function init()
|
||||
closed_areas = {}
|
||||
open_areas = {init_area}
|
||||
history = {}
|
||||
num_1 = nil
|
||||
num_2 = nil
|
||||
max_depth = init_max_depth
|
||||
current_info = ""
|
||||
current_cmd = ""
|
||||
to_exit = false
|
||||
to_apply = false
|
||||
end
|
||||
|
||||
local function draw_info(context, cr, width, height)
|
||||
cr:set_source_rgba(0, 0, 0, 0)
|
||||
cr:rectangle(0, 0, width, height)
|
||||
cr:fill()
|
||||
|
||||
local msg, ext
|
||||
|
||||
for i, a in ipairs(closed_areas) do
|
||||
local sa = shrink_area_with_gap(a, gap)
|
||||
cr:rectangle(sa.x, sa.y, sa.width, sa.height)
|
||||
cr:clip()
|
||||
cr:set_source(api.gears.color(closed_color))
|
||||
cr:rectangle(sa.x, sa.y, sa.width, sa.height)
|
||||
cr:fill()
|
||||
cr:set_source(api.gears.color(border_color))
|
||||
cr:rectangle(sa.x, sa.y, sa.width, sa.height)
|
||||
cr:set_line_width(10.0)
|
||||
cr:stroke()
|
||||
|
||||
cr:select_font_face(label_font_family, "normal", "normal")
|
||||
cr:set_font_size(label_size)
|
||||
cr:set_font_face(cr:get_font_face())
|
||||
msg = tostring(i)
|
||||
ext = cr:text_extents(msg)
|
||||
cr:set_source_rgba(1, 1, 1, 1)
|
||||
cr:move_to(sa.x + sa.width / 2 - ext.width / 2 - ext.x_bearing, sa.y + sa.height / 2 - ext.height / 2 - ext.y_bearing)
|
||||
cr:show_text(msg)
|
||||
cr:reset_clip()
|
||||
end
|
||||
|
||||
for i, a in ipairs(open_areas) do
|
||||
local sa = shrink_area_with_gap(a, gap)
|
||||
cr:rectangle(sa.x, sa.y, sa.width, sa.height)
|
||||
cr:clip()
|
||||
if i == #open_areas then
|
||||
cr:set_source(api.gears.color(active_color))
|
||||
else
|
||||
cr:set_source(api.gears.color(open_color))
|
||||
end
|
||||
cr:rectangle(sa.x, sa.y, sa.width, sa.height)
|
||||
cr:fill()
|
||||
|
||||
cr:set_source(api.gears.color(border_color))
|
||||
cr:rectangle(sa.x, sa.y, sa.width, sa.height)
|
||||
cr:set_line_width(10.0)
|
||||
if i ~= #open_areas then
|
||||
cr:set_dash({5, 5}, 0)
|
||||
cr:stroke()
|
||||
cr:set_dash({}, 0)
|
||||
else
|
||||
cr:stroke()
|
||||
end
|
||||
cr:reset_clip()
|
||||
end
|
||||
|
||||
cr:select_font_face(label_font_family, "normal", "normal")
|
||||
cr:set_font_size(info_size)
|
||||
cr:set_font_face(cr:get_font_face())
|
||||
msg = current_info
|
||||
ext = cr:text_extents(msg)
|
||||
cr:move_to(width / 2 - ext.width / 2 - ext.x_bearing, height / 2 - ext.height / 2 - ext.y_bearing)
|
||||
cr:text_path(msg)
|
||||
cr:set_source_rgba(1, 1, 1, 1)
|
||||
cr:fill()
|
||||
cr:move_to(width / 2 - ext.width / 2 - ext.x_bearing, height / 2 - ext.height / 2 - ext.y_bearing)
|
||||
cr:text_path(msg)
|
||||
cr:set_source_rgba(0, 0, 0, 1)
|
||||
cr:set_line_width(2.0)
|
||||
cr:stroke()
|
||||
end
|
||||
|
||||
local function push_history()
|
||||
history[#history + 1] = {#closed_areas, #open_areas, {}, current_info, current_cmd, max_depth, num_1, num_2}
|
||||
end
|
||||
|
||||
local function discard_history()
|
||||
table.remove(history, #history)
|
||||
end
|
||||
|
||||
local function pop_history()
|
||||
if #history == 0 then return end
|
||||
for i = history[#history][1] + 1, #closed_areas do
|
||||
table.remove(closed_areas, #closed_areas)
|
||||
end
|
||||
|
||||
for i = history[#history][2] + 1, #open_areas do
|
||||
table.remove(open_areas, #open_areas)
|
||||
end
|
||||
|
||||
for i = 1, #history[#history][3] do
|
||||
open_areas[history[#history][2] - i + 1] = history[#history][3][i]
|
||||
end
|
||||
|
||||
current_info = history[#history][4]
|
||||
current_cmd = history[#history][5]
|
||||
max_depth = history[#history][6]
|
||||
num_1 = history[#history][7]
|
||||
num_2 = history[#history][8]
|
||||
|
||||
table.remove(history, #history)
|
||||
end
|
||||
|
||||
local function pop_open_area()
|
||||
local a = open_areas[#open_areas]
|
||||
table.remove(open_areas, #open_areas)
|
||||
local idx = history[#history][2] - #open_areas
|
||||
-- only save when the position has been firstly poped
|
||||
if idx > #history[#history][3] then
|
||||
history[#history][3][#history[#history][3] + 1] = a
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
local function refresh()
|
||||
print("closed areas:")
|
||||
for i, a in ipairs(closed_areas) do
|
||||
print(" " .. _area_tostring(a))
|
||||
end
|
||||
print("open areas:")
|
||||
for i, a in ipairs(open_areas) do
|
||||
print(" " .. _area_tostring(a))
|
||||
end
|
||||
infobox.bgimage = draw_info
|
||||
end
|
||||
|
||||
local function handle_split(method, alt)
|
||||
if num_1 == nil then num_1 = 1 end
|
||||
if num_2 == nil then num_2 = 1 end
|
||||
|
||||
if alt then
|
||||
local tmp = num_1
|
||||
num_1 = num_2
|
||||
num_2 = tmp
|
||||
end
|
||||
|
||||
local a = pop_open_area()
|
||||
local lu, rd
|
||||
|
||||
print("split " .. method .. " " .. tostring(alt) .. " " .. _area_tostring(a))
|
||||
|
||||
if method == "h" then
|
||||
lu = {
|
||||
x = a.x, y = a.y,
|
||||
width = a.width / (num_1 + num_2) * num_1, height = a.height,
|
||||
depth = a.depth + 1,
|
||||
bl = a.bl, br = false, bu = a.bu, bd = a.bd,
|
||||
}
|
||||
rd = {
|
||||
x = a.x + lu.width, y = a.y,
|
||||
width = a.width - lu.width, height = a.height,
|
||||
depth = a.depth + 1,
|
||||
bl = false, br = a.br, bu = a.bu, bd = a.bd,
|
||||
}
|
||||
open_areas[#open_areas + 1] = rd
|
||||
open_areas[#open_areas + 1] = lu
|
||||
elseif method == "v" then
|
||||
lu = {
|
||||
x = a.x, y = a.y,
|
||||
width = a.width, height = a.height / (num_1 + num_2) * num_1,
|
||||
depth = a.depth + 1,
|
||||
bl = a.bl, br = a.br, bu = a.bu, bd = false
|
||||
}
|
||||
rd = {
|
||||
x = a.x, y = a.y + lu.height,
|
||||
width = a.width, height = a.height - lu.height,
|
||||
depth = a.depth + 1,
|
||||
bl = a.bl, br = a.br, bu = false, bd = a.bd,
|
||||
}
|
||||
open_areas[#open_areas + 1] = rd
|
||||
open_areas[#open_areas + 1] = lu
|
||||
elseif method == "w" then
|
||||
local x_interval = a.width / num_1
|
||||
local y_interval = a.height / num_2
|
||||
for y = num_2, 1, -1 do
|
||||
for x = num_1, 1, -1 do
|
||||
local r = {
|
||||
x = a.x + x_interval * (x - 1),
|
||||
y = a.y + y_interval * (y - 1),
|
||||
width = x_interval,
|
||||
height = y_interval,
|
||||
depth = a.depth + 1
|
||||
}
|
||||
if x == 1 then r.bl = a.bl else r.bl = false end
|
||||
if x == num_1 then r.br = a.br else r.br = false end
|
||||
if y == 1 then r.bu = a.bu else r.bu = false end
|
||||
if y == num_2 then r.bd = a.bd else r.bd = false end
|
||||
open_areas[#open_areas + 1] = r
|
||||
end
|
||||
end
|
||||
elseif method == "P" then
|
||||
-- XXX
|
||||
end
|
||||
|
||||
num_1 = nil
|
||||
num_2 = nil
|
||||
end
|
||||
|
||||
local function cleanup()
|
||||
infobox.visible = false
|
||||
end
|
||||
|
||||
local function push_area()
|
||||
closed_areas[#closed_areas + 1] = pop_open_area()
|
||||
infobox.bgimage = draw_info
|
||||
end
|
||||
|
||||
local function handle_command(key)
|
||||
if key == "h" or key == "H" then
|
||||
handle_split("h", key == "H")
|
||||
elseif key == "v" or key == "V" then
|
||||
handle_split("v", key == "V")
|
||||
elseif key == "w" or key == "W" then
|
||||
push_history()
|
||||
if num_1 == nil and num_2 == nil then
|
||||
push_area()
|
||||
else
|
||||
handle_split("w", key == "W")
|
||||
end
|
||||
elseif key == "p" or key == "P" then
|
||||
handle_split("p", key == "P")
|
||||
elseif key == "s" or key == "S" then
|
||||
if #open_areas > 0 then
|
||||
key = "s"
|
||||
local top = pop_open_area()
|
||||
local t = {}
|
||||
while #open_areas > 0 and open_areas[#open_areas].depth == top.depth do
|
||||
t[#t + 1] = pop_open_area()
|
||||
end
|
||||
open_areas[#open_areas + 1] = top
|
||||
for i = #t, 1, -1 do
|
||||
open_areas[#open_areas + 1] = t[i]
|
||||
end
|
||||
num_1 = nil
|
||||
num_2 = nil
|
||||
else
|
||||
return nil
|
||||
end
|
||||
elseif key == " " or key == "-" then
|
||||
key = "-"
|
||||
if num_1 ~= nil then
|
||||
max_depth = num_1
|
||||
num_1 = nil
|
||||
num_2 = nil
|
||||
else
|
||||
push_area()
|
||||
end
|
||||
elseif key == "Return" or key == "." then
|
||||
key = "."
|
||||
while #open_areas > 0 do
|
||||
push_area()
|
||||
end
|
||||
elseif tonumber(key) ~= nil then
|
||||
local v = tonumber(key)
|
||||
if num_1 == nil then
|
||||
num_1 = v
|
||||
elseif num_2 == nil then
|
||||
num_2 = v
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
while #open_areas > 0 and open_areas[#open_areas].depth >= max_depth do
|
||||
push_area()
|
||||
end
|
||||
|
||||
return key
|
||||
end
|
||||
|
||||
print("interactive layout editing starts")
|
||||
|
||||
init()
|
||||
refresh()
|
||||
|
||||
kg = keygrabber.run(function (mod, key, event)
|
||||
if event == "release" then
|
||||
return
|
||||
end
|
||||
|
||||
if key == "BackSpace" then
|
||||
pop_history()
|
||||
elseif key == "Escape" then
|
||||
to_exit = true
|
||||
elseif key == "Up" or key == "Down" then
|
||||
if current_cmd ~= data.cmds[cmd_index] then
|
||||
data.cmds[#data.cmds] = current_cmd
|
||||
end
|
||||
|
||||
if key == "Up" and cmd_index > 1 then
|
||||
cmd_index = cmd_index - 1
|
||||
elseif key == "Down" and cmd_index < #data.cmds then
|
||||
cmd_index = cmd_index + 1
|
||||
end
|
||||
|
||||
print("restore history #" .. tostring(cmd_index) .. ":" .. data.cmds[cmd_index])
|
||||
init()
|
||||
for i = 1, #data.cmds[cmd_index] do
|
||||
cmd = data.cmds[cmd_index]:sub(i, i)
|
||||
|
||||
push_history()
|
||||
local ret = handle_command(cmd)
|
||||
|
||||
current_info = current_info .. ret
|
||||
current_cmd = current_cmd .. ret
|
||||
end
|
||||
|
||||
if #open_areas == 0 then
|
||||
current_info = current_info .. " (enter to save)"
|
||||
end
|
||||
elseif #open_areas > 0 then
|
||||
push_history()
|
||||
local ret = handle_command(key)
|
||||
if ret ~= nil then
|
||||
current_info = current_info .. ret
|
||||
current_cmd = current_cmd .. ret
|
||||
else
|
||||
discard_history()
|
||||
end
|
||||
|
||||
if #open_areas == 0 then
|
||||
current_info = current_info .. " (enter to save)"
|
||||
end
|
||||
else
|
||||
if key == "Return" then
|
||||
table.remove(data.cmds, #data.cmds)
|
||||
if cmd_index <= #data.cmds and current_cmd == data.cmds[cmd_index] then
|
||||
table.remove(data.cmds, cmd_index)
|
||||
end
|
||||
data.cmds[#data.cmds + 1] = current_cmd
|
||||
current_info = "Saved!"
|
||||
to_exit = true
|
||||
to_apply = true
|
||||
end
|
||||
end
|
||||
|
||||
refresh()
|
||||
|
||||
if to_exit then
|
||||
print("interactive layout editing ends")
|
||||
if to_apply then
|
||||
layout = api.layout.get(screen)
|
||||
if layout.set_regions then
|
||||
local areas_with_gap = {}
|
||||
for _, a in ipairs(closed_areas) do
|
||||
areas_with_gap[#areas_with_gap + 1] = shrink_area_with_gap(a, gap)
|
||||
end
|
||||
layout.set_regions(areas_with_gap)
|
||||
api.layout.arrange(screen)
|
||||
end
|
||||
api.gears.timer{
|
||||
timeout = 1,
|
||||
autostart = true,
|
||||
singleshot = true,
|
||||
callback = cleanup
|
||||
}
|
||||
else
|
||||
cleanup()
|
||||
end
|
||||
keygrabber.stop(kg)
|
||||
return
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return
|
||||
{
|
||||
set_region = set_region,
|
||||
cycle_region = cycle_region,
|
||||
start_editor = start_editor,
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
function do_arrange(p, priv)
|
||||
local wa = p.workarea
|
||||
local cls = p.clients
|
||||
local regions = priv.regions
|
||||
|
||||
for i, c in ipairs(cls) do
|
||||
if c.floating then
|
||||
print("Ignore client " .. tostring(c))
|
||||
else
|
||||
local region
|
||||
if c.machi_region == nil then
|
||||
c.machi_region = 1
|
||||
region = 1
|
||||
elseif c.machi_region > #regions or c.machi_region <= 1 then
|
||||
region = 1
|
||||
else
|
||||
region = c.machi_region
|
||||
end
|
||||
|
||||
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_layout(name, regions)
|
||||
local priv = {}
|
||||
|
||||
local function set_regions(regions)
|
||||
priv.regions = regions
|
||||
end
|
||||
|
||||
local function get_regions()
|
||||
return priv.regions
|
||||
end
|
||||
|
||||
set_regions(regions)
|
||||
|
||||
return {
|
||||
name = "machi[" .. name .. "]",
|
||||
arrange = function (p) do_arrange(p, priv) end,
|
||||
get_region_count = function () return #priv.regions end,
|
||||
set_regions = set_regions,
|
||||
get_regions = get_regions,
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
create_layout = create_layout,
|
||||
}
|
Loading…
Reference in New Issue