112 lines
3.7 KiB
Lua
112 lines
3.7 KiB
Lua
|
---------------------------------------------------------------------------
|
||
|
-- @author Emmanuel Lepage-Vallee <elv1313@gmail.com>
|
||
|
-- @copyright 2018-2019 Emmanuel Lepage-Vallee
|
||
|
-- @module root
|
||
|
---------------------------------------------------------------------------
|
||
|
|
||
|
local capi = { root = root }
|
||
|
local gtable = require("gears.table")
|
||
|
local gtimer = require("gears.timer")
|
||
|
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||
|
|
||
|
for _, type_name in ipairs { "button", "key" } do
|
||
|
local prop_name = type_name.."s"
|
||
|
|
||
|
-- The largest amount of wall clock time when loading Awesome 3.4 rc.lua
|
||
|
-- was the awful.util.table.join (now gears.table.join). While the main
|
||
|
-- bottleneck in the newer releases moved into LGI, doing all these `join`
|
||
|
-- slow startup down quite a lot. On top of that, with the ability to add
|
||
|
-- and remove keys and buttons can cause a large overhead of its own. To
|
||
|
-- mitigate that, only set the actual content once per main loop iteration.
|
||
|
--
|
||
|
-- The C code also delay uploading these keys into the X server to prevent
|
||
|
-- too many keyboard map changes from freezing Awesome.
|
||
|
local has_delayed, added, removed = false, {}, {}
|
||
|
|
||
|
local function delay(value)
|
||
|
if value then
|
||
|
table.insert(added, value)
|
||
|
end
|
||
|
|
||
|
if has_delayed then return end
|
||
|
|
||
|
has_delayed = true
|
||
|
|
||
|
gtimer.delayed_call(function()
|
||
|
local new_values = capi.root["_"..prop_name]()
|
||
|
|
||
|
-- In theory, because they are inserted ordered, it is safe to assume
|
||
|
-- the once found, the capi.key/button will be next to each other.
|
||
|
for _, v in ipairs(removed) do
|
||
|
local idx = gtable.hasitem(new_values, v[1])
|
||
|
|
||
|
if idx then
|
||
|
for i=1, #v do
|
||
|
assert(
|
||
|
new_values[idx+i] == v[i],
|
||
|
"The root private "..type_name.." table is corrupted"
|
||
|
)
|
||
|
|
||
|
table.remove(new_values, idx+i)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
idx = gtable.hasitem(added, v)
|
||
|
|
||
|
if idx then
|
||
|
table.remove(added, idx)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local joined = gtable.join(unpack(added))
|
||
|
new_values = gtable.merge(new_values, joined)
|
||
|
|
||
|
capi.root["_"..prop_name](new_values)
|
||
|
|
||
|
has_delayed, added, removed = false, {}, {}
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
capi.root["_append_"..type_name] = function(value)
|
||
|
if not value then return end
|
||
|
|
||
|
local t1 = capi.root._private[prop_name]
|
||
|
|
||
|
-- Simple case
|
||
|
if (not t1) or not next(t1) then
|
||
|
capi.root[prop_name] = {value}
|
||
|
assert(capi.root._private[prop_name])
|
||
|
return
|
||
|
end
|
||
|
|
||
|
delay(value)
|
||
|
end
|
||
|
|
||
|
capi.root["_append_"..prop_name] = function(values)
|
||
|
-- It's pointless to use gears.table.merge, in the background it has the
|
||
|
-- same loop anyway. Also, this isn't done very often.
|
||
|
for _, value in ipairs(values) do
|
||
|
capi.root["_append_"..type_name](value)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
capi.root["_remove_"..type_name] = function(value)
|
||
|
if not capi.root._private[prop_name] then return end
|
||
|
|
||
|
local k = gtable.hasitem(capi.root._private[prop_name], value)
|
||
|
|
||
|
if k then
|
||
|
table.remove(capi.root._private[prop_name], k)
|
||
|
end
|
||
|
|
||
|
-- Because of the legacy API, it is possible the capi.key/buttons will
|
||
|
-- be in the formatted table but not of the awful.key/button one.
|
||
|
assert(value[1])
|
||
|
|
||
|
table.insert(removed, value)
|
||
|
end
|
||
|
|
||
|
assert(root[prop_name])
|
||
|
|
||
|
end
|