From 7bac2924087f33d9e227c0cecc69e32741265465 Mon Sep 17 00:00:00 2001 From: Yessiest Date: Tue, 23 Aug 2022 17:03:15 +0400 Subject: [PATCH] Root menu added + minor fixes --- libs/awmtk2.lua | 8 +- libs/context_menu.lua | 117 ++++++++++++++++++++++++++++ modules/desktop.lua | 59 ++++++++++++-- themes/default/theme.lua | 3 +- themes/reno98/icons/unknown-app.png | Bin 0 -> 999 bytes themes/reno98/icons/unknown-app.svg | 45 +++++++++++ themes/reno98/theme.lua | 25 +++++- widgets/rootmenu.lua | 25 ++++++ widgets/tasklist.lua | 4 +- 9 files changed, 274 insertions(+), 12 deletions(-) create mode 100644 libs/context_menu.lua create mode 100644 themes/reno98/icons/unknown-app.png create mode 100644 themes/reno98/icons/unknown-app.svg create mode 100644 widgets/rootmenu.lua 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 0000000000000000000000000000000000000000..e4f512152345eb274bdf50858d07e141f046068e GIT binary patch literal 999 zcmV4LI?wBuV;RKKIwM5M*xj2kVquBL?Xd0FE4L}!(r|^ z`e_p&oRQz`EZHK2aD-f!jn?(&0whV=tmzJi!<^sm|Mu{D?y$~)`+;;iy#WB{=jWAw znRssxFLrmaaZ`Q?07mP2IXXJZ0oP*ze5h}GY&}{A4AxaI0dxX|3UG00L{vPEzQIBC z)yE9h_2%o$X0uL~Wox=GRaIqbjoRzEgOO#KEG#S}W3kwX&V>Ix4<3T8hGhV40kp9U zpe=wlmI1T{(5B@LXt)VJ#_H8^YH0KMd}MojTTZ9bUahgi!@~{$h(@D-Ez~S@8_?U^tE{c9jWZ0>&^9+W z_m$`Qq9}^>;VYJ9^Qx-$93LP5cDYX}T&Ju@>C7X%@0 zx7&Z1mDeau*#def7K{Ai;v!E7!N9;kGL=fbeX86K(en3zrWgM@L6$ za&oe)x4+rw-U25lC$A$CLGV zJOF?|AYj;tm6es(rBbQi=r}EO8&E2h`Xx!~mt{G1zfBN?b45{x>SHdK>ns!s^+=M` zFxUS6{;yg&6bc!>7p$+ZpDBuBbeJZF4?(Zj%j@Z;E90hCgOR Vh^=s2bl(5~002ovPDHLkV1iZ#zoGyD literal 0 HcmV?d00001 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"