generate key code sequence, xdotool option (with wip combine option)

This commit is contained in:
BZ 2023-09-18 16:48:36 +02:00
parent 161eb45b1a
commit d63c79c917
1 changed files with 109 additions and 58 deletions

167
init.lua
View File

@ -1,9 +1,78 @@
local awful = require("awful") local awful = require("awful")
local glib = require("lgi").GLib local glib = require("lgi").GLib
local gears = require("gears")
local unpack = unpack or table.unpack -- luacheck: globals unpack local unpack = unpack or table.unpack -- luacheck: globals unpack
local awesome, keygrabber, client, root = awesome, keygrabber, client, root
local module = {} local module = {}
local function run_key_sequence(seq)
keygrabber.stop()
for _, s in ipairs(seq) do
if s.action == "press" then
root.fake_input("key_press", s.key)
print("key_press: " .. s.key)
elseif s.action == "release" then
root.fake_input("key_release", s.key)
print("key_release: " .. s.key)
elseif s.action == "press_and_release" then
root.fake_input("key_release", s.key)
root.fake_input("key_press", s.key)
root.fake_input("key_release", s.key)
end
end
end
local function run_key_sequence_xdotool(seq)
keygrabber.stop()
-- combine inputs to speed things up
local queue = nil
local combine = true
print("")
local run_fn = function(s)
if s.action == "press" then
if s.is_combined then
awful.spawn("xdotool key " .. s.key)
print("xdotool key " .. s.key)
else
awful.spawn("xdotool keydown " .. s.key)
print("xdotool keydown " .. s.key)
end
elseif s.action == "release" then
if s.is_combined then
else
awful.spawn("xdotool keyup " .. s.key)
print("xdotool keyup " .. s.key)
end
elseif s.action == "press_and_release" then
awful.spawn("xdotool key " .. s.key)
print("key " .. s.key)
end
end
for _, s in ipairs(seq) do
if queue then
if combine and s.action == queue.action then
queue.key = string.format("%s+%s", queue.key, s.key)
queue.is_combined = true
else
run_fn(queue)
queue = s
end
else
queue = s
end
end
run_fn(queue)
end
-- get key sequence to transition from current mods to next mods
local change_mods = function(current, next) local change_mods = function(current, next)
local sequence = {}
local intersect = {} local intersect = {}
-- determine mods that needs to be released -- determine mods that needs to be released
@ -16,7 +85,7 @@ local change_mods = function(current, next)
end end
end end
if is_unique then if is_unique then
root.fake_input("key_release", c) table.insert(sequence, { action = "release", key = c })
else else
intersect[#intersect + 1] = c intersect[#intersect + 1] = c
end end
@ -32,13 +101,14 @@ local change_mods = function(current, next)
end end
end end
if is_unique then if is_unique then
root.fake_input("key_press", n) table.insert(sequence, { action = "press", key = n })
end end
end end
return sequence
end end
local function new(args) local function new(args)
local awesome, client, root, keygrabber = awesome, client, root, keygrabber -- luacheck: awesome globals client root keygrabber
local cfg = args local cfg = args
or { up = { "k", "Up" }, down = { "j", "Down" }, left = { "h", "Left" }, right = { or { up = { "k", "Up" }, down = { "j", "Down" }, left = { "h", "Left" }, right = {
"l", "l",
@ -57,6 +127,8 @@ local function new(args)
right = cfg.right, right = cfg.right,
} }
local use_xdotool = cfg.use_xdotool or true
local tmux_keys = cfg.tmux local tmux_keys = cfg.tmux
or { or {
mods = { "Control_L" }, mods = { "Control_L" },
@ -74,75 +146,52 @@ local function new(args)
right = "l", right = "l",
} }
local switch_mods_fn = function(current_mods, next_mods, fn, dir) local get_key_sequence = function(current_mods, next_mods, fn, dir)
keygrabber.stop() local sequence = {}
change_mods(current_mods, next_mods) -- release wm mods, press vim/tmux mods
fn(dir) gears.table.merge(sequence, change_mods(current_mods, next_mods))
change_mods(next_mods, current_mods)
-- press navigation direction
gears.table.merge(sequence, fn(dir))
-- release vim/tmux mods, restore wm mods
gears.table.merge(sequence, change_mods(next_mods, current_mods))
return sequence
end end
local tmux = {} local navigate_tmux = function(dir)
tmux.left = function() return {
root.fake_input("key_release", tmux_keys.left) { action = "release", key = tmux_keys[dir] },
root.fake_input("key_press", tmux_keys.left) { action = "press", key = tmux_keys[dir] },
root.fake_input("key_release", tmux_keys.left) { action = "release", key = tmux_keys[dir] },
end }
tmux.right = function()
root.fake_input("key_release", tmux_keys.right)
root.fake_input("key_press", tmux_keys.right)
root.fake_input("key_release", tmux_keys.right)
end
tmux.up = function()
root.fake_input("key_release", tmux_keys.up)
root.fake_input("key_press", tmux_keys.up)
root.fake_input("key_release", tmux_keys.up)
end
tmux.down = function()
root.fake_input("key_release", tmux_keys.down)
root.fake_input("key_press", tmux_keys.down)
root.fake_input("key_release", tmux_keys.down)
end
local tmux_navigate = function(dir)
tmux[dir]()
end end
local vim = {} local navigate_vim = function(dir)
vim.left = function() return {
root.fake_input("key_release", vim_keys.left) --{ action = "release", key = vim_keys[dir] },
root.fake_input("key_press", vim_keys.left) { action = "press", key = vim_keys[dir] },
root.fake_input("key_release", vim_keys.left) { action = "release", key = vim_keys[dir] },
end }
vim.right = function()
root.fake_input("key_release", vim_keys.right)
root.fake_input("key_press", vim_keys.right)
root.fake_input("key_release", vim_keys.right)
end
vim.up = function()
root.fake_input("key_release", vim_keys.up)
root.fake_input("key_press", vim_keys.up)
root.fake_input("key_release", vim_keys.up)
end
vim.down = function()
root.fake_input("key_release", vim_keys.down)
root.fake_input("key_press", vim_keys.down)
root.fake_input("key_release", vim_keys.down)
end
local vim_navigate = function(dir)
vim[dir]()
end end
-- use dynamic titles to determine type of client (default) -- use dynamic titles to determine type of client (default)
local navigate = function(dir) local navigate = function(dir)
local c = client.focus local c = client.focus
local client_name = c and c.name or "" local client_name = c and c.name or ""
local run_fn = use_xdotool and run_key_sequence_xdotool or run_key_sequence
if string.find(client_name, "%- N?VIM$") then if string.find(client_name, "%- N?VIM$") then
switch_mods_fn(wm_keys.mods, vim_keys.mods, vim_navigate, dir) run_fn(get_key_sequence(wm_keys.mods, vim_keys.mods, navigate_vim, dir))
return return
elseif string.find(client_name, "%- TMUX$") then elseif string.find(client_name, "%- TMUX$") then
switch_mods_fn(wm_keys.mods, tmux_keys.mods, tmux_navigate, dir) run_fn(get_key_sequence(wm_keys.mods, tmux_keys.mods, navigate_tmux, dir))
return return
else else
focus(dir) focus(dir)
return
end end
end end
@ -153,14 +202,16 @@ local function new(args)
local pid = c and c.pid or -1 local pid = c and c.pid or -1
awful.spawn.easy_async("pstree -A -T " .. pid, function(out) awful.spawn.easy_async("pstree -A -T " .. pid, function(out)
if string.find(out, "[^.*\n]%-tmux: client") then if string.find(out, "[^.*\n]%-tmux: client") then
return tmux_navigate(dir) get_key_sequence(wm_keys.mods, tmux_keys.mods, navigate_tmux, dir)
return
elseif elseif
string.find(out, "[^.*\n]%-n?vim$") string.find(out, "[^.*\n]%-n?vim$")
or string.find(out, "[^.*\n]%-n?vim%-") or string.find(out, "[^.*\n]%-n?vim%-")
or string.find(out, "^gvim$") or string.find(out, "^gvim$")
or string.find(out, "^gvim%-") or string.find(out, "^gvim%-")
then then
return vim_navigate(dir) get_key_sequence(wm_keys.mods, vim_keys.mods, navigate_vim, dir)
return
else else
focus(dir) focus(dir)
end end