2018-12-31 23:40:08 +01:00
|
|
|
require("awful._compat")
|
|
|
|
|
|
|
|
local runner = require( "_runner" )
|
|
|
|
local placement = require( "awful.placement" )
|
|
|
|
local gtable = require( "gears.table" )
|
|
|
|
local test_client = require( "_client" )
|
2019-12-04 07:37:07 +01:00
|
|
|
local akeyboard = require( "awful.keyboard" )
|
|
|
|
local amouse = require( "awful.mouse" )
|
2018-12-31 23:40:08 +01:00
|
|
|
|
|
|
|
local module = {
|
|
|
|
key = require( "awful.key" ),
|
|
|
|
button = require( "awful.button" )
|
|
|
|
}
|
|
|
|
|
|
|
|
local steps = {}
|
|
|
|
|
|
|
|
local second = {
|
|
|
|
key = { "a", "b", "c", "d" },
|
|
|
|
button = { 1 , 2 , 3 , 4 },
|
|
|
|
}
|
|
|
|
|
|
|
|
local function send_events(event_type, step)
|
|
|
|
root.fake_input("key_press" , "Alt_L")
|
|
|
|
root.fake_input(event_type.."_press" , second[event_type][step])
|
|
|
|
root.fake_input(event_type.."_release", second[event_type][step])
|
|
|
|
root.fake_input("key_release", "Alt_L")
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Test the shared API between the keys and buttons
|
|
|
|
for _, type_name in ipairs { "key", "button" } do
|
|
|
|
local objects = {}
|
|
|
|
|
|
|
|
local pressed, released = {}, {}
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
objects[1] = module[type_name](
|
|
|
|
{"Mod1"}, second[type_name][1], function() pressed[1] = true end, function() released[1] = true end
|
|
|
|
)
|
|
|
|
|
|
|
|
assert(objects[1].has_root_binding == false)
|
|
|
|
assert(not pressed [1])
|
|
|
|
assert(not released[1])
|
|
|
|
|
|
|
|
root["_append_"..type_name](objects[1])
|
|
|
|
|
|
|
|
-- It is async, the result need to be verified later
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
assert(objects[1].has_root_binding)
|
|
|
|
|
|
|
|
-- Test "artificial" execution
|
|
|
|
objects[1]:trigger()
|
|
|
|
|
|
|
|
assert(pressed [1])
|
|
|
|
assert(released[1])
|
|
|
|
|
|
|
|
-- Test adding and removing in the same iteration
|
|
|
|
root["_remove_"..type_name](objects[1])
|
|
|
|
|
|
|
|
assert(second[type_name][2])
|
2019-10-27 21:53:33 +01:00
|
|
|
|
|
|
|
-- Use the multiple parameters syntax.
|
2018-12-31 23:40:08 +01:00
|
|
|
objects[2] = module[type_name](
|
|
|
|
{"Mod1"}, second[type_name][2], function() pressed[2] = true end, function() released[2] = true end
|
|
|
|
)
|
|
|
|
|
|
|
|
root["_append_"..type_name](objects[2])
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
assert(objects[2].has_root_binding == true )
|
|
|
|
assert(objects[1].has_root_binding == false)
|
|
|
|
|
|
|
|
-- Make sure the cursor is not over the wibar
|
|
|
|
placement.centered(mouse)
|
|
|
|
|
|
|
|
assert(second[type_name][2])
|
|
|
|
send_events(type_name, 2)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Wait until the events are registered.
|
|
|
|
table.insert(steps, function()
|
|
|
|
if (not pressed[2]) or (not released[2]) then return end
|
|
|
|
|
|
|
|
-- Spawn a client.
|
|
|
|
test_client("myclient")
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
--FIXME it works when manually tested, but automated testing is too flacky
|
|
|
|
-- to enable...
|
|
|
|
if type_name == "key" then
|
|
|
|
table.insert(steps, function()
|
|
|
|
if #mouse.screen.clients ~= 1 then return end
|
|
|
|
|
|
|
|
placement.maximize(mouse.screen.clients[1])
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
local o1, o2 = nil
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
local c = mouse.screen.clients[1]
|
|
|
|
|
2019-10-27 21:53:33 +01:00
|
|
|
-- This time, use the `args` syntax.
|
|
|
|
local args = {
|
|
|
|
modifiers = {"Mod1"},
|
|
|
|
on_press = function() pressed [3] = true end,
|
|
|
|
on_release = function() released[3] = true end
|
|
|
|
}
|
|
|
|
|
|
|
|
args[type_name] = second[type_name][3]
|
|
|
|
|
|
|
|
-- This time, use the `args` syntax.
|
|
|
|
o1 = module[type_name](args)
|
2018-12-31 23:40:08 +01:00
|
|
|
|
|
|
|
-- Test the old API.
|
|
|
|
c[type_name.."s"](c, gtable.join(o1))
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- This wont work until the client buttons/keys are updated, there is no
|
|
|
|
-- way to know ahead of time.
|
|
|
|
table.insert(steps, function(count)
|
|
|
|
|
|
|
|
if count < 5 then awesome.sync(); return end
|
|
|
|
|
|
|
|
send_events(type_name, 3)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if (not pressed[3]) or (not released[3]) then return end
|
|
|
|
|
|
|
|
local c = mouse.screen.clients[1]
|
|
|
|
|
|
|
|
-- Unset the events to make sure keys can be removed.
|
|
|
|
pressed[3], released[3] = false, false
|
|
|
|
|
|
|
|
o2 = module[type_name](
|
|
|
|
{"Mod1"}, second[type_name][4], function() pressed[4] = true end, function() released[4] = true end
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Test the new API
|
|
|
|
c[type_name.."s"] = {o2}
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function(count)
|
|
|
|
if count < 5 then awesome.sync(); return end
|
|
|
|
|
|
|
|
send_events(type_name, 3)
|
|
|
|
send_events(type_name, 4)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if (not pressed[4]) or (not released[4]) then return end
|
|
|
|
|
|
|
|
assert(not pressed [3])
|
|
|
|
assert(not released[3])
|
|
|
|
|
|
|
|
local c = mouse.screen.clients[1]
|
|
|
|
|
|
|
|
-- Make sure mixing the 2 syntaxes doesn't create a chimera state
|
|
|
|
pressed[4], released[4] = false, false
|
|
|
|
|
|
|
|
-- This *will* happen with older configs because `awful.rules` will
|
|
|
|
-- loop the properties, find the old capi list and fail to understand
|
|
|
|
-- that the content should use the legacy API.
|
2019-10-27 01:54:55 +02:00
|
|
|
|
|
|
|
local joined = gtable.join(o1)
|
|
|
|
|
|
|
|
assert(#joined == 4)
|
|
|
|
|
|
|
|
c[type_name.."s"] = joined
|
|
|
|
|
|
|
|
-- It should have been converted to the new format.
|
|
|
|
assert(#c[type_name.."s"] == 1)
|
2018-12-31 23:40:08 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function(count)
|
|
|
|
if count < 5 then awesome.sync(); return end
|
|
|
|
|
|
|
|
send_events(type_name, 3)
|
|
|
|
send_events(type_name, 4)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if (not pressed[3]) or (not released[3]) then return end
|
|
|
|
|
|
|
|
assert(not pressed [4])
|
|
|
|
assert(not released[4])
|
|
|
|
|
|
|
|
local c = mouse.screen.clients[1]
|
|
|
|
|
2019-10-27 01:54:55 +02:00
|
|
|
assert(#c[type_name.."s"] == 1)
|
2018-12-31 23:40:08 +01:00
|
|
|
|
|
|
|
-- Test setting the object to `false` to simulate an inline Lua
|
|
|
|
-- expression gone wrong. This used to work and is rather
|
|
|
|
-- convenient, so lets not break it even if it is technically a bug.
|
|
|
|
c[type_name.."s"] = false
|
|
|
|
|
|
|
|
assert(#c[type_name.."s"] == 0)
|
|
|
|
|
|
|
|
c[type_name.."s"] = {o1}
|
|
|
|
|
2019-10-27 01:54:55 +02:00
|
|
|
assert(#c[type_name.."s"] == 1)
|
2018-12-31 23:40:08 +01:00
|
|
|
|
|
|
|
-- Test removing the objects using `nil`.
|
|
|
|
c[type_name.."s"] = nil
|
|
|
|
|
|
|
|
assert(#c[type_name.."s"] == 0)
|
|
|
|
|
|
|
|
c[type_name.."s"] = {o1}
|
|
|
|
|
2019-10-27 01:54:55 +02:00
|
|
|
assert(#c[type_name.."s"] == 1)
|
2018-12-31 23:40:08 +01:00
|
|
|
|
|
|
|
-- Test removing using `{}`
|
|
|
|
c[type_name.."s"] = {}
|
|
|
|
|
|
|
|
assert(#c[type_name.."s"] == 0)
|
|
|
|
|
|
|
|
c:kill()
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Cleanup (otherwise there is a race with the root.buttons tests)
|
|
|
|
table.insert(steps, function()
|
|
|
|
if #mouse.screen.clients ~= 0 then return end
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-04 07:37:07 +01:00
|
|
|
local exe1, exe2, exe3, exe4 = false, false, false, false
|
|
|
|
local new1, new2 = nil, nil
|
|
|
|
|
|
|
|
-- Check that you can add new default key/mousebindings at any time.
|
|
|
|
table.insert(steps, function()
|
2021-09-21 01:04:41 +02:00
|
|
|
if #mouse.screen.clients > 0 then return end
|
2019-12-04 07:37:07 +01:00
|
|
|
|
|
|
|
new1 = module.key {
|
|
|
|
key = "a",
|
|
|
|
modifiers = {},
|
|
|
|
on_press = function() exe1 = true end
|
|
|
|
}
|
|
|
|
|
|
|
|
new2 = module.button {
|
|
|
|
button = 8,
|
|
|
|
modifiers = {},
|
|
|
|
on_press = function() exe2 = true end
|
|
|
|
}
|
|
|
|
|
|
|
|
akeyboard.append_client_keybinding(new1)
|
|
|
|
amouse.append_client_mousebinding(new2)
|
|
|
|
|
|
|
|
-- Spawn a client.
|
|
|
|
test_client("myclient")
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if #mouse.screen.clients == 0 then return end
|
|
|
|
|
|
|
|
client.focus = mouse.screen.clients[1]
|
|
|
|
|
|
|
|
-- That should trigger the newly added keybinding.
|
|
|
|
root.fake_input("key_press" , "a")
|
|
|
|
root.fake_input("key_release", "a")
|
|
|
|
|
|
|
|
-- Move the mouse over the client so mousebindings work.
|
|
|
|
placement.centered(mouse, {parent=client.focus})
|
|
|
|
awesome.sync()
|
|
|
|
|
|
|
|
-- Same thing for the mouse.
|
|
|
|
root.fake_input("button_press" , 8)
|
|
|
|
root.fake_input("button_release", 8)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if (not exe1) or (not exe2) then return end
|
|
|
|
|
|
|
|
akeyboard.remove_client_keybinding(new1)
|
|
|
|
amouse.remove_client_mousebinding(new2)
|
|
|
|
|
|
|
|
exe1, exe2 = false, false
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Removing is async, so wait until the next loop.
|
|
|
|
table.insert(steps, function()
|
|
|
|
root.fake_input("key_press" , "a")
|
|
|
|
root.fake_input("key_release", "a")
|
|
|
|
root.fake_input("button_press" , 8)
|
|
|
|
root.fake_input("button_release", 8)
|
|
|
|
awesome.sync()
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Try adding key/mousebindings to existing clients.
|
|
|
|
table.insert(steps, function(count)
|
|
|
|
if count ~= 3 then return end
|
|
|
|
|
|
|
|
assert(not exe1)
|
|
|
|
assert(not exe2)
|
|
|
|
|
|
|
|
-- Append both types at the same time to make sure nothing overwrite
|
|
|
|
-- the list.
|
|
|
|
akeyboard.append_client_keybinding(new1)
|
|
|
|
amouse.append_client_mousebinding(new2)
|
|
|
|
|
|
|
|
new1 = module.key {
|
|
|
|
key = "b",
|
|
|
|
modifiers = {},
|
|
|
|
on_press = function() exe3 = true end
|
|
|
|
}
|
|
|
|
|
|
|
|
new2 = module.button {
|
|
|
|
button = 7,
|
|
|
|
modifiers = {},
|
|
|
|
on_press = function() exe4 = true end
|
|
|
|
}
|
|
|
|
|
|
|
|
-- Append directly on the client.
|
|
|
|
client.focus:append_keybinding(new1)
|
|
|
|
client.focus:append_mousebinding(new2)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Removing is async, so wait until the next loop.
|
|
|
|
table.insert(steps, function()
|
|
|
|
|
|
|
|
root.fake_input("key_press" , "b")
|
|
|
|
root.fake_input("key_release", "b")
|
|
|
|
root.fake_input("button_press" , 7)
|
|
|
|
root.fake_input("button_release", 7)
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
|
|
|
table.insert(steps, function()
|
|
|
|
if (not exe3) or (not exe4) then return end
|
|
|
|
|
|
|
|
-- Note, there is no point to try remove_keybinding, it was already called
|
|
|
|
-- (indirectly) 4 steps ago.
|
|
|
|
|
|
|
|
return true
|
|
|
|
end)
|
|
|
|
|
2018-12-31 23:40:08 +01:00
|
|
|
runner.run_steps(steps)
|
|
|
|
|
|
|
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|