commit 093dec7f93a05ffd2071f39a7f39e01b7908bc2e Author: Hydroxycarbamide Date: Sat Aug 27 21:35:40 2022 +0200 Initial commit diff --git a/bin/bsplock b/bin/bsplock new file mode 100755 index 0000000..b0f6003 --- /dev/null +++ b/bin/bsplock @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +## Copyright (C) 2020-2021 Aditya Shakya +## Everyone is permitted to copy and distribute copies of this file under GNU-GPL3 + +## i3lock for bspwm for Archcraft OS. + +## Get colors ----------------- +FG="$(xrdb -query | grep 'foreground:'| awk '{print $NF}')" +BG="$(xrdb -query | grep 'background:'| awk '{print $NF}')" + +BLACK="$(xrdb -query | grep 'color0:'| awk '{print $NF}')" +RED="$(xrdb -query | grep 'color1:'| awk '{print $NF}')" +GREEN="$(xrdb -query | grep 'color2:'| awk '{print $NF}')" +YELLOW="$(xrdb -query | grep 'color3:'| awk '{print $NF}')" +BLUE="$(xrdb -query | grep 'color4:'| awk '{print $NF}')" +MAGENTA="$(xrdb -query | grep 'color5:'| awk '{print $NF}')" +CYAN="$(xrdb -query | grep 'color6:'| awk '{print $NF}')" +WHITE="$(xrdb -query | grep 'color7:'| awk '{print $NF}')" + +TOTD=`fortune -n 90 -s | head -n 1` + +## Exec ----------------- + +#betterlockscreen --lock \ +#-- \ +#--{time,date,layout,verif,wrong,greeter}-font="Iosevka" \ +i3lock \ +--color="${BG}D9" \ +\ +--insidever-color=${GREEN} \ +--insidewrong-color=${RED} \ +--inside-color="${BG}00" \ +\ +--ringver-color=${GREEN} \ +--ringwrong-color=${RED} \ +--ring-color="#fab387" \ +\ +--line-color=${BG} \ +--separator-color=${BG} \ +\ +--keyhl-color=${YELLOW} \ +--bshl-color=${RED} \ +\ +--verif-color=${BG} \ +--wrong-color=${FG} \ +--layout-color=${FG} \ +\ +--time-color=${FG} \ +--date-color=${FG} \ +\ +--pass-media-keys \ +--pass-screen-keys \ +--pass-power-keys \ +--pass-volume-keys \ +--{time,date,layout,verif,wrong,greeter}-font="Iosevka" \ +--{layout,verif,wrong,greeter}-size=18 \ +--time-size=34 \ +--date-size=18 \ +--greeter-text="${TOTD}" \ +--greeter-color=${CYAN} \ +--verif-text="verifying..." \ +--wrong-text="wrong!" \ +--noinput-text="Empty" \ +--lock-text="Locking..." \ +--lockfailed-text="Failed to lock" \ +--radius 120 \ +--ring-width 8.0 \ +--screen 1 \ +--clock \ +--indicator \ +--time-str="%H:%M %p" \ +--date-str="%b %d, %G" \ +#--blur 7 \ diff --git a/crylia_bar/center_bar.lua b/crylia_bar/center_bar.lua new file mode 100644 index 0000000..441fb2b --- /dev/null +++ b/crylia_bar/center_bar.lua @@ -0,0 +1,138 @@ +-------------------------------------------------------------------------------------------------------------- +-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen -- +-------------------------------------------------------------------------------------------------------------- +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +return function(s, widgets) + + local top_center = awful.popup { + screen = s, + widget = wibox.container.background, + ontop = false, + bg = color["Grey900"], + visible = true, + maximum_width = dpi(500), + placement = function(c) awful.placement.top(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end + } + + top_center:struts { + top = 55 + } + + local function prepare_widgets(widgets) + local layout = { + forced_height = 45, + layout = wibox.layout.fixed.horizontal + } + for i, widget in pairs(widgets) do + if i == 1 then + table.insert(layout, + { + widget, + left = dpi(6), + right = dpi(6), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + elseif i == #widgets then + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(6), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + else + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + end + end + return layout + end + + top_center:setup { + nil, + prepare_widgets(widgets), + nil, + layout = wibox.layout.fixed.horizontal + } + + client.connect_signal( + "manage", + function(c) + if (s == nil or s.selected_tag == nil) then + top_center.visible = false + return + end + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true + end + end + ) + + client.connect_signal( + "unmanage", + function(c) + if (s == nil or s.selected_tag == nil) then + top_center.visible = false + return + end + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true + end + end + ) + + client.connect_signal( + "tag::switched", + function(c) + if (s == nil or s.selected_tag == nil) then + top_center.visible = false + return + end + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true + end + end + ) + + awesome.connect_signal( + "refresh", + function(c) + if (s == nil or s.selected_tag == nil) then + top_center.visible = false + return + end + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true + end + end + ) + +end diff --git a/crylia_bar/dock.lua b/crylia_bar/dock.lua new file mode 100644 index 0000000..55d028d --- /dev/null +++ b/crylia_bar/dock.lua @@ -0,0 +1,313 @@ +-------------------------------------------------------------------------------------------------------------- +-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen -- +-------------------------------------------------------------------------------------------------------------- +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +return function(screen, programs) + + local function create_dock_element(class, program, name, user_icon, is_steam, size) + if program == nil or class == nil then + return + end + is_steam = is_steam or false + user_icon = user_icon or nil + local dock_element = wibox.widget { + { + { + { + resize = true, + forced_width = size, + forced_height = size, + image = user_icon or Get_icon(user_vars.icon_theme, nil, program, class, is_steam), + widget = wibox.widget.imagebox, + id = "icon", + }, + margins = dpi(5), + widget = wibox.container.margin, + id = "margin" + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 10) + end, + bg = color["Grey900"], + widget = wibox.container.background, + id = "background" + }, + top = dpi(5), + left = dpi(5), + right = dpi(5), + widget = wibox.container.margin + } + + for _, c in ipairs(client.get()) do + if string.lower(c.class):match(program) and c == client.focus then + dock_element.background.bg = color["Grey800"] + end + end + + Hover_signal(dock_element.background, color["Grey800"], color["White"]) + + dock_element:connect_signal( + "button::press", + function() + if is_steam then + awful.spawn("steam steam://rungameid/" .. program) + else + awful.spawn(program) + end + end + ) + + awful.tooltip { + objects = { dock_element }, + text = name, + mode = "outside", + preferred_alignments = "middle", + margins = dpi(10) + } + + return dock_element + end + + local dock = awful.popup { + widget = wibox.container.background, + ontop = true, + bg = color["Grey900"], + visible = true, + screen = screen, + type = "dock", + height = user_vars.dock_icon_size + 10, + placement = function(c) awful.placement.bottom(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 15) + end + } + + local fakedock = awful.popup { + widget = wibox.container.background, + ontop = true, + bg = '#00000000', + visible = true, + screen = screen, + type = "dock", + id = "fakedock", + height = dpi(10), + placement = function(c) awful.placement.bottom(c, { margins = dpi(0) }) end, + } + + local function get_dock_elements(pr) + local dock_elements = { layout = wibox.layout.fixed.horizontal } + + for i, p in ipairs(pr) do + dock_elements[i] = create_dock_element(p[1], p[2], p[3], p[4], p[5], user_vars.dock_icon_size) + end + + return dock_elements + end + + local dock_elements = get_dock_elements(programs) + + local function get_fake_elements(amount) + local fake_elements = { layout = wibox.layout.fixed.horizontal } + + for i = 0, amount, 1 do + fake_elements[i] = wibox.widget { + bg = '00000000', + forced_width = user_vars.dock_icon_size + dpi(20), + forced_height = dpi(10), + id = "fake", + widget = wibox.container.background + } + end + return fake_elements + end + + local function create_incicator_widget(prog) + local container = { layout = wibox.layout.flex.horizontal } + local clients = client.get() + for index, pr in ipairs(prog) do + local indicators = { layout = wibox.layout.flex.horizontal, spacing = dpi(5) } + local col = color["Grey600"] + for i, c in ipairs(clients) do + if string.lower(c.class or c.name):match(string.lower(pr[1]) or string.lower(pr[2])) then + if c == client.focus then + col = color["YellowA200"] + elseif c.urgent then + col = color["RedA200"] + elseif c.maximized then + col = color["GreenA200"] + elseif c.minimized then + col = color["BlueA200"] + elseif c.fullscreen then + col = color["PinkA200"] + else + col = color["Grey600"] + end + indicators[i] = wibox.widget { + widget = wibox.container.background, + shape = gears.shape.rounded_rect, + forced_height = dpi(3), + bg = col, + forced_width = dpi(5), + } + end + end + container[index] = wibox.widget { + indicators, + forced_height = dpi(5), + forced_width = dpi(50), + left = dpi(5), + right = dpi(5), + widget = wibox.container.margin, + } + end + + return wibox.widget { + container, + bottom = dpi(5), + widget = wibox.container.margin, + } + end + + fakedock:setup { + get_fake_elements(#programs), + type = 'dock', + layout = wibox.layout.fixed.vertical + } + + local function check_for_dock_hide(s) + for _, client in ipairs(s.selected_tag:clients()) do + if client.fullscreen then + dock.visible = false + fakedock.visible = false + else + fakedock.visible = true + end + end + if #s.selected_tag:clients() < 1 then + dock.visible = true + return + end + if s == mouse.screen then + local minimized + for _, c in ipairs(s.selected_tag:clients()) do + if c.minimized then + minimized = true + end + if c.maximized or c.fullscreen then + dock.visible = false + return + end + if not c.minimized then + local y = c:geometry().y + local h = c.height + if (y + h) >= s.geometry.height - user_vars.dock_icon_size - 35 then + dock.visible = false + return + else + dock.visible = true + end + end + end + if minimized then + dock.visible = true + end + else + dock.visible = false + end + end + + local dock_intelligent_hide = gears.timer { + timeout = 1, + autostart = true, + call_now = true, + callback = function() + check_for_dock_hide(screen) + end + } + + fakedock:connect_signal( + "mouse::enter", + function() + for _, c in ipairs(screen.clients) do + if not c.fullscreen then + dock_intelligent_hide:stop() + dock.visible = true + end + end + end + ) + + client.connect_signal( + "manage", + function() + check_for_dock_hide(screen) + dock:setup { + dock_elements, + create_incicator_widget(programs), + layout = wibox.layout.fixed.vertical + } + end + ) + + client.connect_signal( + "property::minimized", + function() + check_for_dock_hide(screen) + dock:setup { + dock_elements, + create_incicator_widget(programs), + layout = wibox.layout.fixed.vertical + } + end + ) + + client.connect_signal( + "unmanage", + function() + check_for_dock_hide(screen) + dock:setup { + dock_elements, + create_incicator_widget(programs), + layout = wibox.layout.fixed.vertical + } + end + ) + + client.connect_signal( + "focus", + function() + check_for_dock_hide(screen) + dock:setup { + dock_elements, + create_incicator_widget(programs), + layout = wibox.layout.fixed.vertical + } + end + ) + + dock:connect_signal( + "mouse::enter", + function() + dock_intelligent_hide:stop() + end + ) + + dock:connect_signal( + "mouse::leave", + function() + dock_intelligent_hide:again() + end + ) + + dock:setup { + get_dock_elements(programs), + create_incicator_widget(programs), + layout = wibox.layout.fixed.vertical + } +end diff --git a/crylia_bar/init.lua b/crylia_bar/init.lua new file mode 100644 index 0000000..a6dda7c --- /dev/null +++ b/crylia_bar/init.lua @@ -0,0 +1,65 @@ +-------------------------------------------------------------------------------------------------------------- +-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen -- +-------------------------------------------------------------------------------------------------------------- +-- Awesome Libs +local awful = require("awful") + +awful.screen.connect_for_each_screen( +-- For each screen this function is called once +-- If you want to change the modules per screen use the indices +-- e.g. 1 would be the primary screen and 2 the secondary screen. + function(s) + -- Create 9 tags + awful.layout.layouts = user_vars.layouts + awful.tag( + { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, + s, + user_vars.layouts[1] + ) + + require("src.modules.powermenu")(s) + -- TODO: rewrite calendar osd, maybe write an own inplementation + -- require("src.modules.calendar_osd")(s) + require("src.modules.volume_osd")(s) + require("src.modules.brightness_osd")(s) + -- require("src.modules.titlebar") + require("src.modules.volume_controller")(s) + + -- Widgets + --s.battery = require("src.widgets.battery")() + s.audio = require("src.widgets.audio")(s) + s.date = require("src.widgets.date")() + s.clock = require("src.widgets.clock")() + s.bluetooth = require("src.widgets.bluetooth")() + s.layoutlist = require("src.widgets.layout_list")(s) + s.powerbutton = require("src.widgets.power")() + s.kblayout = require("src.widgets.kblayout")(s) + s.taglist = require("src.widgets.taglist")(s) + s.tasklist = require("src.widgets.tasklist")(s) + --s.cpu_freq = require("src.widgets.cpu_info")("freq", "average") + + -- Add more of these if statements if you want to change + -- the modules/widgets per screen. + if s.index == 1 then + s.systray = require("src.widgets.systray")(s) + s.cpu_usage = require("src.widgets.cpu_info")("usage") + s.cpu_temp = require("src.widgets.cpu_info")("temp") + s.gpu_usage = require("src.widgets.gpu_info")("usage") + s.gpu_temp = require("src.widgets.gpu_info")("temp") + + require("crylia_bar.left_bar")(s, { s.layoutlist, s.systray, s.taglist }) + require("crylia_bar.center_bar")(s, { s.tasklist }) + require("crylia_bar.right_bar")(s, { s.gpu_usage, s.gpu_temp, s.cpu_usage, s.cpu_temp, s.audio, s.date, s.clock, s.powerbutton }) + -- require("crylia_bar.dock")(s, user_vars.dock_programs) + end + + if s.index == 2 then + s.network = require("src.widgets.network")() + s.ram_info = require("src.widgets.ram_info")() + + require("crylia_bar.left_bar")(s, { s.layoutlist, s.taglist }) + require("crylia_bar.center_bar")(s, { s.tasklist }) + require("crylia_bar.right_bar")(s, { s.ram_info, s.audio, s.kblayout, s.bluetooth, s.network, s.date, s.clock, s.powerbutton }) + end +end +) diff --git a/crylia_bar/left_bar.lua b/crylia_bar/left_bar.lua new file mode 100644 index 0000000..93f2031 --- /dev/null +++ b/crylia_bar/left_bar.lua @@ -0,0 +1,77 @@ +-------------------------------------------------------------------------------------------------------------- +-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen -- +-------------------------------------------------------------------------------------------------------------- +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +return function(s, widgets) + + local top_left = awful.popup { + screen = s, + widget = wibox.container.background, + ontop = false, + bg = color["Grey900"], + visible = true, + maximum_width = dpi(650), + placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end + } + + top_left:struts { + top = 55 + } + + local function prepare_widgets(widgets) + local layout = { + forced_height = 45, + layout = wibox.layout.fixed.horizontal + } + for i, widget in pairs(widgets) do + if i == 1 then + table.insert(layout, + { + widget, + left = dpi(6), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + elseif i == #widgets then + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(6), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + else + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + end + end + return layout + end + + top_left:setup { + prepare_widgets(widgets), + nil, + nil, + layout = wibox.layout.fixed.horizontal + } +end diff --git a/crylia_bar/right_bar.lua b/crylia_bar/right_bar.lua new file mode 100644 index 0000000..3e4ec2e --- /dev/null +++ b/crylia_bar/right_bar.lua @@ -0,0 +1,76 @@ +-------------------------------------------------------------------------------------------------------------- +-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen -- +-------------------------------------------------------------------------------------------------------------- +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +return function(s, widgets) + + local top_right = awful.popup { + widget = wibox.container.background, + ontop = false, + bg = color["Grey900"], + visible = true, + screen = s, + placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end + } + + top_right:struts { + top = 55 + } + + local function prepare_widgets(widgets) + local layout = { + forced_height = 45, + layout = wibox.layout.fixed.horizontal + } + for i, widget in pairs(widgets) do + if i == 1 then + table.insert(layout, + { + widget, + left = dpi(6), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + elseif i == #widgets then + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(6), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + else + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + end + end + return layout + end + + top_right:setup { + nil, + nil, + prepare_widgets(widgets), + layout = wibox.layout.align.horizontal + } +end diff --git a/mappings/bind_to_tags.lua b/mappings/bind_to_tags.lua new file mode 100644 index 0000000..9019af1 --- /dev/null +++ b/mappings/bind_to_tags.lua @@ -0,0 +1,69 @@ +-- Awesome Libs +local awful = require("awful") +local gears = require("gears") +local globalkeys = require("../mappings/global_keys") +local modkey = user_vars.modkey + +for i = 1, 9 do + globalkeys = gears.table.join(globalkeys, + + -- View tag only + awful.key( + { modkey }, + "#" .. i + 9, + function() + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + tag:view_only() + end + client.emit_signal("tag::switched") + end, + { description = "View Tag " .. i, group = "Tag" } + ), + -- Brings the window over without chaning the tag, reverts automatically on tag change + awful.key( + { modkey, "Control" }, + "#" .. i + 9, + function() + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + awful.tag.viewtoggle(tag) + end + end, + { description = "Toggle Tag " .. i, group = "Tag" } + ), + -- Brings the window over without chaning the tag, reverts automatically on tag change + awful.key( + { modkey, "Shift" }, + "#" .. i + 9, + function() + local screen = awful.screen.focused() + if client.focus then + local tag = screen.tags[i] + if tag then + client.focus:move_to_tag(tag) + tag:view_only() + client.emit_signal("tag::switched") + end + end + end, + { description = "Move focused client on tag " .. i, group = "Tag" } + ), + -- Brings the window over without chaning the tag, reverts automatically on tag change + awful.key( + { modkey, "Control", "Shift" }, + "#" .. i + 9, + function() + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + awful.tag.viewtoggle(tag) + end + end, + { description = "Move focused client on tag " .. i, group = "Tag" } + ) + ) +end +root.keys(globalkeys) diff --git a/mappings/client_buttons.lua b/mappings/client_buttons.lua new file mode 100644 index 0000000..dcbb7e9 --- /dev/null +++ b/mappings/client_buttons.lua @@ -0,0 +1,19 @@ +-- Awesome Libs +local awful = require("awful") +local gears = require("gears") + +local modkey = user_vars.modkey + +return gears.table.join( + awful.button({}, 1, function(c) + c:emit_signal("request::activate", "mouse_click", { raise = true }) + end), + awful.button({ modkey }, 1, function(c) + c:emit_signal("request::activate", "mouse_click", { raise = true }) + awful.mouse.client.move(c) + end), + awful.button({ modkey }, 3, function(c) + c:emit_signal("request::activate", "mouse_click", { raise = true }) + awful.mouse.client.resize(c) + end) +) diff --git a/mappings/client_keys.lua b/mappings/client_keys.lua new file mode 100644 index 0000000..20c0e2e --- /dev/null +++ b/mappings/client_keys.lua @@ -0,0 +1,63 @@ +-- Awesome Libs +local awful = require("awful") +local gears = require("gears") + +local modkey = user_vars.modkey + +return gears.table.join( + awful.key( + { modkey }, + "#41", + function(c) + c.fullscreen = not c.fullscreen + c:raise() + end, + { description = "Toggle fullscreen", group = "Client" } + ), + awful.key( + { modkey }, + "#54", + function(c) + c:kill() + end, + { description = "Close focused client", group = "Client" } + ), + awful.key( + { modkey }, + "#65", + awful.client.floating.toggle, + { description = "Toggle floating window", group = "Client" } + ), + awful.key( + { modkey, "Control" }, + "#23", + awful.client.movetoscreen, + { description = "Move focused client to other screen", group = "Screen" } + ), + awful.key( + { modkey }, + "#58", + function(c) + c.maximized = not c.maximized + c:raise() + end, + { description = "(un)maximize", group = "Client" } + ), + awful.key( + { modkey }, + "#57", + function(c) + if c == client.focus then + c.minimized = true + else + c.minimized = false + if not c:isvisible() and c.first_tag then + c.first_tag:view_only() + end + c:emit_signal('request::activate') + c:raise() + end + end, + { description = "(un)hide", group = "Client" } + ) +) diff --git a/mappings/global_buttons.lua b/mappings/global_buttons.lua new file mode 100644 index 0000000..023a309 --- /dev/null +++ b/mappings/global_buttons.lua @@ -0,0 +1,8 @@ +-- Awesome Libs +local gears = require("gears") +local awful = require("awful") + +root.buttons = gears.table.join( + awful.button({}, 4, awful.tag.viewnext), + awful.button({}, 5, awful.tag.viewprev) +) diff --git a/mappings/global_keys.lua b/mappings/global_keys.lua new file mode 100644 index 0000000..0ae49ff --- /dev/null +++ b/mappings/global_keys.lua @@ -0,0 +1,405 @@ +-- Awesome Libs +local gears = require("gears") +local awful = require("awful") +local hotkeys_popup = require("awful.hotkeys_popup") +local ruled = require("ruled") + +local modkey = user_vars.modkey + +return gears.table.join( + awful.key( + { modkey }, + "#39", + hotkeys_popup.show_help, + { description = "Cheat sheet", group = "Awesome" } + ), + -- Tag browsing + awful.key( + { modkey }, + "#113", + awful.tag.viewprev, + { description = "View previous tag", group = "Tag" } + ), + awful.key( + { modkey }, + "#114", + awful.tag.viewnext, + { description = "View next tag", group = "Tag" } + ), + awful.key( + { modkey }, + "#66", + awful.tag.history.restore, + { description = "Go back to last tag", group = "Tag" } + ), + awful.key( + { modkey }, + "#44", + function() + awful.client.focus.byidx(1) + end, + { description = "Focus next client by index", group = "Client" } + ), + awful.key( + { modkey }, + "#45", + function() + awful.client.focus.byidx(-1) + end, + { description = "Focus previous client by index", group = "Client" } + ), + awful.key( + { "Mod1" }, + "#23", + function() + awful.client.focus.byidx(1) + end, + { description = "Focus next client by index", group = "Client" } + ), + awful.key( + { "Mod1", "Shift" }, + "#23", + function() + awful.client.focus.byidx(-1) + end, + { description = "Focus previous client by index", group = "Client" } + ), + awful.key( + { modkey, "Shift" }, + "#44", + function() + awful.client.swap.byidx(1) + end, + { description = "Swap with next client by index", group = "Client" } + ), + awful.key( + { modkey, "Shift" }, + "#45", + function() + awful.client.swap.byidx(-1) + end, + { description = "Swap with previous client by index", group = "Client" } + ), + awful.key( + { modkey, "Control" }, + "#44", + function() + awful.screen.focus_relative(1) + end, + { description = "Focus the next screen", group = "Screen" } + ), + awful.key( + { modkey, "Control" }, + "#45", + function() + awful.screen.focus_relative(-1) + end, + { description = "Focus the previous screen", group = "Screen" } + ), + awful.key( + { modkey }, + "#30", + awful.client.urgent.jumpto, + { description = "Jump to urgent client", group = "Client" } + ), + awful.key( + { modkey }, + "#36", + function() + awful.spawn(user_vars.terminal) + end, + { description = "Open terminal", group = "Applications" } + ), + awful.key( + { modkey, "Shift" }, + "#27", + awesome.restart, + { description = "Reload awesome", group = "Awesome" } + ), + awful.key( + { modkey }, + "#46", + function() + awful.tag.incmwfact(0.05) + end, + { description = "Increase client width", group = "Layout" } + ), + awful.key( + { modkey }, + "#43", + function() + awful.tag.incmwfact(-0.05) + end, + { description = "Decrease client width", group = "Layout" } + ), + awful.key( + { modkey, "Control" }, + "#43", + function() + awful.tag.incncol(1, nil, true) + end, + { description = "Increase the number of columns", group = "Layout" } + ), + awful.key( + { modkey, "Control" }, + "#46", + function() + awful.tag.incncol(-1, nil, true) + end, + { description = "Decrease the number of columns", group = "Layout" } + ), + awful.key( + { modkey, "Shift" }, + "#23", + function() + awful.layout.inc(1) + end, + { description = "Select previous layout", group = "Layout" } + ), + awful.key( + { modkey }, + "#23", + function() + awful.layout.inc(-1) + end, + { description = "Select next layout", group = "Layout" } + ), + awful.key( + { modkey }, + "#40", + function() + awful.spawn("rofi -show drun -theme ~/.config/rofi/rofi.rasi") + end, + { descripton = "Application launcher", group = "Application" } + ), + awful.key( + { modkey }, + "#53", + function() + awesome.emit_signal("module::powermenu:show") + end, + { description = "Powermenu", group = "Application"} + ), +-- awful.key( +-- { "Mod1" }, +-- "#23", +-- function() +-- awful.spawn("rofi -show window -theme ~/.config/rofi/window.rasi") +-- end, +-- { descripton = "Client switcher (alt+tab)", group = "Application" } +-- ), +-- awful.key( +-- { modkey }, +-- "#23", +-- function() +-- awful.spawn("rofi -show window -theme ~/.config/rofi/window.rasi") +-- end, +-- { descripton = "Client switcher (alt+tab)", group = "Application" } +-- ), + awful.key( + { modkey }, + "#25", + function() + awful.spawn("rofi -show window -theme ~/.config/rofi/window.rasi") + end, + { descripton = "Client switcher (alt+tab)", group = "Application" } + ), + awful.key( + { modkey }, + "#26", + function() + awful.spawn(user_vars.file_manager) + end, + { descripton = "Open file manager", group = "System" } + ), + awful.key( + { modkey, "Shift" }, + "#26", + function() + awesome.emit_signal("module::powermenu:show") + end, + { descripton = "Session options", group = "System" } + ), + awful.key( + { modkey, "Shift"}, + "#39", + function() + awful.spawn(user_vars.screenshot_program) + end, + { description = "Screenshot", group = "Applications" } + ), + awful.key( + {}, + "XF86AudioLowerVolume", + function(c) + awful.spawn.easy_async_with_shell("pactl set-sink-volume @DEFAULT_SINK@ -2%", function() + awesome.emit_signal("module::volume_osd:show", true) + awesome.emit_signal("module::slider:update") + awesome.emit_signal("widget::volume_osd:rerun") + end) + end, + { description = "Lower volume", group = "System" } + ), + awful.key( + {}, + "XF86AudioRaiseVolume", + function(c) + awful.spawn.easy_async_with_shell("pactl set-sink-volume @DEFAULT_SINK@ +2%", function() + awesome.emit_signal("module::volume_osd:show", true) + awesome.emit_signal("module::slider:update") + awesome.emit_signal("widget::volume_osd:rerun") + end) + end, + { description = "Increase volume", group = "System" } + ), + awful.key( + {}, + "XF86AudioMute", + function(c) + awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle") + awesome.emit_signal("module::volume_osd:show", true) + awesome.emit_signal("module::slider:update") + awesome.emit_signal("widget::volume_osd:rerun") + end, + { description = "Mute volume", group = "System" } + ), + awful.key( + {}, + "XF86MonBrightnessUp", + function(c) + --awful.spawn("xbacklight -time 100 -inc 10%+") + awful.spawn.easy_async_with_shell( + "pkexec xfpm-power-backlight-helper --get-brightness", + function(stdout) + awful.spawn.easy_async_with_shell("pkexec xfpm-power-backlight-helper --set-brightness " .. tostring(tonumber(stdout) + BACKLIGHT_SEPS), function(stdou2) + + end) + awesome.emit_signal("module::brightness_osd:show", true) + awesome.emit_signal("module::brightness_slider:update") + awesome.emit_signal("widget::brightness_osd:rerun") + end + ) + end, + { description = "Raise backlight brightness", group = "System" } + ), + awful.key( + {}, + "XF86MonBrightnessDown", + function(c) + awful.spawn.easy_async_with_shell( + "pkexec xfpm-power-backlight-helper --get-brightness", + function(stdout) + awful.spawn.easy_async_with_shell("pkexec xfpm-power-backlight-helper --set-brightness " .. tostring(tonumber(stdout) - BACKLIGHT_SEPS), function(stdout2) + + end) + awesome.emit_signal("module::brightness_osd:show", true) + awesome.emit_signal("module::brightness_slider:update") + awesome.emit_signal("widget::brightness_osd:rerun") + end + ) + end, + { description = "Lower backlight brightness", group = "System" } + ), + awful.key( + {}, + "XF86AudioPlay", + function(c) + awful.spawn("playerctl play-pause") + end, + { description = "Play / Pause audio", group = "System" } + ), + awful.key( + {}, + "XF86AudioNext", + function(c) + awful.spawn("playerctl next") + end, + { description = "Play / Pause audio", group = "System" } + ), + awful.key( + {}, + "XF86AudioPrev", + function(c) + awful.spawn("playerctl previous") + end, + { description = "Play / Pause audio", group = "System" } + ), +-- awful.key( +-- { "Mod1" }, +-- "#50", +-- function() +-- awesome.emit_signal("kblayout::toggle") +-- end, +-- { description = "Toggle keyboard layout", group = "System" } +-- ), + awful.key( + { modkey }, + "#22", + function() + awful.spawn.easy_async_with_shell( + [[xprop | grep WM_CLASS | awk '{gsub(/"/, "", $4); print $4}']], + function(stdout) + if stdout then + ruled.client.append_rule { + rule = { class = stdout:gsub("\n", "") }, + properties = { + floating = true + }, + } + awful.spawn.easy_async_with_shell( + "cat ~/.config/awesome/src/assets/rules.txt", + function(stdout2) + for class in stdout2:gmatch("%a+") do + if class:match(stdout:gsub("\n", "")) then + return + end + end + awful.spawn.with_shell("echo -n '" .. stdout:gsub("\n", "") .. ";' >> ~/.config/awesome/src/assets/rules.txt") + local c = mouse.screen.selected_tag:clients() + for j, client in ipairs(c) do + if client.class:match(stdout:gsub("\n", "")) then + client.floating = true + end + end + end + ) + end + end + ) + end + ), + awful.key( + { modkey, "Shift" }, + "#22", + function() + awful.spawn.easy_async_with_shell( + [[xprop | grep WM_CLASS | awk '{gsub(/"/, "", $4); print $4}']], + function(stdout) + if stdout then + ruled.client.append_rule { + rule = { class = stdout:gsub("\n", "") }, + properties = { + floating = false + }, + } + awful.spawn.easy_async_with_shell( + [[ + REMOVE="]] .. stdout:gsub("\n", "") .. [[;" + STR=$(cat ~/.config/awesome/src/assets/rules.txt) + echo -n ${STR//$REMOVE/} > ~/.config/awesome/src/assets/rules.txt + ]], + function(stdout2) + local c = mouse.screen.selected_tag:clients() + for j, client in ipairs(c) do + if client.class:match(stdout:gsub("\n", "")) then + client.floating = false + end + end + end + ) + end + end + ) + end + ) +) diff --git a/rc.lua b/rc.lua new file mode 100644 index 0000000..0a1132f --- /dev/null +++ b/rc.lua @@ -0,0 +1,19 @@ +----------------------------------------------------------------------------------------- +-- █████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███╗ ███╗███████╗██╗ ██╗███╗ ███╗ -- +-- ██╔══██╗██║ ██║██╔════╝██╔════╝██╔═══██╗████╗ ████║██╔════╝██║ ██║████╗ ████║ -- +-- ███████║██║ █╗ ██║█████╗ ███████╗██║ ██║██╔████╔██║█████╗ ██║ █╗ ██║██╔████╔██║ -- +-- ██╔══██║██║███╗██║██╔══╝ ╚════██║██║ ██║██║╚██╔╝██║██╔══╝ ██║███╗██║██║╚██╔╝██║ -- +-- ██║ ██║╚███╔███╔╝███████╗███████║╚██████╔╝██║ ╚═╝ ██║███████╗╚███╔███╔╝██║ ╚═╝ ██║ -- +-- ╚═╝ ╚═╝ ╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ -- +----------------------------------------------------------------------------------------- +-- Initialising, order is important! +require("src.theme.user_variables") +require("src.theme.init") +require("src.core.error_handling") +require("src.core.signals") +require("src.core.notifications") +require("src.core.rules") +require("mappings.global_buttons") +require("mappings.bind_to_tags") +require("crylia_bar.init") +require("src.tools.auto_starter")(user_vars.autostart) diff --git a/src/assets/fuji.jpg b/src/assets/fuji.jpg new file mode 100644 index 0000000..3c4f212 Binary files /dev/null and b/src/assets/fuji.jpg differ diff --git a/src/assets/icons/ArchLogo.png b/src/assets/icons/ArchLogo.png new file mode 100644 index 0000000..143dc53 Binary files /dev/null and b/src/assets/icons/ArchLogo.png differ diff --git a/src/assets/icons/audio/headphones.svg b/src/assets/icons/audio/headphones.svg new file mode 100644 index 0000000..49d9ff5 --- /dev/null +++ b/src/assets/icons/audio/headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/audio/menu-down.svg b/src/assets/icons/audio/menu-down.svg new file mode 100644 index 0000000..50b8625 --- /dev/null +++ b/src/assets/icons/audio/menu-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/audio/menu-up.svg b/src/assets/icons/audio/menu-up.svg new file mode 100644 index 0000000..5fb8642 --- /dev/null +++ b/src/assets/icons/audio/menu-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/audio/microphone-off.svg b/src/assets/icons/audio/microphone-off.svg new file mode 100644 index 0000000..7e5b853 --- /dev/null +++ b/src/assets/icons/audio/microphone-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/audio/microphone.svg b/src/assets/icons/audio/microphone.svg new file mode 100644 index 0000000..fbf0784 --- /dev/null +++ b/src/assets/icons/audio/microphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/audio/volume-high.svg b/src/assets/icons/audio/volume-high.svg new file mode 100644 index 0000000..521fe87 --- /dev/null +++ b/src/assets/icons/audio/volume-high.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/audio/volume-low.svg b/src/assets/icons/audio/volume-low.svg new file mode 100644 index 0000000..0a7f9ef --- /dev/null +++ b/src/assets/icons/audio/volume-low.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/audio/volume-medium.svg b/src/assets/icons/audio/volume-medium.svg new file mode 100644 index 0000000..fd01e51 --- /dev/null +++ b/src/assets/icons/audio/volume-medium.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/audio/volume-mute.svg b/src/assets/icons/audio/volume-mute.svg new file mode 100644 index 0000000..902d2d5 --- /dev/null +++ b/src/assets/icons/audio/volume-mute.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/audio/volume-off.svg b/src/assets/icons/audio/volume-off.svg new file mode 100644 index 0000000..4048f82 --- /dev/null +++ b/src/assets/icons/audio/volume-off.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-alert.svg b/src/assets/icons/battery/battery-alert.svg new file mode 100644 index 0000000..23a4f32 --- /dev/null +++ b/src/assets/icons/battery/battery-alert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-10.svg b/src/assets/icons/battery/battery-charging-10.svg new file mode 100644 index 0000000..a234828 --- /dev/null +++ b/src/assets/icons/battery/battery-charging-10.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-100.svg b/src/assets/icons/battery/battery-charging-100.svg new file mode 100644 index 0000000..2190190 --- /dev/null +++ b/src/assets/icons/battery/battery-charging-100.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-20.svg b/src/assets/icons/battery/battery-charging-20.svg new file mode 100644 index 0000000..b7c63aa --- /dev/null +++ b/src/assets/icons/battery/battery-charging-20.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-30.svg b/src/assets/icons/battery/battery-charging-30.svg new file mode 100644 index 0000000..e943778 --- /dev/null +++ b/src/assets/icons/battery/battery-charging-30.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-40.svg b/src/assets/icons/battery/battery-charging-40.svg new file mode 100644 index 0000000..9391fbe --- /dev/null +++ b/src/assets/icons/battery/battery-charging-40.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-50.svg b/src/assets/icons/battery/battery-charging-50.svg new file mode 100644 index 0000000..2a51a07 --- /dev/null +++ b/src/assets/icons/battery/battery-charging-50.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-60.svg b/src/assets/icons/battery/battery-charging-60.svg new file mode 100644 index 0000000..0c5b758 --- /dev/null +++ b/src/assets/icons/battery/battery-charging-60.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-70.svg b/src/assets/icons/battery/battery-charging-70.svg new file mode 100644 index 0000000..06345cb --- /dev/null +++ b/src/assets/icons/battery/battery-charging-70.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-80.svg b/src/assets/icons/battery/battery-charging-80.svg new file mode 100644 index 0000000..bf0892a --- /dev/null +++ b/src/assets/icons/battery/battery-charging-80.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-90.svg b/src/assets/icons/battery/battery-charging-90.svg new file mode 100644 index 0000000..f79ffa5 --- /dev/null +++ b/src/assets/icons/battery/battery-charging-90.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging-outline.svg b/src/assets/icons/battery/battery-charging-outline.svg new file mode 100644 index 0000000..41e981d --- /dev/null +++ b/src/assets/icons/battery/battery-charging-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-charging.svg b/src/assets/icons/battery/battery-charging.svg new file mode 100644 index 0000000..2a5da64 --- /dev/null +++ b/src/assets/icons/battery/battery-charging.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-10.svg b/src/assets/icons/battery/battery-discharging-10.svg new file mode 100644 index 0000000..8569269 --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-10.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-20.svg b/src/assets/icons/battery/battery-discharging-20.svg new file mode 100644 index 0000000..ab31690 --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-20.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-30.svg b/src/assets/icons/battery/battery-discharging-30.svg new file mode 100644 index 0000000..fd11566 --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-30.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-40.svg b/src/assets/icons/battery/battery-discharging-40.svg new file mode 100644 index 0000000..2e6a314 --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-40.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-50.svg b/src/assets/icons/battery/battery-discharging-50.svg new file mode 100644 index 0000000..b5aa185 --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-50.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-60.svg b/src/assets/icons/battery/battery-discharging-60.svg new file mode 100644 index 0000000..ee359e2 --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-60.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-70.svg b/src/assets/icons/battery/battery-discharging-70.svg new file mode 100644 index 0000000..077fbdb --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-70.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-80.svg b/src/assets/icons/battery/battery-discharging-80.svg new file mode 100644 index 0000000..a74b05c --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-80.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-discharging-90.svg b/src/assets/icons/battery/battery-discharging-90.svg new file mode 100644 index 0000000..39e3c8f --- /dev/null +++ b/src/assets/icons/battery/battery-discharging-90.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-off.svg b/src/assets/icons/battery/battery-off.svg new file mode 100644 index 0000000..4ba32e4 --- /dev/null +++ b/src/assets/icons/battery/battery-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-outline.svg b/src/assets/icons/battery/battery-outline.svg new file mode 100644 index 0000000..e05e71b --- /dev/null +++ b/src/assets/icons/battery/battery-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery-unknown.svg b/src/assets/icons/battery/battery-unknown.svg new file mode 100644 index 0000000..8e117be --- /dev/null +++ b/src/assets/icons/battery/battery-unknown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/battery/battery.svg b/src/assets/icons/battery/battery.svg new file mode 100644 index 0000000..950597a --- /dev/null +++ b/src/assets/icons/battery/battery.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/bluetooth/bluetooth-off.svg b/src/assets/icons/bluetooth/bluetooth-off.svg new file mode 100644 index 0000000..4a8775a --- /dev/null +++ b/src/assets/icons/bluetooth/bluetooth-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/bluetooth/bluetooth-on.svg b/src/assets/icons/bluetooth/bluetooth-on.svg new file mode 100644 index 0000000..2d7ae3a --- /dev/null +++ b/src/assets/icons/bluetooth/bluetooth-on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/brightness/brightness-high.svg b/src/assets/icons/brightness/brightness-high.svg new file mode 100644 index 0000000..fa2ced4 --- /dev/null +++ b/src/assets/icons/brightness/brightness-high.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/brightness/brightness-low.svg b/src/assets/icons/brightness/brightness-low.svg new file mode 100644 index 0000000..d8818a4 --- /dev/null +++ b/src/assets/icons/brightness/brightness-low.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/brightness/brightness-medium.svg b/src/assets/icons/brightness/brightness-medium.svg new file mode 100644 index 0000000..6de47b0 --- /dev/null +++ b/src/assets/icons/brightness/brightness-medium.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/clock/clock.svg b/src/assets/icons/clock/clock.svg new file mode 100644 index 0000000..d77dd69 --- /dev/null +++ b/src/assets/icons/clock/clock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/cpu/cpu.svg b/src/assets/icons/cpu/cpu.svg new file mode 100644 index 0000000..fcbef7d --- /dev/null +++ b/src/assets/icons/cpu/cpu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/cpu/disk.svg b/src/assets/icons/cpu/disk.svg new file mode 100644 index 0000000..7390ce1 --- /dev/null +++ b/src/assets/icons/cpu/disk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/cpu/gpu.svg b/src/assets/icons/cpu/gpu.svg new file mode 100644 index 0000000..e9294dd --- /dev/null +++ b/src/assets/icons/cpu/gpu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/cpu/ram.svg b/src/assets/icons/cpu/ram.svg new file mode 100644 index 0000000..14503d8 --- /dev/null +++ b/src/assets/icons/cpu/ram.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/icons/cpu/thermometer-high.svg b/src/assets/icons/cpu/thermometer-high.svg new file mode 100644 index 0000000..3f7ea67 --- /dev/null +++ b/src/assets/icons/cpu/thermometer-high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/cpu/thermometer-low.svg b/src/assets/icons/cpu/thermometer-low.svg new file mode 100644 index 0000000..6a5754b --- /dev/null +++ b/src/assets/icons/cpu/thermometer-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/cpu/thermometer.svg b/src/assets/icons/cpu/thermometer.svg new file mode 100644 index 0000000..008696d --- /dev/null +++ b/src/assets/icons/cpu/thermometer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/date/calendar.svg b/src/assets/icons/date/calendar.svg new file mode 100644 index 0000000..d694669 --- /dev/null +++ b/src/assets/icons/date/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/kblayout/keyboard.svg b/src/assets/icons/kblayout/keyboard.svg new file mode 100644 index 0000000..b8f8511 --- /dev/null +++ b/src/assets/icons/kblayout/keyboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/ethernet.svg b/src/assets/icons/network/ethernet.svg new file mode 100644 index 0000000..7e53db2 --- /dev/null +++ b/src/assets/icons/network/ethernet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/no-internet.svg b/src/assets/icons/network/no-internet.svg new file mode 100644 index 0000000..2adb79c --- /dev/null +++ b/src/assets/icons/network/no-internet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/wifi-strength-1.svg b/src/assets/icons/network/wifi-strength-1.svg new file mode 100644 index 0000000..7966383 --- /dev/null +++ b/src/assets/icons/network/wifi-strength-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/wifi-strength-2.svg b/src/assets/icons/network/wifi-strength-2.svg new file mode 100644 index 0000000..393ca82 --- /dev/null +++ b/src/assets/icons/network/wifi-strength-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/wifi-strength-3.svg b/src/assets/icons/network/wifi-strength-3.svg new file mode 100644 index 0000000..4f470d9 --- /dev/null +++ b/src/assets/icons/network/wifi-strength-3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/wifi-strength-4.svg b/src/assets/icons/network/wifi-strength-4.svg new file mode 100644 index 0000000..3974275 --- /dev/null +++ b/src/assets/icons/network/wifi-strength-4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/wifi-strength-off-outline.svg b/src/assets/icons/network/wifi-strength-off-outline.svg new file mode 100644 index 0000000..fe6d7bd --- /dev/null +++ b/src/assets/icons/network/wifi-strength-off-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/network/wifi-strength-outline.svg b/src/assets/icons/network/wifi-strength-outline.svg new file mode 100644 index 0000000..3d54780 --- /dev/null +++ b/src/assets/icons/network/wifi-strength-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/notifications/notification-outline.svg b/src/assets/icons/notifications/notification-outline.svg new file mode 100644 index 0000000..b00e8ce --- /dev/null +++ b/src/assets/icons/notifications/notification-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/notifications/notification.svg b/src/assets/icons/notifications/notification.svg new file mode 100644 index 0000000..59eb5a1 --- /dev/null +++ b/src/assets/icons/notifications/notification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/notifications/play-pause.svg b/src/assets/icons/notifications/play-pause.svg new file mode 100644 index 0000000..5b58b8a --- /dev/null +++ b/src/assets/icons/notifications/play-pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/notifications/skip-next.svg b/src/assets/icons/notifications/skip-next.svg new file mode 100644 index 0000000..2d3a46e --- /dev/null +++ b/src/assets/icons/notifications/skip-next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/notifications/skip-prev.svg b/src/assets/icons/notifications/skip-prev.svg new file mode 100644 index 0000000..62dc70f --- /dev/null +++ b/src/assets/icons/notifications/skip-prev.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/power/power.svg b/src/assets/icons/power/power.svg new file mode 100644 index 0000000..343d1ba --- /dev/null +++ b/src/assets/icons/power/power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/powermenu/defaultpfp.svg b/src/assets/icons/powermenu/defaultpfp.svg new file mode 100644 index 0000000..6d69549 --- /dev/null +++ b/src/assets/icons/powermenu/defaultpfp.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/powermenu/lock.svg b/src/assets/icons/powermenu/lock.svg new file mode 100644 index 0000000..123bd04 --- /dev/null +++ b/src/assets/icons/powermenu/lock.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/powermenu/logout.svg b/src/assets/icons/powermenu/logout.svg new file mode 100644 index 0000000..b40ecd7 --- /dev/null +++ b/src/assets/icons/powermenu/logout.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/powermenu/reboot.svg b/src/assets/icons/powermenu/reboot.svg new file mode 100644 index 0000000..7a91c5f --- /dev/null +++ b/src/assets/icons/powermenu/reboot.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/powermenu/shutdown.svg b/src/assets/icons/powermenu/shutdown.svg new file mode 100644 index 0000000..3b4bebf --- /dev/null +++ b/src/assets/icons/powermenu/shutdown.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/powermenu/suspend.svg b/src/assets/icons/powermenu/suspend.svg new file mode 100644 index 0000000..8f12bc5 --- /dev/null +++ b/src/assets/icons/powermenu/suspend.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/titlebar/close.svg b/src/assets/icons/titlebar/close.svg new file mode 100644 index 0000000..989837c --- /dev/null +++ b/src/assets/icons/titlebar/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/titlebar/maximize.svg b/src/assets/icons/titlebar/maximize.svg new file mode 100644 index 0000000..422ad55 --- /dev/null +++ b/src/assets/icons/titlebar/maximize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/titlebar/minimize.svg b/src/assets/icons/titlebar/minimize.svg new file mode 100644 index 0000000..36a771f --- /dev/null +++ b/src/assets/icons/titlebar/minimize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/titlebar/stick.svg b/src/assets/icons/titlebar/stick.svg new file mode 100644 index 0000000..c832e29 --- /dev/null +++ b/src/assets/icons/titlebar/stick.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/titlebar/unmaximize.svg b/src/assets/icons/titlebar/unmaximize.svg new file mode 100644 index 0000000..12d171f --- /dev/null +++ b/src/assets/icons/titlebar/unmaximize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/titlebar/unstick.svg b/src/assets/icons/titlebar/unstick.svg new file mode 100644 index 0000000..475f722 --- /dev/null +++ b/src/assets/icons/titlebar/unstick.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/layout/cornerne.svg b/src/assets/layout/cornerne.svg new file mode 100644 index 0000000..faba2e6 --- /dev/null +++ b/src/assets/layout/cornerne.svg @@ -0,0 +1,14 @@ + + + Layer 1 + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/cornernw.svg b/src/assets/layout/cornernw.svg new file mode 100644 index 0000000..dc57d80 --- /dev/null +++ b/src/assets/layout/cornernw.svg @@ -0,0 +1,12 @@ + + + Layer 1 + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/cornerse.svg b/src/assets/layout/cornerse.svg new file mode 100644 index 0000000..3a977a2 --- /dev/null +++ b/src/assets/layout/cornerse.svg @@ -0,0 +1,14 @@ + + + Layer 1 + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/cornersw.svg b/src/assets/layout/cornersw.svg new file mode 100644 index 0000000..b68e050 --- /dev/null +++ b/src/assets/layout/cornersw.svg @@ -0,0 +1,14 @@ + + + Layer 1 + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/dwindle.svg b/src/assets/layout/dwindle.svg new file mode 100644 index 0000000..9e59058 --- /dev/null +++ b/src/assets/layout/dwindle.svg @@ -0,0 +1,64 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/src/assets/layout/fairh.svg b/src/assets/layout/fairh.svg new file mode 100644 index 0000000..37c0898 --- /dev/null +++ b/src/assets/layout/fairh.svg @@ -0,0 +1,14 @@ + + + Layer 1 + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/fairv.svg b/src/assets/layout/fairv.svg new file mode 100644 index 0000000..d4f128d --- /dev/null +++ b/src/assets/layout/fairv.svg @@ -0,0 +1,12 @@ + + + Layer 1 + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/floating.svg b/src/assets/layout/floating.svg new file mode 100644 index 0000000..82d2633 --- /dev/null +++ b/src/assets/layout/floating.svg @@ -0,0 +1,12 @@ + + + Layer 1 + + + + + + + + + \ No newline at end of file diff --git a/src/assets/layout/fullscreen.svg b/src/assets/layout/fullscreen.svg new file mode 100644 index 0000000..6ba320b --- /dev/null +++ b/src/assets/layout/fullscreen.svg @@ -0,0 +1,62 @@ + + + + + + + image/svg+xml + + + + + + + + diff --git a/src/assets/layout/max.svg b/src/assets/layout/max.svg new file mode 100644 index 0000000..f1b2b2d --- /dev/null +++ b/src/assets/layout/max.svg @@ -0,0 +1,62 @@ + + + + + + + image/svg+xml + + + + + + + + diff --git a/src/assets/layout/tile.svg b/src/assets/layout/tile.svg new file mode 100644 index 0000000..08c780e --- /dev/null +++ b/src/assets/layout/tile.svg @@ -0,0 +1,9 @@ + + + Layer 1 + + + + + + diff --git a/src/assets/rules.txt b/src/assets/rules.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/space.jpg b/src/assets/space.jpg new file mode 100644 index 0000000..7e53b39 Binary files /dev/null and b/src/assets/space.jpg differ diff --git a/src/assets/userpfp/crylia.png b/src/assets/userpfp/crylia.png new file mode 100644 index 0000000..671fbe2 Binary files /dev/null and b/src/assets/userpfp/crylia.png differ diff --git a/src/assets/userpfp/rickastley.jpg b/src/assets/userpfp/rickastley.jpg new file mode 100644 index 0000000..962cd11 Binary files /dev/null and b/src/assets/userpfp/rickastley.jpg differ diff --git a/src/assets/wallpaper.png b/src/assets/wallpaper.png new file mode 100644 index 0000000..f806d10 Binary files /dev/null and b/src/assets/wallpaper.png differ diff --git a/src/core/error_handling.lua b/src/core/error_handling.lua new file mode 100644 index 0000000..c1e0b25 --- /dev/null +++ b/src/core/error_handling.lua @@ -0,0 +1,25 @@ +---------------------------------------------------------------- +-- This class is to output an error if you fuck up the config -- +---------------------------------------------------------------- +-- Awesome Libs +local naughty = require("naughty") + +do + local in_error = false + awesome.connect_signal( + "debug::error", + function(err) + if in_error then + return + end + in_error = true + + naughty.notify({ + preset = naughty.config.presets.critical, + title = "ERROR", + text = tostring(err) + }) + in_error = false + end + ) +end diff --git a/src/core/notifications.lua b/src/core/notifications.lua new file mode 100644 index 0000000..0c2d602 --- /dev/null +++ b/src/core/notifications.lua @@ -0,0 +1,444 @@ +------------------------------- +-- The Notification defaults -- +------------------------------- +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local cat = require("src.theme.catppuccin") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local menubar = require('menubar') +local naughty = require("naughty") +local wibox = require("wibox") + +local icondir = awful.util.getdir("config") .. "src/assets/icons/notifications/" + +-- TODO: Figure out how to use hover effects without messing up the actions +naughty.config.defaults.ontop = true +naughty.config.defaults.icon_size = dpi(80) +naughty.config.defaults.timeout = 3 +naughty.config.defaults.title = "System Notification" +naughty.config.defaults.margin = dpi(10) +naughty.config.defaults.position = "bottom_right" +naughty.config.defaults.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(10)) +end +naughty.config.defaults.border_width = dpi(4) +naughty.config.defaults.border_color = color["Grey800"] +naughty.config.defaults.spacing = dpi(10) + +naughty.connect_signal( + 'request::icon', + function(n, context, hints) + if context ~= 'app_icon' then + return + end + local path = menubar.utils.lookup_icon(hints.app_icon) or menubar.utils.lookup_icon(hints.app_icon:lower()) + if path then + n.icon = path + end + end +) + +naughty.connect_signal( + "request::display", + function(n) + if n.urgency == "critical" then + n.title = string.format("%s", + color["RedA200"], n.title) or "" + n.message = string.format("%s", color["Red200"], n.message) or "" + n.app_name = string.format("%s", color["RedA400"], n.app_name) or "" + n.bg = cat["Base"] + else + n.title = string.format("%s", + color["Pink200"], n.title) or "" + n.message = string.format("%s", "#ffffffaa", n.message) or "" + n.bg = cat["Base"] + n.timeout = n.timeout or 3 + end + + local use_image = false + + if n.app_name == "Spotify" then + n.actions = { naughty.action { + program = "Spotify", + id = "skip-prev", + icon = gears.color.recolor_image(icondir .. "skip-prev.svg", color["Cyan200"]) + }, naughty.action { + program = "Spotify", + id = "play-pause", + icon = gears.color.recolor_image(icondir .. "play-pause.svg", color["Cyan200"]) + }, naughty.action { + program = "Spotify", + id = "skip-next", + icon = gears.color.recolor_image(icondir .. "skip-next.svg", color["Cyan200"]) + } } + use_image = true + end + + local action_template_widget = {} + + if use_image then + action_template_widget = { + { + { + { + { + id = "icon_role", + widget = wibox.widget.imagebox + }, + id = "centered", + valign = "center", + halign = "center", + widget = wibox.container.place + }, + margins = dpi(5), + widget = wibox.container.margin + }, + forced_height = dpi(35), + forced_width = dpi(35), + fg = color["Cyan200"], + bg = cat["Surface0"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + widget = wibox.container.background, + id = "bgrnd" + }, + id = "mrgn", + top = dpi(10), + bottom = dpi(10), + widget = wibox.container.margin + } + else + action_template_widget = { + { + { + { + { + id = "text_role", + font = "JetBrainsMono Nerd Font, Regular 12", + widget = wibox.widget.textbox + }, + id = "centered", + widget = wibox.container.place + }, + margins = dpi(5), + widget = wibox.container.margin + }, + fg = color["Green200"], + bg = cat["Surface0"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + widget = wibox.container.background, + id = "bgrnd" + }, + id = "mrgn", + top = dpi(10), + bottom = dpi(10), + widget = wibox.container.margin + } + end + + local actions_template = wibox.widget { + notification = n, + base_layout = wibox.widget { + spacing = dpi(40), + layout = wibox.layout.fixed.horizontal + }, + widget_template = action_template_widget, + style = { + underline_normal = false, + underline_selected = true, + bg_normal = color["Grey100"], + bg_selected = color["Grey200"] + }, + widget = naughty.list.actions + } + + local w_template = wibox.widget { + { + { + { + { + { + { + { + { + { + { + image = gears.color.recolor_image(icondir .. "notification-outline.svg", color["Teal200"]), + resize = false, + widget = wibox.widget.imagebox + }, + right = dpi(5), + widget = wibox.container.margin + }, + { + markup = n.app_name or 'System Notification', + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.horizontal + }, + fg = color["Teal200"], + widget = wibox.container.background + }, + margins = dpi(10), + widget = wibox.container.margin + }, + nil, + { + { + { + text = os.date("%H:%M"), + widget = wibox.widget.textbox + }, + id = "background", + fg = color["Teal200"], + widget = wibox.container.background + }, + { + { + { + { + { + font = user_vars.font.specify .. ", 10", + text = "✕", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + start_angle = 4.71239, + thickness = dpi(2), + min_value = 0, + max_value = 360, + value = 360, + widget = wibox.container.arcchart, + id = "arc_chart" + }, + id = "background", + fg = color["Teal200"], + bg = cat["Base"], + widget = wibox.container.background + }, + strategy = "exact", + width = dpi(20), + height = dpi(20), + widget = wibox.container.constraint, + id = "const" + }, + margins = dpi(10), + widget = wibox.container.margin, + id = "arc_margin" + }, + layout = wibox.layout.fixed.horizontal, + id = "arc_app_layout_2" + }, + id = "arc_app_layout", + layout = wibox.layout.align.horizontal + }, + id = "arc_app_bg", + border_color = cat["Surface1"], + border_width = dpi(2), + widget = wibox.container.background + }, + { + { + { + { + { + image = n.icon, + resize = true, + widget = wibox.widget.imagebox, + clip_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 10) + end + }, + width = naughty.config.defaults.icon_size, + height = naughty.config.defaults.icon_size, + strategy = "exact", + widget = wibox.container.constraint + }, + halign = "center", + valign = "top", + widget = wibox.container.place + }, + left = dpi(20), + bottom = dpi(15), + top = dpi(15), + right = dpi(10), + widget = wibox.container.margin + }, + { + { + { + widget = naughty.widget.title, + align = "left" + }, + { + widget = naughty.widget.message, + align = "left" + }, + { + actions_template, + widget = wibox.container.place + }, + layout = wibox.layout.fixed.vertical + }, + left = dpi(10), + bottom = dpi(10), + top = dpi(10), + right = dpi(20), + widget = wibox.container.margin + }, + layout = wibox.layout.fixed.horizontal + }, + id = "widget_layout", + layout = wibox.layout.fixed.vertical + }, + id = "min_size", + strategy = "min", + width = dpi(100), + widget = wibox.container.constraint + }, + id = "max_size", + strategy = "max", + width = Theme.notification_max_width or dpi(500), + widget = wibox.container.constraint + }, + id = "background", + bg = cat["Base"], + border_color = cat["Surface1"], + border_width = dpi(2), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 8) + end, + widget = wibox.container.background + } + + local close = w_template.max_size.min_size.widget_layout.arc_app_bg.arc_app_layout.arc_app_layout_2.arc_margin.const.background + local arc = close.arc_chart + + local timeout = n.timeout + local remove_time = timeout + + if timeout ~= 0 then + arc.value = 360 + local arc_timer = gears.timer { + timeout = 0.1, + call_now = true, + autostart = true, + callback = function() + arc.value = (remove_time - 0) / (timeout - 0) * 360 + remove_time = remove_time - 0.1 + end + } + + w_template:connect_signal( + "mouse::enter", + function() + -- Setting to 0 doesn't work + arc_timer:stop() + n.timeout = 99999 + end + ) + + w_template:connect_signal( + "mouse::leave", + function() + arc_timer:start() + n.timeout = remove_time + end + ) + end + + Hover_signal(close, cat["Base"], color["Teal200"]) + + close:connect_signal( + "button::press", + function() + n:destroy() + end + ) + + w_template:connect_signal( + "button::press", + function(c, d, e, key) + if key == 3 then + n:destroy() + end + -- TODO: Find out how to get the associated client + --[[ if key == 1 then + if n.clients then + n.clients[1]:activate { + switch_to_tag = true, + raise = true + } + end + end ]] + end + ) + + local box = naughty.layout.box { + notification = n, + timeout = 3, + type = "notification", + screen = awful.screen.focused(), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 10) + end, + widget_template = w_template + } + + box.buttons = {} + n.buttons = {} + end +) + +naughty.connect_signal( + "destroyed", + function() + + end +) + +-- Test notification +--[[naughty.notification { + app_name = "System Notification", + title = "A notification 3", + message = "This is very informative and overflowing", + icon = "/home/crylia/.config/awesome/src/assets/userpfp/crylia.png", + urgency = "normal", + timeout = 1, + actions = { + naughty.action { + name = "Accept", + }, + naughty.action { + name = "Refuse", + }, + naughty.action { + name = "Ignore", + }, + } +}--]] + +naughty.connect_signal( + "invoked", + function(_, action) + if action.program == "Spotify" then + if action.id == "skip-prev" then + awful.spawn("playerctl previous") + end + if action.id == "play-pause" then + awful.spawn("playerctl play-pause") + end + if action.id == "skip-next" then + awful.spawn("playerctl next") + end + end + end +) diff --git a/src/core/rules.lua b/src/core/rules.lua new file mode 100644 index 0000000..d27e411 --- /dev/null +++ b/src/core/rules.lua @@ -0,0 +1,80 @@ +------------------------------------------------------------------------------------------------- +-- This class contains rules for float exceptions or special themeing for certain applications -- +------------------------------------------------------------------------------------------------- + +-- Awesome Libs +local awful = require("awful") +local beautiful = require("beautiful") +local ruled = require("ruled") + +awful.rules.rules = { + { + rule = {}, + properties = { + border_width = beautiful.border_width, + border_color = beautiful.border_normal, + focus = awful.client.focus.filter, + raise = true, + keys = require("../../mappings/client_keys"), + buttons = require("../../mappings/client_buttons"), + screen = awful.screen.preferred, + placement = awful.placement.no_overlap + awful.placement.no_offscreen + } + }, + { + rule_any = { + instance = {}, + class = { + "Arandr", + "Lxappearance", + "kdeconnect.app", + "zoom", + "file-roller", + "File-roller", + "steam" + }, + name = {}, + role = { + "AlarmWindow", + "ConfigManager", + "pop-up" + } + }, + properties = { floating = true, titlebars_enabled = true } + }, + { + id = "titlebar", + rule_any = { + type = { "normal", "dialog", "modal", "utility" } + }, + properties = { titlebars_enabled = true } + }, + { + id = "plank", + rule_any = { + name = { "plank" } + }, + properties = { ontop = true, titlebars_enabled = false } + }, + { + id = "cairo-dock", + rule_any = { + name = { "cairo-dock" } + }, + properties = { ontop = true, titlebars_enabled = false } + } +} + +awful.spawn.easy_async_with_shell( + "cat ~/.config/awesome/src/assets/rules.txt", + function(stdout) + for class in stdout:gmatch("%a+") do + ruled.client.append_rule { + rule = { class = class }, + properties = { + floating = true + }, + } + end +end +) diff --git a/src/core/signals.lua b/src/core/signals.lua new file mode 100644 index 0000000..bcafff0 --- /dev/null +++ b/src/core/signals.lua @@ -0,0 +1,193 @@ +---@diagnostic disable: undefined-field +-- Awesome Libs +local awful = require("awful") +local beautiful = require("beautiful") +local gears = require("gears") +local wibox = require("wibox") + +screen.connect_signal( + "added", + function() + awesome.restart() + end +) + +screen.connect_signal( + "removed", + function() + awesome.restart() + end +) + +client.connect_signal( + "manage", + function(c) + if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then + awful.placement.no_offscreen(c) + end + c.shape = function(cr, width, height) + if c.fullscreen or c.maximized or c.maximized_horizontal or c.maximized_vertical then + gears.shape.rectangle(cr, width, height) + else + gears.shape.rounded_rect(cr, width, height, 10) + end + end + end +) + +client.connect_signal( + 'unmanage', + function(c) + if #awful.screen.focused().clients > 0 then + awful.screen.focused().clients[1]:emit_signal( + 'request::activate', + 'mouse_enter', + { + raise = true + } + ) + end + end +) + +client.connect_signal( + 'tag::switched', + function(c) + local focus_timer = timer({ timeout = 0.1 }) + focus_timer:connect_signal("timeout", function() + local object = mouse.object_under_pointer() + if object ~= nil then + client.focus = object + object:raise() + elseif #awful.screen.focused().clients > 0 then + awful.screen.focused().clients[1]:emit_signal( + 'request::activate', + 'mouse_enter', + { + raise = true + } + ) + end + focus_timer:stop() + end) + focus_timer:start() + end +) + +-- Sloppy focus +client.connect_signal( + "mouse::enter", + function(c) + c:emit_signal( + "request::activate", + "mouse_enter", + { + raise = false + } + ) + end +) + +-- Workaround for focused border color, why in the love of god doesnt it work with +-- beautiful.border_focus +client.connect_signal( + "focus", + function(c) + c.border_color = "#a6e3a1" + end +) + +client.connect_signal( + "unfocus", + function(c) + c.border_color = beautiful.border_normal + end +) + +--- Takes a wibox.container.background and connects four signals to it +---@param widget widget.container.background +---@param bg string +---@param fg string +function Hover_signal(widget, bg, fg) + local old_wibox, old_cursor, old_bg, old_fg + + local mouse_enter = function() + if bg then + old_bg = widget.bg + if string.len(bg) == 7 then + widget.bg = bg .. 'dd' + else + widget.bg = bg + end + end + if fg then + old_fg = widget.fg + widget.fg = fg + end + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = "hand1" + end + end + + local button_press = function() + if bg then + if bg then + if string.len(bg) == 7 then + widget.bg = bg .. 'bb' + else + widget.bg = bg + end + end + end + if fg then + widget.fg = fg + end + end + + local button_release = function() + if bg then + if bg then + if string.len(bg) == 7 then + widget.bg = bg .. 'dd' + else + widget.bg = bg + end + end + end + if fg then + widget.fg = fg + end + end + + local mouse_leave = function() + if bg then + widget.bg = old_bg + end + if fg then + widget.fg = old_fg + end + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + + widget:disconnect_signal("mouse::enter", mouse_enter) + + widget:disconnect_signal("button::press", button_press) + + widget:disconnect_signal("button::release", button_release) + + widget:disconnect_signal("mouse::leave", mouse_leave) + + widget:connect_signal("mouse::enter", mouse_enter) + + widget:connect_signal("button::press", button_press) + + widget:connect_signal("button::release", button_release) + + widget:connect_signal("mouse::leave", mouse_leave) + +end diff --git a/src/modules/brightness_osd.lua b/src/modules/brightness_osd.lua new file mode 100644 index 0000000..728eef1 --- /dev/null +++ b/src/modules/brightness_osd.lua @@ -0,0 +1,234 @@ +--------------------------------------- +-- This is the brightness_osd module -- +--------------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/brightness/" + +BACKLIGHT_MAX_BRIGHTNESS = 0 +BACKLIGHT_SEPS = 0 +awful.spawn.easy_async_with_shell( + "pkexec xfpm-power-backlight-helper --get-max-brightness", + function(stdout) + BACKLIGHT_MAX_BRIGHTNESS = tonumber(stdout) + BACKLIGHT_SEPS = BACKLIGHT_MAX_BRIGHTNESS / 100 + BACKLIGHT_SEPS = math.floor(BACKLIGHT_SEPS) +end +) + +return function(s) + + local brightness_osd_widget = wibox.widget { + { + { + { + { + nil, + { + nil, + { + id = "icon", + forced_height = dpi(220), + image = icondir .. "brightness-high.svg", + widget = wibox.widget.imagebox + }, + nil, + expand = "none", + id = "icon_margin2", + layout = wibox.layout.align.vertical + }, + nil, + id = "icon_margin1", + expand = "none", + layout = wibox.layout.align.horizontal + }, + { + { + id = "label", + text = "Brightness", + align = "left", + valign = "center", + widget = wibox.widget.textbox + }, + nil, + { + id = "value", + text = "0%", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "label_value_layout", + forced_height = dpi(48), + layout = wibox.layout.align.horizontal, + }, + { + { + id = "brightness_slider", + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(10), + bar_color = color["Grey800"] .. "88", + bar_active_color = "#ffffff", + handle_color = "#ffffff", + handle_shape = gears.shape.circle, + handle_width = dpi(10), + handle_border_color = color["White"], + maximum = 100, + widget = wibox.widget.slider + }, + id = "slider_layout", + forced_height = dpi(24), + widget = wibox.container.place + }, + id = "icon_slider_layout", + spacing = dpi(0), + layout = wibox.layout.align.vertical + }, + id = "osd_layout", + layout = wibox.layout.align.vertical + }, + id = "container", + left = dpi(24), + right = dpi(24), + widget = wibox.container.margin + }, + bg = color["Grey900"] .. "88", + widget = wibox.container.background, + ontop = true, + visible = true, + type = "notification", + forced_height = dpi(300), + forced_width = dpi(300), + offset = dpi(5), + } + + brightness_osd_widget.container.osd_layout.icon_slider_layout.slider_layout.brightness_slider:connect_signal( + "property::value", + function() + awful.spawn.easy_async_with_shell( + "pkexec xfpm-power-backlight-helper --get-brightness", + function(stdout) + local brightness_value = math.floor((tonumber(stdout) - 1) / (BACKLIGHT_MAX_BRIGHTNESS - 1) * 100) + brightness_osd_widget.container.osd_layout.icon_slider_layout.label_value_layout.value:set_text(tostring(brightness_value) .. "%") + + awesome.emit_signal( + "widget::brightness:update", + brightness_value + ) + + if awful.screen.focused().show_brightness_osd then + awesome.emit_signal( + "module::brightness_osd:show", + true + ) + end + + local icon = icondir .. "brightness" + if brightness_value >= 0 and brightness_value < 34 then + icon = icon .. "-low" + elseif brightness_value >= 34 and brightness_value < 67 then + icon = icon .. "-medium" + elseif brightness_value >= 67 then + icon = icon .. "-high" + end + brightness_osd_widget.container.osd_layout.icon_slider_layout.icon_margin1.icon_margin2.icon:set_image(icon .. ".svg") + end + ) + end + ) + + local update_slider = function() + awful.spawn.easy_async_with_shell( + [[ pkexec xfpm-power-backlight-helper --get-brightness ]], + function(stdout) + stdout = math.floor((tonumber(stdout) - 1) / (BACKLIGHT_MAX_BRIGHTNESS - 1) * 100) + brightness_osd_widget.container.osd_layout.icon_slider_layout.slider_layout.brightness_slider:set_value(stdout) + end + ) + end + + awesome.connect_signal( + "module::brightness_slider:update", + function() + update_slider() + end + ) + + awesome.connect_signal( + "widget::brightness:update", + function(value) + brightness_osd_widget.container.osd_layout.icon_slider_layout.slider_layout.brightness_slider:set_value(tonumber(value)) + end + ) + + update_slider() + + local brightness_container = awful.popup { + widget = wibox.container.background, + ontop = true, + bg = color["Grey900"] .. "00", + stretch = false, + visible = false, + screen = s, + placement = function(c) awful.placement.centered(c, { margins = { top = dpi(200) } }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 15) + end + } + + local hide_brightness_osd = gears.timer { + timeout = 2, + autostart = true, + callback = function() + brightness_container.visible = false + end + } + + brightness_container:setup { + brightness_osd_widget, + layout = wibox.layout.fixed.horizontal + } + + awesome.connect_signal( + "widget::brightness_osd:rerun", + function() + if hide_brightness_osd.started then + hide_brightness_osd:again() + else + hide_brightness_osd:start() + end + end + ) + + awesome.connect_signal( + "module::brightness_osd:show", + function() + if s == mouse.screen then + brightness_container.visible = true + end + end + ) + + brightness_container:connect_signal( + "mouse::enter", + function() + brightness_container.visible = true + hide_brightness_osd:stop() + end + ) + + brightness_container:connect_signal( + "mouse::leave", + function() + brightness_container.visible = true + hide_brightness_osd:again() + end + ) +end diff --git a/src/modules/notification-center/init.lua b/src/modules/notification-center/init.lua new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/powermenu.lua b/src/modules/powermenu.lua new file mode 100644 index 0000000..4bcb943 --- /dev/null +++ b/src/modules/powermenu.lua @@ -0,0 +1,283 @@ +-------------------------------- +-- This is the network widget -- +-------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/powermenu/" + +return function(s) + + -- Profile picture imagebox + local profile_picture = wibox.widget { + image = icondir .. "defaultpfp.svg", + resize = true, + forced_height = dpi(200), + clip_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 30) + end, + widget = wibox.widget.imagebox + } + + -- Username textbox + local profile_name = wibox.widget { + align = 'center', + valign = 'center', + text = " ", + font = "JetBrains Mono Bold 30", + widget = wibox.widget.textbox + } + + -- Get the profile script from /var/lib/AccountsService/icons/${USER} + -- and copy it to the assets folder + -- TODO: If the user doesnt have AccountsService look into $HOME/.faces + local update_profile_picture = function() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/pfp.sh 'userPfp'", + function(stdout) + if stdout then + profile_picture:set_image(stdout:gsub("\n", "")) + else + profile_picture:set_image(icondir .. "defaultpfp.svg") + end + end + ) + end + update_profile_picture() + + -- Get the full username(if set) and the username + hostname + local update_user_name = function() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/pfp.sh 'userName' '" .. user_vars.namestyle .. "'", + function(stdout) + if stdout:gsub("\n", "") == "Rick Astley" then + profile_picture:set_image(awful.util.getdir("config") .. "src/assets/userpfp/" .. "rickastley.jpg") + end + profile_name:set_text(stdout) + end + ) + end + update_user_name() + + -- Universal Button widget + local button = function(name, icon, bg_color, callback) + local item = wibox.widget { + { + { + { + { + { + -- TODO: using gears.color to recolor a SVG will make it look super low res + -- currently I recolor it in the .svg file directly, but later implement + -- a better way to recolor a SVG + -- image = gears.color.recolor_image(icon, color["Grey900"]), + image = icon, + resize = true, + forced_height = dpi(30), + widget = wibox.widget.imagebox + }, + margins = dpi(0), + widget = wibox.container.margin + }, + { + { + text = name, + font = "JetBrains Mono Bold 30", + widget = wibox.widget.textbox + }, + margins = dpi(0), + widget = wibox.container.margin + }, + widget = wibox.layout.fixed.horizontal + }, + margins = dpi(10), + widget = wibox.container.margin + }, + fg = color["Grey900"], + bg = bg_color, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 10) + end, + widget = wibox.container.background, + id = 'background' + }, + spacing = dpi(0), + layout = wibox.layout.align.vertical + } + + item:connect_signal( + "button::release", + function() + callback() + end + ) + + return item + end + + -- Create the power menu actions + local suspend_command = function() + awful.spawn("/home/eric/.config/awesome/bin/bsplock") + awful.spawn("systemctl suspend") + awesome.emit_signal("module::powermenu:hide") + end + + local logout_command = function() + awesome.quit() + end + + local lock_command = function() + awful.spawn("/home/eric/.config/awesome/bin/bsplock") + awesome.emit_signal("module::powermenu:hide") + end + + local shutdown_command = function() + awful.spawn("shutdown now") + awesome.emit_signal("module::powermenu:hide") + end + + local reboot_command = function() + awful.spawn("reboot") + awesome.emit_signal("module::powermenu:hide") + end + + -- Create the buttons with their command and name etc + local shutdown_button = button("Shutdown", icondir .. "shutdown.svg", color["Blue200"], shutdown_command) + local reboot_button = button("Reboot", icondir .. "reboot.svg", color["Red200"], reboot_command) + local suspend_button = button("Suspend", icondir .. "suspend.svg", color["Yellow200"], suspend_command) + local logout_button = button("Logout", icondir .. "logout.svg", color["Green200"], logout_command) + local lock_button = button("Lock", icondir .. "lock.svg", color["Orange200"], lock_command) + + -- Signals to change color on hover + Hover_signal(shutdown_button.background, color["Blue200"], color["Grey900"]) + Hover_signal(reboot_button.background, color["Red200"], color["Grey900"]) + Hover_signal(suspend_button.background, color["Yellow200"], color["Grey900"]) + Hover_signal(logout_button.background, color["Green200"], color["Grey900"]) + Hover_signal(lock_button.background, color["Orange200"], color["Grey900"]) + + -- The powermenu widget + local powermenu = wibox.widget { + layout = wibox.layout.align.vertical, + expand = "none", + nil, + { + { + nil, + { + { + nil, + { + nil, + { + profile_picture, + margins = dpi(0), + widget = wibox.container.margin + }, + nil, + expand = "none", + layout = wibox.layout.align.horizontal + }, + nil, + layout = wibox.layout.align.vertical, + expand = "none" + }, + spacing = dpi(50), + { + profile_name, + margins = dpi(0), + widget = wibox.container.margin + }, + layout = wibox.layout.fixed.vertical + }, + nil, + expand = "none", + layout = wibox.layout.align.horizontal + }, + { + nil, + { + { + shutdown_button, + reboot_button, + logout_button, + lock_button, + suspend_button, + spacing = dpi(30), + layout = wibox.layout.fixed.horizontal + }, + margins = dpi(0), + widget = wibox.container.margin + }, + nil, + expand = "none", + layout = wibox.layout.align.horizontal + }, + layout = wibox.layout.align.vertical + }, + nil + } + + -- Container for the widget, covers the entire screen + local powermenu_container = wibox { + widget = powermenu, + screen = s, + type = "splash", + visible = false, + ontop = true, + bg = "#21212188", + height = s.geometry.height, + width = s.geometry.width, + x = s.geometry.x, + y = s.geometry.y + } + + -- Close on rightclick + powermenu_container:buttons( + gears.table.join( + awful.button( + {}, + 3, + function() + awesome.emit_signal("module::powermenu:hide") + end + ) + ) + ) + + -- Close on Escape + local powermenu_keygrabber = awful.keygrabber { + autostart = false, + stop_event = 'release', + keypressed_callback = function(self, mod, key, command) + if key == 'Escape' then + awesome.emit_signal("module::powermenu:hide") + end + end + } + + -- Signals + awesome.connect_signal( + "module::powermenu:show", + function() + if s == mouse.screen then + powermenu_container.visible = true + powermenu_keygrabber:start() + end + end + ) + + awesome.connect_signal( + "module::powermenu:hide", + function() + powermenu_keygrabber:stop() + powermenu_container.visible = false + end + ) +end diff --git a/src/modules/titlebar.lua b/src/modules/titlebar.lua new file mode 100644 index 0000000..c69f4cc --- /dev/null +++ b/src/modules/titlebar.lua @@ -0,0 +1,252 @@ +----------------------------------- +-- This is the titlebar module -- +----------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/titlebar/" + +awful.titlebar.enable_tooltip = true +awful.titlebar.fallback_name = 'Client' + +local double_click_event_handler = function(double_click_event) + if double_click_timer then + double_click_timer:stop() + double_click_timer = nil + double_click_event() + return + end + double_click_timer = gears.timer.start_new( + 0.20, + function() + double_click_timer = nil + return false + end + ) +end + +local create_click_events = function(c) + local buttons = gears.table.join( + awful.button( + {}, + 1, + function() + double_click_event_handler(function() + if c.floating then + c.float = false + return + end + c.maximized = not c.maximized + c:raise() + end) + c:activate { context = 'titlebar', action = 'mouse_move' } + end + ), + awful.button( + {}, + 3, + function() + c:activate { context = 'titlebar', action = 'mouse_resize' } + end + ) + ) + return buttons +end + +local create_titlebar = function(c, bg, size) + local titlebar = awful.titlebar(c, { + position = "left", + bg = bg, + size = size + }) + + titlebar:setup { + { + { + { + awful.titlebar.widget.closebutton(c), + widget = wibox.container.background, + bg = color["Red200"], + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, 4) + end, + id = "closebutton" + }, + { + awful.titlebar.widget.maximizedbutton(c), + widget = wibox.container.background, + bg = color["Yellow200"], + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, 4) + end, + id = "maximizebutton" + }, + { + awful.titlebar.widget.minimizebutton(c), + widget = wibox.container.background, + bg = color["Green200"], + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, 4) + end, + id = "minimizebutton" + }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical, + id = "spacing" + }, + margins = dpi(8), + widget = wibox.container.margin, + id = "margin" + }, + { + buttons = create_click_events(c), + layout = wibox.layout.flex.vertical + }, + { + { + widget = awful.widget.clienticon(c) + }, + margins = dpi(5), + widget = wibox.container.margin + }, + layout = wibox.layout.align.vertical, + id = "main" + } + Hover_signal(titlebar.main.margin.spacing.closebutton, color["Red200"], color["Grey900"]) + Hover_signal(titlebar.main.margin.spacing.maximizebutton, color["Yellow200"], color["Grey900"]) + Hover_signal(titlebar.main.margin.spacing.minimizebutton, color["Green200"], color["Grey900"]) +end + +local create_titlebar_dialog = function(c, bg, size) + local titlebar = awful.titlebar(c, { + position = "left", + bg = bg, + size = size + }) + + titlebar:setup { + { + { + { + awful.titlebar.widget.closebutton(c), + widget = wibox.container.background, + bg = color["Red200"], + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, 4) + end, + id = "closebutton" + }, + { + awful.titlebar.widget.minimizebutton(c), + widget = wibox.container.background, + bg = color["Green200"], + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, 4) + end, + id = "minimizebutton" + }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical, + id = "spacing" + }, + margins = dpi(8), + widget = wibox.container.margin, + id = "margin" + }, + { + buttons = create_click_events(c), + layout = wibox.layout.flex.vertical + }, + { + { + widget = awful.widget.clienticon(c) + }, + margins = dpi(5), + widget = wibox.container.margin + }, + layout = wibox.layout.align.vertical, + id = "main" + } + Hover_signal(titlebar.main.margin.spacing.closebutton, color["Red200"], color["Grey900"]) + Hover_signal(titlebar.main.margin.spacing.minimizebutton, color["Green200"], color["Grey900"]) +end + +local draw_titlebar = function(c) + if c.type == 'normal' and not c.requests_no_titlebar then + if string.find(c.class, 'Firefox') then + create_titlebar(c, '#121212AA', 35) + elseif c.name == "Steam" then + create_titlebar(c, '#121212AA', 0) + elseif c.name == "Settings" then + create_titlebar(c, '#121212AA', 0) + elseif c.class == "gcr-prompter" or c.class == "Gcr-prompter" then + create_titlebar(c, '#121212AA', 0) + else + create_titlebar(c, '#121212AA', 35) + end + elseif c.type == 'dialog' then + create_titlebar_dialog(c, '#121212AA', 35) + end +end + +client.connect_signal( + "property::maximized", + function(c) + if c.maximized then + Theme.titlebar_maximized_button_normal = icondir .. "unmaximize.svg" + Theme.titlebar_maximized_button_active = icondir .. "unmaximize.svg" + Theme.titlebar_maximized_button_inactive = icondir .. "unmaximize.svg" + elseif not c.minimized then + Theme.titlebar_maximized_button_normal = icondir .. "maximize.svg" + Theme.titlebar_maximized_button_active = icondir .. "maximize.svg" + Theme.titlebar_maximized_button_inactive = icondir .. "maximize.svg" + end + end +) + +client.connect_signal( + "request::titlebars", + function(c) + if c.maximized then + Theme.titlebar_maximized_button_normal = icondir .. "unmaximize.svg" + Theme.titlebar_maximized_button_active = icondir .. "unmaximize.svg" + Theme.titlebar_maximized_button_inactive = icondir .. "unmaximize.svg" + draw_titlebar(c) + elseif not c.minimized then + Theme.titlebar_maximized_button_normal = icondir .. "maximize.svg" + Theme.titlebar_maximized_button_active = icondir .. "maximize.svg" + Theme.titlebar_maximized_button_inactive = icondir .. "maximize.svg" + draw_titlebar(c) + end + if not c.floating or c.maximized then + awful.titlebar.hide(c, 'left') + awful.titlebar.hide(c, 'right') + awful.titlebar.hide(c, 'top') + awful.titlebar.hide(c, 'bottom') + end + end +) + +client.connect_signal( + 'property::floating', + function(c) + if c.floating or (c.floating and c.maximized) then + awful.titlebar.show(c, 'left') + awful.titlebar.hide(c, 'right') + awful.titlebar.hide(c, 'top') + awful.titlebar.hide(c, 'bottom') + else + awful.titlebar.hide(c, 'left') + awful.titlebar.hide(c, 'right') + awful.titlebar.hide(c, 'top') + awful.titlebar.hide(c, 'bottom') + end + end +) diff --git a/src/modules/volume_controller.lua b/src/modules/volume_controller.lua new file mode 100644 index 0000000..a2b7cdb --- /dev/null +++ b/src/modules/volume_controller.lua @@ -0,0 +1,854 @@ +----------------------------------- +-- This is the volume controller -- +----------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local naughty = require("naughty") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/audio/" + +-- Returns the volume controller +return function(s) + + -- Function to create source/sink devices + local function create_device(name, node, sink) + local device = wibox.widget { + { + { + { + { + image = "", + id = "icon", + resize = false, + widget = wibox.widget.imagebox + }, + { + text = name, + id = "node", + widget = wibox.widget.textbox + }, + id = "device_layout", + layout = wibox.layout.align.horizontal + }, + id = "device_margin", + margins = dpi(5), + widget = wibox.container.margin + }, + id = "background", + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background + }, + margins = dpi(5), + widget = wibox.container.margin + } + + if sink == true then + device:connect_signal( + "button::press", + function() + awful.spawn.spawn("./.config/awesome/src/scripts/vol.sh set_sink " .. node) + + awesome.emit_signal("update::background:vol", node) + end + ) + + --#region Signal Functions + local old_wibox, old_cursor, old_bg, old_fg + local bg = "" + local fg = "" + local mouse_enter = function() + if bg then + old_bg = device.background.bg + device.background.bg = bg .. 'dd' + end + if fg then + old_fg = device.background.fg + device.background.fg = fg + end + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = "hand1" + end + end + + local button_press = function() + if bg then + if bg then + if string.len(bg) == 7 then + device.background.bg = bg .. 'bb' + else + device.background.bg = bg + end + end + end + if fg then + device.background.fg = fg + end + end + + local button_release = function() + if bg then + if bg then + if string.len(bg) == 7 then + device.background.bg = bg .. 'dd' + else + device.background.bg = bg + end + end + end + if fg then + device.background.fg = fg + end + end + + local mouse_leave = function() + if bg then + device.background.bg = old_bg + end + if fg then + device.background.fg = old_fg + end + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + + device:connect_signal( + "mouse::enter", + mouse_enter + ) + + device:connect_signal( + "button::press", + button_press + ) + + device:connect_signal( + "button::release", + button_release + ) + + device:connect_signal( + "mouse::leave", + mouse_leave + ) + --#endregion + + awesome.connect_signal( + "update::background:vol", + function(new_node) + if node == new_node then + old_bg = color["Purple200"] + old_fg = color["Grey900"] + bg = color["Purple200"] + fg = color["Grey900"] + device.background:set_bg(color["Purple200"]) + device.background:set_fg(color["Grey900"]) + else + fg = color["Purple200"] + bg = color["Grey700"] + device.background:set_fg(color["Purple200"]) + device.background:set_bg(color["Grey700"]) + end + end + ) + awful.spawn.easy_async_with_shell( + [[ pactl get-default-sink ]], + function(stdout) + local node_active = stdout:gsub("\n", "") + if node == node_active then + bg = color["Purple200"] + fg = color["Grey900"] + device.background:set_bg(color["Purple200"]) + device.background:set_fg(color["Grey900"]) + else + fg = color["Purple200"] + bg = color["Grey700"] + device.background:set_fg(color["Purple200"]) + device.background:set_bg(color["Grey700"]) + end + end + ) + else + + device:connect_signal( + "button::press", + function() + awful.spawn.spawn("./.config/awesome/src/scripts/mic.sh set_source " .. node) + + awesome.emit_signal("update::background:mic", node) + end + ) + + --#region Signal Functions + local old_wibox, old_cursor, old_bg, old_fg + local bg = "" + local fg = "" + local mouse_enter = function() + if bg then + old_bg = device.background.bg + device.background.bg = bg .. 'dd' + end + if fg then + old_fg = device.background.fg + device.background.fg = fg + end + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = "hand1" + end + end + + local button_press = function() + if bg then + if bg then + if string.len(bg) == 7 then + device.background.bg = bg .. 'bb' + else + device.background.bg = bg + end + end + end + if fg then + device.background.fg = fg + end + end + + local button_release = function() + if bg then + if bg then + if string.len(bg) == 7 then + device.background.bg = bg .. 'dd' + else + device.background.bg = bg + end + end + end + if fg then + device.background.fg = fg + end + end + + local mouse_leave = function() + if bg then + device.background.bg = old_bg + end + if fg then + device.background.fg = old_fg + end + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + + device:connect_signal( + "mouse::enter", + mouse_enter + ) + + device:connect_signal( + "button::press", + button_press + ) + + device:connect_signal( + "button::release", + button_release + ) + + device:connect_signal( + "mouse::leave", + mouse_leave + ) + --#endregion + + awesome.connect_signal( + "update::background:mic", + function(new_node) + if node == new_node then + old_bg = color["Blue200"] + old_fg = color["Grey900"] + bg = color["Blue200"] + fg = color["Grey900"] + device.background:set_bg(color["Blue200"]) + device.background:set_fg(color["Grey900"]) + else + fg = color["Blue200"] + bg = color["Grey700"] + device.background:set_fg(color["Blue200"]) + device.background:set_bg(color["Grey700"]) + end + end + ) + awful.spawn.easy_async_with_shell( + [[ pactl get-default-source ]], + function(stdout) + local node_active = stdout:gsub("\n", "") + if node == node_active then + bg = color["Blue200"] + fg = color["Grey900"] + device.background:set_bg(color["Blue200"]) + device.background:set_fg(color["Grey900"]) + else + fg = color["Blue200"] + bg = color["Grey700"] + device.background:set_fg(color["Blue200"]) + device.background:set_bg(color["Grey700"]) + end + end + ) + end + return device + end + + -- Container for the source devices + local dropdown_list_volume = wibox.widget { + { + { + layout = wibox.layout.fixed.vertical, + id = "volume_device_list" + }, + id = "volume_device_background", + bg = color["Grey800"], + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, 4) + end, + widget = wibox.container.background + }, + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + } + + -- Container for the sink devices + local dropdown_list_microphone = wibox.widget { + { + { + layout = wibox.layout.fixed.vertical, + id = "volume_device_list" + }, + id = "volume_device_background", + bg = color["Grey800"], + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, 4) + end, + widget = wibox.container.background + }, + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + } + + local volume_controller = wibox.widget { + { + { + -- Audio Device selector + { + { + { + { + { + resize = false, + image = gears.color.recolor_image(icondir .. "menu-down.svg", color["Purple200"]), + widget = wibox.widget.imagebox, + id = "icon" + }, + id = "center", + halign = "center", + valign = "center", + widget = wibox.container.place, + }, + { + { + text = "Output Device", + widget = wibox.widget.textbox, + id = "device_name" + }, + margins = dpi(5), + widget = wibox.container.margin + }, + id = "audio_volume", + layout = wibox.layout.fixed.horizontal + }, + id = "audio_bg", + bg = color["Grey800"], + fg = color["Purple200"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background + }, + id = "audio_selector_margin", + left = dpi(10), + right = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + { + id = "volume_list", + widget = dropdown_list_volume, + visible = false + }, + -- Microphone selector + { + { + { + { + { + resize = false, + image = gears.color.recolor_image(icondir .. "menu-down.svg", color["LightBlueA200"]), + widget = wibox.widget.imagebox, + id = "icon", + }, + id = "center", + halign = "center", + valign = "center", + widget = wibox.container.place, + }, + { + { + text = "Input Device", + widget = wibox.widget.textbox, + id = "device_name" + }, + margins = dpi(5), + widget = wibox.container.margin + }, + id = "mic_volume", + layout = wibox.layout.fixed.horizontal + }, + id = "mic_bg", + bg = color["Grey800"], + fg = color["LightBlueA200"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background + }, + id = "mic_selector_margin", + left = dpi(10), + right = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + { + id = "mic_list", + widget = dropdown_list_microphone, + visible = false + }, + -- Audio volume slider + { + { + { + resize = false, + widget = wibox.widget.imagebox, + image = gears.color.recolor_image(icondir .. "volume-high.svg", color["Purple200"]), + id = "icon", + }, + { + { + bar_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + bar_height = dpi(5), + bar_color = color["Grey800"], + bar_active_color = color["Purple200"], + handle_color = color["Purple200"], + handle_shape = gears.shape.circle, + handle_border_color = color["Purple200"], + handle_width = dpi(15), + maximum = 100, + forced_height = dpi(26), + widget = wibox.widget.slider, + id = "slider" + }, + bottom = dpi(12), + left = dpi(5), + id = "slider_margin", + widget = wibox.container.margin + }, + id = "audio_volume", + layout = wibox.layout.align.horizontal + }, + id = "audio_volume_margin", + top = dpi(10), + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + }, + -- Microphone volume slider + { + { + { + resize = false, + widget = wibox.widget.imagebox, + image = gears.color.recolor_image(icondir .. "microphone.svg", color["Blue200"]), + id = "icon" + }, + { + { + bar_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + bar_height = dpi(5), + bar_color = color["Grey800"], + bar_active_color = color["Blue200"], + handle_color = color["Blue200"], + handle_shape = gears.shape.circle, + handle_border_color = color["Blue200"], + handle_width = dpi(15), + maximum = 100, + forced_height = dpi(26), + widget = wibox.widget.slider, + id = "slider" + }, + left = dpi(5), + id = "slider_margin", + widget = wibox.container.margin + }, + id = "mic_volume", + layout = wibox.layout.align.horizontal + }, + id = "mic_volume_margin", + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + }, + id = "controller_layout", + layout = wibox.layout.fixed.vertical + }, + id = "controller_margin", + margins = dpi(10), + widget = wibox.container.margin + }, + bg = color["Grey900"], + border_color = color["Grey800"], + border_width = dpi(4), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 12) + end, + forced_width = dpi(400), + widget = wibox.container.background + } + + -- Variables for easier access and better readability + local audio_selector_margin = volume_controller:get_children_by_id("audio_selector_margin")[1] + local volume_list = volume_controller:get_children_by_id("volume_list")[1] + local audio_bg = volume_controller:get_children_by_id("audio_bg")[1] + local audio_volume = volume_controller:get_children_by_id("audio_volume")[1].center + + -- Click event for the audio dropdown + audio_selector_margin:connect_signal( + "button::press", + function() + volume_list.visible = not volume_list.visible + if volume_list.visible then + audio_bg.shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, 4) + end + audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg", color["Teal200"])) + else + audio_bg.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end + audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg", color["Teal200"])) + end + end + ) + + -- Variables for easier access and better readability + local mic_selector_margin = volume_controller:get_children_by_id("mic_selector_margin")[1] + local mic_list = volume_controller:get_children_by_id("mic_list")[1] + local mic_bg = volume_controller:get_children_by_id("mic_bg")[1] + local mic_volume = volume_controller:get_children_by_id("mic_volume")[1].center + + -- Click event for the microphone dropdown + mic_selector_margin:connect_signal( + "button::press", + function() + mic_list.visible = not mic_list.visible + if mic_list.visible then + mic_selector_margin.mic_bg.shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, 4) + end + mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg", color["Teal200"])) + else + mic_bg.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end + mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg", color["Teal200"])) + end + end + ) + + local audio_slider_margin = volume_controller:get_children_by_id("audio_volume_margin")[1].audio_volume.slider_margin.slider + + -- Volume slider change event + audio_slider_margin:connect_signal( + "property::value", + function() + local volume = audio_slider_margin.value + awful.spawn("pactl set-sink-volume @DEFAULT_SINK@ " .. tonumber(volume) .. "%") + end + ) + + local mic_slider_margin = volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider + + -- Microphone slider change event + mic_slider_margin:connect_signal( + "property::value", + function() + local volume = mic_slider_margin.value + awful.spawn("pactl set-source-volume @DEFAULT_SOURCE@ " .. tonumber(volume) .. "%") + awesome.emit_signal("get::mic_volume", volume) + end + ) + + -- Main container + local volume_controller_container = awful.popup { + widget = wibox.container.background, + ontop = true, + bg = color["Grey900"], + stretch = false, + visible = false, + screen = s, + placement = function(c) awful.placement.align(c, { position = "top_right", margins = { right = dpi(305), top = dpi(60) } }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 12) + end + } + + -- Get all source devices + local function get_source_devices() + awful.spawn.easy_async_with_shell( + [[ pactl list sinks | grep -E 'node.name|alsa.card_name' | awk '{gsub(/"/, ""); for(i = 3;i < NF;i++) printf $i " "; print $NF}' ]], + + function(stdout) + local i, j = 1, 1 + local device_list = { layout = wibox.layout.fixed.vertical } + + local node_names, alsa_names = {}, {} + for node_name in stdout:gmatch("[^\n]+") do + if (i % 2) == 0 then + table.insert(node_names, node_name) + end + i = i + 1 + end + + for alsa_name in stdout:gmatch("[^\n]+") do + if (j % 2) == 1 then + table.insert(alsa_names, alsa_name) + end + j = j + 1 + end + + for k = 1, #alsa_names, 1 do + device_list[#device_list + 1] = create_device(alsa_names[k], node_names[k], true) + end + dropdown_list_volume.volume_device_background.volume_device_list.children = device_list + end + ) + end + + get_source_devices() + + -- Get all input devices + local function get_input_devices() + awful.spawn.easy_async_with_shell( + [[ pactl list sources | grep -E "node.name|alsa.card_name" | awk '{gsub(/"/, ""); for(i = 3;i < NF;i++) printf $i " "; print $NF}' ]], + + function(stdout) + local i, j = 1, 1 + local device_list = { layout = wibox.layout.fixed.vertical } + + local node_names, alsa_names = {}, {} + for node_name in stdout:gmatch("[^\n]+") do + if (i % 2) == 0 then + table.insert(node_names, node_name) + end + i = i + 1 + end + + for alsa_name in stdout:gmatch("[^\n]+") do + if (j % 2) == 1 then + table.insert(alsa_names, alsa_name) + end + j = j + 1 + end + + for k = 1, #alsa_names, 1 do + device_list[#device_list + 1] = create_device(alsa_names[k], node_names[k], false) + end + dropdown_list_microphone.volume_device_background.volume_device_list.children = device_list + end + ) + end + + get_input_devices() + + -- Event watcher, detects when device is addes/removed + awful.spawn.with_line_callback( + [[bash -c "LC_ALL=C pactl subscribe | grep --line-buffered 'on server'"]], + { + stdout = function(line) + get_input_devices() + get_source_devices() + end + } + ) + + -- Get microphone volume + local function get_mic_volume() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/mic.sh volume", + function(stdout) + local volume = stdout:gsub("%%", ""):gsub("\n", "") + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(volume)) + if volume > 0 then + volume_controller:get_children_by_id("mic_volume_margin")[1].icon:set_image(gears.color.recolor_image(icondir .. "microphone.svg", color["LightBlue200"])) + else + volume_controller:get_children_by_id("mic_volume_margin")[1].icon:set_image(gears.color.recolor_image(icondir .. "microphone-off.svg", color["LightBlue200"])) + end + end + ) + end + + get_mic_volume() + + -- Check if microphone is muted + local function get_mic_mute() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/mic.sh mute", + function(stdout) + if stdout:match("yes") then + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(0)) + volume_controller:get_children_by_id("mic_volume_margin")[1].icon:set_image(gears.color.recolor_image(icondir .. "microphone-off.svg", color["LightBlue200"])) + else + get_mic_volume() + end + end + ) + end + + get_mic_mute() + + -- When the mouse leaves the popup it stops the mousegrabber and hides the popup. + volume_controller_container:connect_signal( + "mouse::leave", + function() + mousegrabber.run( + function() + awesome.emit_signal("volume_controller::toggle", s) + mousegrabber.stop() + return true + end, + "arrow" + ) + end + ) + + volume_controller_container:connect_signal( + "mouse::enter", + function() + mousegrabber.stop() + end + ) + + -- Grabs all keys and hides popup when anything is pressed + -- TODO: Make it possible to navigate and select using the kb + local volume_controller_keygrabber = awful.keygrabber { + autostart = false, + stop_event = 'release', + keypressed_callback = function(self, mod, key, command) + awesome.emit_signal("volume_controller::toggle", s) + mousegrabber.stop() + end + } + + -- Draw the popup + volume_controller_container:setup { + volume_controller, + layout = wibox.layout.fixed.horizontal + } + + --[[ awesome.connect_signal( + "volume_controller::toggle:keygrabber", + function() + if awful.keygrabber.is_running then + volume_controller_keygrabber:stop() + else + volume_controller_keygrabber:start() + end + + end + ) ]] + + -- Set the volume and icon + awesome.connect_signal( + "get::volume", + function(volume) + volume = tonumber(volume) + local icon = icondir .. "volume" + if volume < 1 then + icon = icon .. "-mute" + + elseif volume >= 1 and volume < 34 then + icon = icon .. "-low" + elseif volume >= 34 and volume < 67 then + icon = icon .. "-medium" + elseif volume >= 67 then + icon = icon .. "-high" + end + + volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.slider_margin.slider:set_value(volume) + volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color.recolor_image(icon .. ".svg", color["Purple200"])) + end + ) + + -- Check if the volume is muted + awesome.connect_signal( + "get::volume_mute", + function(mute) + if mute then + volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "volume-mute.svg", color["Purple200"])) + end + end + ) + + -- Set the microphone volume + awesome.connect_signal( + "get::mic_volume", + function(volume) + if volume > 0 then + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "microphone.svg", color["LightBlue200"])) + else + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "microphone-off.svg", color["LightBlue200"])) + end + end + ) + + -- Toggle container visibility + awesome.connect_signal( + "volume_controller::toggle", + function(scr) + if scr == s then + volume_controller_container.visible = not volume_controller_container.visible + end + + end + ) + +end diff --git a/src/modules/volume_osd.lua b/src/modules/volume_osd.lua new file mode 100644 index 0000000..719793b --- /dev/null +++ b/src/modules/volume_osd.lua @@ -0,0 +1,254 @@ +----------------------------------- +-- This is the volume_old module -- +----------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/audio/" + +-- Returns the volume_osd +return function(s) + + local volume_osd_widget = wibox.widget { + { + { + { + { + nil, + { + nil, + { + id = "icon", + forced_height = dpi(60), + image = icondir .. "volume-high.svg", + widget = wibox.widget.imagebox + }, + nil, + expand = "none", + id = "icon_margin2", + layout = wibox.layout.align.horizontal + }, + nil, + id = "icon_margin1", + expand = "none", + layout = wibox.layout.align.vertical + }, + { + { + { + id = "label", + text = "Volume", + align = "left", + valign = "center", + widget = wibox.widget.textbox + }, + nil, + { + id = "value", + text = "0%", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "label_value_layout", + forced_height = dpi(40), + layout = wibox.layout.align.horizontal, + }, + { + { + id = "volume_slider", + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(10), + bar_color = color["Grey800"] .. "88", + bar_active_color = "#ffffff", + handle_color = "#ffffff", + handle_shape = gears.shape.circle, + handle_width = dpi(10), + handle_border_color = color["White"], + maximum = 100, + widget = wibox.widget.slider + }, + id = "slider_layout", + forced_height = dpi(50), + valign = "center", + widget = wibox.container.place + }, + id = "icon_slider_layout", + spacing = dpi(0), + valign = "center", + layout = wibox.layout.align.vertical + }, + id = "icon_slider_container", + valign = "center", + layout = wibox.layout.align.horizontal + }, + id = "osd_layout", + valign = "center", + layout = wibox.layout.align.vertical + }, + id = "container", + left = dpi(8), + right = dpi(32), + valign = "center", + top = dpi(2), + widget = wibox.container.margin + }, + bg = color["Grey900"] .. '88', + widget = wibox.container.background, + ontop = true, + visible = true, + type = "notification", + forced_height = dpi(90), + forced_width = dpi(300), + valign = "center", + offset = dpi(5) + } + + local function update_osd() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/vol.sh volume", + function(stdout) + local volume_level = stdout:gsub("\n", ""):gsub("%%", "") + awesome.emit_signal("widget::volume") + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.label_value_layout.value:set_text(volume_level .. "%") + + awesome.emit_signal( + "widget::volume:update", + volume_level + ) + + if awful.screen.focused().show_volume_osd then + awesome.emit_signal( + "module::volume_osd:show", + true + ) + end + volume_level = tonumber(volume_level) + local icon = icondir .. "volume" + if volume_level < 1 then + icon = icon .. "-mute" + elseif volume_level >= 1 and volume_level < 34 then + icon = icon .. "-low" + elseif volume_level >= 34 and volume_level < 67 then + icon = icon .. "-medium" + elseif volume_level >= 67 then + icon = icon .. "-high" + end + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.icon_margin1.icon_margin2.icon:set_image(icon .. ".svg") + end + ) + end + + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.slider_layout.volume_slider:connect_signal( + "property::value", + function() + update_osd() + end + ) + + local update_slider = function() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/vol.sh mute", + function(stdout) + if stdout:match("yes") then + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.label_value_layout.value:set_text("0%") + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.icon_margin1.icon_margin2.icon:set_image(icondir .. "volume-mute" .. ".svg") + else + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/vol.sh volume", + function(stdout2) + stdout2 = stdout2:gsub("%%", ""):gsub("\n", "") + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.slider_layout.volume_slider:set_value(tonumber(stdout2)) + update_osd() + end + ) + end + end + ) + end + + -- Signals + awesome.connect_signal( + "module::slider:update", + function() + update_slider() + end + ) + + awesome.connect_signal( + "widget::volume:update", + function(value) + volume_osd_widget.container.osd_layout.icon_slider_container.icon_slider_layout.slider_layout.volume_slider:set_value(tonumber(value)) + end + ) + + update_slider() + + local volume_container = awful.popup { + widget = wibox.container.background, + ontop = true, + bg = color["Grey900"] .. "00", + stretch = false, + visible = false, + screen = s, + placement = function(c) awful.placement.centered(c, { margins = { top = dpi(700) } }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 15) + end + } + + local hide_volume_osd = gears.timer { + timeout = 2, + autostart = true, + callback = function() + volume_container.visible = false + end + } + + volume_container:setup { + volume_osd_widget, + layout = wibox.layout.fixed.horizontal + } + + awesome.connect_signal( + "module::volume_osd:show", + function() + if s == mouse.screen then + volume_container.visible = true + end + end + ) + + volume_container:connect_signal( + "mouse::enter", + function() + volume_container.visible = true + hide_volume_osd:stop() + end + ) + + volume_container:connect_signal( + "mouse::leave", + function() + volume_container.visible = true + hide_volume_osd:again() + end + ) + + awesome.connect_signal( + "widget::volume_osd:rerun", + function() + if hide_volume_osd.started then + hide_volume_osd:again() + else + hide_volume_osd:start() + end + end + ) +end diff --git a/src/scripts/bt.sh b/src/scripts/bt.sh new file mode 100755 index 0000000..d9ddf61 --- /dev/null +++ b/src/scripts/bt.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +DEVICES=$(bluetoothctl paired-devices | cut -f2 -d' '| + while read -r uuid + do + info=`bluetoothctl info $uuid` + if echo "$info" | grep -q "Connected: yes"; then + echo "$info" | head -n 1 | grep "Device" | awk '{print $2}' + fi + done) +NAMES=$(bluetoothctl paired-devices | cut -f2 -d' '| + while read -r uuid + do + info=`bluetoothctl info $uuid` + if echo "$info" | grep -q "Connected: yes"; then + echo "$info" | grep "Name" | awk '{for (i=2; i= 1 and volume < 34 then + icon = icon .. "-low" + elseif volume >= 34 and volume < 67 then + icon = icon .. "-medium" + elseif volume >= 67 then + icon = icon .. "-high" + end + audio_widget.container.audio_layout.label:set_text(volume .. "%") + audio_widget.container.audio_layout.icon_margin.icon_layout.icon:set_image( + gears.color.recolor_image(icon .. ".svg", color["Grey900"])) + awesome.emit_signal("get::volume", volume) + end + ) + end + + local check_muted = function() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/vol.sh mute", + function(stdout) + if stdout:match("yes") then + audio_widget.container.audio_layout.label.visible = false + audio_widget.container:set_right(0) + audio_widget.container.audio_layout.icon_margin.icon_layout.icon:set_image( + gears.color.recolor_image(icondir .. "volume-mute" .. ".svg", color["Grey900"])) + awesome.emit_signal("get::volume_mute", true) + else + audio_widget.container:set_right(10) + awesome.emit_signal("get::volume_mute", false) + get_volume() + end + end + ) + end + + -- Signals + Hover_signal(audio_widget, color["Yellow200"], color["Grey900"]) + + audio_widget:connect_signal( + "button::press", + function() + awesome.emit_signal("module::slider:update") + awesome.emit_signal("widget::volume_osd:rerun") + awesome.emit_signal("volume_controller::toggle", s) + awesome.emit_signal("volume_controller::toggle:keygrabber") + end + ) + + gears.timer { + timeout = 0.5, + call_now = true, + autostart = true, + callback = check_muted + } + + check_muted() + return audio_widget +end diff --git a/src/widgets/battery.lua b/src/widgets/battery.lua new file mode 100644 index 0000000..ea80907 --- /dev/null +++ b/src/widgets/battery.lua @@ -0,0 +1,204 @@ +-------------------------------- +-- This is the battery widget -- +-------------------------------- +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local naughty = require("naughty") +local watch = awful.widget.watch +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/battery/" + +-- Returns the battery widget +return function() + local battery_widget = wibox.widget { + { + { + { + { + { + id = "icon", + image = gears.color.recolor_image(icondir .. "battery-unknown.svg", "#212121"), + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + top = dpi(2), + widget = wibox.container.margin + }, + spacing = dpi(10), + { + visible = false, + align = 'center', + valign = 'center', + id = "label", + widget = wibox.widget.textbox + }, + id = "battery_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Purple200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local battery_tooltip = awful.tooltip { + objects = { battery_widget }, + text = "", + mode = "inside", + preferred_alignments = "middle", + margins = dpi(10) + } + + local get_battery_info = function() + awful.spawn.easy_async_with_shell( + [[ upower -i $(upower -e | grep BAT) | grep "time to " ]], + function(stdout) + if stdout == nil or stdout == '' then + battery_tooltip:set_text('No Battery Found') + return + end + local rem_time = "" + if stdout:match("hour") then + rem_time = "Hours" + else + rem_time = "Minutes" + end + local bat_time = stdout:match("%d+,%d") or stdout:match("%d+.%d") or "" + if stdout:match("empty") then + battery_tooltip:set_text("Remaining battery time: " .. bat_time .. " " .. rem_time) + elseif stdout:match("time to full") then + battery_tooltip:set_text("Battery fully charged in: " .. bat_time .. " " .. rem_time) + end + end + ) + end + get_battery_info() + + local last_battery_check = os.time() + local notify_critical_battery = true + + local battery_warning = function() + naughty.notification { + icon = gears.color.recolor_image(icondir .. "battery-alert.svg", color["White"]), + app_name = "System notification", + title = "Battery is low", + message = "Battery is almost empty", + urgency = "critical" + } + end + + local update_battery = function(status) + awful.spawn.easy_async_with_shell( + [[sh -c "upower -i $(upower -e | grep BAT) | grep percentage | awk '{print \$2}' |tr -d '\n%'"]], + function(stdout) + local battery_percentage = tonumber(stdout) + + if not battery_percentage then + return + end + + battery_widget.container.battery_layout.spacing = dpi(5) + battery_widget.container.battery_layout.label.visible = true + battery_widget.container.battery_layout.label:set_text(battery_percentage .. '%') + + local icon = 'battery' + + if status == 'fully-charged' or status == 'charging' and battery_percentage == 100 then + icon = icon .. '-' .. 'charging' + battery_widget.container.battery_layout.icon_margin.icon_layout.icon:set_image(gears.surface.load_uncached( + gears.color.recolor_image(icondir .. icon .. '.svg', "#212121"))) + return + end + + if battery_percentage > 0 and battery_percentage < 10 and status == 'discharging' then + icon = icon .. '-' .. 'alert' + if (os.difftime(os.time(), last_battery_check) > 300 or notify_critical_battery) then + last_battery_check = os.time() + notify_critical_battery = false + battery_warning() + end + battery_widget.container.battery_layout.icon_margin.icon_layout.icon:set_image(gears.surface.load_uncached( + gears.color.recolor_image(icondir .. icon .. '.svg', "#212121"))) + return + end + + if battery_percentage > 0 and battery_percentage < 10 then + icon = icon .. '-' .. status .. '-' .. 'outline' + elseif battery_percentage >= 10 and battery_percentage < 20 then + icon = icon .. '-' .. status .. '-' .. '10' + elseif battery_percentage >= 20 and battery_percentage < 30 then + icon = icon .. '-' .. status .. '-' .. '20' + elseif battery_percentage >= 30 and battery_percentage < 40 then + icon = icon .. '-' .. status .. '-' .. '30' + elseif battery_percentage >= 40 and battery_percentage < 50 then + icon = icon .. '-' .. status .. '-' .. '40' + elseif battery_percentage >= 50 and battery_percentage < 60 then + icon = icon .. '-' .. status .. '-' .. '50' + elseif battery_percentage >= 60 and battery_percentage < 70 then + icon = icon .. '-' .. status .. '-' .. '60' + elseif battery_percentage >= 70 and battery_percentage < 80 then + icon = icon .. '-' .. status .. '-' .. '70' + elseif battery_percentage >= 80 and battery_percentage < 90 then + icon = icon .. '-' .. status .. '-' .. '80' + elseif battery_percentage >= 90 and battery_percentage < 100 then + icon = icon .. '-' .. status .. '-' .. '90' + end + + battery_widget.container.battery_layout.icon_margin.icon_layout.icon:set_image(gears.surface.load_uncached( + gears.color.recolor_image(icondir .. icon .. '.svg', "#212121"))) + + end + ) + end + + Hover_signal(battery_widget, color["Purple200"], color["Grey900"]) + + battery_widget:connect_signal( + 'button::press', + function() + awful.spawn("xfce4-power-manager-settings") + end + ) + + battery_widget:connect_signal( + "mouse::enter", + function() + get_battery_info() + end + ) + + watch( + [[sh -c "upower -i $(upower -e | grep BAT) | grep state | awk '{print \$2}' | tr -d '\n'"]], + 5, + function(widget, stdout) + local status = stdout:gsub('%\n', '') + if status == nil or status == '' then + battery_widget.container.battery_layout.spacing = dpi(0) + battery_widget.container.battery_layout.label.visible = false + battery_tooltip:set_text('No battery found') + battery_widget.container.battery_layout.icon_margin.icon_layout.icon:set_image(gears.surface.load_uncached( + gears.color.recolor_image(icondir .. 'battery-off' .. '.svg', "#212121"))) + end + update_battery(status) + end + ) + + return battery_widget +end diff --git a/src/widgets/bluetooth.lua b/src/widgets/bluetooth.lua new file mode 100644 index 0000000..0d22343 --- /dev/null +++ b/src/widgets/bluetooth.lua @@ -0,0 +1,131 @@ +---------------------------------- +-- This is the bluetooth widget -- +---------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local naughty = require("naughty") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/bluetooth/" + +-- Returns the bluetooth widget +return function() + local bluetooth_widget = wibox.widget { + { + { + { + id = "icon", + image = gears.color.recolor_image(icondir .. "bluetooth-off.svg"), + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Blue200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local bluetooth_tooltip = awful.tooltip { + objects = { bluetooth_widget }, + text = "", + mode = "inside", + preferred_alignments = "middle", + margins = dpi(10) + } + + local bluetooth_state = "off" + local connected_device = "nothing" + + awful.widget.watch( + "rfkill list bluetooth", + 5, + function(_, stdout) + local icon = icondir .. "bluetooth" + if stdout:match('Soft blocked: yes') or stdout:gsub("\n", "") == '' then + icon = icon .. "-off" + bluetooth_state = "off" + bluetooth_tooltip:set_text("Bluetooth is turned " .. bluetooth_state .. "\n") + else + icon = icon .. "-on" + bluetooth_state = "on" + awful.spawn.easy_async_with_shell( + './.config/awesome/src/scripts/bt.sh', + function(stdout2) + if stdout2 == nil or stdout2:gsub("\n", "") == "" then + bluetooth_tooltip:set_text("Bluetooth is turned " .. bluetooth_state .. "\n" .. "You are currently not connected") + else + connected_device = stdout2:gsub("%(", ""):gsub("%)", "") + bluetooth_tooltip:set_text("Bluetooth is turned " .. bluetooth_state .. "\n" .. "You are currently connected to:\n" .. connected_device) + end + end + ) + end + bluetooth_widget.icon_margin.icon_layout.icon:set_image(gears.color.recolor_image(icon .. ".svg", color["Grey900"])) + end, + bluetooth_widget + ) + + -- Signals + Hover_signal(bluetooth_widget, color["Blue200"], color["Grey900"]) + + bluetooth_widget:connect_signal( + "button::press", + function() + awful.spawn.easy_async_with_shell( + "rfkill list bluetooth", + function(stdout) + if stdout:gsub("\n", "") ~= '' then + if bluetooth_state == "off" then + awful.spawn.easy_async_with_shell( + [[ + rfkill unblock bluetooth + sleep 1 + bluetoothctl power on + ]] , + function() + naughty.notification { + title = "System Notification", + app_name = "Bluetooth", + message = "Bluetooth activated" + } + end + ) + else + awful.spawn.easy_async_with_shell( + [[ + bluetoothctl power off + rfkill block bluetooth + ]] , + function() + naughty.notification { + title = "System Notification", + app_name = "Bluetooth", + message = "Bluetooth deactivated" + } + end + ) + end + end + end + ) + end + ) + + return bluetooth_widget +end diff --git a/src/widgets/clock.lua b/src/widgets/clock.lua new file mode 100644 index 0000000..bf9b4f5 --- /dev/null +++ b/src/widgets/clock.lua @@ -0,0 +1,64 @@ +------------------------------ +-- This is the clock widget -- +------------------------------ + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/clock/" + +-- Returns the clock widget +return function() + + local clock_widget = wibox.widget { + { + { + { + { + { + id = "icon", + image = gears.color.recolor_image(icondir .. "clock.svg", color["Grey900"]), + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + top = dpi(2), + widget = wibox.container.margin + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + format = "%H:%M", + widget = wibox.widget.textclock + }, + id = "clock_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Orange200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + Hover_signal(clock_widget, color["Orange200"], color["Grey900"]) + + return clock_widget +end diff --git a/src/widgets/cpu_info.lua b/src/widgets/cpu_info.lua new file mode 100644 index 0000000..697d874 --- /dev/null +++ b/src/widgets/cpu_info.lua @@ -0,0 +1,226 @@ +--------------------------------- +-- This is the CPU Info widget -- +--------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local watch = awful.widget.watch +local wibox = require("wibox") +require("src.core.signals") + +local icon_dir = awful.util.getdir("config") .. "src/assets/icons/cpu/" + +--TODO: Add tooltip with more CPU and per core information +return function(widget, clock_mode) + + local cpu_usage_widget = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + image = gears.color.recolor_image(icon_dir .. "cpu.svg", color["Grey900"]), + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "cpu_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Blue200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local cpu_temp = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "cpu_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Green200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local cpu_clock = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + image = icon_dir .. "cpu.svg", + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "cpu_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Purple200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local total_prev = 0 + local idle_prev = 0 + + watch( + [[ cat "/proc/stat" | grep '^cpu ' ]], + 3, + function(_, stdout) + local user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice = + stdout:match("(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s") + + local total = user + nice + system + idle + iowait + irq + softirq + steal + + local diff_idle = idle - idle_prev + local diff_total = total - total_prev + local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 + + cpu_usage_widget.container.cpu_layout.label.text = tostring(math.floor(diff_usage)) .. "%" + + total_prev = total + idle_prev = idle + collectgarbage("collect") + end + ) + + watch( + [[ bash -c "sensors | grep 'Tctl:' | awk '{print $2}'" ]], + 3, + function(_, stdout) + + local temp_icon + local temp_color + + local temp_num = tonumber(stdout:match("%d+")) + if temp_num < 50 then + temp_color = color["Green200"] + temp_icon = icon_dir .. "thermometer-low.svg" + elseif temp_num >= 50 and temp_num < 80 then + temp_color = color["Orange200"] + temp_icon = icon_dir .. "thermometer.svg" + elseif temp_num >= 80 then + temp_color = color["Red200"] + temp_icon = icon_dir .. "thermometer-high.svg" + end + Hover_signal(cpu_temp, temp_color, color["Grey900"]) + cpu_temp.container.cpu_layout.icon_margin.icon_layout.icon:set_image(temp_icon) + cpu_temp:set_bg(temp_color) + cpu_temp.container.cpu_layout.label.text = math.floor(temp_num) .. "°C" + end + ) + + watch( + [[ bash -c "cat /proc/cpuinfo | grep "MHz" | awk '{print int($4)}'" ]], + 3, + function(_, stdout) + local cpu_freq = {} + + for value in stdout:gmatch("%d+") do + table.insert(cpu_freq, value) + end + + local average = 0 + + if clock_mode == "average" then + for i = 1, #cpu_freq do + average = average + cpu_freq[i] + end + average = math.floor(average / #cpu_freq) + cpu_clock.container.cpu_layout.label.text = tonumber(average) .. "Mhz" + elseif clock_mode then + cpu_clock.container.cpu_layout.label.text = tonumber(cpu_freq[clock_mode]) .. "Mhz" + end + end + ) + + Hover_signal(cpu_usage_widget, color["Blue200"], color["Grey900"]) + Hover_signal(cpu_clock, color["Purple200"], color["Grey900"]) + + if widget == "usage" then + return cpu_usage_widget + elseif widget == "temp" then + return cpu_temp + elseif widget == "freq" then + return cpu_clock + end + +end diff --git a/src/widgets/date.lua b/src/widgets/date.lua new file mode 100644 index 0000000..5ce7037 --- /dev/null +++ b/src/widgets/date.lua @@ -0,0 +1,92 @@ +----------------------------- +-- This is the date widget -- +----------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/date/" + +-- Returns the date widget +return function() + + local date_widget = wibox.widget { + { + { + { + { + { + id = "icon", + image = gears.color.recolor_image(icondir .. "calendar.svg", color["Grey900"]), + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + top = dpi(2), + widget = wibox.container.margin + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "date_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Teal200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local set_date = function() + date_widget.container.date_layout.label:set_text(os.date("%Y-%m-%d")) + end + + -- Updates the date every minute, dont blame me if you miss silvester + gears.timer { + timeout = 60, + autostart = true, + call_now = true, + callback = function() + set_date() + end + } + + -- Signals + Hover_signal(date_widget, color["Teal200"], color["Grey900"]) + + date_widget:connect_signal( + "mouse::enter", + function() + awesome.emit_signal("widget::calendar_osd:stop", true) + end + ) + + date_widget:connect_signal( + "mouse::leave", + function() + awesome.emit_signal("widget::calendar_osd:rerun", true) + end + ) + + return date_widget +end diff --git a/src/widgets/gpu_info.lua b/src/widgets/gpu_info.lua new file mode 100644 index 0000000..7bb241a --- /dev/null +++ b/src/widgets/gpu_info.lua @@ -0,0 +1,151 @@ +--------------------------------- +-- This is the CPU Info widget -- +--------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local watch = awful.widget.watch +local wibox = require("wibox") +require("src.core.signals") + +local icon_dir = awful.util.getdir("config") .. "src/assets/icons/cpu/" + +return function(widget) + local gpu_usage_widget = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + image = gears.color.recolor_image(icon_dir .. "gpu.svg", color["Grey900"]), + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "gpu_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Green200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + Hover_signal(gpu_usage_widget, color["Green200"], color["Grey900"]) + + local gpu_temp_widget = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + image = gears.color.recolor_image(icon_dir .. "cpu.svg", color["Grey900"]), + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "gpu_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Blue200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + -- GPU Utilization + watch( + [[ bash -c "nvidia-smi -q -d UTILIZATION | grep Gpu | awk '{print $3}'"]], + 3, + function(_, stdout) + gpu_usage_widget.container.gpu_layout.label.text = stdout:gsub("\n", "") .. "%" + awesome.emit_signal("update::gpu_usage_widget", tonumber(stdout)) + end + ) + + -- GPU Temperature + watch( + [[ bash -c "nvidia-smi -q -d TEMPERATURE | grep 'GPU Current Temp' | awk '{print $5}'"]], + 3, + function(_, stdout) + + local temp_icon + local temp_color + local temp_num = tonumber(stdout) + + if temp_num then + + if temp_num < 50 then + temp_color = color["Green200"] + temp_icon = icon_dir .. "thermometer-low.svg" + elseif temp_num >= 50 and temp_num < 80 then + temp_color = color["Orange200"] + temp_icon = icon_dir .. "thermometer.svg" + elseif temp_num >= 80 then + temp_color = color["Red200"] + temp_icon = icon_dir .. "thermometer-high.svg" + end + else + temp_num = "NaN" + temp_color = color["Green200"] + temp_icon = icon_dir .. "thermometer-low.svg" + end + Hover_signal(gpu_temp_widget, temp_color, color["Grey900"]) + gpu_temp_widget.container.gpu_layout.icon_margin.icon_layout.icon:set_image(temp_icon) + gpu_temp_widget:set_bg(temp_color) + gpu_temp_widget.container.gpu_layout.label.text = tostring(temp_num) .. "°C" + awesome.emit_signal("update::gpu_temp_widget", temp_num, temp_icon) + + end + ) + + if widget == "usage" then + return gpu_usage_widget + elseif widget == "temp" then + return gpu_temp_widget + end +end diff --git a/src/widgets/kblayout.lua b/src/widgets/kblayout.lua new file mode 100644 index 0000000..428ee72 --- /dev/null +++ b/src/widgets/kblayout.lua @@ -0,0 +1,391 @@ +------------------------------ +-- This is the audio widget -- +------------------------------ + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/kblayout/" + +return function(s) + local kblayout_widget = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + resize = false, + image = gears.color.recolor_image(icondir .. "keyboard.svg", color["Grey900"]) + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "kblayout_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Green200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local function get_kblayout() + awful.spawn.easy_async_with_shell( + [[ setxkbmap -query | grep layout | awk '{print $2}' ]], + function(stdout) + local layout = stdout:gsub("\n", "") + kblayout_widget.container.kblayout_layout.label.text = layout + awesome.emit_signal("update::background:kblayout") + end + ) + end + + local function create_kb_layout_item(keymap) + -- TODO: Add more, too lazy rn + local longname, shortname + + local xkeyboard_country_code = { + { "af", "أفغانيش(Afghanistan)", "AFG" }, -- Afghanistan + { "al", "Shqip(Albania)", "ALB" }, -- Albania + { "am", "Hայերեն(Armenia)", "ARM" }, -- Armenia + { "ara", "عربي(Arab)", "ARB" }, -- Arabic + { "at", "Österreichisch (Austria)", "AUT" }, -- Austria + { "az", "Azərbaycan(Azerbaijan)", "AZE" }, -- Azerbaijan + { "ba", "Bosanski(Bosnia and Herzegovina)", "BIH" }, -- Bosnia and Herzegovina + { "bd", "", "BGD" }, -- Bangladesh + { "be", "", "BEL" }, -- Belgium + { "bg", "", "BGR" }, -- Bulgaria + { "br", "", "BRA" }, -- Brazil + { "bt", "", "BTN" }, -- Bhutan + { "bw", "", "BWA" }, -- Botswana + { "by", "", "BLR" }, -- Belarus + { "ca", "", "CAN" }, -- Canada + { "cd", "", "COD" }, -- Congo + { "ch", "", "CHE" }, -- Switzerland + { "cm", "", "CMR" }, -- Cameroon + { "cn", "", "CHN" }, -- China + { "cz", "", "CZE" }, -- Czechia + { "de", "Deutsch (Germany)", "GER" }, -- Germany + { "dk", "", "DNK" }, -- Denmark + { "ee", "", "EST" }, -- Estonia + { "es", "", "ESP" }, -- Spain + { "et", "", "ETH" }, -- Ethiopia + { "eu", "?", "?" }, -- EurKey + { "fi", "", "FIN" }, -- Finland + { "fo", "", "FRO" }, -- Faroe Islands + { "fr", "", "FRA" }, -- France + { "gb", "English (Bri'ish)", "ENG" }, -- United Kingdom + { "ge", "", "GEO" }, -- Georgia + { "gh", "", "GHA" }, -- Ghana + { "gn", "", "GIN" }, -- Guinea + { "gr", "", "GRC" }, -- Greece + { "hr", "", "HRV" }, -- Croatia + { "hu", "", "HUN" }, -- Hungary + { "ie", "", "IRL" }, -- Ireland + { "il", "", "ISR" }, -- Israel + { "in", "", "IND" }, -- India + { "iq", "", "IRQ" }, -- Iraq + { "ir", "", "IRN" }, -- Iran + { "is", "", "ISL" }, -- Iceland + { "it", "", "ITA" }, -- Italy + { "jp", "", "JPN" }, -- Japan + { "ke", "", "KEN" }, -- Kenya + { "kg", "", "KGZ" }, -- Kyrgyzstan + { "kh", "", "KHM" }, -- Cambodia + { "kr", "", "KOR" }, -- Korea + { "kz", "", "KAZ" }, -- Kazakhstan + { "la", "", "LAO" }, -- Laos + { "latam", "?", "?" }, -- Latin America + { "latin", "?", "?" }, -- Latin + { "lk", "", "LKA" }, -- Sri Lanka + { "lt", "", "LTU" }, -- Lithuania + { "lv", "", "LVA" }, -- Latvia + { "ma", "", "MAR" }, -- Morocco + { "mao", "?", "?" }, -- Maori + { "me", "", "MNE" }, -- Montenegro + { "mk", "", "MKD" }, -- Macedonia + { "ml", "", "MLI" }, -- Mali + { "mm", "", "MMR" }, -- Myanmar + { "mn", "", "MNG" }, -- Mongolia + { "mt", "", "MLT" }, -- Malta + { "mv", "", "MDV" }, -- Maldives + { "ng", "", "NGA" }, -- Nigeria + { "nl", "", "NLD" }, -- Netherlands + { "no", "", "NOR" }, -- Norway + { "np", "", "NRL" }, -- Nepal + { "ph", "", "PHL" }, -- Philippines + { "pk", "", "PAK" }, -- Pakistan + { "pl", "", "POL" }, -- Poland + { "pt", "", "PRT" }, -- Portugal + { "ro", "", "ROU" }, -- Romania + { "rs", "", "SRB" }, -- Serbia + { "ru", "Русский (Russia)", "RUS" }, -- Russia + { "se", "", "SWE" }, -- Sweden + { "si", "", "SVN" }, -- Slovenia + { "sk", "", "SVK" }, -- Slovakia + { "sn", "", "SEN" }, -- Senegal + { "sy", "", "SYR" }, -- Syria + { "th", "", "THA" }, -- Thailand + { "tj", "", "TJK" }, -- Tajikistan + { "tm", "", "TKM" }, -- Turkmenistan + { "tr", "", "TUR" }, -- Turkey + { "tw", "", "TWN" }, -- Taiwan + { "tz", "", "TZA" }, -- Tanzania + { "ua", "", "UKR" }, -- Ukraine + { "us", "English (United States)", "USA" }, -- USA + { "uz", "", "UZB" }, -- Uzbekistan + { "vn", "", "VNM" }, -- Vietnam + { "za", "", "ZAF" } -- South Africa + } + + for _, c in ipairs(xkeyboard_country_code) do + if c[1] == keymap then + longname = c[2] + shortname = c[3] + end + end + + local kb_layout_item = wibox.widget { + { + { + -- Short name e.g. GER, ENG, RUS + { + { + text = shortname, + widget = wibox.widget.textbox, + font = user_vars.font.extrabold, + id = "shortname" + }, + fg = color["Red200"], + widget = wibox.container.background, + id = "background2" + }, + { + { + text = longname, + widget = wibox.widget.textbox, + font = user_vars.font.bold, + id = "longname", + }, + fg = color["Purple200"], + widget = wibox.container.background, + id = "background1" + }, + spacing = dpi(15), + layout = wibox.layout.fixed.horizontal, + id = "container" + }, + margins = dpi(10), + widget = wibox.container.margin, + id = "margin" + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 8) + end, + bg = color["Grey800"], + fg = color["White"], + widget = wibox.container.background, + id = "background", + keymap = keymap + } + + -- TODO: Hover effects, this is more pain than I'm willing to take for now + awesome.connect_signal( + "update::background:kblayout", + function() + awful.spawn.easy_async_with_shell( + [[ setxkbmap -query | grep layout | awk '{print $2}' ]], + function(stdout) + local layout = stdout:gsub("\n", "") + if kb_layout_item.keymap == layout then + kb_layout_item.bg = color["DeepPurple200"] + kb_layout_item:get_children_by_id("background2")[1].fg = color["Grey900"] + kb_layout_item:get_children_by_id("background1")[1].fg = color["Grey900"] + else + kb_layout_item.bg = color["Grey800"] + kb_layout_item:get_children_by_id("background2")[1].fg = color["Red200"] + kb_layout_item:get_children_by_id("background1")[1].fg = color["Purple200"] + end + end + ) + end + ) + + get_kblayout() + + kb_layout_item:connect_signal( + "button::press", + function() + awful.spawn.easy_async_with_shell( + "setxkbmap " .. keymap, + function() + awesome.emit_signal("kblayout::hide:kbmenu") + mousegrabber.stop() + get_kblayout() + end + ) + end + ) + return kb_layout_item + end + + local function get_kblist() + local kb_layout_items = { + layout = wibox.layout.fixed.vertical, + spacing = dpi(10) + } + for i, keymap in pairs(user_vars.kblayout) do + kb_layout_items[i] = create_kb_layout_item(keymap) + end + local cont = { + { + kb_layout_items, + margins = dpi(10), + widget = wibox.container.margin + }, + layout = wibox.layout.fixed.vertical, + } + return cont + end + + local kb_menu_widget = awful.popup { + screen = s, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 12) + end, + widget = wibox.container.background, + bg = color["Grey900"], + fg = color["White"], + border_width = dpi(4), + border_color = color["Grey800"], + width = dpi(100), + max_height = dpi(600), + visible = false, + ontop = true, + placement = function(c) awful.placement.align(c, { position = "top_right", margins = { right = dpi(255), top = dpi(60) } }) end + } + + kb_menu_widget:connect_signal( + "mouse::leave", + function() + mousegrabber.run( + function() + kblayout_widget.bg = color["Green200"] + awesome.emit_signal("kblayout::hide:kbmenu") + mousegrabber.stop() + return true + end, + "arrow" + ) + end + ) + + kb_menu_widget:connect_signal( + "mouse::enter", + function() + mousegrabber.stop() + end + ) + + kb_menu_widget:setup( + get_kblist() + ) + + local function toggle_kb_layout() + awful.spawn.easy_async_with_shell( + "setxkbmap -query | grep layout: | awk '{print $2}'", + function(stdout) + for j, n in ipairs(user_vars.kblayout) do + if stdout:match(n) then + if j == #user_vars.kblayout then + awful.spawn.easy_async_with_shell( + "setxkbmap " .. user_vars.kblayout[1], + function() + get_kblayout() + end + ) + else + awful.spawn.easy_async_with_shell( + "setxkbmap " .. user_vars.kblayout[j + 1], + function() + get_kblayout() + end + ) + end + end + end + end + ) + end + + awesome.connect_signal( + "kblayout::toggle", + function() + toggle_kb_layout() + end + ) + + -- Signals + Hover_signal(kblayout_widget, color["Green200"], color["Grey900"]) + + local kblayout_keygrabber = awful.keygrabber { + autostart = false, + stop_event = 'release', + keypressed_callback = function(self, mod, key, command) + awesome.emit_signal("kblayout::hide:kbmenu") + mousegrabber.stop() + end + } + + kblayout_widget:connect_signal( + "button::press", + function() + mousegrabber.stop() + if kb_menu_widget.visible then + kb_menu_widget.visible = false + kblayout_keygrabber:stop() + else + kb_menu_widget.visible = true + kblayout_keygrabber:start() + end + end + ) + + awesome.connect_signal( + "kblayout::hide:kbmenu", + function() + kb_menu_widget.visible = false + kblayout_keygrabber:stop() + end + ) + + get_kblayout() + kb_menu_widget.visible = false + return kblayout_widget +end diff --git a/src/widgets/layout_list.lua b/src/widgets/layout_list.lua new file mode 100644 index 0000000..7f8d5ca --- /dev/null +++ b/src/widgets/layout_list.lua @@ -0,0 +1,48 @@ +---------------------------------- +-- This is the layoutbox widget -- +---------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Returns the layoutbox widget +return function(s) + local layout = wibox.widget { + { + { + awful.widget.layoutbox { + screen = s + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + left = dpi(5), + right = dpi(5), + forced_width = dpi(40), + widget = wibox.container.margin + }, + bg = color["LightBlue200"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + -- Signals + Hover_signal(layout, color["LightBlue200"], color["Grey900"]) + + layout:connect_signal( + "button::press", + function() + awful.layout.inc(-1) + end + ) + + return layout +end diff --git a/src/widgets/network.lua b/src/widgets/network.lua new file mode 100644 index 0000000..60f2db3 --- /dev/null +++ b/src/widgets/network.lua @@ -0,0 +1,337 @@ +-------------------------------- +-- This is the network widget -- +-------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local naughty = require("naughty") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/network/" + +-- Insert your interfaces here, get the from ip a +local interfaces = { + wlan_interface = user_vars.network.wlan, + lan_interface = user_vars.network.ethernet +} + +local network_mode = nil + +-- Returns the network widget +return function() + local startup = true + local reconnect_startup = true + local wifi_strength + local network_widget = wibox.widget { + { + { + { + { + { + id = 'icon', + image = gears.color.recolor_image(icondir .. "no-internet" .. ".svg", color["Grey900"]), + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + top = dpi(2), + widget = wibox.container.margin + }, + spacing = dpi(10), + { + id = "label", + visible = false, + valign = "center", + align = "center", + widget = wibox.widget.textbox + }, + id = "network_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Red200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local network_tooltip = awful.tooltip { + text = "Loading", + objects = { network_widget }, + mode = "inside", + preferred_alignments = "middle", + margins = dpi(10) + } + + local check_for_internet = [=[ + status_ping=0 + packets="$(ping -q -w2 -c2 1.1.1.1 | grep -o "100% packet loss")" + if [ ! -z "${packets}" ]; + then + status_ping=0 + else + status_ping=1 + fi + if [ $status_ping -eq 0 ]; + then + echo "Connected but no internet" + fi + ]=] + + local update_startup = function() + if startup then + startup = false + end + end + + local update_reconnect_startup = function(status) + reconnect_startup = status + end + + local update_tooltip = function(message) + network_tooltip:set_markup(message) + end + + local network_notify = function(message, title, app_name, icon) + naughty.notification { + text = message, + title = title, + app_name = app_name, + icon = gears.color.recolor_image(icon, color["White"]), + timeout = 3 + } + end + + local update_wireless = function() + network_mode = "wireless" + + local notify_connected = function(essid) + local message = "You are now connected to " .. essid + local title = "Connection successfull" + local app_name = "System Notification" + local icon = icondir .. "wifi-strength-4.svg" + network_notify(message, title, app_name, icon) + end + + local update_wireless_data = function(healthy) + awful.spawn.easy_async_with_shell( + [[ iw dev ]] .. interfaces.wlan_interface .. [[ link ]], + function(stdout) + local essid = stdout:match("SSID: (.-)\n") or "N/A" + local bitrate = stdout:match("tx bitrate: (.+/s)") or "N/A" + local message = "Connected to " .. essid .. "\nSignal strength " .. tostring(wifi_strength) .. "%\n" .. "Bit rate " .. tostring(bitrate) .. "" + + if healthy then + update_tooltip(message) + else + update_tooltip("You are connected but have no internet" .. message) + end + + if reconnect_startup or startup then + notify_connected(essid) + update_reconnect_startup(false) + end + end + ) + end + + local update_wireless_icon = function(strength) + awful.spawn.easy_async_with_shell( + check_for_internet, + function(stdout) + local icon = "wifi-strength" + if not stdout:match("Connected but no internet") then + if startup or reconnect_startup then + awesome.emit_signal("system::network_connected") + end + icon = icon .. '-' .. tostring(strength) + update_wireless_data(true) + else + icon = icon .. "-" .. tostring(strength) + update_wireless_data(false) + end + network_widget.container.network_layout.spacing = dpi(8) + network_widget.container.network_layout.icon_margin.icon_layout.icon:set_image(gears.color.recolor_image(icondir .. icon .. ".svg", color["Grey900"])) + end + ) + end + + local update_wireless_strength = function() + awful.spawn.easy_async_with_shell( + [[ awk 'NR==3 {printf "%3.0f", ($3/70)*100}' /proc/net/wireless ]], + function(stdout) + if not tonumber(stdout) then + return + end + wifi_strength = tonumber(stdout) + network_widget.container.network_layout.spacing = dpi(8) + network_widget.container.network_layout.label.visible = true + network_widget.container.network_layout.label:set_text(tostring(wifi_strength .. "%")) + local wifi_strength_rounded = math.floor(wifi_strength / 25 + 0.5) + update_wireless_icon(wifi_strength_rounded) + end + ) + end + + update_wireless_strength() + update_startup() + end + + local update_wired = function() + network_mode = "wired" + + local notify_connected = function() + local message = "You are now connected to " .. interfaces.lan_interface + local title = "Connection successfull" + local app_name = "System Notification" + local icon = icondir .. "ethernet.svg" + network_notify(message, title, app_name, icon) + end + + awful.spawn.easy_async_with_shell( + check_for_internet, + function(stdout) + local icon = "ethernet" + + if stdout:match("Connected but no internet") then + icon = "no-internet" + update_tooltip( + "No internet" + ) + else + update_tooltip("You are connected to:\nEthernet Interface " .. interfaces.lan_interface .. "") + if startup or reconnect_startup then + awesome.emit_signal("system::network_connected") + notify_connected() + update_startup() + end + update_reconnect_startup(false) + end + network_widget.container.network_layout.label.visible = false + network_widget.container.network_layout.spacing = dpi(0) + network_widget.container.network_layout.icon_margin.icon_layout.icon:set_image(icondir .. icon .. ".svg") + end + ) + + end + + local update_disconnected = function() + local notify_wireless_disconnected = function(essid) + local message = "WiFi has been disconnected" + local title = "Connection lost" + local app_name = "System Notification" + local icon = icondir .. "wifi-strength-off-outline.svg" + network_notify(message, title, app_name, icon) + end + local notify_wired_disconnected = function(essid) + local message = "Ethernet has been unplugged" + local title = "Connection lost" + local app_name = "System Notification" + local icon = icondir .. "no-internet.svg" + network_notify(message, title, app_name, icon) + end + local icon = "wifi-strength-off-outline" + if network_mode == "wireless" then + icon = "wifi-strength-off-outline" + if not reconnect_startup then + update_reconnect_startup(true) + notify_wireless_disconnected() + end + elseif network_mode == "wired" then + icon = "no-internet" + if not reconnect_startup then + update_reconnect_startup(true) + notify_wired_disconnected() + end + end + network_widget.container.network_layout.label.visible = false + update_tooltip("Network unreachable") + network_widget.container.network_layout.spacing = dpi(0) + network_widget.container.network_layout.icon_margin.icon_layout.icon:set_image(gears.color.recolor_image(icondir .. icon .. ".svg", color["Grey900"])) + end + + local check_network_mode = function() + awful.spawn.easy_async_with_shell( + [=[ + wireless="]=] .. tostring(interfaces.wlan_interface) .. [=[" + wired="]=] .. tostring(interfaces.lan_interface) .. [=[" + net="/sys/class/net/" + wireless_state="down" + wired_state="down" + network_mode="" + function check_network_state(){ + if [[ "${wireless_state}" == "up" ]]; + then + network_mode="wireless" + elif [[ "${wired_state}" == "up" ]]; + then + network_mode="wired" + else + network_mode="No internet connected" + fi + } + function check_network_directory(){ + if [[ -n "${wireless}" && -d "${net}${wireless}" ]]; + then + wireless_state="$(cat "${net}${wireless}/operstate")" + fi + if [[ -n "${wired}" && -d "${net}${wired}" ]]; + then + wired_state="$(cat "${net}${wired}/operstate")" + fi + check_network_state + } + function print_network_mode(){ + check_network_directory + printf "${network_mode}" + } + print_network_mode + ]=], + function(stdout) + local mode = stdout:gsub("%\n", "") + if stdout:match("No internet connected") then + update_disconnected() + elseif stdout:match("wireless") then + update_wireless() + elseif stdout:match("wired") then + update_wired() + end + end + ) + end + + gears.timer { + timeout = 5, + autostart = true, + call_now = true, + callback = function() + check_network_mode() + end + } + + -- Signals + Hover_signal(network_widget, color["Red200"], color["Grey900"]) + + network_widget:connect_signal( + "button::press", + function() + awful.spawn("gnome-control-center wlan") + end + ) + + return network_widget +end diff --git a/src/widgets/power.lua b/src/widgets/power.lua new file mode 100644 index 0000000..95812ab --- /dev/null +++ b/src/widgets/power.lua @@ -0,0 +1,63 @@ +-------------------------------- +-- This is the power widget -- +-------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +require("src.core.signals") + +-- Icon directory path +local icondir = awful.util.getdir("config") .. "src/assets/icons/power/" + +return function() + + local power_widget = wibox.widget { + { + { + { + { + { + id = "icon", + image = gears.color.recolor_image(icondir .. "power.svg", color["Grey900"]), + widget = wibox.widget.imagebox, + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + id = "icon_margin", + top = dpi(2), + widget = wibox.container.margin + }, + id = "power_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Red200"], + fg = color["Grey800"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + -- Signals + Hover_signal(power_widget, color["Red200"], color["Grey900"]) + + power_widget:connect_signal( + "button::release", + function() + awesome.emit_signal("module::powermenu:show") + end + ) + + return power_widget +end diff --git a/src/widgets/ram_info.lua b/src/widgets/ram_info.lua new file mode 100644 index 0000000..09b9c2e --- /dev/null +++ b/src/widgets/ram_info.lua @@ -0,0 +1,72 @@ +--------------------------------- +-- This is the RAM Info widget -- +--------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local watch = awful.widget.watch +local wibox = require("wibox") +require("src.core.signals") + +local icon_dir = awful.util.getdir("config") .. "src/assets/icons/cpu/" + +return function() + local ram_widget = wibox.widget { + { + { + { + { + { + id = "icon", + widget = wibox.widget.imagebox, + image = gears.color.recolor_image(icon_dir .. "ram.svg", color["Grey900"]), + resize = false + }, + id = "icon_layout", + widget = wibox.container.place + }, + top = dpi(2), + widget = wibox.container.margin, + id = "icon_margin" + }, + spacing = dpi(10), + { + id = "label", + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + id = "ram_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "container", + left = dpi(8), + right = dpi(8), + widget = wibox.container.margin + }, + bg = color["Red200"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + Hover_signal(ram_widget, color["Red200"], color["Grey900"]) + + watch( + [[ bash -c "cat /proc/meminfo| grep Mem | awk '{print $2}'" ]], + 3, + function(_, stdout) + + local MemTotal, MemFree, MemAvailable = stdout:match("(%d+)\n(%d+)\n(%d+)\n") + + ram_widget.container.ram_layout.label.text = tostring(string.format("%.1f", ((MemTotal - MemAvailable) / 1024 / 1024)) .. "/" .. string.format("%.1f", (MemTotal / 1024 / 1024)) .. "GB"):gsub(",", ".") + end + ) + + return ram_widget +end diff --git a/src/widgets/systray.lua b/src/widgets/systray.lua new file mode 100644 index 0000000..95111d7 --- /dev/null +++ b/src/widgets/systray.lua @@ -0,0 +1,48 @@ +-------------------------------- +-- This is the power widget -- +-------------------------------- + +-- Awesome Libs +local awful = require("awful") +local color = require("src.theme.colors") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +require("src.core.signals") + +return function(s) + local systray = wibox.widget { + { + { + wibox.widget.systray(), + widget = wibox.container.margin, + id = 'st' + }, + strategy = "exact", + layout = wibox.container.constraint, + id = "container" + }, + widget = wibox.container.background, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + bg = color["BlueGrey800"] + } + -- Signals + Hover_signal(systray.container, color["Red200"], color["Grey900"]) + + awesome.connect_signal("systray::update", function() + local num_entries = awesome.systray() + + if num_entries == 0 then + systray.container.st:set_margins(0) + else + systray.container.st:set_margins(dpi(6)) + end + end) + + systray.container.st.widget:set_base_size(dpi(20)) + + return systray +end diff --git a/src/widgets/taglist.lua b/src/widgets/taglist.lua new file mode 100644 index 0000000..97798bd --- /dev/null +++ b/src/widgets/taglist.lua @@ -0,0 +1,220 @@ +-------------------------------- +-- This is the taglist widget -- +-------------------------------- + +-- Awesome Libs +local wibox = require("wibox") +local awful = require("awful") +local gears = require("gears") +local dpi = require("beautiful").xresources.apply_dpi +local color = require("src.theme.colors") +require("src.tools.icon_handler") + +local list_update = function(widget, buttons, label, data, objects) + widget:reset() + + for _, object in ipairs(objects) do + + local tag_widget = wibox.widget { + { + { + { + text = "", + align = "center", + valign = "center", + visible = true, + font = user_vars.font.extrabold, + forced_width = dpi(25), + id = "label", + widget = wibox.widget.textbox + }, + id = "margin", + left = dpi(5), + right = dpi(5), + widget = wibox.container.margin + }, + id = "container", + layout = wibox.layout.fixed.horizontal + }, + fg = color["White"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local function create_buttons(buttons, object) + if buttons then + local btns = {} + for _, b in ipairs(buttons) do + local btn = awful.button { + modifiers = b.modifiers, + button = b.button, + on_press = function() + b:emit_signal('press', object) + end, + on_release = function() + b:emit_signal('release', object) + end + } + btns[#btns + 1] = btn + end + return btns + end + end + + tag_widget:buttons(create_buttons(buttons, object)) + + tag_widget.container.margin.label:set_text(object.index) + if object.urgent == true then + tag_widget:set_bg(color["RedA200"]) + tag_widget:set_fg(color["Grey900"]) + elseif object == awful.screen.focused().selected_tag then + tag_widget:set_bg(color["White"]) + tag_widget:set_fg(color["Grey900"]) + else + tag_widget:set_bg("#3A475C") + end + + -- Set the icon for each client + for _, client in ipairs(object:clients()) do + tag_widget.container.margin:set_right(0) + local icon = wibox.widget { + { + id = "icon_container", + { + id = "icon", + resize = true, + widget = wibox.widget.imagebox + }, + widget = wibox.container.place + }, + forced_width = dpi(33), + margins = dpi(6), + widget = wibox.container.margin + } + icon.icon_container.icon:set_image(Get_icon(user_vars.icon_theme, client)) + tag_widget.container:setup({ + icon, + strategy = "exact", + layout = wibox.container.constraint, + }) + end + + --#region Hover_signal + local old_wibox, old_cursor, old_bg + tag_widget:connect_signal( + "mouse::enter", + function() + old_bg = tag_widget.bg + if object == awful.screen.focused().selected_tag then + tag_widget.bg = '#dddddd' .. 'dd' + else + tag_widget.bg = '#3A475C' .. 'dd' + end + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = "hand1" + end + end + ) + + tag_widget:connect_signal( + "button::press", + function() + if object == awful.screen.focused().selected_tag then + tag_widget.bg = '#bbbbbb' .. 'dd' + else + tag_widget.bg = '#3A475C' .. 'dd' + end + end + ) + + tag_widget:connect_signal( + "button::release", + function() + if object == awful.screen.focused().selected_tag then + tag_widget.bg = '#dddddd' .. 'dd' + else + tag_widget.bg = '#3A475C' .. 'dd' + end + end + ) + + tag_widget:connect_signal( + "mouse::leave", + function() + tag_widget.bg = old_bg + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + --#endregion + + widget:add(tag_widget) + widget:set_spacing(dpi(6)) + end +end + +return function(s) + return awful.widget.taglist( + s, + awful.widget.taglist.filter.noempty, + gears.table.join( + awful.button( + {}, + 1, + function(t) + t:view_only() + end + ), + awful.button( + { modkey }, + 1, + function(t) + if client.focus then + client.focus:move_to_tag(t) + end + end + ), + awful.button( + {}, + 3, + function(t) + if client.focus then + client.focus:toggle_tag(t) + end + end + ), + awful.button( + { modkey }, + 3, + function(t) + if client.focus then + client.focus:toggle_tag(t) + end + end + ), + awful.button( + {}, + 4, + function(t) + awful.tag.viewnext(t.screen) + end + ), + awful.button( + {}, + 5, + function(t) + awful.tag.viewprev(t.screen) + end + ) + ), + {}, + list_update, + wibox.layout.fixed.horizontal() + ) +end diff --git a/src/widgets/tasklist.lua b/src/widgets/tasklist.lua new file mode 100644 index 0000000..fdc219a --- /dev/null +++ b/src/widgets/tasklist.lua @@ -0,0 +1,210 @@ +--------------------------------- +-- This is the tasklist widget -- +--------------------------------- + +-- Awesome Libs +local awful = require('awful') +local wibox = require('wibox') +local dpi = require('beautiful').xresources.apply_dpi +local gears = require('gears') +local color = require('src.theme.colors') + +local list_update = function(widget, buttons, label, data, objects) + widget:reset() + for _, object in ipairs(objects) do + local task_widget = wibox.widget { + { + { + { + { + nil, + { + id = "icon", + resize = true, + widget = wibox.widget.imagebox + }, + nil, + layout = wibox.layout.align.horizontal, + id = "layout_icon" + }, + forced_width = dpi(33), + margins = dpi(3), + widget = wibox.container.margin, + id = "margin" + }, + { + text = "", + align = "center", + valign = "center", + visible = true, + widget = wibox.widget.textbox, + id = "title" + }, + layout = wibox.layout.fixed.horizontal, + id = "layout_it" + }, + right = dpi(5), + left = dpi(5), + widget = wibox.container.margin, + id = "container" + }, + bg = color["White"], + fg = color["Grey900"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 5) + end, + widget = wibox.container.background + } + + local task_tool_tip = awful.tooltip { + objects = { task_widget }, + mode = "inside", + preferred_alignments = "middle", + preferred_positions = "bottom", + margins = dpi(10), + gaps = 0, + delay_show = 1 + } + + local function create_buttons(buttons, object) + if buttons then + local btns = {} + for _, b in ipairs(buttons) do + local btn = awful.button { + modifiers = b.modifiers, + button = b.button, + on_press = function() + b:emit_signal('press', object) + end, + on_release = function() + b:emit_signal('release', object) + end + } + btns[#btns + 1] = btn + end + return btns + end + end + + task_widget:buttons(create_buttons(buttons, object)) + + local text, _ = label(object, task_widget.container.layout_it.title) + if object == client.focus then + if text == nil or text == '' then + task_widget.container.layout_it.title:set_margins(0) + else + local text_full = text:match('>(.-)<') + if text_full then + if object.class == nil then + text = object.name + else + text = object.class:sub(1, 20) + end + task_tool_tip:set_text(text_full) + task_tool_tip:add_to_object(task_widget) + else + task_tool_tip:remove_from_object(task_widget) + end + end + task_widget:set_bg(color["White"]) + task_widget:set_fg(color["Grey900"]) + task_widget.container.layout_it.title:set_text(text) + else + task_widget:set_bg("#3A475C") + task_widget.container.layout_it.title:set_text('') + end + task_widget.container.layout_it.margin.layout_icon.icon:set_image(Get_icon(user_vars.icon_theme, object)) + widget:add(task_widget) + widget:set_spacing(dpi(6)) + + --#region Hover_signal + local old_wibox, old_cursor, old_bg + task_widget:connect_signal( + "mouse::enter", + function() + old_bg = task_widget.bg + if object == client.focus then + task_widget.bg = '#dddddddd' + else + task_widget.bg = '#3A475Cdd' + end + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = "hand1" + end + end + ) + + task_widget:connect_signal( + "button::press", + function() + if object == client.focus then + task_widget.bg = "#ffffffaa" + else + task_widget.bg = '#3A475Caa' + end + end + ) + + task_widget:connect_signal( + "button::release", + function() + if object == client.focus then + task_widget.bg = "#ffffffdd" + else + task_widget.bg = '#3A475Cdd' + end + end + ) + + task_widget:connect_signal( + "mouse::leave", + function() + task_widget.bg = old_bg + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + --#endregion + + end + return widget +end + +return function(s) + return awful.widget.tasklist( + s, + awful.widget.tasklist.filter.currenttags, + awful.util.table.join( + awful.button( + {}, + 1, + function(c) + if c == client.focus then + c.minimized = true + else + c.minimized = false + if not c:isvisible() and c.first_tag then + c.first_tag:view_only() + end + c:emit_signal('request::activate') + c:raise() + end + end + ), + awful.button( + {}, + 3, + function(c) + c:kill() + end + ) + ), + {}, + list_update, + wibox.layout.fixed.horizontal() + ) +end