This commit is contained in:
Ryan Thomas 2022-02-10 01:54:02 -05:00
parent 7ee2345112
commit e103398e4e
2 changed files with 115 additions and 139 deletions

252
core.lua
View File

@ -3,15 +3,38 @@
-- Module to control the awesomewm systray from the keyboard using -- Module to control the awesomewm systray from the keyboard using
-- vimium-like number hints. Developed and tested on awesome v4.3. -- vimium-like number hints. Developed and tested on awesome v4.3.
--TODO: -- TO DO: move widget to table (remove globals)
--Continue testing, clean up -- cleanup
local awful = require("awful") local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local beautiful = require("beautiful") local b = require("beautiful")
local wibox = require("wibox") local wibox = require("wibox")
local s
local font = b.systray_hints_font or b.taglist_font or b.font
local bgcolor = b.systray_hints_bg or b.taglist_bg_occupied or "#55465a"
local highlight = b.systray_hints_bg_highlight or "#aa53aa"
local highlight_alt = b.systray_hints_bg_highlight_alt or "#426f5a"
local fgcolor = b.systray_hints_fg or b.taglist_fg_occupied or "#fdf6e3"
local bordercolor = "#fdf6e333"
awful.screen.connect_for_each_screen(function(screen) if screen.systray then s = screen end end)
if s == nil then return nil end
local systray_hints = {
arrows = { "Left", "Down", "Up", "Right" },
--arrows = { "h", "j", "k", "l" },
default_button = 3,
--default_button = 1,
hints = hints,
systray = s.systray,
wibox = s.mywibox, --where the system tray is located
run = run,
}
local total
local was_hidden local was_hidden
local icon_count local icon_count
local icon_width local icon_width
@ -19,62 +42,44 @@ local half_icon
local first_icon_x local first_icon_x
local icons_y local icons_y
local s local function delay(time, cmd)
gears.timer( { timeout = time, autostart = true, single_shot = true,
local systray_hints_font = beautiful.systray_hints_font or beautiful.taglist_font or beautiful.font callback = function () cmd () end, } )
local systray_hints_bg = beautiful.systray_hints_bg or beautiful.taglist_bg_occupied or "#d6d" end
local systray_hints_hi = beautiful.systray_hints_bg_highlight or beautiful.bg_urgent or "#dd6"
local systray_hints_fg = beautiful.systray_hints_fg or beautiful.taglist_fg_occupied or "#000000"
awful.screen.connect_for_each_screen(function(screen) if screen.systray then s = screen end end) local function execute(choice, mouse_button)
if s == nil then return nil end
-- G L O B A L S
-- Edit here or override to configure options.
-- Arrows are key names optionally pressed at run-time before entering a number to specify which mouse button is to be clicked. Default is right-click, which is last in the index. The first key will set a left click, and the two middle options (up/down) trigger hover (no click).
systray_hints = {
arrows = { "Left", "Down", "Up", "Right" },
--arrows = { "h", "j", "k", "l" },
default_button = 3, -- right-click by default
--default_button = 1, -- left click by default
wibox = s.mywibox, --where to look for the system tray
systray = s.systray,
}
local function click(choice, mouse_button)
--local function click(choice, mouse_button, first_icon_x, icons_y, icon_width)
local target local target
local factor local factor
local saved_coords local saved_coords
saved_coords = mouse.coords({x = x, y = y}) --save saved_coords = mouse.coords({x = x, y = y})
if choice == 1 then factor = 0 else factor = choice - 1 end if choice == 1 then factor = 0 else factor = choice - 1 end
target = first_icon_x + ( icon_width * factor ) target = first_icon_x + ( icon_width * factor )
mouse.coords { x = target , y = icons_y } mouse.coords { x = target , y = icons_y }
if mouse_button ~= 2 then -- don't click; just hover if mouse_button ~= 2 then
root.fake_input("button_press" , tostring(mouse_button)) root.fake_input("button_press" , tostring(mouse_button))
root.fake_input("button_release", tostring(mouse_button)) root.fake_input("button_release", tostring(mouse_button))
delay(0.05, function () mouse.coords({x = saved_coords.x, y = saved_coords.y}, true) end)
gears.timer( { timeout = 0.05,
autostart = true,
single_shot = true,
callback = function()
mouse.coords({x = saved_coords.x, y = saved_coords.y}, true) --restore
end } )
end end
if systray_hints.hints then systray_hints.hints.visible = false end
end end
local function highlight_options(total)
local color
for i = 9, total do
color = highlight_alt
if i == 9 then
i = 1
color = highlight
end
systray_hints.hints.widget:get_children()[1]:get_children()[i].widget:set_bg(color)
end
end
local function get_key_input(total) local function get_key_input(total)
@ -84,53 +89,40 @@ local function get_key_input(total)
local mouse_button = systray_hints.default_button local mouse_button = systray_hints.default_button
local function conc(n) return tonumber( 1 .. n ) end local function conc(n) return tonumber( 1 .. n ) end
local function execute(n, mouse_button)
click(n, mouse_button)
if systray_hints_widget then systray_hints_widget.visible = false end
end
grabber = awful.keygrabber { grabber = awful.keygrabber {
mask_modkeys = true, mask_modkeys = true,
autostart = true, autostart = true,
--start_callback = bcn("Let us begin."), --test
keypressed_callback = function(self, mod, key, cmd) keypressed_callback = function(self, mod, key, cmd)
if key == '1' and total > 9 then if key == '1' and total > 9 then
if systray_hints_widget then if systray_hints.hints then
systray_hints_widget.widget:get_children()[1]:get_all_children()[1].systray_hint_background_item_1.bg = systray_hints_hi highlight_options(total)
end end
grabber.keypressed_callback = function(self, mod, key, cmd) grabber.keypressed_callback = function(self, mod, key, cmd)
if key == "Return" then if key == "Return" then
execute(1, mouse_button) execute(1, mouse_button)
grabber:stop() grabber:stop()
elseif not key:match("%D") then elseif not key:match("%D") and conc(key) <= total then
execute(conc(key), mouse_button) execute(conc(key), mouse_button)
grabber:stop() grabber:stop()
else else
grabber:stop() grabber:stop()
if was_hidden then s.systray.visible = false end if was_hidden then s.systray.visible = false end
if systray_hints_widget then systray_hints_widget.visible = false end if systray_hints.hints then systray_hints.hints.visible = false end
end end
end end
elseif key == systray_hints.arrows[1] then mouse_button = 1 elseif key == systray_hints.arrows[1] then mouse_button = 1
elseif key == systray_hints.arrows[4] then mouse_button = 3 elseif key == systray_hints.arrows[4] then mouse_button = 3
elseif key == systray_hints.arrows[2] or key == systray_hints.arrows[3] then mouse_button = 2 elseif key == systray_hints.arrows[2] or key == systray_hints.arrows[3] then mouse_button = 2
elseif not key:match("%D") then elseif not key:match("%D") and tonumber(key) <= total then
execute(key, mouse_button) execute(tonumber(key), mouse_button)
grabber:stop() grabber:stop()
else else
grabber:stop() grabber:stop()
if was_hidden then s.systray.visible = false end if was_hidden then s.systray.visible = false end
if systray_hints_widget then systray_hints_widget.visible = false end if systray_hints.hints then systray_hints.hints.visible = false end
end end
end, end,
@ -141,92 +133,81 @@ end
local function show_systray_hints_widget(sys_hints_geo_x, sys_hints_geo_y, w, sys_hints_icon_count, s) local function show_hints(sys_hints_geo_x, sys_hints_geo_y, w, sys_hints_icon_count, s)
local sys_hints_icon_width = w - 2 local sys_hints_icon_width = w - 2 --subtract for margins
if sys_hints_geo_y >= 100 then
sys_hints_geo_y = sys_hints_geo_y - sys_hints_icon_width
else sys_hints_geo_y = sys_hints_geo_y + sys_hints_icon_width
--Decide if hints should display above or below systray icons.
end
--hide if already displayed
if systray_hints.hints then systray_hints.hints.visible = false end
local num_rows = sys_hints_icon_count
local sys_hints_list = {}
local systray_widget_list = {}
--Subtract 2px from icon width for left/right margins local widget_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 5)
end
local var = {}
for i = 1, num_rows do table.insert(sys_hints_list, tostring(i)) end
for k, v in pairs(sys_hints_list) do
var["text_" .. v] = wibox.widget.textbox(tostring(v))
local text_alias = var["text_" .. v]
text_alias.font = font -- "Sans 14"
text_alias.markup = '<span color="' .. fgcolor ..
'">' .. v .. '</span>'
if sys_hints_geo_y >= 100 then local item_place = {}
sys_hints_geo_y = sys_hints_geo_y - sys_hints_icon_width table.insert(item_place, text_alias)
else sys_hints_geo_y = sys_hints_geo_y + sys_hints_icon_width
--Decide if hints should display above or below systray icons.
end
--hide if already displayed item_place.widget = wibox.container.place
if systray_hints_widget then
systray_hints_widget.visible = false
end
local num_rows = sys_hints_icon_count local item_background = {}
local sys_hints_list = {} table.insert(item_background, item_place)
local systray_widget_list = {}
local widget_shape = function(cr, width, height) item_background.widget = wibox.container.background
gears.shape.rounded_rect(cr, width, height, 5) item_background.bg = bgcolor -- "#ff00ff"
end item_background.forced_width = sys_hints_icon_width
item_background.shape = widget_shape
item_background.shape_border_width = 2
item_background.shape_border_color = bordercolor
tostring(v)
local var = {} local item_margin = {}
for i = 1, num_rows do table.insert(sys_hints_list, tostring(i)) end table.insert(item_margin, item_background)
for k, v in pairs(sys_hints_list) do
var["text_" .. v] = wibox.widget.textbox(tostring(v)) item_margin.widget = wibox.container.margin
local text_alias = var["text_" .. v] item_margin.right = 1
text_alias.font = systray_hints_font -- "Sans 14" item_margin.left = 1
text_alias.markup = '<span color="' .. systray_hints_fg ..
'">' .. v .. '</span>'
local item_container_place = {} local complete_widget = item_margin
table.insert(item_container_place, text_alias) table.insert(systray_widget_list, complete_widget)
item_container_place.widget = wibox.container.place end
local item_container_background = {} systray_widget_list.layout = wibox.layout.fixed.horizontal
table.insert(item_container_background, item_container_place) systray_hints.hints = awful.popup {
item_container_background.widget = wibox.container.background widget = {
item_container_background.bg = systray_hints_bg -- "#ff00ff" screen = s,
item_container_background.forced_width = sys_hints_icon_width systray_widget_list,
item_container_background.shape = widget_shape
item_container_background.shape_border_width = 2
item_container_background.shape_border_color = systray_hints_fg .. 33
item_container_background.id = "systray_hint_background_item_" ..
tostring(v)
local item_container_margin = {} layout = wibox.layout.fixed.horizontal,
table.insert(item_container_margin, item_container_background) },
item_container_margin.widget = wibox.container.margin x = sys_hints_geo_x,
item_container_margin.right = 1 y = sys_hints_geo_y,
item_container_margin.left = 1 visible = true,
ontop = true,
local complete_widget = item_container_margin bg = "#00000000",
table.insert(systray_widget_list, complete_widget)
end
systray_widget_list.layout = wibox.layout.fixed.horizontal
systray_hints_widget = awful.popup {
widget = {
screen = s,
systray_widget_list,
layout = wibox.layout.fixed.horizontal,
},
x = sys_hints_geo_x,
y = sys_hints_geo_y,
visible = true,
ontop = true,
bg = "#00000000",
--hide_on_right_click = true
} }
end end
local function find_widget_in_wibox(wb, wdg) local function find_widget_in_wibox(wb, wdg)
local function get_geometry(hi) local function get_geometry(hi)
@ -239,7 +220,7 @@ local function find_widget_in_wibox(wb, wdg)
first_icon_x = math.floor( x + half_icon) first_icon_x = math.floor( x + half_icon)
icons_y = math.floor(y + half_icon) icons_y = math.floor(y + half_icon)
show_systray_hints_widget( math.floor(x), math.floor(y), icon_width, icon_count, s ) show_hints( math.floor(x), math.floor(y), icon_width, icon_count, s )
get_key_input(icon_count) get_key_input(icon_count)
end end
@ -250,10 +231,9 @@ local function find_widget_in_wibox(wb, wdg)
return return
end end
for _, child in ipairs(hi:get_children()) do for _, child in ipairs(hi:get_children()) do
-- return traverse(child)
traverse(child) traverse(child)
-- Others have return traverse(child) here instead, but for us this returned -- allow for additional round of recursion across container widgets.
-- only container widgets. Removing "return" allows for an
-- additional round of recursion.
end end
end end
return traverse(wb._drawable._widget_hierarchy) return traverse(wb._drawable._widget_hierarchy)
@ -264,15 +244,11 @@ systray_hints.run = function ()
if not s.systray.visible then if not s.systray.visible then
was_hidden = true was_hidden = true
s.systray.visible = true s.systray.visible = true
gears.timer( { timeout = 0.05, delay(0.05, function () find_widget_in_wibox(systray_hints.wibox, systray_hints.systray) end)
autostart = true,
single_shot = true,
callback = function()
find_widget_in_wibox(systray_hints.wibox, systray_hints.systray)
end } )
else else
find_widget_in_wibox(systray_hints.wibox, systray_hints.systray) find_widget_in_wibox(systray_hints.wibox, systray_hints.systray)
end end
end end
return systray_hints

View File

@ -1 +1 @@
require("systray-hints.core") return require("systray_hints.core")