systray_hints/init.lua

234 lines
7.1 KiB
Lua
Raw Normal View History

2022-02-10 07:54:57 +01:00
-- S Y S T R A Y H I N T S
-- rts/oarion7 - ryanthomas.org
2022-02-11 08:03:04 +01:00
-- Control the awesomewm systray from the keyboard using vimium-like
-- number hints. Developed and tested on awesome v4.3.
2022-02-10 07:54:57 +01:00
local awful = require("awful")
local gears = require("gears")
local b = require("beautiful")
local wibox = require("wibox")
local s
2022-02-11 08:03:04 +01:00
awful.screen.connect_for_each_screen(function(screen)
if screen.systray then s = screen end
end)
2022-02-10 07:54:57 +01:00
if s == nil then return nil end
2022-02-11 08:03:04 +01:00
local systray_hints = {
font = b.systray_hints_font or b.taglist_font or b.font,
bgcolor = b.systray_hints_bg or b.taglist_bg_occupied or "#55465a",
highlight = b.systray_hints_bg_highlight or "#aa53aa",
highlight_alt = b.systray_hints_bg_highlight_alt or "#426f5a",
color = b.systray_hints_fg or b.taglist_fg_occupied or "#fdf6e3",
bordercolor = "#fdf6e333",
spacing = 1,
mouse_buttons = { "Left", "Up", "Right" },
default_button = 3,
popup = popup,
systray = s.systray,
wibox = s.mywibox, --wibox in which to locate the system tray
run = run,
2022-02-10 07:54:57 +01:00
}
local total
local was_hidden
local icon_width
2022-02-11 08:03:04 +01:00
local icons_x
2022-02-10 07:54:57 +01:00
local icons_y
local function delay(time, cmd)
gears.timer( { timeout = time, autostart = true, single_shot = true,
callback = function () cmd () end, } )
end
local function execute(choice, mouse_button)
2022-02-11 08:03:04 +01:00
local saved
2022-02-10 07:54:57 +01:00
local factor
2022-02-11 08:03:04 +01:00
local target
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
saved = mouse.coords({x = x, y = y})
2022-02-10 07:54:57 +01:00
if choice == 1 then factor = 0 else factor = choice - 1 end
2022-02-11 08:03:04 +01:00
target = icons_x + ( icon_width * factor )
2022-02-10 07:54:57 +01:00
mouse.coords { x = target , y = icons_y }
if mouse_button ~= 2 then
root.fake_input("button_press" , tostring(mouse_button))
root.fake_input("button_release", tostring(mouse_button))
2022-02-11 08:03:04 +01:00
delay(0.05, function () mouse.coords({x = saved.x, y = saved.y}, true) end)
2022-02-10 07:54:57 +01:00
end
2022-02-11 08:03:04 +01:00
if systray_hints.popup then systray_hints.popup.visible = false end
2022-02-10 07:54:57 +01:00
end
2022-02-11 08:03:04 +01:00
local function highlight_multidigits(total)
2022-02-10 07:54:57 +01:00
local color
for i = 9, total do
2022-02-11 08:03:04 +01:00
color = systray_hints.highlight_alt
2022-02-10 07:54:57 +01:00
if i == 9 then
i = 1
2022-02-11 08:03:04 +01:00
color = systray_hints.highlight
2022-02-10 07:54:57 +01:00
end
2022-02-11 08:03:04 +01:00
systray_hints.popup.widget:get_children()[1]:get_children()[i].widget:set_bg(color)
2022-02-10 07:54:57 +01:00
end
end
local function get_key_input(total)
local grabber
local mouse_button
local function conc(n) return tonumber( 1 .. n ) end
2022-02-11 08:03:04 +01:00
mouse_button = systray_hints.default_button
2022-02-10 07:54:57 +01:00
grabber = awful.keygrabber {
mask_modkeys = true,
autostart = true,
keypressed_callback = function(self, mod, key, cmd)
if key == '1' and total > 9 then
2022-02-11 08:03:04 +01:00
if systray_hints.popup then
highlight_multidigits(total)
2022-02-10 07:54:57 +01:00
end
grabber.keypressed_callback = function(self, mod, key, cmd)
if key == "Return" then
execute(1, mouse_button)
grabber:stop()
elseif not key:match("%D") and conc(key) <= total then
execute(conc(key), mouse_button)
grabber:stop()
else
grabber:stop()
2022-02-11 08:03:04 +01:00
if was_hidden then systray_hints.systray.visible = false end
if systray_hints.popup then systray_hints.popup.visible = false end
2022-02-10 07:54:57 +01:00
end
end
2022-02-11 08:03:04 +01:00
elseif key == systray_hints.mouse_buttons[1] then mouse_button = 1
elseif key == systray_hints.mouse_buttons[2] then mouse_button = 2
elseif key == systray_hints.mouse_buttons[3] then mouse_button = 3
2022-02-10 07:54:57 +01:00
elseif not key:match("%D") and tonumber(key) <= total then
execute(tonumber(key), mouse_button)
grabber:stop()
else
grabber:stop()
2022-02-11 08:03:04 +01:00
if was_hidden then systray_hints.systray.visible = false end
if systray_hints.popup then systray_hints.popup.visible = false end
2022-02-10 07:54:57 +01:00
end
end,
}
end
2022-02-14 16:39:31 +01:00
local function show_popup(x, y, w, h)
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
local hints = {}
local hint_width
2022-02-10 07:54:57 +01:00
2022-02-14 16:39:31 +01:00
local x = math.floor(x)
local y = math.floor(y)
total = math.floor( ( w - ( w % h ) ) / h + 1 )
icon_width = math.floor(w / total )
icons_x = math.floor( x + icon_width / 2)
icons_y = math.floor( y + icon_width / 2)
hint_width = icon_width - ( systray_hints.spacing * 2 )
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
--Decide whether hints should display above or below systray icons.
if y >= 100 then y = y - hint_width else y = y + hint_width end
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
--Hide if already displayed
if systray_hints.popup then systray_hints.popup.visible = false end
2022-02-10 07:54:57 +01:00
local widget_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 5)
end
2022-02-11 08:03:04 +01:00
for i = 1, total do
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
local text
local placement = {}
local background = {}
local margins = {}
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
text = wibox.widget.textbox(tostring(i))
text.font = systray_hints.font
text.markup = '<span color="' .. systray_hints.color .. '">' ..
i .. '</span>'
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
table.insert(placement, text)
placement.widget = wibox.container.place
table.insert(background, placement)
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
background.widget = wibox.container.background
background.bg = systray_hints.bgcolor
background.forced_width = hint_width
background.shape = widget_shape
background.shape_border_width = 2
background.shape_border_color = systray_hints.bordercolor
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
table.insert(margins, background)
2022-02-10 07:54:57 +01:00
2022-02-11 08:03:04 +01:00
margins.widget = wibox.container.margin
margins.right = systray_hints.spacing
margins.left = systray_hints.spacing
table.insert(hints, margins)
2022-02-10 07:54:57 +01:00
end
2022-02-11 08:03:04 +01:00
hints.layout = wibox.layout.fixed.horizontal
systray_hints.popup = awful.popup {
2022-02-10 07:54:57 +01:00
widget = {
2022-02-11 08:03:04 +01:00
screen = s,
hints,
layout = wibox.layout.fixed.horizontal,
2022-02-10 07:54:57 +01:00
},
2022-02-11 08:03:04 +01:00
x = x,
y = y,
visible = true,
ontop = true,
bg = "#00000000",
2022-02-10 07:54:57 +01:00
}
end
2022-02-14 16:39:31 +01:00
local function get_geometry(hi)
2022-02-10 07:54:57 +01:00
local g = gears.matrix.transform_rectangle
2022-02-14 16:39:31 +01:00
return g(hi:get_matrix_to_device(), 0, 0, hi:get_size())
end
2022-02-10 07:54:57 +01:00
2022-02-14 16:39:31 +01:00
local function find_widget(wb, wdg)
2022-02-10 07:54:57 +01:00
2022-02-14 16:39:31 +01:00
local hierarchy
2022-02-10 07:54:57 +01:00
local function traverse(hi)
if hi:get_widget() == wdg then
2022-02-14 16:39:31 +01:00
hierarchy = hi
2022-02-10 07:54:57 +01:00
end
for _, child in ipairs(hi:get_children()) do
traverse(child)
end
end
2022-02-14 16:39:31 +01:00
traverse(wb._drawable._widget_hierarchy)
return hierarchy
2022-02-10 07:54:57 +01:00
end
systray_hints.run = function ()
2022-02-14 16:39:31 +01:00
local function show_hints()
show_popup( get_geometry(find_widget(systray_hints.wibox, systray_hints.systray)) )
get_key_input(total)
end
2022-02-11 08:03:04 +01:00
if not systray_hints.systray.visible then
2022-02-10 07:54:57 +01:00
was_hidden = true
2022-02-11 08:03:04 +01:00
systray_hints.systray.visible = true
2022-02-14 16:39:31 +01:00
delay(0.05, function ()
show_hints()
end)
2022-02-10 07:54:57 +01:00
else
2022-02-14 16:39:31 +01:00
show_hints()
2022-02-10 07:54:57 +01:00
end
end
return systray_hints