widgets: stop aborting on machines without backlight/battery/pulseaudio

The release profile builds with panic = "abort", so a panic in any helper
thread took the whole dashboard down:

- backlight: WalkDir yields /sys/class/backlight itself, so detect() was
  always true and new() picked the class dir as the device, then panicked
  reading brightness. Use min_depth(1) and tolerate read errors.
- battery: detect() only checked that UPower's DisplayDevice answered,
  which it does on every machine; use IsPresent. The monitor thread now
  returns an error instead of unwrapping, and publishes its first reading.
- pulseaudio: a failed connection panicked ("damn"); clicks before the
  first sink query unwrapped a None channel map. Both are now handled, and
  the connect loop no longer busy-spins.
- bar widget: don't underflow when narrower than the label column.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-10-03 09:15:54 +00:00
co-authored by Claude Fable 5.1
parent 01af00b5ea
commit c033335912
4 changed files with 126 additions and 111 deletions
+7 -15
View File
@@ -62,21 +62,13 @@ impl Widget for BarWidget {
let val = self.inner_widget.value();
let c = self.inner_widget.color();
draw_bar(
&mut view.offset((bar_offset, 0)),
c,
self.geometry.width - bar_offset,
size,
val,
)
.unwrap();
let bar_width = self.geometry.width.saturating_sub(bar_offset);
if bar_width < 2 {
return self.geometry;
}
draw_bar(&mut view.offset((bar_offset, 0)), c, bar_width, size, val).unwrap();
draw_box(
&mut view.offset((bar_offset, 0)),
c,
(self.geometry.width - bar_offset, size),
)
.unwrap();
draw_box(&mut view.offset((bar_offset, 0)), c, (bar_width, size)).unwrap();
self.geometry
}
@@ -108,7 +100,7 @@ impl Widget for BarWidget {
match event {
Event::PointerEvent(ev) => {
let offset = 4 * self.size.ceil() as u32;
if ev.pos.0 >= offset {
if ev.pos.0 >= offset && self.geometry.width > offset {
let val = (ev.pos.0 - offset) as f32 / (self.geometry.width - offset) as f32;
self.inner_widget.click(val, ev.button);
}