From a423d30cde871ff1c4b85ffe954c8f6b8a21dcf3 Mon Sep 17 00:00:00 2001 From: Yessiest Date: Thu, 25 Aug 2022 19:27:31 +0400 Subject: [PATCH] Menu work --- libs/builder.lua | 2 +- libs/context_menu.lua | 34 ++++----- libs/debug.lua | 3 +- modules/desktop.lua | 68 ++++------------- modules/xdg_data.lua | 2 +- themes/reno98/config/client_menu.json | 7 ++ themes/reno98/config/global.json | 7 ++ themes/reno98/config/root_menu.json | 22 ++++++ themes/reno98/config/titlebar_top.json | 6 +- themes/reno98/config/wibar_top.json | 1 + themes/reno98/icons/lock.png | Bin 0 -> 510 bytes themes/reno98/icons/power.png | Bin 0 -> 787 bytes themes/reno98/icons/reno98.png | Bin 0 -> 718 bytes themes/reno98/icons/sleep.png | Bin 0 -> 721 bytes themes/reno98/icons/unknown-app.png | Bin 999 -> 768 bytes themes/reno98/icons/unknown-app.svg | 45 ----------- themes/reno98/theme.lua | 63 ++++++++++++---- widgets/base/popuptitle.lua | 17 +++++ widgets/base/systray.lua | 16 ++++ widgets/base/tagswitcher.lua | 58 +++++++++++++++ widgets/clientbuttons.lua | 85 +++++++++++++++++++++ widgets/clientcontrols.lua | 64 ++++++++++++++++ widgets/clientmenu.lua | 69 +++++++++++++++++ widgets/rootbuttons.lua | 85 +++++++++++++++++++++ widgets/rootcontrols.lua | 25 +++++++ widgets/rootmenu.lua | 80 +++++++++++++++----- widgets/xdgmenu.lua | 99 +++++++++++++++++++++++++ 27 files changed, 706 insertions(+), 152 deletions(-) create mode 100644 themes/reno98/config/client_menu.json create mode 100644 themes/reno98/config/global.json create mode 100644 themes/reno98/config/root_menu.json create mode 100644 themes/reno98/icons/lock.png create mode 100644 themes/reno98/icons/power.png create mode 100644 themes/reno98/icons/reno98.png create mode 100644 themes/reno98/icons/sleep.png delete mode 100644 themes/reno98/icons/unknown-app.svg create mode 100644 widgets/base/popuptitle.lua create mode 100644 widgets/base/systray.lua create mode 100644 widgets/base/tagswitcher.lua create mode 100644 widgets/clientbuttons.lua create mode 100644 widgets/clientcontrols.lua create mode 100644 widgets/clientmenu.lua create mode 100644 widgets/rootbuttons.lua create mode 100644 widgets/rootcontrols.lua create mode 100644 widgets/xdgmenu.lua 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 0000000000000000000000000000000000000000..cc3cdabaf3eb836ebf51e90c8cbcc506acbeaed7 GIT binary patch literal 510 zcmVpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10gFjQ zK~z|U?Uubx0znjozoTek3^eq{N*{sB#AqkJfz~F5Xl(6Cco8LtK7hv3%16-3SSvyy zHj-=MVwPbSb_Z4(PI9x^*>mqXGdq7WGkhUw1;EU{d}}PE6f8(OlXNes19X9|q)yOw zDk-1JftigBKtKg(0X8Py1FjO)P9VMvTqh8AqX{fcWFYAIjfZ$YuEveTI0MHKMZbYd zU=LUeq72l5UIhQh%K%US+D@?#V0%Q)PE1bT$H0kGs5eSHl(!o(5)~fwwpAnVNLfJtS9W@BpA@h z#gG7AfyXI{miRq0hA_&&gP9#pLtWAZa1ixv=Br?CU~XV;VAMXaC8;?josy4%{*5Hq)$07*qoM6N<$g0yeW A-v9sr literal 0 HcmV?d00001 diff --git a/themes/reno98/icons/power.png b/themes/reno98/icons/power.png new file mode 100644 index 0000000000000000000000000000000000000000..94be34cfda2759ecb363ba33633424dbb119ef02 GIT binary patch literal 787 zcmV+u1MK{XP)Vl&|00009a7bBm000j< z000j<0hc-3!T<(mcm~^s}x#VL7{TxImt%=^~OjZoP>N*sxyz0OmY!v7m*ne`6?oJL?rq}MPyh+UW&-Hh;(E+W-Mz3 zSfhGrFM0McV;l2qr+{70_6_KZT6Pf`0v-WJjOl1(;vImPxLFaoRx@+pBCu_;Qs6bv z7MXby@G5|@1q=jtJJ1gN2n5~7lu|A7)P4w<3}CGTr4adI!1-3jo~TLg`P~j+&Q*~E z=K@ZXHR?QyJoTLlVE6ju&y8^fXeo&NF!0v+FRChuh?IddW*?5K>LvwT_Orx%rk`ehFadrUWpf13Jg#I&pYsthEoQ!%;JTMD-StpZ^%<^8 z#(@5GUQg`a`VOuP`~zS-&#ffl_A_pH9wflBd80uQX^6-qT12D~7&Pi-fHKw1UxCX7 zXFX)_cY$)&*}e)i6-3+&yf^p@eq-r3Mg=AcA`f-7itXof0jC@PNIV+AeDc@sIdaE;+!1Xtb}+YCNrU{d7zXYFp>q3# z>rP9+$25~R+)u-4-~wpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10$WK$ zK~!jg?U_4hR8bIyzu9O|L?jRk(JB@eL69h-jVLw|L{k`IW6(yBuolV+J|f5lM3TxC zkrWnc6M_)MS1PeFAQ%yig`iEeOOr%YeB`&erU*Otp4}~$<>YH;&g`7|IB?HdlSCtv zt9Jvnvb=$Mvm!L{ms#1v(kxk8++iM=2Bv_~W_X13qk{E|Sfd}}U<32cgx4kpym%!T zjQ@t77HKwkO*95(oC&uk2E2Hc+-j9hg(Svf;EOZiO^E?7UM&U>H%f;y^P(~E$(iux z#6UHCHrpY139Kv^H#pcPJx;3;kAW%2Kzj`a06v%v2rfF|%k5GzZGAijCLIGEH5ho4 zaRz|S4rx5CMmz>490R)(175sZ4DRoej%4OVW8k?n;eCk#FJ27>H}*>TpxkH-JaZ=8 znHccmm0<960gfJ!=7QHmV_?jga93i$i#yB-rgQLa0Y+!x$#Lmt1?v}y$H0g);hx06 zh}m~wbxMi%IoR1<PW1!?1$d|bfl+4xxZ-EUdCI94LPoFdq+Cw?wF)-*DD5TuT z2F0$wx5?ihW7KHcntJA28w~N z68&bkffE^NSBuhx(4HVB0|m#xUpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10$xc( zK~z|U#n;b^O<^3z@z=S7NR06-YN9A>A&pE}h%Ah3l$1ZgRx>3b`~wtX!^*;jg)D`I z#bl%GXfljx{3tABhR5RG$?@Fh%sI!s@~vm_eEanMyw9)i^F3Jz!T*eTRfSoWEx>;4 z!cMHmQY^v*#xRO|co;&Mu2eXLFz3Q@oWfg#it9awvADE;iTUBy)m1f)*9=b720#N> zIxxgIfi~zThg3U}NiDcvS-My)M9|R1us*Z%(%ZA4|-CV5Bkt4&i51fCEv{&*)14>`vUJ4S#DMLeS8Rz5a~bA%subV_&qt6GC{I z&{d9EfWavLpg_MT+TZKMJP)uo%0Da6_ecAu-2zx0vU{fcJ zDBp_TMa9o10DAC3dn+zI^{O03!`jM%MM=>jfx1E3dEQQs&GoSC(1>50C>nsNNq@>Jgm&Yk(F+pXR(cUc-0_Csp`0%UUL- zk!9I@%@(~&vm>ta`{(qn=J-B}yLc2T{+w0@_*d}@i459Z>@TXe00000NkvXXu0mjf D_PR-> literal 0 HcmV?d00001 diff --git a/themes/reno98/icons/unknown-app.png b/themes/reno98/icons/unknown-app.png index e4f512152345eb274bdf50858d07e141f046068e..0d0f8bd5e8ea3ae920e781c2f950257f873b871b 100644 GIT binary patch literal 768 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F>>p_??`B~p#prB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&3=B-Yo-U3d6?5Ls_Rba#lyErj z>*i~y85U5mphGv;QSeA!i6Y+<^^DhUcXnL$z25Xioa1ik#i_HkVs~r{u}WAP6xf~7 z+Ql`IMQFB#qQKe1g@VPYMuIg*es=9lpM1yK)1r6=JG1$z@3p^X&e+mmqSgQ-roG-3 zd`U>?$G-W6GU<1j-g%w&STH4uY1x`@M^-OyK67pg>(oUL&t<*7T6(v;@9~eY=j`i> zCX4D7_Eo=m$}M?p$N8rnru7A{zdb+jS5 z%F&65+|?Bh=lS_eZ*1Ssbl^n`SB-z9YL~UCg3N-~u@6-GS4>Q3j8uz!D4}1yQGfTO z3xW(E8ZzfSWGI+>m7{dg^6ZAYE_%~nTm64nYrJ7?-1^twf%Z=cz4SP1D;JCZQnQ5& z=Pms^57)oCU3@LvdVbjCDc;o@)2+5gItVqK?fvn+c%N_6ncIxJ1i3aGcynL!`;4QN zzqfDSy6)RU?l|+3hR4fK|B}1u|AOITh0OWSDzQq6Gkw^OSv5SbOxb+%MC+ooni?Ae zGymqd<|{+I{FhzMbaQiaY58Zm?ls%7+Ip55440TLQIU8dsjettgbcDqLajV+K!B)CK(!7VQ@Z-v8Q z?mGHu6Cj+C-|Q^eB7|^+T$hd3_2&X4N!qOG4u`{>-|zqS@OtjB&Vc)Ye{?#%0RZRc z=aqk%cyA9cc6YIHQ+^2mM(cVxIy%Y$*JA;EsBe30Jz53~)>SV7bOMD6aB*owR6LHp z!9n!Z#|+l>=IhL6vrd*}Yq~F0Rb^_8+UvQ4k!6`IEG#5rvDk>tg#SGc9)higWdLmf zw6P4JEr2$b0kj3srsWN2f4B)g#_H8^YH0KMd}MojTTZ9bUahgi!@~{$h(@D-Ez~S@8_?U^tE{c9jWZ0> z&^9+W_m$`Qq9}^>;VYJ9^Qx-$93LP5cDYD$S;^HDt2*JR>Kr)p|y?v_O57F}XfTkD_3{o0fIuK%*oc*tmDip z6bki7lGHHQ{{H^2S~(O78NL^+udkmeiehw_CWa3|uh+}#f9aJ3#XpZOk1Z^=-MR#}in_8I#@Y(5fW^6Xwv-)mtGPfTU7($-w d{~(@*KW0RT5v_1rbl(5~002ovPDHLkV1h#mwio~a 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