switcher: added error handling in keygrabber just in case

This commit is contained in:
Xinhao Yuan 2019-10-13 11:47:14 -04:00
parent 35edb168db
commit c82cb3e7a1
1 changed files with 188 additions and 183 deletions

View File

@ -249,204 +249,209 @@ function module.start(c, exit_keys)
api.awful.keygrabber.stop(kg)
end
kg = api.awful.keygrabber.run(
function (mod, key, event)
if event == "release" then
if exit_keys and exit_keys[key] then
exit()
end
return
local function handle_key(mod, key, event)
if event == "release" then
if exit_keys and exit_keys[key] then
exit()
end
if key_translate_tab[key] ~= nil then
key = key_translate_tab[key]
return
end
if key_translate_tab[key] ~= nil then
key = key_translate_tab[key]
end
maintain_tablist()
assert(tablist ~= nil)
if key == "Tab" then
if #tablist > 0 then
tablist_index = tablist_index % #tablist + 1
c = tablist[tablist_index]
c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise()
infobox.bgimage = draw_info
end
elseif key == "Up" or key == "Down" or key == "Left" or key == "Right" then
local shift = false
local ctrl = false
for i, m in ipairs(mod) do
if m == "Shift" then shift = true
elseif m == "Control" then ctrl = true
end
end
maintain_tablist()
assert(tablist ~= nil)
if key == "Tab" then
if #tablist > 0 then
tablist_index = tablist_index % #tablist + 1
c = tablist[tablist_index]
c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise()
infobox.bgimage = draw_info
end
elseif key == "Up" or key == "Down" or key == "Left" or key == "Right" then
local shift = false
local ctrl = false
for i, m in ipairs(mod) do
if m == "Shift" then shift = true
elseif m == "Control" then ctrl = true
end
end
local current_region = nil
if c and (shift or ctrl) then
for i, a in ipairs(regions) do
if a.x <= traverse_x and traverse_x < a.x + a.width and
a.y <= traverse_y and traverse_y < a.y + a.height
then
current_region = i
break
end
end
if shift then
if current_region == nil or
regions[current_region].x ~= c.x or
regions[current_region].y ~= c.y
then
traverse_x = c.x + traverse_radius
traverse_y = c.y + traverse_radius
current_region = nil
end
elseif ctrl then
local ex = c.x + c.width + c.border_width * 2
local ey = c.y + c.height + c.border_width * 2
if current_region == nil or
regions[current_region].x + regions[current_region].width ~= ex or
regions[current_region].y + regions[current_region].height ~= ey
then
traverse_x = ex - traverse_radius
traverse_y = ey - traverse_radius
current_region = nil
end
end
end
local choice = nil
local choice_value
local current_region = nil
if c and (shift or ctrl) then
for i, a in ipairs(regions) do
if a.x <= traverse_x and traverse_x < a.x + a.width and
a.y <= traverse_y and traverse_y < a.y + a.height
then
current_region = i
end
local v
if key == "Up" then
if a.x < traverse_x + threshold
and traverse_x < a.x + a.width + threshold then
v = traverse_y - a.y - a.height
else
v = -1
end
elseif key == "Down" then
if a.x < traverse_x + threshold
and traverse_x < a.x + a.width + threshold then
v = a.y - traverse_y
else
v = -1
end
elseif key == "Left" then
if a.y < traverse_y + threshold
and traverse_y < a.y + a.height + threshold then
v = traverse_x - a.x - a.width
else
v = -1
end
elseif key == "Right" then
if a.y < traverse_y + threshold
and traverse_y < a.y + a.height + threshold then
v = a.x - traverse_x
else
v = -1
end
end
if (v > threshold) and (choice_value == nil or choice_value > v) then
choice = i
choice_value = v
break
end
end
if choice == nil then
choice = current_region
if key == "Up" then
traverse_y = screen.workarea.y
elseif key == "Down" then
traverse_y = screen.workarea.y + screen.workarea.height
elseif key == "Left" then
traverse_x = screen.workarea.x
else
traverse_x = screen.workarea.x + screen.workarea.width
if shift then
if current_region == nil or
regions[current_region].x ~= c.x or
regions[current_region].y ~= c.y
then
traverse_x = c.x + traverse_radius
traverse_y = c.y + traverse_radius
current_region = nil
end
elseif ctrl then
local ex = c.x + c.width + c.border_width * 2
local ey = c.y + c.height + c.border_width * 2
if current_region == nil or
regions[current_region].x + regions[current_region].width ~= ex or
regions[current_region].y + regions[current_region].height ~= ey
then
traverse_x = ex - traverse_radius
traverse_y = ey - traverse_radius
current_region = nil
end
end
if choice ~= nil then
traverse_x = max(regions[choice].x + traverse_radius, min(regions[choice].x + regions[choice].width - traverse_radius, traverse_x))
traverse_y = max(regions[choice].y + traverse_radius, min(regions[choice].y + regions[choice].height - traverse_radius, traverse_y))
tablist = nil
if c and ctrl and draft_mode then
local lu = c.machi_lu
local rd = c.machi_rd
if shift then
lu = choice
if regions[rd].x + regions[rd].width <= regions[lu].x or
regions[rd].y + regions[rd].height <= regions[lu].y
then
rd = nil
end
else
rd = choice
if regions[rd].x + regions[rd].width <= regions[lu].x or
regions[rd].y + regions[rd].height <= regions[lu].y
then
lu = nil
end
end
if lu ~= nil and rd ~= nil then
machi.layout.set_geometry(c, regions[lu], regions[rd], 0, c.border_width)
elseif lu ~= nil then
machi.layout.set_geometry(c, regions[lu], nil, 0, c.border_width)
elseif rd ~= nil then
c.x = min(c.x, regions[rd].x)
c.y = min(c.y, regions[rd].y)
machi.layout.set_geometry(c, nil, regions[rd], 0, c.border_width)
end
c.machi_lu = lu
c.machi_rd = rd
c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise()
api.layout.arrange(screen)
elseif c and shift then
-- move the window
if draft_mode then
c.x = regions[choice].x
c.y = regions[choice].y
else
machi.layout.set_geometry(c, regions[choice], regions[choice], 0, c.border_width)
c.machi_region = choice
end
c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise()
api.layout.arrange(screen)
tablist = nil
else
maintain_tablist()
-- move the focus
if #tablist > 0 and tablist[1] ~= c then
c = tablist[1]
api.client.focus = c
end
end
infobox.bgimage = draw_info
end
elseif key == "Escape" or key == "Return" then
exit()
else
log(DEBUG, "Unhandled key " .. key)
end
local choice = nil
local choice_value
for i, a in ipairs(regions) do
if a.x <= traverse_x and traverse_x < a.x + a.width and
a.y <= traverse_y and traverse_y < a.y + a.height
then
current_region = i
end
local v
if key == "Up" then
if a.x < traverse_x + threshold
and traverse_x < a.x + a.width + threshold then
v = traverse_y - a.y - a.height
else
v = -1
end
elseif key == "Down" then
if a.x < traverse_x + threshold
and traverse_x < a.x + a.width + threshold then
v = a.y - traverse_y
else
v = -1
end
elseif key == "Left" then
if a.y < traverse_y + threshold
and traverse_y < a.y + a.height + threshold then
v = traverse_x - a.x - a.width
else
v = -1
end
elseif key == "Right" then
if a.y < traverse_y + threshold
and traverse_y < a.y + a.height + threshold then
v = a.x - traverse_x
else
v = -1
end
end
if (v > threshold) and (choice_value == nil or choice_value > v) then
choice = i
choice_value = v
end
end
if choice == nil then
choice = current_region
if key == "Up" then
traverse_y = screen.workarea.y
elseif key == "Down" then
traverse_y = screen.workarea.y + screen.workarea.height
elseif key == "Left" then
traverse_x = screen.workarea.x
else
traverse_x = screen.workarea.x + screen.workarea.width
end
end
if choice ~= nil then
traverse_x = max(regions[choice].x + traverse_radius, min(regions[choice].x + regions[choice].width - traverse_radius, traverse_x))
traverse_y = max(regions[choice].y + traverse_radius, min(regions[choice].y + regions[choice].height - traverse_radius, traverse_y))
tablist = nil
if c and ctrl and draft_mode then
local lu = c.machi_lu
local rd = c.machi_rd
if shift then
lu = choice
if regions[rd].x + regions[rd].width <= regions[lu].x or
regions[rd].y + regions[rd].height <= regions[lu].y
then
rd = nil
end
else
rd = choice
if regions[rd].x + regions[rd].width <= regions[lu].x or
regions[rd].y + regions[rd].height <= regions[lu].y
then
lu = nil
end
end
if lu ~= nil and rd ~= nil then
machi.layout.set_geometry(c, regions[lu], regions[rd], 0, c.border_width)
elseif lu ~= nil then
machi.layout.set_geometry(c, regions[lu], nil, 0, c.border_width)
elseif rd ~= nil then
c.x = min(c.x, regions[rd].x)
c.y = min(c.y, regions[rd].y)
machi.layout.set_geometry(c, nil, regions[rd], 0, c.border_width)
end
c.machi_lu = lu
c.machi_rd = rd
c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise()
api.layout.arrange(screen)
elseif c and shift then
-- move the window
if draft_mode then
c.x = regions[choice].x
c.y = regions[choice].y
else
machi.layout.set_geometry(c, regions[choice], regions[choice], 0, c.border_width)
c.machi_region = choice
end
c:emit_signal("request::activate", "mouse.move", {raise=false})
c:raise()
api.layout.arrange(screen)
tablist = nil
else
maintain_tablist()
-- move the focus
if #tablist > 0 and tablist[1] ~= c then
c = tablist[1]
api.client.focus = c
end
end
infobox.bgimage = draw_info
end
elseif key == "Escape" or key == "Return" then
exit()
else
log(DEBUG, "Unhandled key " .. key)
end
end
kg = api.awful.keygrabber.run(
function (...)
ok, _ = pcall(handle_key, ...)
if not ok then exit() end
end
)
end