Add widget: Brightness
- Use `/sys/class/backlight/` values
This commit is contained in:
parent
fa206d7f42
commit
8851869f07
84
src/widgets/brightnesswidget.rs
Normal file
84
src/widgets/brightnesswidget.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
use super::common::run_cmd;
|
||||||
|
use crate::TopBar;
|
||||||
|
use slint::{ComponentHandle, SharedString, Timer, TimerMode};
|
||||||
|
use std::{fs, time::Duration};
|
||||||
|
|
||||||
|
/// Read a file and trim whitespace
|
||||||
|
fn read_file(path: &str) -> Option<String> {
|
||||||
|
fs::read_to_string(path).ok().map(|s| s.trim().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return (`brightness`, `max_brightness`)
|
||||||
|
/// Use the first device listed under /sys/class/backlight/
|
||||||
|
fn read_brightness_raw() -> Option<(u32, u32)> {
|
||||||
|
let base = "/sys/class/backlight";
|
||||||
|
let mut entries = fs::read_dir(base).ok()?;
|
||||||
|
|
||||||
|
// First device (intel_backlight, amdgpu_bl0, acpi_video0, etc.)
|
||||||
|
let dev = entries.next()?.ok()?.path();
|
||||||
|
|
||||||
|
let b = read_file(dev.join("brightness").to_str()?)?.parse().ok()?;
|
||||||
|
let m = read_file(dev.join("max_brightness").to_str()?)?
|
||||||
|
.parse()
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
Some((b, m))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert brightness raw values into a 0–100% percentage
|
||||||
|
fn brightness_percent() -> u8 {
|
||||||
|
if let Some((b, m)) = read_brightness_raw()
|
||||||
|
&& m > 0
|
||||||
|
{
|
||||||
|
return ((b as f32 / m as f32) * 100.0).round() as u8;
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pick an icon based on percentage
|
||||||
|
fn brightness_icon(p: u8) -> SharedString {
|
||||||
|
let icon = match p {
|
||||||
|
0 => "", // off
|
||||||
|
1..=20 => "", // low
|
||||||
|
21..=60 => "", // medium
|
||||||
|
_ => "", // high
|
||||||
|
};
|
||||||
|
SharedString::from(icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tooltip text displayed when hovering the icon
|
||||||
|
fn brightness_tooltip(p: u8) -> String {
|
||||||
|
format!("Brightness: {p}%")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start timer to update brightness every second
|
||||||
|
fn start_brightness_updater(ui: &TopBar) {
|
||||||
|
let weak = ui.as_weak();
|
||||||
|
|
||||||
|
let timer = Box::leak(Box::new(Timer::default()));
|
||||||
|
timer.start(TimerMode::Repeated, Duration::from_secs(1), move || {
|
||||||
|
if let Some(ui) = weak.upgrade() {
|
||||||
|
// Read brightness
|
||||||
|
let p = brightness_percent();
|
||||||
|
|
||||||
|
// Update properties on the root component
|
||||||
|
ui.set_brightness_icon(brightness_icon(p));
|
||||||
|
ui.set_brightness_tooltip(brightness_tooltip(p).into());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public entry for this widget
|
||||||
|
pub fn install(ui: &TopBar) {
|
||||||
|
let weak = ui.as_weak();
|
||||||
|
|
||||||
|
// Click callback (open brightness settings)
|
||||||
|
ui.on_show_brightness(move || {
|
||||||
|
if weak.upgrade().is_some() {
|
||||||
|
run_cmd("xclock"); // Fix later
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start updating
|
||||||
|
start_brightness_updater(ui);
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
mod batterywidget;
|
mod batterywidget;
|
||||||
|
mod brightnesswidget;
|
||||||
mod common;
|
mod common;
|
||||||
mod datewidget;
|
mod datewidget;
|
||||||
mod timewidget;
|
mod timewidget;
|
||||||
@ -11,6 +12,7 @@ pub fn install_callbacks(ui: &TopBar) {
|
|||||||
datewidget::install(ui);
|
datewidget::install(ui);
|
||||||
batterywidget::install(ui);
|
batterywidget::install(ui);
|
||||||
volumewidget::install(ui);
|
volumewidget::install(ui);
|
||||||
|
brightnesswidget::install(ui);
|
||||||
|
|
||||||
// In the future:
|
// In the future:
|
||||||
// networkwidget::install(ui);
|
// networkwidget::install(ui);
|
||||||
|
|||||||
@ -27,7 +27,6 @@ export component TopBar inherits Window {
|
|||||||
in property <color> battery_bg_clicked;*/
|
in property <color> battery_bg_clicked;*/
|
||||||
callback show_battery();
|
callback show_battery();
|
||||||
|
|
||||||
|
|
||||||
// Volume widget
|
// Volume widget
|
||||||
in property <string> volume_tooltip;
|
in property <string> volume_tooltip;
|
||||||
in property <string> volume_icon;
|
in property <string> volume_icon;
|
||||||
@ -37,6 +36,15 @@ export component TopBar inherits Window {
|
|||||||
in property <color> volume_bg_clicked;*/
|
in property <color> volume_bg_clicked;*/
|
||||||
callback show_volume();
|
callback show_volume();
|
||||||
|
|
||||||
|
// brightness widget
|
||||||
|
in property <string> brightness_tooltip;
|
||||||
|
in property <string> brightness_icon;
|
||||||
|
/*in property <color> brightness_icon_color;
|
||||||
|
in property <color> brightness_bg_normal;
|
||||||
|
in property <color> brightness_bg_hover;
|
||||||
|
in property <color> brightness_bg_clicked;*/
|
||||||
|
callback show_brightness();
|
||||||
|
|
||||||
title: "chocobar";
|
title: "chocobar";
|
||||||
width: bar_width *1px;
|
width: bar_width *1px;
|
||||||
height: bar_height *1px;
|
height: bar_height *1px;
|
||||||
@ -81,6 +89,18 @@ export component TopBar inherits Window {
|
|||||||
HorizontalLayout {
|
HorizontalLayout {
|
||||||
alignment: end; // Right-align
|
alignment: end; // Right-align
|
||||||
|
|
||||||
|
// SquareIconWidget - brightness
|
||||||
|
SquareIconWidget {
|
||||||
|
bar_height: root.bar_height;
|
||||||
|
icon_text: root.brightness_icon;
|
||||||
|
tooltip_text: root.brightness_tooltip;
|
||||||
|
/*icon_color: root.brightness_icon_color;
|
||||||
|
bg_normal: root.brightness_bg_normal;
|
||||||
|
bg_hover: root.brightness_bg_hover;
|
||||||
|
bg_clicked: root.brightness_bg_clicked;*/
|
||||||
|
square_btn_callback => root.show_brightness();
|
||||||
|
}
|
||||||
|
|
||||||
// SquareIconWidget - Volume
|
// SquareIconWidget - Volume
|
||||||
SquareIconWidget {
|
SquareIconWidget {
|
||||||
bar_height: root.bar_height;
|
bar_height: root.bar_height;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user