aboutsummaryrefslogtreecommitdiffstats
path: root/modules/desktop/eww/bar
diff options
context:
space:
mode:
Diffstat (limited to 'modules/desktop/eww/bar')
-rw-r--r--modules/desktop/eww/bar/bar.nix2
-rw-r--r--modules/desktop/eww/bar/bar.yuck17
-rw-r--r--modules/desktop/eww/bar/system-stats.lua86
3 files changed, 98 insertions, 7 deletions
diff --git a/modules/desktop/eww/bar/bar.nix b/modules/desktop/eww/bar/bar.nix
index f7ef9cf..0daf7a6 100644
--- a/modules/desktop/eww/bar/bar.nix
+++ b/modules/desktop/eww/bar/bar.nix
@@ -104,6 +104,7 @@
"@@icon-ram@@"
"@@icon-audio@@"
"@@icon-calendar@@"
+ "@@icon-battery@@"
]
[
(lib.getExe niri-status)
@@ -116,6 +117,7 @@
(toString ../../../../assets/icons/bar/ram.svg)
(toString ../../../../assets/icons/bar/audio.svg)
(toString ../../../../assets/icons/bar/calendar.svg)
+ (toString ../../../../assets/icons/bar/battery.svg)
]
(builtins.readFile ./bar.yuck);
};
diff --git a/modules/desktop/eww/bar/bar.yuck b/modules/desktop/eww/bar/bar.yuck
index 2f5046d..f8f48d0 100644
--- a/modules/desktop/eww/bar/bar.yuck
+++ b/modules/desktop/eww/bar/bar.yuck
@@ -4,17 +4,16 @@
(defpoll full_date :interval "60s" "date '+%A, %d %B %Y'")
(deflisten niri_status :initial "{\"workspaces\":[],\"active_windows\":[]}" "@@niri-status-script@@")
(deflisten system_stats
- :initial "{\"cpu\":{\"percent\":0,\"per_core\":[],\"freq_mhz\":null,\"load_avg\":null,\"tooltip\":\"CPU: 0%\"},\"ram\":{\"percent\":0,\"used\":\"0B\",\"total\":\"0B\",\"available\":\"0B\",\"swap_percent\":0,\"swap_used\":\"0B\",\"swap_total\":\"0B\",\"speed_mhz\":null,\"tooltip\":\"RAM: 0%\"},\"net\":{\"status\":\"down\",\"tooltip\":\"Network Offline\",\"routes\":[]},\"sound\":{\"percent\":0,\"mute\":true,\"sink\":null,\"tooltip\":\"Volume: unknown\"}}"
+ :initial "{\"cpu\":{\"percent\":0,\"per_core\":[],\"freq_mhz\":null,\"load_avg\":null,\"tooltip\":\"CPU: 0%\"},\"ram\":{\"percent\":0,\"used\":\"0B\",\"total\":\"0B\",\"available\":\"0B\",\"swap_percent\":0,\"swap_used\":\"0B\",\"swap_total\":\"0B\",\"speed_mhz\":null,\"tooltip\":\"RAM: 0%\"},\"net\":{\"status\":\"down\",\"tooltip\":\"Network Offline\",\"routes\":[]},\"sound\":{\"percent\":0,\"mute\":true,\"sink\":null,\"tooltip\":\"Volume: unknown\"},\"battery\":{\"percent\":0,\"present\":false,\"charging\":false,\"status\":\"none\",\"tooltip\":\"No battery\"}}"
"@@system-stats-script@@")
(defwindow bar
:monitor 0
- :geometry (geometry
- :x "0px"
- :y "0px"
- :width "60px"
- :height "100%"
- :anchor "top right")
+ :geometry (geometry :x "0px"
+ :y "0px"
+ :width "60px"
+ :height "100%"
+ :anchor "top right")
:stacking "fg"
:focusable "none"
:reserve (struts :distance "60px" :side "right")
@@ -71,6 +70,10 @@
:tooltip "${system_stats.ram.tooltip}"
(image :class "system-icon" :path "@@icon-ram@@" :image-width 24 :image-height 24)
(label :class "system-label" :text "${system_stats.ram.percent}%"))
+ (box :orientation "v" :class "system-item" :space-evenly false :spacing 4
+ :tooltip "${system_stats.battery.tooltip}"
+ (image :class "system-icon" :path "@@icon-battery@@" :image-width 24 :image-height 24)
+ (label :class "system-label" :text "${system_stats.battery.present ? (system_stats.battery.percent + '%') : '-'}"))
(eventbox :onclick "pamixer --toggle-mute"
:onscroll "bash -c '[ \"{}\" = \"up\" ] && pamixer --increase 5 --unmute || pamixer --decrease 5'"
:cursor "pointer" :halign "fill"
diff --git a/modules/desktop/eww/bar/system-stats.lua b/modules/desktop/eww/bar/system-stats.lua
index c15cbdc..c7ee4fb 100644
--- a/modules/desktop/eww/bar/system-stats.lua
+++ b/modules/desktop/eww/bar/system-stats.lua
@@ -530,6 +530,84 @@ local function get_sound_state()
}
end
+-- ------------------------------------------------ battery
+local function find_battery_path()
+ local handle = io.popen("ls /sys/class/power_supply/ 2>/dev/null")
+ if not handle then
+ return nil
+ end
+ local out = handle:read("*a")
+ handle:close()
+ for name in out:gmatch("[^\n]+") do
+ if posix.stat("/sys/class/power_supply/" .. name .. "/capacity") then
+ return "/sys/class/power_supply/" .. name
+ end
+ end
+ return nil
+end
+
+local function get_battery_state(path)
+ if not path then
+ return { percent = 0, present = false, charging = false, tooltip = "No battery", status = "none" }
+ end
+
+ local function read_file(subpath)
+ local f = io.open(path .. "/" .. subpath)
+ if not f then
+ return nil
+ end
+ local s = f:read("*l")
+ f:close()
+ return s and s:match("^%s*(.-)%s*$")
+ end
+
+ local capacity_str = read_file("capacity")
+ local capacity = capacity_str and tonumber(capacity_str)
+ if not capacity then
+ return { percent = 0, present = false, charging = false, tooltip = "No battery", status = "none" }
+ end
+
+ local status_str = read_file("status")
+ local charging = (status_str == "Charging" or status_str == "Full")
+
+ local time_to_empty = read_file("time_to_empty_now")
+ local time_to_full = read_file("time_to_full_now")
+ local time_str = nil
+ if not charging and time_to_empty then
+ local secs = tonumber(time_to_empty)
+ if secs and secs > 0 then
+ local h = math.floor(secs / 3600)
+ local m = math.floor((secs % 3600) / 60)
+ time_str = string.format("%dh%dm remaining", h, m)
+ end
+ elseif charging and time_to_full then
+ local secs = tonumber(time_to_full)
+ if secs and secs > 0 then
+ local h = math.floor(secs / 3600)
+ local m = math.floor((secs % 3600) / 60)
+ time_str = string.format("%dh%dm until full", h, m)
+ end
+ end
+
+ local lines = { string.format("Battery: %d%%", capacity) }
+ if status_str then
+ lines[#lines + 1] = "Status: " .. status_str
+ end
+ if time_str then
+ lines[#lines + 1] = time_str
+ end
+
+ return {
+ percent = capacity,
+ present = true,
+ charging = charging,
+ status = nonnull(status_str),
+ tooltip = table.concat(lines, "\n"),
+ }
+end
+
+local battery_path = find_battery_path()
+
-- ------------------------------------------------ state + emit
local state = {
cpu = {
@@ -561,6 +639,13 @@ local state = {
sink = NULL,
tooltip = "Volume: unknown",
},
+ battery = {
+ percent = 0,
+ present = false,
+ charging = false,
+ status = "none",
+ tooltip = "No battery",
+ },
}
local function emit()
@@ -744,6 +829,7 @@ local function main()
state.cpu = cpu_state
state.ram = ram_state
+ state.battery = get_battery_state(battery_path)
-- Net status is always refreshed here too, so even with inotify
-- permanently unavailable we still pick up link changes within
-- CPU_INTERVAL seconds.