my complicated awesomewm config (SUNSETTED)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

193 lines
7.4 KiB

local awful = require("awful")
local gears = require("gears")
local menubar_utils = require("menubar.utils")
local wibox = require("wibox")
local beautiful = require("beautiful")
local awmtk = require("awmtk")
local function cascade_close(path,limit)
for I = #path,limit or 1,-1 do
if path[I] then
path[I].visible = false
end
path[I] = nil
end
end
local function merge_into_widget(widget,args)
for k,v in ipairs(args) do
table.insert(widget,v)
end
end
local function get_button_container()
--This function prevents mouse.current_widget_geometry from picking up textboxes
local output = {}
local geo = mouse.current_widgets
for k,v in pairs(geo) do
if tostring(v):match("^widget_background") then
output = mouse.current_widget_geometries[k]
break
end
end
return output
end
local function loader(options)
local style = awmtk.style(awmtk.defaults,options.style or {},"menu_")
options = options or {}
-- Define styles
local button_bg_on = style.menu_button_bg_focus
local button_bg_off = style.menu_button_bg_normal
local userlinks = wibox.widget {
layout = (
options.vertical and
wibox.layout.fixed.vertical
) or wibox.layout.fixed.horizontal,
spacing = style.menu_container_spacing or 4,
}
local button_template = function(v)
return {
layout = (
options.vertical and
wibox.layout.fixed.horizontal
) or wibox.layout.fixed.vertical,
(v[3] and {
widget = wibox.widget.imagebox,
resize = true,
image = v[3],
}),
{
markup = v[1] or "",
widget = wibox.widget.textbox,
ellipsize = "end"
},
spacing = 2
}
end
local button_style = {
bg = button_bg_off,
forced_height = style.menu_button_height or
style.menu_height or
24,
forced_width = style.menu_button_width or
style.menu_width or
140
}
local menu_template = function(tree_layer)
return {
layout = (
options.vertical
and wibox.layout.fixed.vertical
) or wibox.layout.fixed.horizontal,
spacing = (
options.vertical and
style.menu_container_spacing_vertical
) or style.menu_container_spacing_horizontal,
tree_layer = tree_layer,
}
end
local menu_popup_template = {
visible = false,
ontop = true,
preferred_positions = (options.vertical and {"right","left"}) or {"top","bottom"},
preferred_anchors = (options.inverse and {"back","front"}) or {"front","back"},
}
--Create menu root
local menu = menu_template(1)
local tree_path = {"spacer"}
--Insert widgets above/before the menu
merge_into_widget(menu,options.before or {})
local function generate_menu(leaf,menu)
--Iterate over a table of widget defining tables
for k,v in ipairs(leaf) do
if type(v) ~= "table" then
--Error if the structure is invalid
error("Invalid leaf type "..type(v).." in menu tree")
else
local tree_layer = menu.tree_layer+1
--Create a button widget
local new_button = style.button(button_template(v),button_style)
if type(v[2]) == "table" then
--Create a popup template for the new menu leaf
local new_popup = menu_template(tree_layer)
--Add buttons and widgets to the new leaf
merge_into_widget(new_popup,v[2].before or {})
generate_menu(v[2],new_popup)
merge_into_widget(new_popup,v[2].after or {})
new_popup = awful.popup(style.container(new_popup,menu_popup_template))
new_button:connect_signal("mouse::enter",function()
--Hide cascading leaves of a branch when leaf changes
if menu.current_selection and (menu.current_selection ~= new_popup) then
cascade_close(tree_path,tree_layer)
end
--Move the new popup widget closer to mouse and align it precisely to the button
if mouse.current_widget_geometry then
local geo = get_button_container()
tree_path[tree_layer] = new_popup
--Apparently it's a thing that needed fixing.
--I don't question it, and neither should you.
if geo and geo.x and geo.y then
new_popup:move_next_to(geo)
end
--previous method call aligns the popup to the button,
--NOT the buttons within the popup. So we do that ourselves (somewhat).
if new_popup.current_anchor == "front" then
new_popup.y = new_popup.y - style.menu_container_inner_margin
else
new_popup.y = new_popup.y + style.menu_container_inner_margin
end
new_popup.visible = true
menu.current_selection = new_popup
end
end)
elseif type(v[2]) == "function" then
new_button:connect_signal("button::press",function()
cascade_close(tree_path,1)
v[2]()
end)
elseif type(v[2]) == "string" then
new_button:connect_signal("button::press",function()
cascade_close(tree_path,1)
awful.spawn(v[2])
end)
end
new_button:connect_signal("mouse::enter",function()
--Set button bg
if menu.current_button then
menu.current_button.bg = button_bg_off
end
menu.current_button = new_button
menu.current_button.bg = button_bg_on
end)
table.insert(menu,new_button)
end
end
end
generate_menu(options.items,menu)
--Insert widgets below/after the menu
merge_into_widget(menu,options.after or {})
menu = awful.popup(style.container(menu,menu_popup_template))
tree_path[1] = menu
menu.toggle = function(x,y)
if (not x) or (not y) then
x = mouse.coords().x
y = mouse.coords().y
end
menu.x = x
menu.y = y
if menu.x+menu.width > menu.screen.geometry.width then
menu.x = menu.x-menu.width
end
if menu.y+menu.height > menu.screen.geometry.height then
menu.y = menu.y-menu.height
end
if menu.visible then
cascade_close(tree_path,2)
end
tree_path[1] = menu
menu.visible = (not menu.visible)
end
menu.show = function(self)
menu.toggle()
end
return menu
end
return loader