diff --git a/libs/awmtk2.lua b/libs/awmtk2.lua index 480184c..e50b111 100644 --- a/libs/awmtk2.lua +++ b/libs/awmtk2.lua @@ -141,6 +141,10 @@ awmtk.proto_style.titlebar = awmtk.create_delta("titlebar", { awmtk.proto_style.wibar = awmtk.create_delta("wibar", { margins = 1 }, awmtk.proto_style,awmtk.proto_style.base) + +awmtk.proto_style.menu = awmtk.create_delta("menu", { + margins = 1 +}, awmtk.proto_style,awmtk.proto_style.base) -- }}} -- {{{ Generic templates @@ -224,7 +228,7 @@ awmtk.proto_templates = { article = function(style) -- Article is a template that combines 3 common pieces of a full item: -- Icon, name and description. Designed to be placed within a container - -- or a button. Also supports usage in tasklist via _id suffixes. + -- or a button. return function(options) return awmtk.merge({ (options.icon and { @@ -339,7 +343,7 @@ awmtk.proto_templates = { top = style.wibar.top },options or {}) end - end, + end } -- Last but not least - we export a default template lib and default style. diff --git a/libs/context_menu.lua b/libs/context_menu.lua new file mode 100644 index 0000000..529da0f --- /dev/null +++ b/libs/context_menu.lua @@ -0,0 +1,117 @@ +-- POLYMENU - brutal deluxe +-- This isn't in the widgets folder because it's too meta to be there +local awful = require("awful") +local gears = require("gears") +local menubar_utils = require("menubar.utils") +local wibox = require("wibox") +local awmtk2 = require("awmtk2") + +local function position_popup(popup,widget,style) + -- Position the popup somewhere nearby our original widget + popup:move_next_to(mouse.current_wibox) + -- Figure out the geometry of the base widget + local widget_geo + for k,v in pairs(mouse.current_widgets) do + if widget == v then + widget_geo = mouse.current_widget_geometries[k] + end + end + -- Align y coordinate of the popup to the button + if widget_geo then + local wibox_geo = mouse.current_wibox:geometry() + if popup.current_anchor == "front" then + popup.y = widget_geo.y + wibox_geo.y - style.popup.margins + else + popup.y = widget_geo.y + wibox_geo.y + style.popup.margins + widget_geo.height - popup:geometry().height + end + end + -- Finally, make widget visible + popup.visible = true +end + +return function(args) + local style = awmtk2.create_style("menu", awmtk2.default, args.style) + local templates = awmtk2.create_template_lib("menu", awmtk2.templates, args.templates) + local t = awmtk2.build_templates(templates,style) + local function menu_builder(element,layer,root_layer) + local new_element = wibox.widget(t.button(t.article({ + icon = element[3], + resize = true, + title = element[1] + }),{ + forced_width = style.button.forced_width, + forced_height = style.button.forced_height + })) + if type(element[2]) == "string" then + new_element:connect_signal("button::press",style.button.onpress) + new_element:connect_signal("button::press",function(widget) + awful.spawn(element[2]) + end) + new_element:connect_signal("button::release",function(widget) + style.button.onrelease(widget) + if root_layer.focused then + root_layer.focused:emit_signal("cascade_close") + end + end) + elseif type(element[2]) == "function" then + new_element:connect_signal("button::press",style.button.onpress) + new_element:connect_signal("button::press",element[2]) + new_element:connect_signal("button::release",function(widget) + style.button.onrelease(widget) + if root_layer.focused then + root_layer.focused:emit_signal("cascade_close") + end + end) + elseif type(element[2]) == "table" then + local layout = { + spacing = style.base.spacing, + layout = wibox.layout.fixed.vertical + } + for k,v in pairs(element[2]) do + table.insert(layout,menu_builder(v,layout,root_layer)) + end + local next_layer = awful.popup(t.popup(layout,{ + visible = false, + ontop = true, + preferred_positions = {"right","left"}, + preferred_anchors = {"front","back"}, + })) + local function open_layer(widget) + if layer.focused == widget and + next_layer.visible then + return + end + if layer.focused then + layer.focused:emit_signal("cascade_close") + end + layer.focused = widget + position_popup(next_layer, new_element, style) + end + new_element:connect_signal("cascade_close",function() + style.button.onrelease(new_element) + if layout.focused then + layout.focused:emit_signal("cascade_close") + end + next_layer.visible = false + end) + -- that sweet "just move the mouse 4head" navigation + if style.base.menu_slide then + new_element:connect_signal("mouse::enter",open_layer) + new_element:connect_signal("mouse::enter",style.button.onpress) + else + new_element:connect_signal("button::press",style.button.onpress) + new_element:connect_signal("button::press",open_layer) + end + end + return new_element + end + local root_layer = { + layout = wibox.layout.fixed.vertical, + id = "menu_root", + spacing = style.base.spacing + } + for k,v in pairs(args.items) do + table.insert(root_layer,menu_builder(v,root_layer,root_layer)) + end + return root_layer +end diff --git a/modules/desktop.lua b/modules/desktop.lua index 57a942f..88d2d2c 100644 --- a/modules/desktop.lua +++ b/modules/desktop.lua @@ -5,6 +5,7 @@ local awful = require("awful") local beautiful = require("beautiful") local builder = require("builder") local mbarutils = require("menubar").utils +local menugen = require("context_menu") local function read_file(fname) local fhandler = io.open(fname,"r") @@ -14,13 +15,58 @@ local function read_file(fname) return data end end + +do -- {{{ Root menu +local style = awmtk2.create_style("root_menu",awmtk2.default,{}) +local templates = awmtk2.create_template_lib("root_menu",awmtk2.templates,{}) +local t = awmtk2.build_templates(templates,style) +local config_file = io.open(root_path.."/themes/"..global.theme.."/config/root_menu.json","r") +local config +if config_file then + config = config_file:read("*a") + config_file:close() +else + config = [[{"list": [ + {"widget": "widgets.rootmenu"} + ], + "vertical": true +}]] +end +local root_menu = awful.popup(t.popup(builder( + config, + { + style = style, + screen = mouse.screen, + } +))) +local buttons = root.buttons() +root.buttons(gears.table.join(buttons, + awful.button({}, 3, function() + if root_menu.visible then + local roots = root_menu.widget:get_children_by_id("menu_root") + for k,v in pairs(roots) do + for _,w in ipairs(v.children) do + if type(w) == "table" and w.emit_signal then + w:emit_signal("cascade_close") + end + end + end + end + root_menu.visible = (not root_menu.visible) + if root_menu.visible then + root_menu:move_next_to(gears.table.join(mouse.coords(),{ + width = 0, + height = 0 + })) + end + end) +)) +end -- }}} + -- {{{ Placeholder Icons client.connect_signal("request::titlebars",function(c) if (not c.icon) and beautiful.icon_default then - local icon = gears.surface(beautiful.icon_default) - if icon then - c.icon = icon._native - end + c.icon = beautiful.icon_default._native end end) -- }}} @@ -67,6 +113,7 @@ client.connect_signal("request::titlebars",function(c) if titlebar_config[v] then contents = builder(titlebar_config[v],{ client = c, + screen = c.screen, style = style[v], buttons = buttons }) @@ -113,8 +160,8 @@ awful.screen.connect_for_each_screen(function(s) position = v:gsub("wibar_",""), screen = s, visible = true, - stretch = style[v].stretch or true, - ontop = style[v].ontop or true, + stretch = style[v].stretch, + ontop = style[v].ontop, width = style[v].width, height = style[v].height, border_width = style[v].border_width, diff --git a/themes/default/theme.lua b/themes/default/theme.lua index d076f8f..ebec173 100644 --- a/themes/default/theme.lua +++ b/themes/default/theme.lua @@ -135,7 +135,8 @@ theme.widgets = { wibar = { height = 24, margins = 2, - width = 60 + width = 60, + stretch = true } }, titlebar = { diff --git a/themes/reno98/icons/unknown-app.png b/themes/reno98/icons/unknown-app.png new file mode 100644 index 0000000..e4f5121 Binary files /dev/null and b/themes/reno98/icons/unknown-app.png differ diff --git a/themes/reno98/icons/unknown-app.svg b/themes/reno98/icons/unknown-app.svg new file mode 100644 index 0000000..5206870 --- /dev/null +++ b/themes/reno98/icons/unknown-app.svg @@ -0,0 +1,45 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/themes/reno98/theme.lua b/themes/reno98/theme.lua index 020730f..f8bc444 100644 --- a/themes/reno98/theme.lua +++ b/themes/reno98/theme.lua @@ -285,7 +285,8 @@ end theme.icon_theme = "Chicago95" -- Default icon for clients -theme.icon_default = "/usr/share/icons/Chicago95/apps/22/terminal.png" +-- This one has to be baked as a surface to avoid memory leaks +theme.icon_default = gears.surface(themes_path.."reno98/icons/unknown-app.png") theme.widgets = { default = { @@ -331,7 +332,8 @@ theme.widgets = { shape = function(cr,width,height) return gears.shape.rounded_rect(cr,width,height,0) end, - bgimage = theme.bgimage_outset + bgimage = theme.bgimage_outset, + stretch = true } }, clock = { @@ -364,6 +366,25 @@ theme.widgets = { bgimage_minimize = theme.bgimage_outset } }, + menu = { + base = { + -- Enables the ability to just drag the mouse on an entry to open it + menu_slide = true, + spacing = 1 + }, + button = { + forced_height = 20, + forced_width = 160 + }, + popup = { + margins = 2 + } + }, + root_menu = { + popup = { + margins = 2 + } + }, titlebar = { titlebar_top = { bgimage_normal = theme.titlebar_bgimage_top, diff --git a/widgets/rootmenu.lua b/widgets/rootmenu.lua new file mode 100644 index 0000000..524e8ea --- /dev/null +++ b/widgets/rootmenu.lua @@ -0,0 +1,25 @@ +-- Base for widgets +local awmtk2 = require("awmtk2") +local wibox = require("wibox") +local gears = require("gears") +local awful = require("awful") +local beautiful = require("beautiful") +local menugen = require("context_menu") + +return function(args) + local style = awmtk2.create_style("root_menu",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("root_menu",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local widget = menugen({ + items = { + {"Awesome", { + {"open config dir", "xdg-open "..root_path}, + {"open docs", "xdg-open https://awesomewm.org/doc/api/"}, + {"restart", function() awesome.restart() end}, + {"quit", function() awesome.quit() end} + }, beautiful.awesome_icon}, + {"open terminal", global.terminal} + } + }) + return widget +end diff --git a/widgets/tasklist.lua b/widgets/tasklist.lua index d113e09..5771fdd 100644 --- a/widgets/tasklist.lua +++ b/widgets/tasklist.lua @@ -96,7 +96,9 @@ return function(args) c:connect_signal("unfocus",onunfocus) c:connect_signal("property::urgent",onurgent) c:connect_signal("property::minimized",onminimize) - onfocus() + if client.focus == c then + onfocus() + end end, -- Uncomment this only, and **ONLY** if you actually need it. --id = "background_role"