refactor(power): switch the CPU widget backend to power-profiles-daemon
Update PKGBUILD version / update-pkgver (push) Successful in 5s

auto-cpufreq switches the scaling governor, but under amd-pstate in
active mode the platform decides from the min/max and EPP registers and
ignores the governor. power-profiles-daemon writes exactly those knobs,
and its polkit policy allows switch-profile for the active session, so
the popout no longer loses focus to a pkexec prompt.

- CpuGovService.qml: powerprofilesctl get/set, no pkexec
- indicator + popout: powersave -> power-saver, Auto (reset) -> balanced
- moonarch-cpugov, moonarch-waybar-cpugov: same switch, the Waybar module
  now reads the profile instead of scaling_governor
- power-profiles-daemon moves from aur.txt to official.txt (it is in extra)
- post-install.sh and moonarch-doctor name it in their service lists
This commit is contained in:
nevaforget committed 2026-08-25 08:30:18 +02:00
1 parent e21c046e32
commit 0e110894b1
12 files changed
+57 -52

No files matched your search

+1 -1
View File
@@ -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)
+7
View File
@@ -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.
+2 -2
View File
@@ -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)
+6 -6
View File
@@ -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"
################################################################################
+11 -16
View File
@@ -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" \
@@ -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 "—";
}
@@ -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 {
@@ -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;
}
}
-1
View File
@@ -36,6 +36,5 @@ mpv-modernz-git
mpv-thumbfast-git
# System & Tools
auto-cpufreq
stasis
wayland-pipewire-idle-inhibit
+1
View File
@@ -109,6 +109,7 @@ neovim
# System
fwupd
plocate
power-profiles-daemon
rebuild-detector
snapper
snap-pac
+1 -1
View File
@@ -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
+1 -1
View File
@@ -163,7 +163,7 @@ SERVICES=(
"greetd"
"systemd-timesyncd"
"ufw"
"auto-cpufreq"
"power-profiles-daemon"
)
for service in "${SERVICES[@]}"; do