diff --git a/README.md b/README.md index e938289..cab99da 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,6 @@ programs.nova-shell.modules = { weather.interval = 3600000; # refresh interval in ms (default 1h) temperature.warm = 55; # °C threshold for warm color temperature.hot = 75; # °C threshold for hot color - temperature.device = "x86_pkg_temp"; # pin to a specific thermal zone (default: system max) battery.warning = 30; # % for warning notification battery.critical = 10; # % for critical blink + notification cpu.interval = 2000; # polling interval in ms diff --git a/modules/Modules.qml b/modules/Modules.qml index c7a4b6d..4a0053e 100644 --- a/modules/Modules.qml +++ b/modules/Modules.qml @@ -56,8 +56,7 @@ QtObject { property var temperature: ({ enable: true, warm: 80, - hot: 90, - device: "" + hot: 90 }) property var gpu: ({ enable: true diff --git a/modules/NotifItem.qml b/modules/NotifItem.qml index fc5d552..d3e96b9 100644 --- a/modules/NotifItem.qml +++ b/modules/NotifItem.qml @@ -46,8 +46,7 @@ QtObject { readonly property Connections _notifConn: Connections { target: root.notification function onClosed() { - if (root.state !== "dismissed") - M.NotifService.dismiss(root.id); + M.NotifService.dismiss(root.id); } } diff --git a/modules/SystemStats.qml b/modules/SystemStats.qml index 7345727..a668be4 100644 --- a/modules/SystemStats.qml +++ b/modules/SystemStats.qml @@ -32,8 +32,7 @@ QtObject { // ── Temperature ────────────────────────────────────────────────────── property int tempCelsius: 0 - property var tempHistory: [] // 150 samples @ 4s each ≈ 10 min - property var tempDevices: [] // [{name, celsius}] sorted hottest-first + property var tempHistory: [] // 150 samples @ 4s each ≈ 10 min // ── GPU ────────────────────────────────────────────────────────────── property bool gpuAvailable: false @@ -96,8 +95,6 @@ QtObject { root.tempCelsius = ev.celsius; const th = root.tempHistory.concat([ev.celsius]); root.tempHistory = th.length > 150 ? th.slice(th.length - 150) : th; - if (ev.devices) - root.tempDevices = ev.devices; } else if (ev.type === "gpu") { root.gpuAvailable = true; root.gpuVendor = ev.vendor; diff --git a/modules/Temperature.qml b/modules/Temperature.qml index d7aa47c..0106632 100644 --- a/modules/Temperature.qml +++ b/modules/Temperature.qml @@ -9,17 +9,7 @@ M.BarSection { readonly property int _warm: M.Modules.temperature.warm || 80 readonly property int _hot: M.Modules.temperature.hot || 90 - readonly property string _deviceFilter: M.Modules.temperature.device || "" - - // If a device filter is set, use that device's temp; otherwise fall back to system max - readonly property int _temp: { - if (_deviceFilter !== "") { - const dev = M.SystemStats.tempDevices.find(d => d.name === _deviceFilter); - if (dev) - return dev.celsius; - } - return M.SystemStats.tempCelsius; - } + readonly property int _temp: M.SystemStats.tempCelsius property color _stateColor: _temp > _hot ? M.Theme.base08 : _temp > _warm ? M.Theme.base0A : root.accentColor Behavior on _stateColor { @@ -267,57 +257,6 @@ M.BarSection { } } - // Per-device breakdown - Rectangle { - width: parent.width - 16 - height: 1 - anchors.horizontalCenter: parent.horizontalCenter - color: M.Theme.base03 - visible: M.SystemStats.tempDevices.length > 0 - } - - Repeater { - model: M.SystemStats.tempDevices - delegate: Item { - required property var modelData - width: hoverPanel.contentWidth - height: 22 - - readonly property bool _isActive: root._deviceFilter === modelData.name - - Rectangle { - anchors.fill: parent - anchors.leftMargin: 8 - anchors.rightMargin: 8 - color: _isActive ? Qt.rgba(root.accentColor.r, root.accentColor.g, root.accentColor.b, 0.12) : "transparent" - radius: 3 - } - - Text { - anchors.left: parent.left - anchors.leftMargin: 12 - anchors.verticalCenter: parent.verticalCenter - text: modelData.name - color: _isActive ? root.accentColor : M.Theme.base04 - font.pixelSize: M.Theme.fontSize - 2 - font.family: M.Theme.fontFamily - elide: Text.ElideRight - width: parent.width - 80 - } - - Text { - anchors.right: parent.right - anchors.rightMargin: 12 - anchors.verticalCenter: parent.verticalCenter - text: modelData.celsius + "\u00B0C" - color: root._tempColor(modelData.celsius) - font.pixelSize: M.Theme.fontSize - 2 - font.family: M.Theme.fontFamily - font.bold: _isActive - } - } - } - Item { width: 1 height: 4 diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 440b902..7911c9b 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -141,14 +141,6 @@ in default = 90; description = "Temperature threshold for hot state (°C)."; }; - device = lib.mkOption { - type = lib.types.str; - default = ""; - description = '' - Thermal zone device name to use for the primary temperature reading - (e.g. "x86_pkg_temp", "acpitz"). Leave empty to use the system maximum. - ''; - }; }; battery = moduleOpt "battery" { warning = lib.mkOption { diff --git a/stats-daemon/src/temp.rs b/stats-daemon/src/temp.rs index 2c93ef9..54beb3c 100644 --- a/stats-daemon/src/temp.rs +++ b/stats-daemon/src/temp.rs @@ -1,79 +1,25 @@ -use std::collections::HashMap; use std::fs; use std::io::Write; -#[derive(Debug)] -pub struct ThermalDevice { - pub name: String, - pub celsius: i32, -} - -pub fn read_thermal_devices() -> Vec { - let mut by_name: HashMap = HashMap::new(); - +pub fn read_temp_celsius() -> Option { + let mut max: Option = None; for i in 0.. { - let temp_path = format!("/sys/class/thermal/thermal_zone{i}/temp"); - let type_path = format!("/sys/class/thermal/thermal_zone{i}/type"); - - let temp_str = match fs::read_to_string(&temp_path) { - Ok(s) => s, + let path = format!("/sys/class/thermal/thermal_zone{i}/temp"); + match fs::read_to_string(&path) { + Ok(s) => { + if let Ok(millic) = s.trim().parse::() { + let c = millic / 1000; + max = Some(max.map_or(c, |m: i32| m.max(c))); + } + } Err(_) => break, - }; - - let millic: i32 = match temp_str.trim().parse() { - Ok(v) => v, - Err(_) => continue, - }; - let celsius = millic / 1000; - - let name = fs::read_to_string(&type_path) - .map(|s| s.trim().to_string()) - .unwrap_or_else(|_| format!("zone{i}")); - - // Keep the highest temp seen for each device type - let entry = by_name.entry(name).or_insert(celsius); - if celsius > *entry { - *entry = celsius; } } - - let mut devices: Vec = by_name - .into_iter() - .map(|(name, celsius)| ThermalDevice { name, celsius }) - .collect(); - - // Sort descending by temp so the hottest shows first - devices.sort_by(|a, b| b.celsius.cmp(&a.celsius)); - devices + max } pub fn emit_temp(out: &mut impl Write) { - let devices = read_thermal_devices(); - if devices.is_empty() { - return; + if let Some(c) = read_temp_celsius() { + let _ = writeln!(out, "{{\"type\":\"temp\",\"celsius\":{c}}}"); } - - let max = devices.iter().map(|d| d.celsius).max().unwrap_or(0); - - let devices_json: Vec = devices - .iter() - .map(|d| { - format!( - "{{\"name\":{},\"celsius\":{}}}", - json_str(&d.name), - d.celsius - ) - }) - .collect(); - - let _ = writeln!( - out, - "{{\"type\":\"temp\",\"celsius\":{max},\"devices\":[{}]}}", - devices_json.join(",") - ); -} - -fn json_str(s: &str) -> String { - let escaped = s.replace('\\', "\\\\").replace('"', "\\\""); - format!("\"{escaped}\"") }