239 lines
7.2 KiB
Lua
239 lines
7.2 KiB
Lua
---------------------------------------------------------------------------
|
|
--- Utilities related to the keyboard and keybindings.
|
|
--
|
|
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
|
|
-- @copyright 2018-2019 Emmanuel Lepage Vallee
|
|
-- @inputmodule awful.keyboard
|
|
---------------------------------------------------------------------------
|
|
|
|
local capi = {root = root, awesome = awesome, client = client}
|
|
local module = {}
|
|
|
|
--- Convert the modifiers into pc105 key names
|
|
local conversion = nil
|
|
|
|
local function generate_conversion_map()
|
|
if conversion then return conversion end
|
|
|
|
local mods = capi.awesome._modifiers
|
|
assert(mods)
|
|
|
|
conversion = {}
|
|
|
|
for mod, keysyms in pairs(mods) do
|
|
for _, keysym in ipairs(keysyms) do
|
|
assert(keysym.keysym)
|
|
conversion[mod] = conversion[mod] or keysym.keysym
|
|
conversion[keysym.keysym] = mod
|
|
end
|
|
end
|
|
|
|
return conversion
|
|
end
|
|
|
|
capi.awesome.connect_signal("xkb::map_changed", function() conversion = nil end)
|
|
|
|
--- Execute a key combination.
|
|
--
|
|
-- If an awesome keybinding is assigned to the combination, it should be
|
|
-- executed.
|
|
--
|
|
-- To limit the chances of accidentally leaving a modifier key locked when
|
|
-- calling this function from a keybinding, make sure is attached to the
|
|
-- release event and not the press event.
|
|
--
|
|
-- @see root.fake_input
|
|
-- @tparam table modifiers A modified table. Valid modifiers are: `Any`, `Mod1`,
|
|
-- `Mod2`, `Mod3`, `Mod4`, `Mod5`, `Shift`, `Lock` and `Control`.
|
|
-- @tparam string key The key.
|
|
-- @noreturn
|
|
-- @staticfct awful.keyboard.emulate_key_combination
|
|
function module.emulate_key_combination(modifiers, key)
|
|
local modmap = generate_conversion_map()
|
|
local active = capi.awesome._active_modifiers
|
|
|
|
-- Release all modifiers
|
|
for _, m in ipairs(active) do
|
|
assert(modmap[m])
|
|
capi.root.fake_input("key_release", modmap[m])
|
|
end
|
|
|
|
for _, v in ipairs(modifiers) do
|
|
local m = modmap[v]
|
|
if m then
|
|
capi.root.fake_input("key_press", m)
|
|
end
|
|
end
|
|
|
|
capi.root.fake_input("key_press" , key)
|
|
capi.root.fake_input("key_release", key)
|
|
|
|
for _, v in ipairs(modifiers) do
|
|
local m = modmap[v]
|
|
if m then
|
|
capi.root.fake_input("key_release", m)
|
|
end
|
|
end
|
|
|
|
-- Restore the previous modifiers all modifiers. Please note that yes,
|
|
-- there is a race condition if the user was fast enough to release the
|
|
-- key during this operation.
|
|
for _, m in ipairs(active) do
|
|
capi.root.fake_input("key_press", modmap[m])
|
|
end
|
|
end
|
|
|
|
--- Add an `awful.key` based keybinding to the global set.
|
|
--
|
|
-- A **global** keybinding is one which is always present, even when there is
|
|
-- no focused client. If your intent is too add a keybinding which acts on
|
|
-- the focused client do **not** use this.
|
|
--
|
|
-- @staticfct awful.keyboard.append_global_keybinding
|
|
-- @tparam awful.key key The key object.
|
|
-- @noreturn
|
|
-- @see awful.key
|
|
-- @see awful.keyboard.append_global_keybindings
|
|
-- @see awful.keyboard.remove_global_keybinding
|
|
|
|
function module.append_global_keybinding(key)
|
|
capi.root._append_key(key)
|
|
end
|
|
|
|
--- Add multiple `awful.key` based keybindings to the global set.
|
|
--
|
|
-- A **global** keybinding is one which is always present, even when there is
|
|
-- no focused client. If your intent is too add a keybinding which acts on
|
|
-- the focused client do **not** use this
|
|
--
|
|
-- @tparam table keys A table of `awful.key` objects. Optionally, it can have
|
|
-- a `group` entry. If set, the `group` property will be set on all `awful.keys`
|
|
-- objects.
|
|
-- @noreturn
|
|
-- @see awful.key
|
|
-- @see awful.keyboard.append_global_keybinding
|
|
-- @see awful.keyboard.remove_global_keybinding
|
|
|
|
function module.append_global_keybindings(keys)
|
|
local g = keys.group
|
|
keys.group = nil
|
|
|
|
-- Avoid the boilerplate. If the user is adding multiple keys at once, then
|
|
-- they are probably related.
|
|
if g then
|
|
for _, k in ipairs(keys) do
|
|
k.group = g
|
|
end
|
|
end
|
|
|
|
capi.root._append_keys(keys)
|
|
keys.group = g
|
|
end
|
|
|
|
--- Remove a keybinding from the global set.
|
|
--
|
|
-- @staticfct awful.keyboard.remove_global_keybinding
|
|
-- @tparam awful.key key The key object.
|
|
-- @noreturn
|
|
-- @see awful.key
|
|
-- @see awful.keyboard.append_global_keybinding
|
|
|
|
function module.remove_global_keybinding(key)
|
|
capi.root._remove_key(key)
|
|
end
|
|
|
|
|
|
local default_keys = {}
|
|
|
|
--- Add an `awful.key` to the default client keys.
|
|
--
|
|
-- @staticfct awful.keyboard.append_client_keybinding
|
|
-- @tparam awful.key key The key.
|
|
-- @noreturn
|
|
-- @emits client_keybinding::added
|
|
-- @emitstparam client_keybinding::added awful.key key The key.
|
|
-- @see awful.key
|
|
-- @see awful.keyboard.append_client_keybindings
|
|
|
|
function module.append_client_keybinding(key)
|
|
table.insert(default_keys, key)
|
|
|
|
for _, c in ipairs(capi.client.get(nil, false)) do
|
|
c:append_keybinding(key)
|
|
end
|
|
|
|
capi.client.emit_signal("client_keybinding::added", key)
|
|
end
|
|
|
|
--- Add a `awful.key`s to the default client keys.
|
|
--
|
|
-- @staticfct awful.keyboard.append_client_keybindings
|
|
-- @tparam table keys A table containing `awful.key` objects.
|
|
-- @noreturn
|
|
-- @emits client_keybinding::added
|
|
-- @emitstparam client_keybinding::added awful.key key The key.
|
|
-- @see awful.key
|
|
-- @see awful.keyboard.append_client_keybinding
|
|
function module.append_client_keybindings(keys)
|
|
for _, key in ipairs(keys) do
|
|
module.append_client_keybinding(key)
|
|
end
|
|
end
|
|
|
|
--- Remove a key from the default client keys.
|
|
--
|
|
-- @staticfct awful.keyboard.remove_client_keybinding
|
|
-- @tparam awful.key key The key.
|
|
-- @treturn boolean True if the key was removed and false if it wasn't found.
|
|
-- @see awful.keyboard.append_client_keybinding
|
|
|
|
function module.remove_client_keybinding(key)
|
|
for k, v in ipairs(default_keys) do
|
|
if key == v then
|
|
table.remove(default_keys, k)
|
|
|
|
for _, c in ipairs(capi.client.get(nil, false)) do
|
|
c:remove_keybinding(key)
|
|
end
|
|
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
--- Get X11 keysym and a one-character representation from an Awesome keycode.
|
|
--
|
|
-- A "one-character representation" is a single UTF-8 representing the typical
|
|
-- output from that keysym in a text editor (e.g. " " for space, "ñ" for
|
|
-- n_tilde, "Ā" for A_macron). It usually matches the main engraving of the key
|
|
-- for level-0 symbols (but lowercase).
|
|
--
|
|
-- Keycodes may be given in a string in any valid format for `awful.key`:
|
|
-- "#" + keycode, the symkey name and the UTF-8 representation will all work.
|
|
--
|
|
-- If no suitable keysym is found, or a malformed keycode is given as an
|
|
-- argument, this function will return (nil, nil)
|
|
--
|
|
-- @treturn[1] string keysym The keysym name
|
|
-- @treturn[1] nil keysym If no valid keysym is found
|
|
-- @treturn[2] string printsymbol The xkb_keysym_to_utf8 result
|
|
-- @treturn[2] nil printsymbol If the keysym has no printable representation.
|
|
-- @staticfct awful.keyboard.get_key_name
|
|
function module.get_key_name(key)
|
|
return capi.awesome._get_key_name(key)
|
|
end
|
|
|
|
|
|
capi.client.connect_signal("scanning", function()
|
|
capi.client.emit_signal("request::default_keybindings", "context")
|
|
end)
|
|
|
|
-- Private function to be used by `ruled.client`.
|
|
function module._get_client_keybindings()
|
|
return default_keys
|
|
end
|
|
|
|
return module
|