diff --git a/CLAUDE.md b/CLAUDE.md index 5dd38e8..1487758 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -139,7 +139,7 @@ The video player is `mpv` with [ModernZ](https://github.com/Samillion/ModernZ) a Diagnostic script that checks the system state against moonarch defaults: - Packages (official.txt + aur.txt installed? Orphans?) -- System services (NetworkManager, bluetooth, greetd, ufw, auto-cpufreq, etc.) +- System services (NetworkManager, bluetooth, greetd, ufw, power-profiles-daemon, etc.) - User services (kanshi, wlsunset, stasis, walker, nautilus, cliphist-text, cliphist-image) - Config files (SHA256 comparison deployed vs. moonarch default) - Helper scripts + symlinks (moonup, moondoc) diff --git a/DECISIONS.md b/DECISIONS.md index 6397a0b..273b103 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1,5 +1,12 @@ # Decisions +## 2026-08-24 – power-profiles-daemon replaces auto-cpufreq + +- **Who**: Dominik, ClaudeCode +- **Why**: auto-cpufreq was the CPU widget's backend, chosen for the widget rather than for the hardware. Upstream describes it as a laptop tool and, for AMD trouble, points at `amd_pstate.enable=0` — back to the old driver. But under `amd-pstate` in active mode the kernel documents that the "platform ignores the desired performance level request and takes into account only the values set to the minimum, maximum and energy performance preference registers": the governor auto-cpufreq switches is not the knob that decides anything, EPP is. +- **Tradeoffs**: ppd writes exactly those knobs — `ppd-driver-amd-pstate.c` / `ppd-driver-intel-pstate.c` set EPP, `ppd-driver-platform-profile.c` the ACPI `platform_profile` that auto-cpufreq never touched — and its polkit policy allows `switch-profile` for the active session, so the popout no longer loses its focus to a pkexec prompt. What is given up is auto-cpufreq's load-dependent automatic: ppd offers three fixed profiles and leaves the reacting to the firmware. It also has no `watch` subcommand, so the widget keeps its 60s fallback poll instead of becoming event-driven. moonix switched with it (its `services.power-profiles-daemon` module asserts against auto-cpufreq, so the choice is one or the other) — and since moonix deploys this repo's quickshell config, the widget could not stay on the old backend either. +- **How**: `CpuGovService.qml` calls `powerprofilesctl get` / `set` (no pkexec); indicator and popout follow the profile names — `powersave` → `power-saver`, `Auto (reset)` → `balanced`. Same switch in `moonarch-cpugov` and `moonarch-waybar-cpugov`, the latter now reading the profile instead of `scaling_governor`, which under amd-pstate says nothing about it. `power-profiles-daemon` moves from `aur.txt` to `official.txt` (it is in `extra`), and the service list in `post-install.sh` and `moonarch-doctor` names it instead. + ## 2026-08-18 – swaylock config moves to /etc/swaylock, background is pre-blurred - **Who**: Dominik, ClaudeCode - **Why**: A second machine showed no lock screen background. The config was installed to `/etc/xdg/swaylock/config`, which swaylock never reads (only `~/.swaylock/config`, `$XDG_CONFIG_HOME/swaylock/config`, `SYSCONFDIR/swaylock/config`), and was made effective by seeding it into user homes from `post-install.sh` and the `.install` hook. Both seeds are conditional — the hook fires only on a moonarch-git install/upgrade and only under `[ ! -f ]` — so a machine that pulled no update since swaylock arrived (2026-08-14) ran with no config at all. Verified by running swaylock against a throwaway `HOME`: it rejects an invalid option from `~/.config/swaylock/config` before connecting to the compositor, and reports nothing when the same file sits in `/etc/xdg/`. The machine this was investigated on had the same gap unnoticed — its home copy had been renamed to `config.bak`, so neither machine was actually reading a config. Second request: the background should be blurred. diff --git a/README.md b/README.md index 452284e..d4cd211 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ defaults/ bin/ Helper scripts (deployed to /usr/bin/) moonarch-sink-switcher Audio output switcher (walker dmenu + pactl) moonarch-vpn VPN connection manager (walker dmenu + nmcli) - moonarch-cpugov CPU governor switcher (walker dmenu + auto-cpufreq) + moonarch-cpugov Power profile switcher (walker dmenu + powerprofilesctl) moonarch-btnote Bluetooth device battery monitor (upower + notify-send) moonarch-capsnote Caps Lock toggle notification moonarch-waybar-cpugov Waybar module: CPU governor status @@ -197,7 +197,7 @@ are part of the system and updated via `paru -Syu`. | bluetooth | Bluetooth stack (bluez) | | systemd-timesyncd | NTP time synchronization | | ufw | Firewall (deny incoming, allow outgoing) | -| auto-cpufreq | CPU frequency scaling (AC: performance, battery: powersave) | +| power-profiles-daemon | Power profiles over D-Bus (EPP + ACPI platform_profile) | ### User Services (systemd --user) diff --git a/defaults/bin/moonarch-cpugov b/defaults/bin/moonarch-cpugov index d31ae4b..1a1b3e0 100755 --- a/defaults/bin/moonarch-cpugov +++ b/defaults/bin/moonarch-cpugov @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# ABOUTME: Walker-dmenu CPU governor switcher using auto-cpufreq. -# ABOUTME: Allows switching between performance, powersave, and reset modes. +# ABOUTME: Walker-dmenu CPU power profile switcher using power-profiles-daemon. +# ABOUTME: Allows switching between the performance, power-saver and balanced profiles. declare -A LABELS declare -A COMMANDS @@ -8,14 +8,14 @@ declare -A COMMANDS ### # List of defined 'bangs' -COMMANDS["󰓅"]="pkexec auto-cpufreq --force=performance" +COMMANDS["󰓅"]="powerprofilesctl set performance" LABELS["󰓅"]="Performance" -COMMANDS["󰌪"]='pkexec auto-cpufreq --force=powersave' +COMMANDS["󰌪"]='powerprofilesctl set power-saver' LABELS["󰌪"]="Powersave" -COMMANDS[""]='pkexec auto-cpufreq --force=reset' -LABELS[""]="Reset" +COMMANDS[""]='powerprofilesctl set balanced' +LABELS[""]="Balanced" ################################################################################ diff --git a/defaults/bin/moonarch-waybar-cpugov b/defaults/bin/moonarch-waybar-cpugov index bbb14c3..c4cf692 100755 --- a/defaults/bin/moonarch-waybar-cpugov +++ b/defaults/bin/moonarch-waybar-cpugov @@ -1,8 +1,10 @@ #!/usr/bin/bash -# ABOUTME: Waybar module that outputs the CPU governor as JSON. +# ABOUTME: Waybar module that outputs the active power profile as JSON. # ABOUTME: Referenced by the Waybar custom/cpugov config. -CPU_GOV=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null) +# The ppd profile, not scaling_governor: under amd-pstate in active mode the governor +# stays where the driver put it and says nothing about the profile the user picked. +CPU_GOV=$(powerprofilesctl get 2>/dev/null) case $CPU_GOV in performance) @@ -11,27 +13,20 @@ case $CPU_GOV in balanced) CPU_GOV_SHORT=󰾅 ;; - powersave) + power-saver) CPU_GOV_SHORT=󰌪 ;; - userspace) - CPU_GOV_SHORT=uspace - ;; - ondemand) - CPU_GOV_SHORT=ondmnd - ;; - conservative) - CPU_GOV_SHORT=cons - ;; - schedutil) - CPU_GOV_SHORT=sutil - ;; *) CPU_GOV_SHORT="?" ;; esac -CPU_GOV_FULL="${CPU_GOV^}" +case $CPU_GOV in + performance) CPU_GOV_FULL="Performance" ;; + balanced) CPU_GOV_FULL="Balanced" ;; + power-saver) CPU_GOV_FULL="Powersave" ;; + *) CPU_GOV_FULL="Unknown" ;; +esac jq --compact-output -n \ --arg text "$CPU_GOV_SHORT" \ diff --git a/defaults/xdg/quickshell/moonarch/CpuGovIndicator.qml b/defaults/xdg/quickshell/moonarch/CpuGovIndicator.qml index 77c79aa..f10976e 100644 --- a/defaults/xdg/quickshell/moonarch/CpuGovIndicator.qml +++ b/defaults/xdg/quickshell/moonarch/CpuGovIndicator.qml @@ -1,5 +1,5 @@ -// ABOUTME: CPU governor bar widget — glyph reflects the active auto-cpufreq profile (CpuGovService.state). -// ABOUTME: Click opens the cpugov popout to switch profiles (performance / powersave / auto). +// ABOUTME: CPU power profile bar widget — glyph reflects the active ppd profile (CpuGovService.state). +// ABOUTME: Click opens the cpugov popout to switch profiles (performance / balanced / power-saver). pragma ComponentBehavior: Bound import QtQuick @@ -30,15 +30,15 @@ Item { implicitWidth: iconText.implicitWidth implicitHeight: Theme.barHeight - // Glyph per profile; "default" = auto-cpufreq picks by load. Unknown/unread falls back to the raw state. + // Glyph per profile; "balanced" = ppd's default, the platform picks by load. Unknown/unread shows nothing. readonly property string icon: { switch (CpuGovService.state) { case "performance": return String.fromCodePoint(0xf04c5); // speedometer - case "powersave": + case "power-saver": return String.fromCodePoint(0xf032a); // leaf - case "default": - return String.fromCodePoint(0xf0f85); // speedometer-medium (Auto) + case "balanced": + return String.fromCodePoint(0xf0f85); // speedometer-medium default: return ""; } @@ -47,10 +47,10 @@ Item { switch (CpuGovService.state) { case "performance": return qsTr("Performance"); - case "powersave": + case "power-saver": return qsTr("Powersave"); - case "default": - return qsTr("Auto"); + case "balanced": + return qsTr("Balanced"); default: return "—"; } diff --git a/defaults/xdg/quickshell/moonarch/CpuGovPopout.qml b/defaults/xdg/quickshell/moonarch/CpuGovPopout.qml index 448b534..64c2227 100644 --- a/defaults/xdg/quickshell/moonarch/CpuGovPopout.qml +++ b/defaults/xdg/quickshell/moonarch/CpuGovPopout.qml @@ -1,4 +1,4 @@ -// ABOUTME: CPU governor popout — Performance / Powersave / Auto(reset), backed by CpuGovService. +// ABOUTME: CPU power profile popout — Performance / Powersave / Balanced, backed by CpuGovService. // ABOUTME: The active profile is marked from CpuGovService.state; switching goes through the same service. pragma ComponentBehavior: Bound import QtQuick @@ -29,13 +29,13 @@ PopoutPanel { }, { "label": qsTr("Powersave"), - "mode": "powersave", - "state": "powersave" + "mode": "power-saver", + "state": "power-saver" }, { - "label": qsTr("Auto (reset)"), - "mode": "reset", - "state": "default" + "label": qsTr("Balanced"), + "mode": "balanced", + "state": "balanced" } ] delegate: ListRow { diff --git a/defaults/xdg/quickshell/moonarch/CpuGovService.qml b/defaults/xdg/quickshell/moonarch/CpuGovService.qml index 6c92bbc..eadaf2b 100644 --- a/defaults/xdg/quickshell/moonarch/CpuGovService.qml +++ b/defaults/xdg/quickshell/moonarch/CpuGovService.qml @@ -1,5 +1,5 @@ -// ABOUTME: CPU governor service — reads/sets the auto-cpufreq force override for the whole shell. -// ABOUTME: state = "performance" | "powersave" | "default" (auto); shared by indicator + popout so both stay in sync. +// ABOUTME: CPU power profile service — reads/sets the power-profiles-daemon profile for the whole shell. +// ABOUTME: state = "performance" | "balanced" | "power-saver"; shared by indicator + popout so both stay in sync. pragma Singleton import QtQuick import Quickshell @@ -8,13 +8,14 @@ import Quickshell.Io Singleton { id: root - // auto-cpufreq force override, the profile the user picked — NOT scaling_governor (which flips with - // load under "default" and would misreport Auto). "" only until the first read (or on read failure). + // The active ppd profile — NOT scaling_governor: under amd-pstate in active mode the platform picks the + // frequency from the min/max and EPP registers, so the governor says nothing about the chosen profile. + // "" only until the first read (or on read failure). property string state: "" Process { id: stateProc - command: ["auto-cpufreq", "--get-state"] + command: ["powerprofilesctl", "get"] stdout: StdioCollector { id: stateOut } @@ -25,8 +26,8 @@ Singleton { stateProc.running = true; } - // The override only changes via apply() (→ instant refresh) or the walker menu (no quickshell signal), - // so poll as a slow fallback to catch an out-of-band switch. + // The profile changes via apply() (→ instant refresh), the walker menu, or a program holding a profile + // over D-Bus. powerprofilesctl has no watch subcommand, so poll as a slow fallback for those. Timer { interval: 60000 running: true @@ -35,14 +36,16 @@ Singleton { onTriggered: root.refresh() } + // No pkexec: ppd's polkit policy allows switch-profile for the active session, so the popout keeps + // the focus instead of losing it to an auth prompt. Process { id: applyProc onExited: (code, status) => root.refresh() } - function apply(mode) { + function apply(profile) { if (applyProc.running) return; - applyProc.command = ["pkexec", "auto-cpufreq", "--force=" + mode]; + applyProc.command = ["powerprofilesctl", "set", profile]; applyProc.running = true; } } diff --git a/packages/aur.txt b/packages/aur.txt index bc6c047..3086db2 100644 --- a/packages/aur.txt +++ b/packages/aur.txt @@ -36,6 +36,5 @@ mpv-modernz-git mpv-thumbfast-git # System & Tools -auto-cpufreq stasis wayland-pipewire-idle-inhibit diff --git a/packages/official.txt b/packages/official.txt index 73abbfc..b6dd0ee 100644 --- a/packages/official.txt +++ b/packages/official.txt @@ -109,6 +109,7 @@ neovim # System fwupd plocate +power-profiles-daemon rebuild-detector snapper snap-pac diff --git a/scripts/moonarch-doctor b/scripts/moonarch-doctor index 261f20d..947deaa 100755 --- a/scripts/moonarch-doctor +++ b/scripts/moonarch-doctor @@ -184,7 +184,7 @@ fi section "System Services" -for svc in NetworkManager bluetooth greetd systemd-timesyncd ufw auto-cpufreq; do +for svc in NetworkManager bluetooth greetd systemd-timesyncd ufw power-profiles-daemon; do check_system_service "$svc" done diff --git a/scripts/post-install.sh b/scripts/post-install.sh index 052ecf0..f7552cc 100755 --- a/scripts/post-install.sh +++ b/scripts/post-install.sh @@ -163,7 +163,7 @@ SERVICES=( "greetd" "systemd-timesyncd" "ufw" - "auto-cpufreq" + "power-profiles-daemon" ) for service in "${SERVICES[@]}"; do