diff --git a/awesome/src/theme/user_variables.lua b/awesome/src/theme/user_variables.lua
index efac15f..eb5357e 100644
--- a/awesome/src/theme/user_variables.lua
+++ b/awesome/src/theme/user_variables.lua
@@ -8,11 +8,39 @@ local home = os.getenv("HOME")
-- If you want different default programs, wallpaper path or modkey; edit this file.
user_vars = {
+ -- The battery that should be displayed in the battery widget.
+ --[[
+ You can choose from one of these values (default is internal battery):
+ "UNKNOWN"
+ "LINE_POWER"
+ "TABLET"
+ "COMPUTER"
+ "GAMING_INPUT"
+ "LAST"
+ "BATTERY"
+ "UPS"
+ "MONITOR"
+ "MOUSE"
+ "KEYBOARD"
+ "PDA"
+ "PHONE"
+ "MEDIA_PLAYER"
+ More information at: https://lazka.github.io/pgi-docs/UPowerGlib-1.0/enums.html#UPowerGlib.DeviceKind.KEYBOARD
+ ]]
+ battery_kind = "BATTERY",
+
+ -- Here you can specify a battery to use. e.g. "/org/freedesktop/UPower/devices/battery_BAT0"
+ -- Default is nil (use the internal battery)
+ battery_path = nil,
+
+ -- This is opened when clicked on the battery icon, set it to whatever you like
+ energy_manager = "xfce4-power-manager-settings",
+
-- Uses the openweather api https://home.openweathermap.org/api_keys
-- City ID is also from there
weather_secrets = {
- key = "e71b00168ca7219563dde4514a425b14",
- city_id = "2864118",
+ key = "",
+ city_id = "",
unit = "metric" -- "metric" or "imperial"
},
diff --git a/awesome/src/widgets/battery.lua b/awesome/src/widgets/battery.lua
index 6ed2c55..909955e 100644
--- a/awesome/src/widgets/battery.lua
+++ b/awesome/src/widgets/battery.lua
@@ -1,21 +1,28 @@
+---@diagnostic disable: undefined-field
--------------------------------
-- 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 lgi = require("lgi")
local naughty = require("naughty")
-local watch = awful.widget.watch
+local upower_glib = lgi.require("UPowerGlib")
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()
+---Returns the battery widget
+---@return wibox.widget
+return function(battery_kind)
+
+ -- Battery wibox.widget
local battery_widget = wibox.widget {
{
{
@@ -58,145 +65,171 @@ return function()
widget = wibox.container.background
}
- local battery_tooltip = awful.tooltip {
+ -- Color change on mouse over
+ Hover_signal(battery_widget, color["Purple200"], color["Grey900"])
+
+ -- Open an energy manager on click
+ battery_widget:connect_signal(
+ 'button::press',
+ function()
+ awful.spawn(user_vars.energy_manager)
+ end
+ )
+
+ ---Gets every enery device path
+ ---@return table string battery device paths
+ local function get_device_path()
+ local paths = upower_glib.Client():get_devices()
+ local path_table = {}
+ for _, path in ipairs(paths) do
+ table.insert(path_table, path:get_object_path())
+ end
+ return path_table
+ end
+
+ ---Takes a path and returns the glib object
+ ---@param path string battery device path
+ ---@return UPowerGlib.Device battery battery device object
+ local function get_device_from_path(path)
+ local devices = upower_glib.Client():get_devices()
+
+ for _, device in ipairs(devices) do
+ if device:get_object_path() == path then
+ return device
+ end
+ end
+ end
+
+ local 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()
+ ---Sets the battery information for the widget
+ ---@param device UPowerGlib.Device battery
+ local function set_battery(device)
+ local battery_percentage = math.floor(device.percentage + 0.5)
+ local battery_status = upower_glib.DeviceState[device.state]:lower()
+ local battery_temp = device.temperature
- local last_battery_check = os.time()
- local notify_critical_battery = true
+ local battery_time = 1
+
+ if device.time_to_empty ~= 0 then
+ battery_time = device.time_to_empty
+ else
+ battery_time = device.time_to_full
+ end
+
+ battery_time = math.floor(battery_time / 3600) .. "h, " .. math.floor((battery_time / 60) % 60) .. "m"
+
+ if battery_temp == 0.0 then
+ battery_temp = "NaN"
+ else
+ battery_temp = math.floor(battery_temp + 0.5) .. "°C"
+ end
+
+ if not battery_percentage then
+ return
+ end
+
+ battery_widget:get_children_by_id("battery_layout")[1].spacing = dpi(5)
+ battery_widget:get_children_by_id("label")[1].visible = true
+ battery_widget:get_children_by_id("label")[1].text = battery_percentage .. '%'
+
+ tooltip.markup = "Battery Status: "
+ .. battery_status .. "\nRemaining time: "
+ .. battery_time .. "\nTemperature: "
+ .. battery_temp .. ""
+
+ local icon = 'battery'
+
+ if battery_status == 'fully-charged' or battery_status == 'charging' and battery_percentage == 100 then
+ icon = icon .. '-' .. 'charging.svg'
+ naughty.notification {
+ title = "Battery notification",
+ message = "Battery is fully charged",
+ icon = icondir .. icon,
+ timeout = 5
+ }
+ battery_widget:get_children_by_id("icon")[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir .. icon, "#212121"))
+ return
+ elseif battery_percentage > 0 and battery_percentage < 10 and battery_status == 'discharging' then
+ icon = icon .. '-' .. 'alert.svg'
+ naughty.notification {
+ title = "Battery warning",
+ message = "Battery is running low!\n" .. battery_percentage .. "% left",
+ urgency = "critical",
+ icon = icondir .. icon,
+ timeout = 60
+ }
+ battery_widget:get_children_by_id("icon")[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir .. icon, "#212121"))
+ return
+ end
+
+ if battery_percentage > 0 and battery_percentage < 10 then
+ icon = icon .. '-' .. battery_status .. '-' .. 'outline'
+ elseif battery_percentage >= 10 and battery_percentage < 20 then
+ icon = icon .. '-' .. battery_status .. '-' .. '10'
+ elseif battery_percentage >= 20 and battery_percentage < 30 then
+ icon = icon .. '-' .. battery_status .. '-' .. '20'
+ elseif battery_percentage >= 30 and battery_percentage < 40 then
+ icon = icon .. '-' .. battery_status .. '-' .. '30'
+ elseif battery_percentage >= 40 and battery_percentage < 50 then
+ icon = icon .. '-' .. battery_status .. '-' .. '40'
+ elseif battery_percentage >= 50 and battery_percentage < 60 then
+ icon = icon .. '-' .. battery_status .. '-' .. '50'
+ elseif battery_percentage >= 60 and battery_percentage < 70 then
+ icon = icon .. '-' .. battery_status .. '-' .. '60'
+ elseif battery_percentage >= 70 and battery_percentage < 80 then
+ icon = icon .. '-' .. battery_status .. '-' .. '70'
+ elseif battery_percentage >= 80 and battery_percentage < 90 then
+ icon = icon .. '-' .. battery_status .. '-' .. '80'
+ elseif battery_percentage >= 90 and battery_percentage < 100 then
+ icon = icon .. '-' .. battery_status .. '-' .. '90'
+ end
+
+ battery_widget:get_children_by_id("icon")[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir .. icon .. '.svg', "#212121"))
+ awesome.emit_signal("update::battery_widget", battery_percentage, icondir .. icon .. ".svg")
- 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)
+ ---This function attaches a device path to the dbus interface
+ ---It will only display on a widget if the user specified a device kind
+ ---This device will then be filtered out and sent information to the widget itself
+ ---The rest will only report in the background to other widgets e.g. Bluetooth devices
+ ---Will report to the bluetooth widget.
+ ---@param path string device path /org/freedesktop/...
+ local function attach_to_device(path)
+ local device_path = user_vars.battery_path or path or ""
- if not battery_percentage then
- return
- end
+ battery_widget.device = get_device_from_path(device_path) or upower_glib.Client():get_display_device()
- 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 .. '%')
+ battery_widget.device.on_notify = function(device)
+ battery_widget:emit_signal("upower::update", device)
+ end
- local icon = 'battery'
+ -- Check which device kind the user wants to display
+ -- If there are multiple then the first is used
+ if upower_glib.DeviceKind[battery_widget.device.kind] == battery_kind then
+ set_battery(battery_widget.device)
+ end
- 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")))
- awesome.emit_signal("update::battery_widget", battery_percentage, icondir .. icon .. ".svg")
- end
- )
+ -- The delayed call will fire every time awesome finishes its main event loop
+ gears.timer.delayed_call(battery_widget.emit_signal, battery_widget, "upower::update", battery_widget.device)
end
- Hover_signal(battery_widget, color["Purple200"], color["Grey900"])
+ for _, device in ipairs(get_device_path()) do
+ attach_to_device(device)
+ end
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")))
+ "upower::update",
+ function(widget, device)
+ if upower_glib.DeviceKind[battery_widget.device.kind] == battery_kind then
+ set_battery(device)
end
- update_battery(status)
end
)