diff --git a/libs/builder.lua b/libs/builder.lua index 0e0956d..6ca8a74 100644 --- a/libs/builder.lua +++ b/libs/builder.lua @@ -48,7 +48,7 @@ return function(description,opts) return require(struct.widget)(gears.table.join({ layout = (struct.layout and inner_builder(struct.layout)), client = (struct.client and c), screen = (struct.screen and s) - },struct.options or {})) + },struct.options or {},opts.passthrough or {})) elseif struct.list then -- List descriptions local list = { layout = wibox.layout.fixed[( diff --git a/libs/context_menu.lua b/libs/context_menu.lua index 529da0f..f2b557a 100644 --- a/libs/context_menu.lua +++ b/libs/context_menu.lua @@ -11,7 +11,7 @@ local function position_popup(popup,widget,style) 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 + for k,v in pairs(mouse.current_widgets or {}) do if widget == v then widget_geo = mouse.current_widget_geometries[k] end @@ -30,6 +30,8 @@ local function position_popup(popup,widget,style) end return function(args) + -- A way to communicate that all widgets in menu got closed + args.on_close = args.on_close or function() end 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) @@ -42,26 +44,22 @@ return function(args) forced_width = style.button.forced_width, forced_height = style.button.forced_height })) + local onpress = function(widget) + style.button.onrelease(widget) + if root_layer.focused then + root_layer.focused:emit_signal("cascade::kill") + end + end 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) + new_element:connect_signal("button::release",onpress) 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) + new_element:connect_signal("button::release",onpress) elseif type(element[2]) == "table" then local layout = { spacing = style.base.spacing, @@ -82,18 +80,20 @@ return function(args) return end if layer.focused then - layer.focused:emit_signal("cascade_close") + 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() + local onclose = function() style.button.onrelease(new_element) if layout.focused then - layout.focused:emit_signal("cascade_close") + layout.focused:emit_signal("cascade::close") end next_layer.visible = false - end) + end + new_element:connect_signal("cascade::close",onclose) + new_element:connect_signal("cascade::kill",onclose) -- that sweet "just move the mouse 4head" navigation if style.base.menu_slide then new_element:connect_signal("mouse::enter",open_layer) diff --git a/libs/debug.lua b/libs/debug.lua index a341515..6c9fa86 100644 --- a/libs/debug.lua +++ b/libs/debug.lua @@ -1,7 +1,6 @@ local naughty = require("naughty") local debug = {} --- Thanks, u/skhil --- (https://www.reddit.com/r/awesomewm/comments/te49nb/why_does_awesomes_ram_consumption_get_higher_and/) +-- from (https://www.reddit.com/r/awesomewm/comments/te49nb/why_does_awesomes_ram_consumption_get_higher_and/) function debug.print_awesome_memory_stats(message) print(os.date(), "\nLua memory usage:", collectgarbage("count")) out_string = tostring(os.date()) .. "\nLua memory usage:"..tostring(collectgarbage("count")).."\n" diff --git a/modules/desktop.lua b/modules/desktop.lua index 88d2d2c..074ade0 100644 --- a/modules/desktop.lua +++ b/modules/desktop.lua @@ -6,6 +6,7 @@ local beautiful = require("beautiful") local builder = require("builder") local mbarutils = require("menubar").utils local menugen = require("context_menu") +local json = require("dkjson") local function read_file(fname) local fhandler = io.open(fname,"r") @@ -16,53 +17,6 @@ local function read_file(fname) 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 @@ -71,12 +25,20 @@ client.connect_signal("request::titlebars",function(c) end) -- }}} --- {{{ Global widgets -local runmenu = require("widgets.dismal")({ - x = 0, - y = 26 -}) --- }}} +do -- {{{ Global widgets +local config_file = io.open(root_path.."/themes/"..global.theme.."/config/global.json","r") +local config +if config_file then + config = config_file:read("*a") + config_file:close() +else + config = "[]" +end +for k,v in pairs(json.decode(config) or {}) do + require(k)(v) +end +end -- }}} + do -- {{{ Titlebars local titlebar_config = {} diff --git a/modules/xdg_data.lua b/modules/xdg_data.lua index c17d378..76c6c47 100644 --- a/modules/xdg_data.lua +++ b/modules/xdg_data.lua @@ -82,8 +82,8 @@ for k,v in pairs(desktop_dirs) do end, output_done = function() -- Call a global signal - awesome.emit_signal("xdg::dir_finished",v) desktop_dirs_complete = desktop_dirs_complete + 1 + awesome.emit_signal("xdg::dir_finished",v) end }) end diff --git a/themes/reno98/config/client_menu.json b/themes/reno98/config/client_menu.json new file mode 100644 index 0000000..17fff5a --- /dev/null +++ b/themes/reno98/config/client_menu.json @@ -0,0 +1,7 @@ +{ + "list": [ + {"widget": "widgets.clientcontrols"}, + {"widget": "widgets.clientbuttons"} + ], + "vertical":true +} diff --git a/themes/reno98/config/global.json b/themes/reno98/config/global.json new file mode 100644 index 0000000..683ea04 --- /dev/null +++ b/themes/reno98/config/global.json @@ -0,0 +1,7 @@ +{ + "widgets.dismal":{ + "x":0, + "y":26 + }, + "widgets.rootmenu":{} +} diff --git a/themes/reno98/config/root_menu.json b/themes/reno98/config/root_menu.json new file mode 100644 index 0000000..a61658b --- /dev/null +++ b/themes/reno98/config/root_menu.json @@ -0,0 +1,22 @@ +{ + "list": [ + {"widget": "widgets.base.popuptitle", + "options":{ + "icon":"icons/reno98.png", + "title":"Reno 98" + } + }, + {"widget": "widgets.base.tagswitcher", + "screen":true + }, + {"widget": "widgets.rootcontrols"}, + {"widget": "widgets.xdgmenu", + "options": { + "exclude_category": [ + "Other" + ] + } + } + ], + "vertical": true +} diff --git a/themes/reno98/config/titlebar_top.json b/themes/reno98/config/titlebar_top.json index c55f941..0f66a5b 100644 --- a/themes/reno98/config/titlebar_top.json +++ b/themes/reno98/config/titlebar_top.json @@ -1,9 +1,9 @@ { "align": { "left": [ - { - "builtin": "iconwidget", - "client": true + { + "widget":"widgets.clientmenu", + "client":true } ], "center": [ diff --git a/themes/reno98/config/wibar_top.json b/themes/reno98/config/wibar_top.json index 67264e1..d1d6c26 100644 --- a/themes/reno98/config/wibar_top.json +++ b/themes/reno98/config/wibar_top.json @@ -10,6 +10,7 @@ { "widget": "widgets.base.subpanel", "layout": { "list": [ + { "widget": "widgets.base.systray" }, { "widget": "widgets.base.clock" } ] } diff --git a/themes/reno98/icons/lock.png b/themes/reno98/icons/lock.png new file mode 100644 index 0000000..cc3cdab Binary files /dev/null and b/themes/reno98/icons/lock.png differ diff --git a/themes/reno98/icons/power.png b/themes/reno98/icons/power.png new file mode 100644 index 0000000..94be34c Binary files /dev/null and b/themes/reno98/icons/power.png differ diff --git a/themes/reno98/icons/reno98.png b/themes/reno98/icons/reno98.png new file mode 100644 index 0000000..b1e98ef Binary files /dev/null and b/themes/reno98/icons/reno98.png differ diff --git a/themes/reno98/icons/sleep.png b/themes/reno98/icons/sleep.png new file mode 100644 index 0000000..1000808 Binary files /dev/null and b/themes/reno98/icons/sleep.png differ diff --git a/themes/reno98/icons/unknown-app.png b/themes/reno98/icons/unknown-app.png index e4f5121..0d0f8bd 100644 Binary files a/themes/reno98/icons/unknown-app.png 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 deleted file mode 100644 index 5206870..0000000 --- a/themes/reno98/icons/unknown-app.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/themes/reno98/theme.lua b/themes/reno98/theme.lua index f8bc444..163b6af 100644 --- a/themes/reno98/theme.lua +++ b/themes/reno98/theme.lua @@ -1,3 +1,4 @@ +-- Reno98 - a retro replica of a very recognizable theme local theme_assets = require("beautiful.theme_assets") local xresources = require("beautiful.xresources") local dpi = xresources.apply_dpi @@ -8,7 +9,7 @@ local themes_path = root_path.."/themes/" local theme = {} -theme.font = "Liberation Sans 8" +theme.font = "Terminus 8" theme.bg_normal = "#c0c0c0" theme.bg_focus = "#808080" @@ -54,13 +55,9 @@ theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel( ) theme.menu_height = dpi(15) theme.menu_width = dpi(100) +theme.systray_icon_spacing = 2 -- Define the image to load -theme.titlebar_close_button_normal = themes_path.."reno98/titlebar/close_normal.png" -theme.titlebar_close_button_focus = themes_path.."reno98/titlebar/close_focus.png" - -theme.titlebar_minimize_button_normal = themes_path.."reno98/titlebar/minimize_normal.png" -theme.titlebar_minimize_button_focus = themes_path.."reno98/titlebar/minimize_focus.png" theme.titlebar_ontop_button_normal_inactive = themes_path.."reno98/titlebar/ontop_normal_inactive.png" theme.titlebar_ontop_button_focus_inactive = themes_path.."reno98/titlebar/ontop_focus_inactive.png" @@ -77,6 +74,15 @@ theme.titlebar_floating_button_focus_inactive = themes_path.."reno98/titlebar/f theme.titlebar_floating_button_normal_active = themes_path.."reno98/titlebar/floating_normal_active.png" theme.titlebar_floating_button_focus_active = themes_path.."reno98/titlebar/floating_focus_active.png" +theme = theme_assets.recolor_titlebar(theme,theme.fg_normal,"normal") +theme = theme_assets.recolor_titlebar(theme,theme.fg_focus,"focus") + +theme.titlebar_close_button_normal = themes_path.."reno98/titlebar/close_normal.png" +theme.titlebar_close_button_focus = themes_path.."reno98/titlebar/close_focus.png" + +theme.titlebar_minimize_button_normal = themes_path.."reno98/titlebar/minimize_normal.png" +theme.titlebar_minimize_button_focus = themes_path.."reno98/titlebar/minimize_focus.png" + theme.titlebar_maximized_button_normal_inactive = themes_path.."reno98/titlebar/maximized_normal_inactive.png" theme.titlebar_maximized_button_focus_inactive = themes_path.."reno98/titlebar/maximized_focus_inactive.png" theme.titlebar_maximized_button_normal_active = themes_path.."reno98/titlebar/maximized_normal_active.png" @@ -342,10 +348,34 @@ theme.widgets = { margins = 0 } }, + root_menu = { + base = { + spacing = 2 + } + }, + client_menu = { + base = { + spacing = 2 + } + }, + taglist = { + base = { + spacing = 2 + }, + button = { + bgimage_focus = theme.bgimage_inset, + bgimage_normal = theme.bgimage_outset, + margins = 2 + }, + container = { + margins = 3 + } + }, subpanel = { container = { bgimage = theme.bgimage_inset, - bg = theme.bgimage_normal + bg = theme.bgimage_normal, + margins = 2 } }, dismal = { @@ -370,19 +400,26 @@ theme.widgets = { base = { -- Enables the ability to just drag the mouse on an entry to open it menu_slide = true, - spacing = 1 + spacing = 2 }, button = { forced_height = 20, forced_width = 160 }, - popup = { - margins = 2 + }, + systray = { + container = { + bgimage = function() end, + margins = 0 } }, - root_menu = { - popup = { - margins = 2 + client_buttons = { + button = { + forced_width = 20, + forced_height = 20 + }, + base = { + spacing = 2 } }, titlebar = { diff --git a/widgets/base/popuptitle.lua b/widgets/base/popuptitle.lua new file mode 100644 index 0000000..d762c6e --- /dev/null +++ b/widgets/base/popuptitle.lua @@ -0,0 +1,17 @@ +-- Base for widgets +local awmtk2 = require("awmtk2") +local wibox = require("wibox") +local gears = require("gears") +local awful = require("awful") +local beautiful = require("beautiful") + +return function(args) + local style = awmtk2.create_style("popuptitle",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("popuptitle",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local widget = wibox.widget(t.container(t.article({ + icon = root_path.."/themes/"..global.theme.."/"..args.icon, + title = args.title + }))) + return widget +end diff --git a/widgets/base/systray.lua b/widgets/base/systray.lua new file mode 100644 index 0000000..2ebdae9 --- /dev/null +++ b/widgets/base/systray.lua @@ -0,0 +1,16 @@ +-- Base for widgets +local awmtk2 = require("awmtk2") +local wibox = require("wibox") +local gears = require("gears") +local awful = require("awful") +local beautiful = require("beautiful") + +return function(args) + local style = awmtk2.create_style("systray",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("systray",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local widget = wibox.widget(t.container({ + widget = wibox.widget.systray + })) + return widget +end diff --git a/widgets/base/tagswitcher.lua b/widgets/base/tagswitcher.lua new file mode 100644 index 0000000..c7d33e1 --- /dev/null +++ b/widgets/base/tagswitcher.lua @@ -0,0 +1,58 @@ +-- Base for widgets +local awmtk2 = require("awmtk2") +local wibox = require("wibox") +local gears = require("gears") +local awful = require("awful") +local beautiful = require("beautiful") + +return function(args) + local style = awmtk2.create_style("taglist",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("taglist",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local widget = wibox.widget(t.container(awful.widget.taglist({ + screen = args.screen, + filter = awful.widget.taglist.filter.all, + style = { + shape = style.button.shape + }, + layout = { + spacing = style.base.spacing, + spacing_widget = style.base.spacing_widget, + layout = style.base.layout or wibox.layout.fixed.horizontal + }, + widget_template = t.button(t.article({ + icon_id = "icon_role", + title_id = "text_role" + }),{ + id = "background", + create_callback = function(self, tag, index, tags) + self:connect_signal("button::press",function(self,x,y,b) + if b == 1 then + awful.tag.viewmore({tag}) + elseif b == 3 then + awful.tag.viewtoggle(tag) + end + end) + local bg = self:get_children_by_id("background")[1] + if tag.selected then + bg.bgimage = style.button.bgimage_focus + bg.bg = style.button.bg_focus + else + bg.bgimage = style.button.bgimage_normal + bg.bg = style.button.bg_normal + end + end, + update_callback = function(self, tag, index, tags) + local bg = self:get_children_by_id("background")[1] + if tag.selected then + bg.bgimage = style.button.bgimage_focus + bg.bg = style.button.bg_focus + else + bg.bgimage = style.button.bgimage_normal + bg.bg = style.button.bg_normal + end + end + }) + }))) + return widget +end diff --git a/widgets/clientbuttons.lua b/widgets/clientbuttons.lua new file mode 100644 index 0000000..cf41053 --- /dev/null +++ b/widgets/clientbuttons.lua @@ -0,0 +1,85 @@ +-- +local awmtk2 = require("awmtk2") +local wibox = require("wibox") +local gears = require("gears") +local awful = require("awful") +local beautiful = require("beautiful") + +return function(args) + local style = awmtk2.create_style("client_buttons",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("client_buttons",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local floating_on = beautiful.titlebar_floating_button_normal_inactive + local floating_off = beautiful.titlebar_floating_button_normal_active + local ontop_on = beautiful.titlebar_ontop_button_normal_inactive + local ontop_off = beautiful.titlebar_ontop_button_normal_active + local sticky_on = beautiful.titlebar_sticky_button_normal_inactive + local sticky_off = beautiful.titlebar_sticky_button_normal_active + local floating = wibox.widget(t.button({ + image = (client.focus and client.focus.floating and floating_on) or floating_off, + widget = wibox.widget.imagebox, + id = "icon" + },{ + forced_height = style.button.forced_height, + forced_width = style.button.forced_width + })) + floating:connect_signal("button::press",style.button.onpress) + floating:connect_signal("button::release",style.button.onrelease) + floating:connect_signal("button::press",function(widget) + client.focus.floating = (not client.focus.floating) + widget:emit_signal("widget::update",widget) + end) + floating:connect_signal("widget::update",function(widget) + local icon = widget:get_children_by_id("icon")[1] + icon.image = (client.focus.floating and floating_on) or floating_off + end) + local ontop = wibox.widget(t.button({ + image = (client.focus and client.focus.ontop and ontop_on) or ontop_off, + widget = wibox.widget.imagebox, + id = "icon" + },{ + forced_height = style.button.forced_height, + forced_width = style.button.forced_width + })) + ontop:connect_signal("button::press",style.button.onpress) + ontop:connect_signal("button::release",style.button.onrelease) + ontop:connect_signal("button::press",function(widget) + client.focus.ontop = (not client.focus.ontop) + widget:emit_signal("widget::update",widget) + end) + ontop:connect_signal("widget::update",function(widget) + local icon = widget:get_children_by_id("icon")[1] + icon.image = (client.focus.ontop and ontop_on) or ontop_off + end) + local sticky = wibox.widget(t.button({ + image = (client.focus and client.focus.sticky and sticky_on) or sticky_off, + widget = wibox.widget.imagebox, + id = "icon" + },{ + forced_height = style.button.forced_height, + forced_width = style.button.forced_width + })) + sticky:connect_signal("button::press",style.button.onpress) + sticky:connect_signal("button::release",style.button.onrelease) + sticky:connect_signal("button::press",function(widget) + client.focus.sticky = (not client.focus.sticky) + widget:emit_signal("widget::update",widget) + end) + sticky:connect_signal("widget::update",function(widget) + local icon = widget:get_children_by_id("icon")[1] + icon.image = (client.focus.sticky and sticky_on) or sticky_off + end) + client.connect_signal("focus",function(c) + sticky:emit_signal("widget::update") + ontop:emit_signal("widget::update") + floating:emit_signal("widget::update") + end) + local widget = wibox.widget({ + floating, + ontop, + sticky, + layout = wibox.layout.fixed.horizontal, + spacing = style.base.spacing + }) + return widget +end diff --git a/widgets/clientcontrols.lua b/widgets/clientcontrols.lua new file mode 100644 index 0000000..e4e8498 --- /dev/null +++ b/widgets/clientcontrols.lua @@ -0,0 +1,64 @@ +-- Basic client control keys +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("client_controls",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("client_controls",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local move_to_tag = {} + local add_to_tag = {} + awful.screen.connect_for_each_screen(function(s) + table.insert(move_to_tag,{ + "Screen "..s.index, + (function() + local t = {} + for k,v in pairs(s.tags) do + table.insert(t,{v.name,function() + if client.focus then + client.focus:tags({v}) + end + end}) + end + return t + end)() + }) + table.insert(add_to_tag,{ + "Screen "..s.index, + (function() + local t = {} + for k,v in pairs(s.tags) do + table.insert(t,{v.name,function() + if client.focus then + local tags = client.focus:tags() + for k,tag in pairs(tags) do + if v == tag then + table.remove(tags,k) + client.focus:tags(tags) + return + end + end + table.insert(tags,v) + client.focus:tags(tags) + end + end}) + end + return t + end)() + }) + end) + local widget = menugen({ + items = { + { "Kill client", function() client.focus:kill() end }, + { "Raise client", function() client.focus:raise() end}, + { "Lower client", function() client.focus:lower() end}, + { "Move to tag", move_to_tag }, + { "Switch on tag", add_to_tag } + }, + }) + return widget +end diff --git a/widgets/clientmenu.lua b/widgets/clientmenu.lua new file mode 100644 index 0000000..df82746 --- /dev/null +++ b/widgets/clientmenu.lua @@ -0,0 +1,69 @@ +-- 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") +local builder = require("builder") +local style = awmtk2.create_style("client_menu",awmtk2.default,{}) +local templates = awmtk2.create_template_lib("client_menu",awmtk2.templates,{}) +local t = awmtk2.build_templates(templates,style) + +-- Create a global context menu for clients first +if not context_menu then +local config_file = io.open(root_path.."/themes/"..global.theme..'/config/client_menu.json',"r") +local config +if config_file then + config = config_file:read("*a") + config_file:close() +else + config = [[{"list":[{"widget":"widgets.clientcontrols"}]}]] +end +context_menu = awful.popup(t.popup(builder( + config, + { + style = style.base, + } +))) +context_menu:connect_signal("button::press",function(self,x,y,b) + if b == 3 then + context_menu.visible = false + end +end) +context_menu:connect_signal("property::visible",function(self,x,y,b) + if not context_menu.visible then + local children = context_menu.widget:get_children_by_id("menu_root") + for k,v in pairs(children) do + for k2,v2 in pairs(v.children) do + v2:emit_signal("cascade::close") + end + end + end +end) +client.connect_signal("focus",function() + context_menu.visible = false +end) +for _,layout in pairs(context_menu.widget:get_children_by_id("menu_root")) do + for _,button in pairs(layout.children) do + button:connect_signal("cascade::kill",function() + context_menu.visible = false + end) + end +end +end + +return function(args) + local widget = wibox.widget({ + widget = awful.widget.clienticon, + client = args.client + }) + widget:connect_signal("button::press",function() + context_menu.visible = (not context_menu.visible) + if context_menu.visible then + context_menu.x = mouse.coords().x + context_menu.y = mouse.coords().y + end + end) + return widget +end diff --git a/widgets/rootbuttons.lua b/widgets/rootbuttons.lua new file mode 100644 index 0000000..cf41053 --- /dev/null +++ b/widgets/rootbuttons.lua @@ -0,0 +1,85 @@ +-- +local awmtk2 = require("awmtk2") +local wibox = require("wibox") +local gears = require("gears") +local awful = require("awful") +local beautiful = require("beautiful") + +return function(args) + local style = awmtk2.create_style("client_buttons",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("client_buttons",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + local floating_on = beautiful.titlebar_floating_button_normal_inactive + local floating_off = beautiful.titlebar_floating_button_normal_active + local ontop_on = beautiful.titlebar_ontop_button_normal_inactive + local ontop_off = beautiful.titlebar_ontop_button_normal_active + local sticky_on = beautiful.titlebar_sticky_button_normal_inactive + local sticky_off = beautiful.titlebar_sticky_button_normal_active + local floating = wibox.widget(t.button({ + image = (client.focus and client.focus.floating and floating_on) or floating_off, + widget = wibox.widget.imagebox, + id = "icon" + },{ + forced_height = style.button.forced_height, + forced_width = style.button.forced_width + })) + floating:connect_signal("button::press",style.button.onpress) + floating:connect_signal("button::release",style.button.onrelease) + floating:connect_signal("button::press",function(widget) + client.focus.floating = (not client.focus.floating) + widget:emit_signal("widget::update",widget) + end) + floating:connect_signal("widget::update",function(widget) + local icon = widget:get_children_by_id("icon")[1] + icon.image = (client.focus.floating and floating_on) or floating_off + end) + local ontop = wibox.widget(t.button({ + image = (client.focus and client.focus.ontop and ontop_on) or ontop_off, + widget = wibox.widget.imagebox, + id = "icon" + },{ + forced_height = style.button.forced_height, + forced_width = style.button.forced_width + })) + ontop:connect_signal("button::press",style.button.onpress) + ontop:connect_signal("button::release",style.button.onrelease) + ontop:connect_signal("button::press",function(widget) + client.focus.ontop = (not client.focus.ontop) + widget:emit_signal("widget::update",widget) + end) + ontop:connect_signal("widget::update",function(widget) + local icon = widget:get_children_by_id("icon")[1] + icon.image = (client.focus.ontop and ontop_on) or ontop_off + end) + local sticky = wibox.widget(t.button({ + image = (client.focus and client.focus.sticky and sticky_on) or sticky_off, + widget = wibox.widget.imagebox, + id = "icon" + },{ + forced_height = style.button.forced_height, + forced_width = style.button.forced_width + })) + sticky:connect_signal("button::press",style.button.onpress) + sticky:connect_signal("button::release",style.button.onrelease) + sticky:connect_signal("button::press",function(widget) + client.focus.sticky = (not client.focus.sticky) + widget:emit_signal("widget::update",widget) + end) + sticky:connect_signal("widget::update",function(widget) + local icon = widget:get_children_by_id("icon")[1] + icon.image = (client.focus.sticky and sticky_on) or sticky_off + end) + client.connect_signal("focus",function(c) + sticky:emit_signal("widget::update") + ontop:emit_signal("widget::update") + floating:emit_signal("widget::update") + end) + local widget = wibox.widget({ + floating, + ontop, + sticky, + layout = wibox.layout.fixed.horizontal, + spacing = style.base.spacing + }) + return widget +end diff --git a/widgets/rootcontrols.lua b/widgets/rootcontrols.lua new file mode 100644 index 0000000..6cea1b7 --- /dev/null +++ b/widgets/rootcontrols.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/rootmenu.lua b/widgets/rootmenu.lua index 524e8ea..7ecfe9b 100644 --- a/widgets/rootmenu.lua +++ b/widgets/rootmenu.lua @@ -1,25 +1,71 @@ --- 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") +local builder = require("builder") 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 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 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 + 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.rootcontrols"}],"vertical": true}]] + end + -- TODO: Refactor this whole mess + root_menu = awful.popup(t.popup({ + markup = "brainhurt the game", + widget = wibox.widget.textbox + })) + root_menu:connect_signal("button::press",function(self,x,y,b) + if b == 3 then + root_menu.visible = false + end + end) + root_menu._menu_private = {} + root_menu.widget = wibox.widget(t.popup(builder( + config, + { + style = style.base, + screen = mouse.screen, + passthrough = { + parent = root_menu, + _tracking_layer = root_menu._menu_private + } + } + )).widget) + for _,layout in pairs(root_menu.widget:get_children_by_id("menu_root")) do + print(layout) + for _,button in pairs(layout.children) do + button:connect_signal("cascade::kill",function() + root_menu.visible = false + end) + end + end + root_menu:connect_signal("property::visible",function() + 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 + w:emit_signal("cascade::close") + end + end + end) + local buttons = root.buttons() + root.buttons(gears.table.join(buttons, + awful.button({}, 3, function() + 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) + )) + return root_menu +end diff --git a/widgets/xdgmenu.lua b/widgets/xdgmenu.lua new file mode 100644 index 0000000..41abdfc --- /dev/null +++ b/widgets/xdgmenu.lua @@ -0,0 +1,99 @@ +-- Generic application menu +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") +local menuutils = require("menubar").utils + +return function(args) + local style = awmtk2.create_style("xdg_menu",awmtk2.default,args.style) + local templates = awmtk2.create_template_lib("xdg_menu",awmtk2.templates,args.templates) + local t = awmtk2.build_templates(templates,style) + -- Add a "loading" indicator while XDG is still parsing data + local widget = wibox.widget({ + t.container({ + markup = "Loading XDG menu...", + widget = wibox.widget.textbox + }), + layout = wibox.layout.fixed.vertical, + id = "xdg_menu_root" + }) + + local function exclude(name) + for k,v in pairs(args.exclude or {}) do + if name:match(v) then + return true + end + end + return false + end + + awesome.connect_signal("xdg::all_finished",function() + if not args.parent then return end + local items = {} + for k,v in pairs(xdg.categories) do + local noprocess = false + for k2,v2 in pairs(args.exclude_category or {}) do + if k == v2 then + noprocess = true + end + end + if (not noprocess) and (#v.apps > 0) then + local category = {k,{},menuutils.lookup_icon_uncached(v.icon)} + for _,item in pairs(v.apps) do + if not exclude(item.name) then + table.insert(category[2], { + item.name, + item.exec:gsub("%%%w","") or "", + gears.filesystem.file_readable(item.icon or "") and item.icon + }) + end + end + table.insert(items,category) + end + end + -- uhhh there's a lot of things about async, some of which i can't explain + local xdg_menu_root = widget:get_children_by_id("xdg_menu_root")[1] + xdg_menu_root:reset() + local menu = wibox.widget(menugen({ + items = items, + })) + local menu_root = menu:get_children_by_id("menu_root")[1] + for k,v in pairs(menu_root.children) do + v:connect_signal("cascade::kill",function() + args.parent.visible = false + end) + args.parent:connect_signal("property::visible",function() + if not args.parent.visible then + v:emit_signal("cascade::close") + end + end) + menu:connect_signal("widget::redraw_needed",function() + if not menu.visible then + v:emit_signal("cascade::close") + end + end) + end + local appswitch = wibox.widget(t.button(t.textbox({ + markup = "Applications", + id = "apptext" + }))) + appswitch:connect_signal("button::press",function(self) + menu.visible = (not menu.visible) + local textbox = appswitch:get_children_by_id("apptext")[1] + if menu.visible then + style.button.onpress(self) + textbox:set_markup("Applications") + else + style.button.onrelease(self) + textbox:set_markup("Applications") + end + end) + menu.visible = false + xdg_menu_root:add(appswitch) + xdg_menu_root:add(menu) + end) + return widget +end