|
local awful = require("awful") |
|
local wibox = require("wibox") |
|
local gears = require("gears") |
|
|
|
local clients_hints = {} |
|
local clients_widgets = {} |
|
local clients_texts = {} |
|
local hints = {} |
|
local hints_tree = {} |
|
local registered = false |
|
|
|
local function randchar() |
|
return string.char(math.random(26) + 96) |
|
end |
|
|
|
local function produce_hint() |
|
local hint = "" |
|
|
|
while true do |
|
local new_hint = randchar() .. randchar() |
|
|
|
if hints[new_hint] == nil then |
|
hint = new_hint |
|
break |
|
end |
|
end |
|
|
|
return hint |
|
end |
|
|
|
local function register() |
|
if registered then |
|
return |
|
end |
|
|
|
client.connect_signal("manage", function(c) |
|
local hint = produce_hint() |
|
hints[hint] = true |
|
clients_hints[c] = hint |
|
|
|
local hint_1 = hint:sub(1, 1) |
|
local hint_2 = hint:sub(2, 2) |
|
|
|
if hints_tree[hint_1] == nil then |
|
hints_tree[hint_1] = {} |
|
end |
|
|
|
hints_tree[hint_1][hint_2] = c |
|
end) |
|
|
|
client.connect_signal("unmanage", function(c) |
|
local hint = clients_hints[c] |
|
|
|
hints[hint] = nil |
|
clients_hints[c] = nil |
|
clients_texts[c] = nil |
|
clients_widgets[c] = nil |
|
|
|
local hint_1 = hint:sub(1, 1) |
|
local hint_2 = hint:sub(2, 2) |
|
|
|
hints_tree[hint_1][hint_2] = nil |
|
|
|
if next(hints_tree[hint_1]) == nil then |
|
hints_tree[hint_1] = nil |
|
end |
|
end) |
|
|
|
registered = true |
|
end |
|
|
|
register() |
|
|
|
local function visible_clients(c) |
|
if c.first_tag == nil then |
|
return false |
|
end |
|
|
|
return c.minimized == false and c.hidden == false and c.maximized == false and c.first_tag.selected == true |
|
end |
|
|
|
local function show_hints() |
|
for c in awful.client.iterate(visible_clients) do |
|
local hint = clients_hints[c] |
|
|
|
local widget = clients_widgets[c] |
|
local textbox = clients_texts[c] |
|
|
|
if widget == nil then |
|
textbox = wibox.widget({ |
|
markup = "", |
|
widget = wibox.widget.textbox, |
|
}) |
|
|
|
widget = awful.popup({ |
|
ontop = true, |
|
visible = false, |
|
screen = c.screen, |
|
client = c, |
|
widget = { |
|
{ |
|
textbox, |
|
left = 8, |
|
right = 8, |
|
top = 4, |
|
bottom = 4, |
|
widget = wibox.container.margin, |
|
}, |
|
bg = "#ffff00", |
|
shape = function(cr, w, h) |
|
gears.shape.rounded_rect(cr, w, h, 4) |
|
end, |
|
widget = wibox.widget.background, |
|
}, |
|
}) |
|
clients_widgets[c] = widget |
|
clients_texts[c] = textbox |
|
end |
|
|
|
widget.x = c.x + 10 |
|
widget.y = c.y + 10 |
|
widget.visible = true |
|
textbox.markup = "<span foreground='black'>" .. hint:upper() .. "</span>" |
|
end |
|
|
|
local keygrabber |
|
local matched = "" |
|
|
|
keygrabber = awful.keygrabber({ |
|
stop_key = "Escape", |
|
stop_callback = function() |
|
for _, widget in pairs(clients_widgets) do |
|
widget.visible = false |
|
end |
|
end, |
|
keypressed_callback = function(_, _, key) |
|
key = key:lower() |
|
|
|
if matched == "" then |
|
if hints_tree[key] ~= nil then |
|
local count = 0 |
|
local key_2 = "" |
|
for _key_2, c in pairs(hints_tree[key]) do |
|
local textbox = clients_texts[c] |
|
count = count + 1 |
|
key_2 = _key_2 |
|
|
|
textbox.markup = "<span foreground='black'><span font_weight='heavy' background='blue' foreground='yellow'>" |
|
.. key:upper() |
|
.. "</span>" |
|
.. _key_2:upper() |
|
.. "</span>" |
|
end |
|
|
|
if count == 1 then |
|
client.focus = hints_tree[key][key_2] |
|
keygrabber:stop() |
|
end |
|
|
|
matched = key |
|
else |
|
keygrabber:stop() |
|
end |
|
else |
|
if hints_tree[matched][key] ~= nil then |
|
client.focus = hints_tree[matched][key] |
|
matched = "" |
|
end |
|
keygrabber:stop() |
|
end |
|
end, |
|
}) |
|
|
|
keygrabber:start() |
|
end |
|
|
|
return show_hints |