feat(waybar): combined power menu on the battery + profile icons
All checks were successful
Check / eval (push) Successful in 3m5s
All checks were successful
Check / eval (push) Successful in 3m5s
Item 36(b). Adds `nomarchy-menu powermgmt` — one flat rofi menu of power
Profile rows (→ powerprofilesctl set) + Charge limit rows (→ the same
theme-sync writer batterylimit uses), each half self-gating on its
hardware. No backend duplication; Custom charge stays in the dedicated
batterylimit picker.
Opened two ways (Bernardo's call): the Waybar battery icon AND the
power-profile icon — the profile icon's click flips from cycle → menu.
Wired in waybar.nix and all four whole-swaps (parity). Named `powermgmt`
to avoid the whole-swaps' existing `custom/powermenu` shutdown button
(→ nomarchy-menu power), which is left untouched. The granular System ▸
Power profile / Battery limit rows stay ("keep both").
nomarchy-powerprofile-cycle kept as a standalone bin, now unbound by
default.
Verified: V0 green; V1 HM built (bash -n) — powermgmt case ships, the
generated waybar-config.json wires both icons (2 hits), all four jsoncs
re-wired and still parse, shutdown buttons intact. Click→menu→apply is
V3 (queued).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -26,29 +26,6 @@ next, in what order*.
|
||||
|
||||
## NEXT
|
||||
|
||||
### 36. Battery / power quick menu `[human]`
|
||||
(Raised by Bernardo, 2026-07-07 — item 6.) Slice (a) — the charge-threshold
|
||||
toggle in the rofi System submenu — shipped 2026-07-07 (iteration #64;
|
||||
`nomarchy-menu batterylimit`, self-gated on the sysfs node, and MOVED out
|
||||
of the gum control-center). Remaining:
|
||||
- (b) **Battery-icon click → a dedicated power menu** offering charge
|
||||
threshold + power profile. Mockup provided by Bernardo 2026-07-08 (a
|
||||
`power-menu` rofi script from another system): a `rofi -dmenu` with
|
||||
icon'd rows via the `\x00icon\x1f<name>` protocol — "Charge to 100%",
|
||||
"Limit to 80%" (battery-*-charging-symbolic icons) + power-profile rows
|
||||
(power-profile-{power-saver,performance}-symbolic), each `case` firing a
|
||||
backend command + `notify-send`. The submitted script drives **TLP**
|
||||
(`tlp fullcharge` / `tlp setcharge 75 80 BAT0`) and ryzenadj (ignore the
|
||||
ryzenadj half). **Nomarchy adaptation:** reuse the existing writers, not
|
||||
raw TLP — charge rows call `nomarchy-menu batterylimit`'s logic
|
||||
(sysfs `charge_control_end_threshold` + baked `settings.power.
|
||||
batteryChargeLimit`), profile rows call `power-profile`'s (PPD). Wire the
|
||||
Waybar **battery module `on-click`** (generated `waybar.nix` + all four
|
||||
whole-swap jsoncs — parity) to a new `nomarchy-menu powermenu`. Open
|
||||
call left: whether to *replace* the separate System ▸ Battery limit /
|
||||
Power profile rows or keep both surfaces. Pairs with the instant-effect
|
||||
follow-up in PROPOSED (a udev grant makes the charge write no-rebuild).
|
||||
|
||||
### 29. Laptop docking / external-monitor UX `[human]` (needs hardware)
|
||||
(Raised by Bernardo, 2026-07-07.) The shipped display application is
|
||||
weak and unintuitive, and Hyprland's model for workspaces across
|
||||
|
||||
@@ -282,6 +282,16 @@ QA machine), the **T14s** (webcam case).
|
||||
shows a single arrow, no double; (c) on this single-monitor box,
|
||||
System › Display → pick a resolution → Back returns to System
|
||||
(not back into the same resolution list).
|
||||
- [ ] **Combined power menu** (iteration #67, item 36b) — after
|
||||
`home-update` + relogin: clicking EITHER the Waybar battery icon OR
|
||||
the power-profile icon opens one "Power" menu listing Profile: rows
|
||||
+ Charge limit: rows; picking a profile calls `powerprofilesctl set`
|
||||
(verify `powerprofilesctl get` changes), picking a charge preset
|
||||
writes `settings.power.batteryChargeLimit` (applies next rebuild).
|
||||
The prompt shows the current profile + limit. System ▸ Power profile
|
||||
/ Battery limit still work directly; the whole-swap bars (summer-day/
|
||||
night, executive-slate, boreal) behave the same and their shutdown
|
||||
power-button (if present) still opens the lock/logout menu.
|
||||
|
||||
## AMD dev box only
|
||||
- [ ] **AMD runtime bits** — VA-API (`vainfo` → radeonsi), amd-pstate EPP
|
||||
|
||||
@@ -17,6 +17,31 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-08 — Combined power menu on the bar icons (iteration #67, item 36b)
|
||||
- **Task:** BACKLOG item 36(b), now unblocked. Bernardo's calls: keep the
|
||||
granular System ▸ Battery limit / Power profile rows; build ONE combined
|
||||
menu; open it two ways — the Waybar **battery** icon AND the
|
||||
**power-profile** icon (the profile icon's click flips from cycle → menu).
|
||||
- **Did:** New `nomarchy-menu powermgmt` (rofi.nix): a flat list of Profile
|
||||
rows (→ `powerprofilesctl set`, like the power-profile picker) + Charge
|
||||
limit rows (→ the same theme-sync writer as batterylimit), each half
|
||||
self-gating on its hardware; no backend duplication, no Custom flow (that
|
||||
stays in the dedicated batterylimit picker). Wired `battery.on-click` +
|
||||
`custom/powerprofile.on-click` → `powermgmt` in waybar.nix AND all four
|
||||
whole-swaps (parity). Named `powermgmt` to avoid the whole-swaps' existing
|
||||
`custom/powermenu` (that's the shutdown button → `nomarchy-menu power`,
|
||||
left untouched). `nomarchy-powerprofile-cycle` kept as a standalone bin
|
||||
(now just unbound by default).
|
||||
- **Verified:** V0 green; V1 HM built (bash -n passed) — shipped
|
||||
nomarchy-menu has the `powermgmt` case; generated waybar-config.json wires
|
||||
both icons to it (2 hits); all four whole-swap jsoncs re-wired and still
|
||||
parse as JSON, shutdown buttons intact.
|
||||
- **Pending:** V3 — click either icon → menu opens, picking a profile /
|
||||
charge preset actually applies (queued in HARDWARE-QUEUE). The
|
||||
instant-charge-write follow-up stays PROPOSED/`[blocked:hw]`.
|
||||
- **Next suggestion:** back to the queue — item 33 (rofi scrollbar) or a
|
||||
QA sweep; both remaining NEXT items lean human/hardware.
|
||||
|
||||
## 2026-07-08 — Capture rows show Print-key hints (iteration #66, direct requests)
|
||||
- **Task:** Two live requests from Bernardo. (1) Fold his provided
|
||||
power-menu mockup into item 36(b). (2) "make sure all menu items that
|
||||
|
||||
@@ -256,6 +256,56 @@ let
|
||||
[ "$choice" = "$BACK" ] && exec "$0" system
|
||||
[ -n "$choice" ] && powerprofilesctl set "$choice" ;;
|
||||
|
||||
powermgmt)
|
||||
# Combined power menu (item 36b) — power PROFILE + battery CHARGE cap
|
||||
# in one flat list, opened from BOTH the Waybar battery and
|
||||
# power-profile icons (the two granular System ▸ Power profile /
|
||||
# Battery limit rows stay for direct access). No new backend: profile
|
||||
# rows drive powerprofilesctl like the power-profile picker, charge
|
||||
# rows drive the same theme-sync writer as batterylimit. Each half
|
||||
# self-gates on its hardware, so a desktop with neither just toasts.
|
||||
bats=(/sys/class/power_supply/BAT*)
|
||||
haveppd=false; command -v powerprofilesctl >/dev/null 2>&1 && haveppd=true
|
||||
havecharge=false; [ -e "''${bats[0]}/charge_control_end_threshold" ] && havecharge=true
|
||||
if ! $haveppd && ! $havecharge; then
|
||||
notify-send "Power" "No power-profile or charge-limit control on this machine."
|
||||
exit 0
|
||||
fi
|
||||
curp=""; $haveppd && curp=$(powerprofilesctl get 2>/dev/null)
|
||||
curc=$(nomarchy-theme-sync get settings.power.batteryChargeLimit 2>/dev/null)
|
||||
choice=$( {
|
||||
if $haveppd; then
|
||||
powerprofilesctl list 2>/dev/null | sed -nE 's/^[* ] ([a-z-]+):$/\1/p' \
|
||||
| while IFS= read -r p; do
|
||||
case "$p" in
|
||||
performance) row "Profile: $p" battery-profile-performance ;;
|
||||
balanced) row "Profile: $p" battery-profile-balanced ;;
|
||||
power-saver) row "Profile: $p" battery-profile-powersave ;;
|
||||
*) row "Profile: $p" preferences-system-power ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if $havecharge; then
|
||||
row "Charge limit: 80% (recommended)" battery-080
|
||||
row "Charge limit: 90%" battery-090
|
||||
row "Charge limit: 60%" battery-060
|
||||
row "Charge limit: Off (100%)" battery-100
|
||||
fi
|
||||
back
|
||||
} | rofi -dmenu -show-icons -p "Power — profile: ''${curp:-n/a}, limit: ''${curc:-default}") || exit 0
|
||||
set_limit() {
|
||||
nomarchy-theme-sync --quiet set settings.power.batteryChargeLimit "$1" --no-switch
|
||||
notify-send "Battery limit" "$2 — applies on the next rebuild."
|
||||
}
|
||||
case "$choice" in
|
||||
"$BACK") exec "$0" ;;
|
||||
"Profile: "*) powerprofilesctl set "''${choice#Profile: }" ;;
|
||||
"Charge limit: 80%"*) set_limit 80 "Set to 80%" ;;
|
||||
"Charge limit: 90%"*) set_limit 90 "Set to 90%" ;;
|
||||
"Charge limit: 60%"*) set_limit 60 "Set to 60%" ;;
|
||||
"Charge limit: Off"*) set_limit null "Off — charges to 100%" ;;
|
||||
esac ;;
|
||||
|
||||
theme)
|
||||
# Visual picker: a grid of real desktop previews (rows + Name→slug
|
||||
# map generated from the presets at build time). Pick a card → apply
|
||||
@@ -790,7 +840,7 @@ ${themeRows}
|
||||
esac ;;
|
||||
|
||||
*)
|
||||
echo "usage: nomarchy-menu [lookfeel|tools|system|power|power-profile|batterylimit|theme|clipboard|calc|files|emoji|web|network|bluetooth|audio|display|display-profile|printers|capture|colorpicker|keybinds|ask|dnd|nightlight|autotimezone|autocommit|vpn|snapshot]" >&2
|
||||
echo "usage: nomarchy-menu [lookfeel|tools|system|power|power-profile|powermgmt|batterylimit|theme|clipboard|calc|files|emoji|web|network|bluetooth|audio|display|display-profile|printers|capture|colorpicker|keybinds|ask|dnd|nightlight|autotimezone|autocommit|vpn|snapshot]" >&2
|
||||
exit 64 ;;
|
||||
esac
|
||||
'';
|
||||
|
||||
@@ -199,13 +199,19 @@ let
|
||||
format = "<span size='${toString (t.fonts.size + 2)}pt'>{icon}</span> {capacity}%";
|
||||
format-charging = "<span size='${toString (t.fonts.size + 2)}pt'></span> {capacity}%";
|
||||
format-icons = [ "" "" "" "" "" ];
|
||||
# Click either the battery or the power-profile icon → the combined
|
||||
# power menu (profile + charge cap). The granular System rows stay.
|
||||
on-click = "nomarchy-menu powermgmt";
|
||||
};
|
||||
|
||||
"custom/powerprofile" = {
|
||||
exec = "nomarchy-powerprofile-status";
|
||||
return-type = "json";
|
||||
interval = 5;
|
||||
on-click = "nomarchy-powerprofile-cycle";
|
||||
# Opens the same combined power menu as the battery icon (item 36b).
|
||||
# nomarchy-powerprofile-cycle stays a standalone bin for downstream
|
||||
# rebinding — it's just no longer the default click.
|
||||
on-click = "nomarchy-menu powermgmt";
|
||||
};
|
||||
|
||||
# VPN shield — self-hides unless a NM VPN/WireGuard tunnel or Tailscale is
|
||||
|
||||
@@ -135,14 +135,14 @@
|
||||
"",
|
||||
""
|
||||
],
|
||||
"on-click": "nomarchy-menu power",
|
||||
"on-click": "nomarchy-menu powermgmt",
|
||||
"tooltip-format": "Battery status"
|
||||
},
|
||||
"custom/powerprofile": {
|
||||
"return-type": "json",
|
||||
"interval": 5,
|
||||
"exec": "nomarchy-powerprofile-status",
|
||||
"on-click": "nomarchy-powerprofile-cycle"
|
||||
"on-click": "nomarchy-menu powermgmt"
|
||||
},
|
||||
"tray": {
|
||||
"icon-size": 15,
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
"return-type": "json",
|
||||
"interval": 5,
|
||||
"exec": "nomarchy-powerprofile-status",
|
||||
"on-click": "nomarchy-powerprofile-cycle"
|
||||
"on-click": "nomarchy-menu powermgmt"
|
||||
},
|
||||
"battery": {
|
||||
"interval": 30,
|
||||
@@ -129,7 +129,7 @@
|
||||
"",
|
||||
""
|
||||
],
|
||||
"on-click": "nomarchy-menu power",
|
||||
"on-click": "nomarchy-menu powermgmt",
|
||||
"tooltip-format": "Battery status"
|
||||
},
|
||||
"custom/vpn": {
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"format-plugged": "<span size='13pt'></span> {capacity}%",
|
||||
"format-full": " 100%",
|
||||
"format-icons": ["", "", "", "", ""],
|
||||
"on-click": "nomarchy-menu power",
|
||||
"on-click": "nomarchy-menu powermgmt",
|
||||
"tooltip-format": "Battery status"
|
||||
},
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
"return-type": "json",
|
||||
"interval": 5,
|
||||
"exec": "nomarchy-powerprofile-status",
|
||||
"on-click": "nomarchy-powerprofile-cycle"
|
||||
"on-click": "nomarchy-menu powermgmt"
|
||||
},
|
||||
|
||||
"custom/recording": {
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"format-charging": "<span size='13pt'></span> {capacity}%",
|
||||
"format-plugged": "<span size='13pt'></span> {capacity}%",
|
||||
"format-icons": ["", "", "", "", ""],
|
||||
"on-click": "nomarchy-menu power",
|
||||
"on-click": "nomarchy-menu powermgmt",
|
||||
"tooltip-format": "Battery status"
|
||||
},
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
"return-type": "json",
|
||||
"interval": 5,
|
||||
"exec": "nomarchy-powerprofile-status",
|
||||
"on-click": "nomarchy-powerprofile-cycle"
|
||||
"on-click": "nomarchy-menu powermgmt"
|
||||
},
|
||||
|
||||
"custom/recording": {
|
||||
|
||||
Reference in New Issue
Block a user