commit a3b1d3c50126fefaf55036baaa14dc0b973bcb81 Author: Rokas Puzonas Date: Sun Jun 4 15:59:49 2023 +0300 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..5854a6e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# AwesomeWM + +Original gotten from: https://github.com/Manas140/dotfiles diff --git a/bar/init.lua b/bar/init.lua new file mode 100644 index 0000000..f10f15d --- /dev/null +++ b/bar/init.lua @@ -0,0 +1,99 @@ +local sys_widgets = require("bar.sys") +local oth = require("bar.oth") + +local main = wibox.widget{ + { + { + oth.launch, + oth.search, + spacing = dpi(20), + layout = wibox.layout.fixed.vertical + }, + left = dpi(2), + right = dpi(2), + bottom = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + shape = help.rrect(beautiful.br), + bg = beautiful.bg2, + widget = wibox.container.background +} + +local sys = wibox.widget{ + { + { + { + -- sys_widgets.net, + -- sys_widgets.blu, + sys_widgets.vol, + spacing = dpi(20), + layout = wibox.layout.fixed.vertical + }, + oth.sep, + sys_widgets.clock, + layout = wibox.layout.fixed.vertical + }, + left = dpi(2), + right = dpi(2), + bottom = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + shape = help.rrect(beautiful.br), + bg = beautiful.bg2, + widget = wibox.container.background +} + +awful.screen.connect_for_each_screen(function(s) + local wibar = awful.wibar({ + position = "left", + bg = beautiful.bg, + fg = beautiful.fg, + width = dpi(50), + screen = s + }) + + wibar:setup { + layout = wibox.layout.align.vertical, + { -- Top + main, + left = dpi(5), + right = dpi(5), + top = dpi(10), + bottom = dpi(5), + widget = wibox.container.margin, + }, + { -- Middle + { + { + { + require('bar.tag')(s), + require('bar.task')(s), + layout = wibox.layout.fixed.vertical, + }, + bg = beautiful.bg2, + shape = help.rrect(beautiful.br), + widget = wibox.container.background + }, + top = dpi(5), + bottom = dpi(5), + left = dpi(5), + right = dpi(5), + widget = wibox.container.margin, + }, + layout = wibox.layout.flex.vertical, + }, + { -- Bottom + { + sys, + layout = wibox.layout.fixed.vertical, + }, + top = dpi(5), + left = dpi(5), + right = dpi(5), + bottom = dpi(10), + widget = wibox.container.margin, + }, + } +end) diff --git a/bar/oth.lua b/bar/oth.lua new file mode 100644 index 0000000..996f869 --- /dev/null +++ b/bar/oth.lua @@ -0,0 +1,59 @@ +local M = {} + +local utils = require("utils") +local bindings = utils.bindings +local buttonbind = utils.buttonbind +local spawn_with_shell = utils.wrap_spawn_with_shell + +-- Separator +M.sep = wibox.widget { + { + forced_height = dpi(2), + shape = gears.shape.line, + widget = wibox.widget.separator + }, + top = dpi(15), + left = dpi(5), + right = dpi(5), + bottom = dpi(15), + widget = wibox.container.margin +} + +M.launch = wibox.widget { + { + markup = "", + font = beautiful.icofont, + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + }, + widget = wibox.container.background, +} + +M.search = wibox.widget { + { + markup = "", + font = beautiful.icofont, + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + }, + widget = wibox.container.background, +} + +M.search:buttons(bindings{ + buttonbind({}, 1, spawn_with_shell("rofi -show drun")) +}) + +M.launch:buttons(bindings{ + buttonbind({}, 1, function() + if not dashboard.visible then + M.launch.fg = beautiful.pri + else + M.launch.fg = beautiful.fg + end + dashboard.toggle() + end) +}) + +return M diff --git a/bar/sys.lua b/bar/sys.lua new file mode 100644 index 0000000..66c1583 --- /dev/null +++ b/bar/sys.lua @@ -0,0 +1,70 @@ +local M = {} + +-- Wifi +M.net = wibox.widget{ + font = beautiful.icofont, + align = 'center', + widget = wibox.widget.textbox +} + +-- Volume +M.vol = wibox.widget{ + font = beautiful.icofont, + align = 'center', + widget = wibox.widget.textbox +} + +-- Bluethooth +M.blu = wibox.widget{ + font = beautiful.icofont, + align = 'center', + widget = wibox.widget.textbox +} + +-- Clock +M.clock = wibox.widget{ + font = beautiful.barfont, + format = '%H\n%M', + refresh = 1, + align = 'center', + valign = 'center', + widget = wibox.widget.textclock +} + +awesome.connect_signal('blu::value', function(stat) + if stat:match('no') then + M.blu.opacity = 0.25 + M.blu.markup = '' + else + M.blu.opacity = 1 + M.blu.markup = '' + end +end) + +awesome.connect_signal('net::value', function(stat) + if stat:match('up') then + M.net.opacity = 1 + M.net.markup = '' + else + M.net.opacity = 0.25 + M.net.markup = '' + end +end) + +awesome.connect_signal('vol::value', function(mut, val) + if mut == 0 then + M.vol.opacity = 1 + if val > 70 then + M.vol.markup = '' + elseif val > 30 then + M.vol.markup = '' + else + M.vol.markup = '' + end + else + M.vol.opacity = 0.25 + M.vol.markup = '' + end +end) + +return M diff --git a/bar/tag.lua b/bar/tag.lua new file mode 100644 index 0000000..481daa9 --- /dev/null +++ b/bar/tag.lua @@ -0,0 +1,28 @@ +return function(s) + local tag = awful.widget.taglist { + screen = s, + filter = awful.widget.taglist.filter.selected, + widget_template = { + { + id = 'text_role', + align = 'center', + widget = wibox.widget.textbox, + }, + top = dpi(10), + bottom = dpi(10), + left = dpi(15), + right = dpi(15), + widget = wibox.container.margin + }, + id = 'background_role', + widget = wibox.container.background, + + create_callback = function(self, _, index, _) + self:get_children_by_id('text_role').markup = index + end, + update_callback = function(self, _, index, _) + self:get_children_by_id('text_role').markup = index + end + } + return tag +end diff --git a/bar/task.lua b/bar/task.lua new file mode 100644 index 0000000..4f35d4c --- /dev/null +++ b/bar/task.lua @@ -0,0 +1,56 @@ +local tasklist_buttons = gears.table.join( + -- Left click + awful.button({}, 1, function (c) + if c == client.focus then + c.minimized = true + else + c:emit_signal("request::activate", "tasklist", {raise = true}) + end + end) +) + +return function(s) + local task = wibox.widget { + widget = awful.widget.tasklist { + screen = s, + filter = awful.widget.tasklist.filter.currenttags, + buttons = tasklist_buttons, + layout = { + layout = wibox.layout.fixed.vertical + }, + style = { + shape = help.rrect(1), + }, + widget_template = { + { + wibox.widget.base.make_widget(), + forced_width = dpi(4), + id = 'background_role', + widget = wibox.container.background, + }, + { + { + id = 'clienticon', + widget = awful.widget.clienticon, + }, + margins = dpi(7), + widget = wibox.container.margin + }, + nil, + create_callback = function(self, c, _, _) + self:get_children_by_id('clienticon')[1].client = c + self:connect_signal('mouse::enter', function() + awesome.emit_signal("bling::task_preview::visibility", s, + true, c) + end) + self:connect_signal('mouse::leave', function() + awesome.emit_signal("bling::task_preview::visibility", s, + false, c) + end) + end, + layout = wibox.layout.align.horizontal, + }, + } + } + return task +end diff --git a/bling b/bling new file mode 160000 index 0000000..e6de047 --- /dev/null +++ b/bling @@ -0,0 +1 @@ +Subproject commit e6de047ced41051236a390b081105f598cb0ad8b diff --git a/client.lua b/client.lua new file mode 100644 index 0000000..43954e3 --- /dev/null +++ b/client.lua @@ -0,0 +1,16 @@ +-- Sloppy Focus +client.connect_signal('mouse::enter', function(c) + c:emit_signal('request::activate', 'mouse_enter', {raise = false}) +end) + +client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) +client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) + +-- Rounded Corners +client.connect_signal("manage", function (c) + c.shape = help.rrect(beautiful.br) +end) + +client.connect_signal("property::maximized", function(c) + c.maximized = false -- no need for maximize +end) diff --git a/dashboard/init.lua b/dashboard/init.lua new file mode 100644 index 0000000..8dbf7b0 --- /dev/null +++ b/dashboard/init.lua @@ -0,0 +1,123 @@ +local wid = require('dashboard.wid') +local sliders = require('dashboard.sliders') + +local sep = wibox.widget{ + { + forced_height = dpi(2), + shape = gears.shape.line, + widget = wibox.widget.separator + }, + top = dpi(10), + bottom = dpi(10), + widget = wibox.container.margin +} + +local sliders = wibox.widget{ + { + { + { + { + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox + }, + sliders.snd, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + { + { + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox + }, + sliders.temp, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + { + { + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox + }, + sliders.mem, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + -- { + -- { + -- font = beautiful.icofont, + -- text = '', + -- widget = wibox.widget.textbox, + -- }, + -- sli.fs, + -- spacing = dpi(10), + -- layout = wibox.layout.fixed.horizontal + -- }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical + }, + widget = wibox.container.margin, + margins = dpi(20) + }, + bg = beautiful.bg2, + shape = help.rrect(beautiful.br), + widget = wibox.container.background +} + +local buttons = wibox.widget{ + { + { + wid.wifi, + wid.blu, + wid.vol, + -- wid.nig, + spacing = dpi(10), + layout = wibox.layout.flex.horizontal + }, + top = dpi(20), + bottom = dpi(20), + right = dpi(15), + left = dpi(15), + widget = wibox.container.margin + }, + shape = help.rrect(beautiful.br), + widget = wibox.container.background, + bg = beautiful.bg2 +} + +local dashboard = awful.popup{ + widget = { + { + { + -- require('dashboard.oth').clock, + require('dashboard.oth').cal, + layout = wibox.layout.flex.vertical, + spacing = dpi(20) + }, + require('dashboard.play'), + sliders, + buttons, + spacing = dpi(20), + layout = wibox.layout.fixed.vertical + }, + margins = dpi(20), + -- forced_height = awful.screen.focused().geometry.height - 20, + forced_width = dpi(265), + widget = wibox.container.margin + }, + shape = help.rrect(beautiful.br), + visible = false, + bg = beautiful.bg, + ontop = true, + placement = function(c) + (awful.placement.bottom_left)(c, {margins = {left = 60, bottom = 10}}) + end +} + +dashboard.toggle = function() + dashboard.visible = not dashboard.visible +end + +return dashboard diff --git a/dashboard/oth.lua b/dashboard/oth.lua new file mode 100644 index 0000000..b6fd61d --- /dev/null +++ b/dashboard/oth.lua @@ -0,0 +1,24 @@ +local M = {} + +M.cal = wibox.widget { + { + { + { + align = 'center', + format="%Y-%m-%d %H:%M", + refresh=1, + widget = wibox.widget.textclock + }, + spacing = dpi(5), + layout = wibox.layout.fixed.vertical, + }, + widget = wibox.container.margin, + margins = dpi(20), + }, + shape = help.rrect(beautiful.br), + bg = beautiful.bg2, + fg = beautiful.fg2, + widget = wibox.container.background, +} + +return M diff --git a/dashboard/play.lua b/dashboard/play.lua new file mode 100644 index 0000000..2d76abf --- /dev/null +++ b/dashboard/play.lua @@ -0,0 +1,136 @@ +local bling = require("bling") +local playerctl = bling.signal.playerctl.lib() + +local prev = wibox.widget { + align = 'center', + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox, +} + +local next = wibox.widget { + align = 'center', + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox, +} + +local play = wibox.widget { + align = 'center', + font = beautiful.icofont, + markup = '', + widget = wibox.widget.textbox, +} + +play:buttons(gears.table.join( + awful.button({}, 1, function() playerctl:play_pause() end))) + +next:buttons(gears.table.join( + awful.button({}, 1, function() playerctl:next() end))) + +prev:buttons(gears.table.join( + awful.button({}, 1, function() playerctl:previous() end))) + +local position = wibox.widget { + forced_height = dpi(3), + shape = help.rrect(beautiful.br), + color = beautiful.pri, + background_color = beautiful.fg2..'4D', + forced_width = dpi(175), + widget = wibox.widget.progressbar, +} + +local art = wibox.widget { + image = beautiful.wall, + resize = true, + -- clip_shape = help.rrect(beautiful.br), + opacity = 0.25, + forced_height = dpi(120), + forced_width = dpi(120), + widget = wibox.widget.imagebox +} + +local name = wibox.widget { + markup = 'Nothing Playing', + align = 'center', + valign = 'center', + forced_height = dpi(15), + widget = wibox.widget.textbox +} + +local artist_name = wibox.widget { + markup = 'None', + align = 'center', + valign = 'center', + forced_height = dpi(20), + widget = wibox.widget.textbox +} + +local player = wibox.widget { + { + art, + { + { + widget = wibox.widget.textbox, + }, + bg = { + type = "linear", + from = { 0, 0}, + to = { 120, 0}, + stops = { { 0, beautiful.bg2.."00" }, { 1, beautiful.bg2.."FF" } } + }, + widget = wibox.container.background, + }, + { + { + name, + artist_name, + position, + { + prev, + play, + next, + layout = wibox.layout.flex.horizontal, + }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical, + }, + margins = dpi(20), + widget = wibox.container.margin, + }, + layout = wibox.layout.stack, + }, + forced_height = dpi(120), + shape = help.rrect(beautiful.br), + bg = beautiful.bg2, + widget = wibox.container.background, +} + +-- Get Song Info +playerctl:connect_signal("metadata", function(_, title, artist, album_path, album, new, player_name) + -- Set art widget + if new then + art.image = beautiful.wall + end + art:set_image(gears.surface.load_uncached(album_path)) + name:set_markup_silently(help.fg(""..title.."", beautiful.pri)) + artist_name:set_markup_silently(artist) + -- naughty.notify { title=title, text=artist, icon=album_path } +end) + +playerctl:connect_signal("playback_status", function (_, playing, _) + if playing then + play:set_markup_silently(help.fg("", beautiful.pri)) + position.color = beautiful.pri + else + play:set_markup_silently("") + position.color = beautiful.fg.."66" + end +end) + +playerctl:connect_signal("position", function (_, a, b, _) + position.value = a + position.max_value = b +end) + +return player diff --git a/dashboard/sliders.lua b/dashboard/sliders.lua new file mode 100644 index 0000000..0709d45 --- /dev/null +++ b/dashboard/sliders.lua @@ -0,0 +1,97 @@ +local M = {} + +M.vol = wibox.widget{ + bar_shape = help.rrect(beautiful.br), + bar_height = dpi(20), + handle_width = dpi(10), + bar_color = '#00000000', + handle_color = beautiful.pri, + handle_shape = help.rrect(beautiful.br), + forced_height = dpi(20), + forced_width = dpi(175), + widget = wibox.widget.slider +} + +M.snd = wibox.widget{ + { + id = 'prg', + max_value = 100, + value = M.vol.value, + forced_height = dpi(20), + shape = help.rrect(beautiful.br), + color = beautiful.pri, + background_color = beautiful.bg3, + forced_width = dpi(175), + widget = wibox.widget.progressbar + }, + M.vol, + layout = wibox.layout.stack +} + +M.mem = wibox.widget{ + max_value = 100, + value = 0, + forced_height = dpi(20), + shape = help.rrect(beautiful.br), + color = beautiful.pri, + background_color = beautiful.bg3, + forced_width = dpi(175), + widget = wibox.widget.progressbar +} + +M.fs = wibox.widget{ + max_value = 100, + value = 0, + forced_height = dpi(20), + shape = help.rrect(beautiful.br), + color = beautiful.pri, + background_color = beautiful.bg3, + forced_width = dpi(175), + widget = wibox.widget.progressbar +} + +M.temp = wibox.widget{ + max_value = 80000, + value = 0, + forced_height = dpi(20), + shape = help.rrect(beautiful.br), + color = beautiful.pri, + background_color = beautiful.bg3, + forced_width = dpi(175), + widget = wibox.widget.progressbar +} + +awesome.connect_signal('vol::value', function(mut, val) + if mut == 0 then + M.vol.handle_color = beautiful.pri + M.snd:get_children_by_id('prg')[1].color = beautiful.pri + else + M.vol.handle_color = beautiful.fg2 + M.snd:get_children_by_id('prg')[1].color = beautiful.fg2 + end + M.vol.value = val + M.snd:get_children_by_id('prg')[1].value = val +end) + +awesome.connect_signal('mem::value', function(val, max) + M.mem.max_value = max + M.mem.value = val +end) + +awesome.connect_signal('temp::value', function(val) + print(val) + M.temp.value = val +end) + +awesome.connect_signal('fs::value', function(val, max) + M.fs.max_value = max + M.fs.value = val +end) + +M.vol:connect_signal('property::value', function(val) + local volume = require("external.volume") + volume.set_volume(val.value) + M.snd:get_children_by_id('prg')[1].value = val.value +end) + +return M diff --git a/dashboard/wid.lua b/dashboard/wid.lua new file mode 100644 index 0000000..b63670c --- /dev/null +++ b/dashboard/wid.lua @@ -0,0 +1,165 @@ +local M = {} + +local on = beautiful.pri +local off = beautiful.fg2 + +M.vol = wibox.widget { + { + { + id = "vol", + widget = wibox.widget.textbox, + font = beautiful.icofont, + markup = "", + halign = "center", + align = 'center', + }, + widget = wibox.container.margin, + top = dpi(15), + bottom = dpi(15), + }, + fg = beautiful.pri, + bg = beautiful.bg3, + shape = help.rrect(beautiful.br), + widget = wibox.container.background, +} + +M.wifi = wibox.widget { + { + { + id = 'wifi', + widget = wibox.widget.textbox, + font = beautiful.icofont, + markup = "", + halign = "center", + align = 'center', + }, + widget = wibox.container.margin, + margins = dpi(5), + }, + fg = on, + bg = beautiful.bg3, + shape = help.rrect(beautiful.br), + widget = wibox.container.background, +} + +M.nig = wibox.widget { + { + { + id = "nig", + widget = wibox.widget.textbox, + font = beautiful.icofont, + markup = "", + halign = "center", + align = 'center', + }, + widget = wibox.container.margin, + margins = dpi(5), + }, + fg = beautiful.pri, + bg = beautiful.bg3, + shape = help.rrect(beautiful.br), + widget = wibox.container.background, +} + +M.blu = wibox.widget { + { + { + id = 'blu', + widget = wibox.widget.textbox, + font = beautiful.icofont, + markup = "", + halign = "center", + align = 'center', + }, + widget = wibox.container.margin, + margins = dpi(5), + }, + fg = on, + bg = beautiful.bg3, + shape = help.rrect(beautiful.br), + widget = wibox.container.background, +} + +local blue = true + +M.blu:buttons(gears.table.join( + awful.button({}, 1, function() + blue = not blue + if blue then + awful.spawn.with_shell("bluetoothctl power on") + M.blu:get_children_by_id("blu")[1].markup = "" + M.blu.fg = on + else + awful.spawn.with_shell("bluetoothctl power off") + M.blu:get_children_by_id("blu")[1].markup = "" + M.blu.fg = off + end + end) +)) + +local vol = true + +awesome.connect_signal('vol::value', function(mut, val) + if mut == 0 then + M.vol:get_children_by_id("vol")[1].markup = "" + M.vol.fg = on + vol = true + else + M.vol:get_children_by_id("vol")[1].markup = "" + M.vol.fg = off + vol = false + end +end) + +M.vol:buttons(gears.table.join(awful.button({}, 1, function() + vol = not vol + require("external.volume").toggle_mute() +end))) + +local wifi = true + +awesome.connect_signal("net::value", function(_, stat) + if stat:match("up") then + M.wifi.fg = on + M.wifi:get_children_by_id("wifi")[1].markup = "" + wifi = true + else + M.wifi.fg = off + M.wifi:get_children_by_id("wifi")[1].markup = "" + wifi = false + end +end) + +M.wifi:buttons(gears.table.join( + awful.button({}, 1, function() + wifi = not wifi + if wifi then + M.wifi.fg = on + M.wifi:get_children_by_id("wifi")[1].markup = "" + awful.spawn.with_shell("nmcli radio wifi on") + else + M.wifi.fg = off + M.wifi:get_children_by_id("wifi")[1].markup = "" + awful.spawn.with_shell("nmcli radio wifi off") + end + end) +)) + +local nig = true -- enabled in rc.lua using autostart + +M.nig:buttons(gears.table.join( + awful.button({}, 1, function() + nig = not nig + if nig then + M.nig:get_children_by_id("nig")[1].markup = "" + M.nig.fg = on + awful.spawn.with_shell("redshift -x && redshift -O 4000K") + else + M.nig:get_children_by_id("nig")[1].markup = "" + M.nig.fg = off + awful.spawn.with_shell("redshift -x") + end + end) +)) + +return M diff --git a/external/bluetooth.lua b/external/bluetooth.lua new file mode 100644 index 0000000..62f5929 --- /dev/null +++ b/external/bluetooth.lua @@ -0,0 +1,34 @@ +local bluetooth = {} + +local DEFAULT_SIGNAL = "bluetooth::value" + +local blue = [[ bluetoothctl show | grep "Powered:" ]] + +--- callback: function(stat) +function bluetooth.get(callback) + awful.spawn.easy_async_with_shell(blue, function(out) + if out == "" then + callback("no") + else + local val = gears.string.split(out, " ") + callback(val[2]) + end + end) +end + +function bluetooth.emit(name) + bluetooth.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function bluetooth.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() bluetooth.emit(signal_name) end + } +end + +return bluetooth diff --git a/external/fs.lua b/external/fs.lua new file mode 100644 index 0000000..0915734 --- /dev/null +++ b/external/fs.lua @@ -0,0 +1,29 @@ +local fs = {} + +local DEFAULT_SIGNAL = "fs::value" + +local fs_script = [[ df -h --output=used,size / | sed 's/G//g' ]] + +function fs.get(callback) + awful.spawn.easy_async_with_shell(fs_script, function (out) + local val = gears.string.split(out, " ") + callback(tonumber(val[6]), tonumber(val[8])) + end) +end + +function fs.emit(name) + fs.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function fs.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() fs.emit(signal_name) end + } +end + +return fs diff --git a/external/memory.lua b/external/memory.lua new file mode 100644 index 0000000..52672c7 --- /dev/null +++ b/external/memory.lua @@ -0,0 +1,39 @@ +local memory = {} + +local DEFAULT_SIGNAL = "memory::value" + +local mem = [[ + while IFS=':k ' read -r mem1 mem2 _; do + case "$mem1" in + MemTotal) + memt="$(( mem2 / 1024 ))";; + MemAvailable) + memu="$(( memt - mem2 / 1024))";; + esac; + done < /proc/meminfo; + printf "%d %d" "$memu" "$memt"; ]] + +--- callback: function(total, available) +function memory.get(callback) + awful.spawn.easy_async_with_shell(mem, function (out) + local val = gears.string.split(out, " ") + callback(tonumber(val[1]), tonumber(val[2])) + end) +end + +function memory.emit(name) + memory.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function memory.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() memory.emit(signal_name) end + } +end + +return memory diff --git a/external/network.lua b/external/network.lua new file mode 100644 index 0000000..f202478 --- /dev/null +++ b/external/network.lua @@ -0,0 +1,100 @@ +local network = {} + +local DEFAULT_SIGNAL = "network::usage" + +local units = "KiB" +local units_scalar = 1024 +local ignored_devices = {"lo", "docker"} + +local easy_timer = require("helpers").easy_timer + +local function isIgnored(name) + if not ignored_devices then return false end + + for _, pattern in ipairs(ignored_devices) do + if name:find(pattern) then + return true + end + end + + return false +end + +function network.get() + local statistics = { + total_received = 0, + total_sent = 0, + devices = {} + } + + local file = io.open("/proc/net/dev", "r") + if not file then return statistics end + + -- Skip first 2 line that describe the format + local _ = file:read("*l") + local _ = file:read("*l") + -- Read every devices. 1 device per line + for line in file:lines() do + -- Parse line, only extract total sent and received + local name, total_received, total_sent = line:match("^%s*([^%s]+):%s+(%d+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)") + + if not isIgnored(name) then + total_sent = tonumber(total_sent) + total_received = tonumber(total_received) + + -- Save parsed data + statistics.devices[name] = { + total_sent = total_sent, + total_received = total_received + } + statistics.total_received = statistics.total_received + total_received + statistics.total_sent = statistics.total_sent + total_sent + end + end + + file:close() + return statistics, units +end + +local last_stats +function network.emit(signal_name) + local current_stats = network.get() + + current_stats.total_received = current_stats.total_received / units_scalar + current_stats.total_sent = current_stats.total_sent / units_scalar + + if last_stats then + current_stats.received = current_stats.total_received - last_stats.total_received + current_stats.sent = current_stats.total_sent - last_stats.total_sent + else + current_stats.received = 0 + current_stats.sent = 0 + end + + for name, device in pairs(current_stats.devices) do + device.total_received = device.total_received / units_scalar + device.total_sent = device.total_sent / units_scalar + + if last_stats then + device.received = device.total_received - last_stats.devices[name].total_received + device.sent = device.total_sent - last_stats.devices[name].total_sent + else + current_stats.received = 0 + current_stats.sent = 0 + end + end + + awesome.emit_signal(signal_name or DEFAULT_SIGNAL, current_stats, units) + last_stats = current_stats +end + +function network.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() network.emit(signal_name) end + } +end + +return network diff --git a/external/taskwarrior.lua b/external/taskwarrior.lua new file mode 100644 index 0000000..d787e47 --- /dev/null +++ b/external/taskwarrior.lua @@ -0,0 +1,32 @@ +local taskwarrior = {} + +local DEFAULT_SIGNAL = "taskwarrior::stats" + +local task_script = [[echo $(task +PENDING count) $(task +OVERDUE count)]] + +--- callback: function(pending, overdue) +function taskwarrior.get(callback) + awful.spawn.easy_async_with_shell(task_script, function(out) + local pending, overdue = out:match("(%d+)%s+(%d+)") + pending = tonumber(pending) + overdue = tonumber(overdue) + callback(pending, overdue) + end) +end + +function taskwarrior.emit(name) + taskwarrior.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function taskwarrior.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 10, + call_now = true, + autostart = true, + callback = function() taskwarrior.emit(signal_name) end + } +end + +return taskwarrior diff --git a/external/temperature.lua b/external/temperature.lua new file mode 100644 index 0000000..dec7b83 --- /dev/null +++ b/external/temperature.lua @@ -0,0 +1,30 @@ +local temperature = {} + +local DEFAULT_SIGNAL = "temperature::value" + +-- 'temp' get cpu temperature of motherboard +local temp = [[ cat /sys/class/thermal/thermal_zone0/temp ]] + +--- callback: function(temperature) +function temperature.get(callback) + awful.spawn.easy_async_with_shell(temp, function (out) + callback(tonumber(out)) + end) +end + +function temperature.emit(name) + temperature.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function temperature.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() temperature.emit(signal_name) end + } +end + +return temperature diff --git a/external/volume.lua b/external/volume.lua new file mode 100644 index 0000000..e5f5cd0 --- /dev/null +++ b/external/volume.lua @@ -0,0 +1,45 @@ +local volume = {} + +-- TODO: Refactor 'last_registered_signal' +local last_registered_signal + +local DEFAULT_SIGNAL = "volume::value" + +local vol = [[ str=$( pulsemixer --get-volume ); printf "$(pulsemixer --get-mute) ${str% *}\n" ]] + +function volume.set_volume(val) + -- awful.spawn.with_shell('killall pulsemixer; pulsemixer --set-volume ' .. tonumber(val)) + awful.spawn.with_shell('pulsemixer --set-volume ' .. tonumber(val)) + -- volume.emit(last_registered_signal) +end + +function volume.toggle_mute() + awful.spawn.with_shell('pulsemixer --toggle-mute ') + volume.emit(last_registered_signal) +end + +--- callback: function(is_muted, volume) +function volume.get(callback) + awful.spawn.easy_async_with_shell(vol, function(out) + local val = gears.string.split(out, " ") + callback(tonumber(val[1]), tonumber(val[2])) + end) +end + +function volume.emit(name) + volume.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function volume.register_signal(signal_name, update_interval) + last_registered_signal = signal_name or DEFAULT_SIGNAL + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() volume.emit(signal_name) end + } +end + +return volume diff --git a/external/wifi.lua b/external/wifi.lua new file mode 100644 index 0000000..e6495bb --- /dev/null +++ b/external/wifi.lua @@ -0,0 +1,34 @@ +local wifi = {} + +local DEFAULT_SIGNAL = "wifi::value" + +local net = [[ printf "$(cat /sys/class/net/w*/operstate)~|~$(nmcli radio wifi)" ]] + +--- callback: function(operstate, "up"|"down") +function wifi.get(callback) + awful.spawn.easy_async_with_shell(net, function(out) + local val = gears.string.split(out, "~|~") + local w = "down" + if val[2]:match("enabled") then + w = "up" + end + callback(val[1], w) + end) +end + +function wifi.emit(name) + wifi.get(function(...) + awesome.emit_signal(name or DEFAULT_SIGNAL, ...) + end) +end + +function wifi.register_signal(signal_name, update_interval) + gears.timer { + timeout = update_interval or 5, + call_now = true, + autostart = true, + callback = function() wifi.emit(signal_name) end + } +end + +return wifi diff --git a/help.lua b/help.lua new file mode 100644 index 0000000..01bd933 --- /dev/null +++ b/help.lua @@ -0,0 +1,13 @@ +local help = {} + +help.rrect = function(rad) + return function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, rad) + end +end + +help.fg = function (text, color) + return ""..text.."" +end + +return help diff --git a/keys.lua b/keys.lua new file mode 100644 index 0000000..4dc4f62 --- /dev/null +++ b/keys.lua @@ -0,0 +1,93 @@ +local keys = {} + +local tag_amount = 5 +local mod = 'Mod4' +local alt = "Mod1" +local ctrl = "Control" +local shift = "Shift" + +keys.tags = tag_amount + +local utils = require("utils") +local bindings = utils.bindings +local group = utils.group +local keybind = utils.keybind +local keybind_grp = utils.keybind_grp +local buttonbind = utils.buttonbind +local spawn_process = utils.wrap_spawn + +-- Keybindings +awful.keyboard.append_global_keybindings(bindings{ + group("awesome", { + keybind({mod, ctrl}, 'r', awesome.restart), + keybind({mod}, 'd', function() dashboard.toggle() end), + }), + + --Hardware ( Laptop Users ) + -- awful.key({}, 'XF86MonBrightnessUp', function() awful.spawn.with_shell('xbacklight +5') end), + -- awful.key({}, 'XF86MonBrightnessDown', function() awful.spawn.with_shell('xbacklight -5') end), + -- awful.key({}, 'XF86AudioRaiseVolume', function() awful.spawn.with_shell('pactl set-sink-volume @DEFAULT_SINK@ +5%') end), + -- awful.key({}, 'XF86AudioLowerVolume', function() awful.spawn.with_shell('pactl set-sink-volume @DEFAULT_SINK@ -4%') end), + + -- Window management + group("window", { + keybind({alt}, 'Tab' , function() awful.client.focus.byidx(1) end), + keybind({mod}, 'Right', function() awful.tag.incmwfact(0.025) end), + keybind({mod}, 'Left' , function() awful.tag.incmwfact(-0.025) end), + keybind({mod}, 'Up' , function() awful.client.incwfact(0.05) end), + keybind({mod}, 'Down' , function() awful.client.incwfact(-0.05) end), + }), + + -- Applications + group("apps", { + keybind({mod}, 'Return', spawn_process('kitty')), + keybind({alt}, 'space', spawn_process('rofi -show drun')), + }), + + -- Playerctl + group("playerctl", { + keybind({ctrl, mod}, "Down" , function() require("playerctl"):play_pause() end), + keybind({ctrl, mod}, "Right", function() require("playerctl"):next() end), + keybind({ctrl, mod}, "Left" , function() require("playerctl"):previous() end) + }), + + -- Screenshots + keybind({mod}, 's', function() awful.util.spawn('flameshot gui') end) +}) + +-- Keyboard Control +client.connect_signal('request::default_keybindings', function() + awful.mouse.append_client_mousebindings(bindings{ + keybind({mod}, 'q' , function(c) c:kill() end), + keybind({mod}, 'm' , function(c) c.minimized = true end), + keybind({mod}, 'space', function(c) c.fullscreen = not c.fullscreen; c:raise() end), + keybind({mod}, 'Tab' , function() awful.client.floating.toggle() end) + }) +end) + +-- Mouse controls +client.connect_signal('request::default_mousebindings', function() + awful.mouse.append_client_mousebindings(bindings{ + buttonbind({} , 1, function(c) client.focus = c end), + buttonbind({mod}, 1, function() awful.mouse.client.move() end), + buttonbind({mod}, 2, function(c) c:kill() end), + buttonbind({mod}, 3, function() awful.mouse.client.resize() end) + }) +end) + +-- Tag controls +awful.keyboard.append_global_keybindings(bindings{ + keybind_grp({mod}, 'numrow', function(idx) + local screen = awful.screen.focused() + local tag = screen.tags[idx] + if tag then tag:view_only() end + end), + keybind_grp({mod, shift}, 'numrow', function(idx) + if client.focus then + local tag = client.focus.screen.tags[idx] + if tag then client.focus:move_to_tag(tag) end + end + end), +}) + +return keys diff --git a/menu.lua b/menu.lua new file mode 100644 index 0000000..618edf7 --- /dev/null +++ b/menu.lua @@ -0,0 +1,24 @@ +local menu = { + { "Refresh", awesome.restart }, + { "Logout", function() awesome.quit() end }, + { "Restart", function() awful.spawn.with_shell('loginctl reboot') end }, + { "Shutdown", function() awful.spawn.with_shell('loginctl poweroff') end }, +} + +local main = awful.menu { + items = { + { "Awesome", menu }, + { "Terminal", "kitty" }, + { "Browser", "brave" }, + { "Editor", "kitty -e nvim" }, + { "Music", "spotify" }, + { "Files", "nautilus" }, + } +} + +main.wibox.shape = help.rrect(beautiful.br) + +root.buttons(gears.table.join( + awful.button({ }, 3, function () main:toggle() end), + awful.button({ }, 1, function () main:hide() end) +)) diff --git a/music.lua b/music.lua new file mode 100644 index 0000000..310cc9c --- /dev/null +++ b/music.lua @@ -0,0 +1,134 @@ +local playerctl = require("playerctl") + +local prev = wibox.widget { + align = 'center', + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox, +} + +local next = wibox.widget { + align = 'center', + font = beautiful.icofont, + text = '', + widget = wibox.widget.textbox, +} + +local play = wibox.widget { + align = 'center', + font = beautiful.icofont, + markup = '', + widget = wibox.widget.textbox, +} + +local name = wibox.widget { + markup = 'Nothing Playing', + align = 'left', + widget = wibox.widget.textbox +} + +local art = wibox.widget { + image = beautiful.wall, + resize = true, + -- clip_shape = help.rrect(beautiful.br), + opacity = 0.75, + forced_height = dpi(45), + forced_width = dpi(45), + widget = wibox.widget.imagebox +} + +local artist_name = wibox.widget { + markup = 'None', + align = 'left', + widget = wibox.widget.textbox +} + +playerctl:connect_signal("metadata", function(_, title, artist, album_path, album, new, player_name) + -- Set art widget + if new then + art.image = beautiful.wall + end + art:set_image(gears.surface.load_uncached(album_path)) + name:set_markup_silently(help.fg(""..title.."", beautiful.pri)) + artist_name:set_markup_silently(artist) +end) + +playerctl:connect_signal("playback_status", function (_, playing, _) + if playing then + play:set_markup_silently(help.fg("", beautiful.pri)) + else + play:set_markup_silently("") + end +end) + +local prg = wibox.widget { + forced_height = dpi(3), + color = beautiful.pri, + background_color = beautiful.fg2..'4D', + widget = wibox.widget.progressbar, +} + +playerctl:connect_signal("playback_status", function (_, playing, _) + if playing then + play:set_markup_silently(help.fg("", beautiful.pri)) + prg.color = beautiful.pri + else + play:set_markup_silently("") + prg.color = beautiful.fg.."66" + end +end) + + +playerctl:connect_signal("position", function (_, a, b, _) + prg.max_value = b + prg.value = a +end) + +play:buttons(gears.table.join( + awful.button({}, 1, function() playerctl:play_pause() end))) + +next:buttons(gears.table.join( + awful.button({}, 1, function() playerctl:next() end))) + +prev:buttons(gears.table.join( + awful.button({}, 1, function() playerctl:previous() end))) + + +client.connect_signal("property::name", function(c) + if c.name == 'Music' then + awful.titlebar(c, { + size = 65, + position = "bottom", + fg_focus = beautiful.fg.."66", + }):setup { + prg, + { + { + { -- Left + art, + { + name, + artist_name, + spacing = dpi(5), + layout = wibox.layout.fixed.vertical, + }, + spacing = dpi(15), + layout = wibox.layout.fixed.horizontal, + }, + nil, + { -- Middle + prev, + play, + next, + spacing = dpi(30), + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.align.horizontal, + }, + margins = dpi(10), + widget = wibox.container.margin + }, + layout = wibox.layout.fixed.vertical + } + end +end) diff --git a/notif.lua b/notif.lua new file mode 100644 index 0000000..f5fc89a --- /dev/null +++ b/notif.lua @@ -0,0 +1,32 @@ +naughty.config.defaults.ontop = true +naughty.config.defaults.timeout = 3 +naughty.config.defaults.screen = awful.screen.focused() + +naughty.config.padding = dpi(10) + +naughty.config.spacing = dpi(5) +naughty.config.defaults.shape = help.rrect(beautiful.br) + +naughty.config.defaults.border_width = dpi(15) +naughty.config.defaults.border_color = beautiful.bg + +naughty.config.defaults.title = "Notification" +naughty.config.defaults.position = "bottom_right" + +naughty.config.defaults.fg = beautiful.fg +naughty.config.defaults.bg = beautiful.bg + +naughty.config.presets.normal = { + fg = beautiful.fg, + bg = beautiful.bg, +} + +naughty.config.presets.low = { + fg = beautiful.ok, + bg = beautiful.bg, +} + +naughty.config.presets.critical = { + fg = beautiful.err, + bg = beautiful.bg, +} diff --git a/playerctl.lua b/playerctl.lua new file mode 100644 index 0000000..3c1b737 --- /dev/null +++ b/playerctl.lua @@ -0,0 +1,3 @@ +local bling = require("bling") +local playerctl = bling.signal.playerctl.lib() +return playerctl diff --git a/rc.lua b/rc.lua new file mode 100644 index 0000000..f24b180 --- /dev/null +++ b/rc.lua @@ -0,0 +1,60 @@ +-- Importing libraries +gears = require('gears') +awful = require('awful') +wibox = require('wibox') +naughty = require("naughty") +beautiful = require('beautiful') +dpi = beautiful.xresources.apply_dpi + +beautiful.init('~/.config/awesome/theme/init.lua') +keys = require('keys') +help = require('help') +dashboard = require("dashboard") +sig = require('signals') + +require('notif') +require('bar') +require('menu') +require('rule') +require('titlebar') +require('music') +require('client') +require('awful.autofocus') + +local function set_wallpaper(s) + if beautiful.wall then + local wall = beautiful.wall + if type(wall) == "function" then + wall = wall(s) + end + gears.wallpaper.maximized(wall, s, true) + end +end + +screen.connect_signal("property::geometry", set_wallpaper) + +-- Layouts +awful.layout.append_default_layouts({ + awful.layout.suit.tile, + awful.layout.suit.floating +}) + +-- Virtual desktops/ Tabs +awful.screen.connect_for_each_screen(function(s) + set_wallpaper(s) + local tagTable = {} + for i = 1, keys.tags do + table.insert(tagTable, tostring(i)) + end + awful.tag(tagTable, s, awful.layout.layouts[1]) +end) + +-- Autostart +-- awful.spawn.with_shell('redshift -x && redshift -O 4000K') +-- awful.spawn.with_shell('killall xsettingsd; xsettingsd &') +awful.spawn.with_shell('killall flameshot; flameshot') + +-- TODO: Is this needed? +-- Garbage Collection +collectgarbage('setpause', 110) +collectgarbage('setstepmul', 1000) diff --git a/rule.lua b/rule.lua new file mode 100644 index 0000000..2a80d38 --- /dev/null +++ b/rule.lua @@ -0,0 +1,29 @@ +awful.rules.rules = { + { + rule = {}, + properties = { + border_width = beautiful.border_width, + border_color = beautiful.border_color, + focus = awful.client.focus.filter, + raise = true, + maximized = false, + screen = awful.screen.preferred, + placement = awful.placement.no_overlap + + awful.placement.no_offscreen + } + }, + + -- Add titlebars to normal clients + {rule_any = {type = {'normal'}}, properties = {titlebars_enabled = true}}, + + -- Floating, Titlebar exceptions + { + rule_any = { + class = {'gnome', 'gtk', 'Lxappearance', 'qt5ct', 'feh'}, + name = {'Event Tester', 'Komikku', 'marker'}, + role = {'pop-up', 'GtkFileChooserDialog'}, + type = {'dialog'} + }, + properties = {floating = true, titlebars_enabled = false} + } +} diff --git a/signals.lua b/signals.lua new file mode 100644 index 0000000..13822bf --- /dev/null +++ b/signals.lua @@ -0,0 +1,13 @@ +local memory = require("external.memory") +local wifi = require("external.wifi") +local volume = require("external.volume") +local bluetooth = require("external.bluetooth") +local temperature = require("external.temperature") +local fs = require("external.fs") + +memory.register_signal("mem::value") +wifi.register_signal("net::value") +volume.register_signal("vol::value") +bluetooth.register_signal("blu::value") +temperature.register_signal("temp::value") +-- fs.register_signal("fs::value") diff --git a/theme/circle.svg b/theme/circle.svg new file mode 100644 index 0000000..22c3587 --- /dev/null +++ b/theme/circle.svg @@ -0,0 +1,6 @@ + + + diff --git a/theme/init.lua b/theme/init.lua new file mode 100644 index 0000000..0205812 --- /dev/null +++ b/theme/init.lua @@ -0,0 +1,79 @@ +local theme = {} + +local gfs = require("gears.filesystem") +local theme_path = gfs.get_configuration_dir() .. "/theme/" +theme.font = 'JetBrains Mono Medium 10' +theme.barfont = 'JetBrains Mono Medium 12' +theme.icofont = 'Material Icons Round 14' + +theme.ok = "#8C977D" +theme.err = "#B66467" +theme.pri = "#8DA3B9" + +theme.br = dpi(2) + +theme.wall = theme_path..'wall.png' + +theme.bg = "#121212" +theme.bg2 = "#181818" +theme.bg3 = "#1e1e1e" + +theme.fg = "#e8e3e3" +theme.fg2 = "#424242" + +theme.fg_focus = theme.fg +theme.fg_normal = theme.fg.."40" +theme.fg_minimize = theme.fg2 + +theme.bg_normal = theme.bg2 +theme.bg_urgent = theme.err.."40" +theme.bg_minimize = theme.fg.."10" +theme.bg_focus = theme.fg2.."cc" + +theme.useless_gap = dpi(5) +theme.snap_bg = theme.fg2 + +theme.border_width = dpi(5) +theme.border_color = theme.bg + +theme.titlebar_fg = theme.fg.."40" +theme.titlebar_fg_normal = theme.fg2 +theme.titlebar_fg_focus = theme.fg +theme.titlebar_bg = theme.bg +theme.titlebar_bg_normal = theme.bg +theme.titlebar_font = theme.font + +theme.taglist_bg = theme.bg +theme.taglist_bg_focus = theme.pri +theme.taglist_font = theme.barfont + +theme.menu_bg_normal = theme.bg +theme.menu_bg_focus = theme.bg2 +theme.menu_font = theme.font +theme.menu_border_color = theme.bg +theme.menu_height = dpi(30) +theme.menu_width = dpi(130) +theme.menu_border_width = dpi(10) +theme.menu_submenu_icon = theme_path.."menu.svg" + +theme.tasklist_plain_task_name = true + +theme.notification_bg = theme.bg +theme.notification_fg = theme.fg +theme.notification_width = dpi(225) +theme.notification_max_height = dpi(80) +theme.notification_icon_size = dpi(80) + +theme.separator_color = theme.fg2 + +theme.titlebar_minimize_button_focus= gears.color.recolor_image(theme_path.."circle.svg", theme.ok) +theme.titlebar_minimize_button_normal= theme_path.."circle.svg" + +theme.titlebar_close_button_normal = theme_path.."circle.svg" +theme.titlebar_close_button_focus= gears.color.recolor_image(theme_path.."circle.svg", theme.err) + +theme.icon_theme = "Reversal" + +-- theme.playerctl_player = {"spotify", "%any"} + +return theme diff --git a/theme/menu.svg b/theme/menu.svg new file mode 100644 index 0000000..2b2ebab --- /dev/null +++ b/theme/menu.svg @@ -0,0 +1,6 @@ + + + diff --git a/theme/wall.png b/theme/wall.png new file mode 100644 index 0000000..e67ef28 Binary files /dev/null and b/theme/wall.png differ diff --git a/titlebar.lua b/titlebar.lua new file mode 100644 index 0000000..6b8821a --- /dev/null +++ b/titlebar.lua @@ -0,0 +1,57 @@ +local utils = require("utils") +local bindings = utils.bindings +local buttonbind = utils.buttonbind + +client.connect_signal('request::titlebars', function(c) + local function move_client() + client.focus = c + c:raise() + awful.mouse.client.move(c) + end + + local function resize_client() + client.focus = c + c:raise() + awful.mouse.client.resize(c) + end + + local buttons = bindings{ + buttonbind({}, 1, move_client), + buttonbind({}, 3, resize_client), + } + + awful.titlebar(c, {size = 30}):setup{ + { + { -- Left + { -- Title + align = 'center', + widget = awful.titlebar.widget.titlewidget(c) + }, + -- awful.titlebar.widget.iconwidget(c), + buttons = buttons, + layout = wibox.layout.fixed.horizontal + }, + { -- Middle + buttons = buttons, + layout = wibox.layout.flex.horizontal + }, + { -- Right + { + awful.titlebar.widget.minimizebutton(c), + awful.titlebar.widget.closebutton(c), + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + top = dpi(5), + bottom = dpi(5), + widget = wibox.container.margin + }, + layout = wibox.layout.align.horizontal + }, + right = dpi(10), + left = dpi(10), + top = dpi(0), + bottom = dpi(5), + widget = wibox.container.margin + } +end) diff --git a/utils.lua b/utils.lua new file mode 100644 index 0000000..3da258a --- /dev/null +++ b/utils.lua @@ -0,0 +1,92 @@ +-- Helpful reference when working with cairo: +-- * https://github.com/pavouk/lgi/blob/master/samples/cairo.lua +-- * https://www.cairographics.org/manual/cairo-cairo-t.html +-- * https://www.cairographics.org/operators/ +-- * https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-operator-t + +local utils = {} + +local lgi = require("lgi") +local cairo = lgi.cairo + +function utils.bindings(keybindings_tree) + local keybindings = {} + local trees = {keybindings_tree} + while #trees > 0 do + local tree = table.remove(trees) + for _, subtree in ipairs(tree) do + if type(subtree) == "table" and not subtree.binding then + table.insert(trees, subtree) + else + subtree.binding = nil + table.insert(keybindings, subtree) + end + end + end + return keybindings +end + +function utils.group(group_name, keybindings) + for _, key in ipairs(keybindings) do + key.group = group_name + end + return keybindings +end + +function utils.keybind(modifiers, key, on_press) + local keybind_keys = awful.key{ + modifiers = modifiers, + key = key, + on_press = on_press, + } + keybind_keys.binding = true + return keybind_keys +end + +function utils.keybind_grp(modifiers, keygroup, on_press) + local keys_grp = awful.key{ + modifiers = modifiers, + keygroup = keygroup, + on_press = on_press, + } + keys_grp.binding = true + return keys_grp +end + +function utils.buttonbind(modifiers, key, on_press) + local btns = awful.button(modifiers, key, on_press) + btns.binding = true + return btns +end + +function utils.wrap_spawn(process) + return function() + awful.spawn(process) + end +end + +function utils.wrap_spawn_with_shell(process) + return function() + awful.spawn(process) + end +end + +function utils.clone_image(img) + local cloned = cairo.ImageSurface.create(cairo.Format.ARGB32, img.width, img.height) + local cr = cairo.Context(cloned) + cr:set_source_surface(img, 0, 0) + cr:paint() + return cloned +end + +function utils.overwrite_colored_image(img, on_top_image, color) + local cr = cairo.Context(img) + cr:set_operator(2) -- CAIRO_OPERATOR_OVER = 2 + cr:set_source_surface(on_top_image, 0, 0) + cr:paint() + cr:set_source(gears.color(color)) + cr:set_operator(5) -- CAIRO_OPERATOR_ATOP = 5 + cr:paint() +end + +return utils