Give a laptop its first week: the keys, the lid, the battery's endgame
The audit's fourth tier -- what a Framework owner reaches for in the first week and found missing. The power button stops being an instant, unconfirmed poweroff: a shipped logind drop-in tells the daemon to stand down and the compositor binds the key to the power menu, the way GNOME turns it into a question. Holding it still hard-cuts through firmware. change-settings restarts logind so the change applies without waiting for a boot, and the Power page says what the button does now. The function row fills in: F10 (XF86RFKill) toggles airplane mode through a new panama-osd verb that blocks or unblocks every radio and says which way it went; F9 (XF86Display) opens the Displays page, the honest action until mirroring exists. And the lid becomes a switch bind: closing a docked lid turns the internal panel off so nothing renders inside a closed shell and no workspace strands on an invisible output, and opening it restores the panel with the mode and scale chosen in Settings. panama-lid owns both decisions; undocked machines suspend via logind before any of it matters. The battery gets an endgame. On battery the screen dims to 30% two-thirds of the way to blanking -- GNOME's single largest idle battery saver -- and restores exactly the level it saved. At the urgent threshold the machine suspends after a fifteen-second grace, cancelled by plugging in, because a suspend preserves the session for days and a hard cut at 0% preserves nothing; "Only warn" remains a choice on the Power page. Hibernate joins the power menu, but only where logind answers CanHibernate with yes -- an entry that fails silently is worse than none. And brightness stops being two code paths: the Displays page now embeds the same control the quick-settings panel uses, so the built-in backlight and DDC/CI monitors share one surface that withdraws itself where neither exists. The lid contract narrows to what its principle protects -- a HandleLidSwitch drop-in -- so deliberate policy for other keys can ship. Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# A stray press of the power button should ask, not act. Fedora's logind
|
||||
# default is HandlePowerKey=poweroff -- an instant, unconfirmed shutdown.
|
||||
# Panama binds the key in the compositor to open its power menu instead
|
||||
# (keybinds.lua), the way GNOME turns the key into a dialog, so logind is
|
||||
# told to stand down. Holding the button still hard-cuts through firmware,
|
||||
# which remains the escape hatch this file cannot and should not remove.
|
||||
[Login]
|
||||
HandlePowerKey=ignore
|
||||
@@ -34,6 +34,10 @@ local osd = function(action)
|
||||
return "$HOME/.config/quickshell/scripts/panama-osd " .. action
|
||||
end
|
||||
|
||||
local lid = function(action)
|
||||
return "$HOME/.config/quickshell/scripts/panama-lid " .. action
|
||||
end
|
||||
|
||||
local dictate = function(action)
|
||||
return "$HOME/.config/quickshell/scripts/panama-dictate " .. action
|
||||
end
|
||||
@@ -458,6 +462,30 @@ bind("XF86AudioStop", hl.dsp.exec_cmd(osd("media stop")), { locked = true , desc
|
||||
bind("XF86MonBrightnessUp", hl.dsp.exec_cmd(osd("brightness up 5")), { locked = true, repeating = true , description = "Brightness up" })
|
||||
bind("XF86MonBrightnessDown", hl.dsp.exec_cmd(osd("brightness down 5")), { locked = true, repeating = true , description = "Brightness down" })
|
||||
|
||||
-- Airplane mode. The Framework's F10 emits exactly this keysym, and for a
|
||||
-- while it emitted it into silence. panama-osd owns the toggle so the OSD
|
||||
-- can say which way it went.
|
||||
bind("XF86RFKill", hl.dsp.exec_cmd(osd("airplane toggle")), { locked = true, description = "Airplane mode" })
|
||||
|
||||
-- F9 on the same row. GNOME shows a display-switching OSD here; until
|
||||
-- mirroring exists (DESKTOP-PARITY gap), the honest action is the page where
|
||||
-- displays are actually arranged.
|
||||
bind("XF86Display", hl.dsp.exec_cmd("qs ipc call settings page displays"), { description = "Display settings" })
|
||||
|
||||
-- The power button. logind is told to ignore it (config/copy ships the
|
||||
-- drop-in) so a stray press is a question, not an instant poweroff -- the
|
||||
-- menu this opens is the question. Until the next boot after that drop-in
|
||||
-- lands, logind still acts on the key; this bind costs nothing extra then.
|
||||
bind("XF86PowerOff", hl.dsp.exec_cmd("qs ipc call powermenu toggle"), { locked = true, description = "Power menu" })
|
||||
|
||||
-- The lid, as a switch rather than a key. Closing a docked lid turns the
|
||||
-- internal panel off so nothing renders inside a closed shell and no
|
||||
-- workspace strands on an invisible output; opening it turns the panel back
|
||||
-- on. panama-lid owns the decision -- undocked machines suspend via logind
|
||||
-- before this matters, and the guard's inhibitor handles staying awake.
|
||||
bind("switch:on:Lid Switch", hl.dsp.exec_cmd(lid("close")), { locked = true, description = "Lid closed" })
|
||||
bind("switch:off:Lid Switch", hl.dsp.exec_cmd(lid("open")), { locked = true, description = "Lid opened" })
|
||||
|
||||
category("Applications")
|
||||
-- Hardware keys GNOME mapped that have obvious equivalents.
|
||||
bind("XF86Tools", hl.dsp.exec_cmd(settings), { description = "Settings" })
|
||||
|
||||
@@ -125,6 +125,20 @@ Singleton {
|
||||
label: "Urgent at",
|
||||
detail: "Interrupt at this level, even during Do Not Disturb"
|
||||
},
|
||||
// What the desktop DOES at the critical threshold, beyond interrupting.
|
||||
// Suspend by default, which is GNOME's behavior: sleep preserves the
|
||||
// session at a level the firmware can hold for days, and the
|
||||
// alternative -- a hard cut at 0% -- preserves nothing.
|
||||
{
|
||||
key: "batteryCriticalAction", type: "enum", def: "suspend", group: "battery",
|
||||
label: "At the urgent level",
|
||||
detail: "What happens when the battery reaches the urgent threshold while discharging",
|
||||
options: [
|
||||
{ value: "suspend", label: "Suspend" },
|
||||
{ value: "nothing", label: "Only warn" }
|
||||
]
|
||||
},
|
||||
|
||||
// Only offered where the firmware exposes a ceiling; the Power page
|
||||
// hides the control entirely otherwise. 100 means charge to full.
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// (see PowerButton); Lock and Suspend are one press because neither loses work.
|
||||
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import QtQuick
|
||||
import qs.config
|
||||
@@ -31,6 +32,23 @@ PanelWindow {
|
||||
|
||||
property int currentIndex: 0
|
||||
|
||||
// Hibernate appears only where it can deliver: logind answers "yes" only
|
||||
// with a resume-capable swap configured, and a menu entry that fails
|
||||
// silently is worse than none. Checked once per shell run -- swap does
|
||||
// not come and go.
|
||||
property bool canHibernate: false
|
||||
|
||||
Process {
|
||||
id: hibernateProbe
|
||||
command: ["busctl", "call", "org.freedesktop.login1",
|
||||
"/org/freedesktop/login1", "org.freedesktop.login1.Manager",
|
||||
"CanHibernate"]
|
||||
running: true
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: win.canHibernate = this.text.includes('"yes"')
|
||||
}
|
||||
}
|
||||
|
||||
// A uwsm-managed session logs out by stopping the uwsm unit; a plain
|
||||
// "Hyprland" session must ask the compositor to exit instead. The branch
|
||||
// used to test merely that the uwsm BINARY existed -- but uwsm is always
|
||||
@@ -41,7 +59,11 @@ PanelWindow {
|
||||
// compositor unit, wayland-wm@*.service, so that is what decides.
|
||||
readonly property string logoutScript: 'if systemctl --user list-units --no-legend --state=active "wayland-wm@*.service" 2>/dev/null | grep -q .; then exec uwsm stop; else exec hyprctl dispatch "hl.dsp.exit()"; fi'
|
||||
|
||||
readonly property var entries: [
|
||||
// The rows actually shown: an entry may declare `available: false` to
|
||||
// withdraw itself (hibernate on a machine with no resume swap).
|
||||
readonly property var entries: allEntries.filter(entry => entry.available !== false)
|
||||
|
||||
readonly property var allEntries: [
|
||||
{
|
||||
glyph: "",
|
||||
label: "Lock",
|
||||
@@ -60,6 +82,13 @@ PanelWindow {
|
||||
destructive: false,
|
||||
cmd: ["systemctl", "suspend"]
|
||||
},
|
||||
{
|
||||
glyph: "",
|
||||
label: "Hibernate",
|
||||
destructive: false,
|
||||
available: win.canHibernate,
|
||||
cmd: ["systemctl", "hibernate"]
|
||||
},
|
||||
{
|
||||
glyph: "",
|
||||
label: "Restart",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import QtQuick
|
||||
import qs.config
|
||||
import qs.services
|
||||
import qs.modules.quicksettings
|
||||
import qs.widgets
|
||||
|
||||
SettingsPage {
|
||||
@@ -289,35 +290,21 @@ SettingsPage {
|
||||
// writing it into settings.json would mean restoring a value the panel had
|
||||
// already moved on from. So there is no schema key here and no SliderRow --
|
||||
// the rows read and write the display directly.
|
||||
// One brightness surface for both kinds this machine may have, shared
|
||||
// with the quick-settings panel so the two can never disagree. This card
|
||||
// was DDC/CI-only for a while, which on a laptop meant Settings showed
|
||||
// an error about external-monitor brightness while the panel's backlight
|
||||
// worked fine one panel over.
|
||||
SettingsCard {
|
||||
visible: Brightness.available || Brightness.lastError !== ""
|
||||
visible: pageBrightness.visible || Brightness.lastError !== ""
|
||||
title: "Brightness"
|
||||
subtitle: Brightness.available
|
||||
? "Sent to the monitor over DDC/CI, the same channel its buttons use."
|
||||
subtitle: pageBrightness.visible
|
||||
? "The built-in panel through its backlight; external monitors over DDC/CI, the same channel their buttons use."
|
||||
: Brightness.lastError
|
||||
|
||||
Repeater {
|
||||
model: Brightness.displays
|
||||
|
||||
SettingRow {
|
||||
id: brightnessRow
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
label: Displays.monitorNamed(modelData.connector)?.description || modelData.connector
|
||||
detail: modelData.connector ? modelData.connector + " · " + modelData.value + "%"
|
||||
: modelData.value + "%"
|
||||
divider: brightnessRow.index < Brightness.displays.length - 1
|
||||
controlWidth: 190
|
||||
|
||||
ValueSlider {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
BrightnessControl {
|
||||
id: pageBrightness
|
||||
width: parent.width
|
||||
value: brightnessRow.modelData.value / 100
|
||||
onMoved: v => Brightness.set(brightnessRow.modelData.bus, Math.round(v * 100))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,9 @@ SettingsPage {
|
||||
// page rendered them -- search delivered people to this card and the
|
||||
// controls were not here.
|
||||
SliderRow { setting: "batteryLowPercent" }
|
||||
SliderRow {
|
||||
setting: "batteryCriticalPercent"
|
||||
SliderRow { setting: "batteryCriticalPercent" }
|
||||
ChoiceRow {
|
||||
setting: "batteryCriticalAction"
|
||||
divider: Battery.chargeLimitSupported
|
||||
}
|
||||
|
||||
@@ -149,6 +150,15 @@ SettingsPage {
|
||||
}
|
||||
}
|
||||
|
||||
// Informational like the lid card above it: the behavior is a logind
|
||||
// drop-in plus a compositor bind (see keybinds.lua), not a preference,
|
||||
// and saying what a physical button does beats leaving it to be
|
||||
// discovered by pressing it.
|
||||
SettingsCard {
|
||||
title: "The power button"
|
||||
subtitle: "A press opens the power menu instead of powering off immediately. Holding it still forces power off through the firmware, as ever."
|
||||
}
|
||||
|
||||
// Only shown when the numbers are actually contradictory, rather than as a
|
||||
// permanent warning nobody reads.
|
||||
SettingsCard {
|
||||
|
||||
@@ -117,6 +117,25 @@ generate() {
|
||||
printf ' inhibit_sleep = 2\n'
|
||||
printf '}\n'
|
||||
|
||||
# On battery, dim before blanking -- GNOME's single largest idle
|
||||
# battery saver, and the gentle warning that the screen is about to
|
||||
# go. Two-thirds of the way to blank, floor of 30 seconds; -s saves
|
||||
# the level and -r restores exactly it, so a person's brightness
|
||||
# choice survives the round trip. Only where a real backlight exists:
|
||||
# a desktop's DDC monitor is not worth waking over this.
|
||||
if on_battery && (( blank_min > 0 )) \
|
||||
&& command -v brightnessctl >/dev/null 2>&1 \
|
||||
&& [[ -n "$(ls /sys/class/backlight 2>/dev/null)" ]]; then
|
||||
dim_at=$(( blank_min * 60 * 2 / 3 ))
|
||||
(( dim_at < 30 )) && dim_at=30
|
||||
printf '\n# %s seconds -> dim, undone on activity.\n' "$dim_at"
|
||||
printf 'listener {\n'
|
||||
printf ' timeout = %s\n' "$dim_at"
|
||||
printf ' on-timeout = brightnessctl -c backlight -s set 30%%\n'
|
||||
printf ' on-resume = brightnessctl -c backlight -r\n'
|
||||
printf '}\n'
|
||||
fi
|
||||
|
||||
if (( blank_min > 0 )); then
|
||||
printf '\n# %s minutes -> screen off.\n' "$blank_min"
|
||||
printf 'listener {\n'
|
||||
|
||||
@@ -68,16 +68,64 @@ cmd_guard() {
|
||||
sleep infinity
|
||||
}
|
||||
|
||||
# The internal panel's connector name, from the compositor: eDP, LVDS and
|
||||
# DSI are built in, everything else arrived through a cable -- the same rule
|
||||
# panama-hw and LidPolicy use.
|
||||
internal_connector() {
|
||||
hyprctl -j monitors all 2>/dev/null \
|
||||
| jq -r '[.[] | select(.name | test("^(eDP|LVDS|DSI)"; "i"))][0].name // empty'
|
||||
}
|
||||
|
||||
# Bound to the lid switch by keybinds.lua. Closing a DOCKED lid turns the
|
||||
# internal panel off, so nothing renders inside a closed shell and no
|
||||
# workspace strands on an invisible output; an undocked lid does nothing here
|
||||
# because logind is already suspending the machine. Failure direction: if the
|
||||
# disable never runs, the panel stays lit inside the shell -- wasteful, not
|
||||
# harmful.
|
||||
cmd_close() {
|
||||
"$HW" laptop || exit 0
|
||||
"$HW" external-monitor || exit 0
|
||||
local internal
|
||||
internal="$(internal_connector)"
|
||||
[[ -n "$internal" ]] || exit 0
|
||||
hyprctl eval "hl.monitor({ output = \"$internal\", disable = true })" >/dev/null
|
||||
}
|
||||
|
||||
# Re-enable on open, preferring what the person chose for this panel in
|
||||
# Settings (the same displays store monitors.lua reads at startup) and
|
||||
# falling back to the panel's preferred mode.
|
||||
cmd_open() {
|
||||
"$HW" laptop || exit 0
|
||||
local internal entry mode scale
|
||||
internal="$(internal_connector)"
|
||||
[[ -n "$internal" ]] || exit 0
|
||||
entry="$(jq -c --arg name "$internal" '.displays[$name] // empty' \
|
||||
"${XDG_CONFIG_HOME:-$HOME/.config}/panama/settings.json" 2>/dev/null)"
|
||||
if [[ -n "$entry" ]]; then
|
||||
mode="$(jq -r '.mode' <<<"$entry")"
|
||||
scale="$(jq -r '.scale' <<<"$entry")"
|
||||
hyprctl eval "hl.monitor({ output = \"$internal\", mode = \"$mode\", position = \"auto\", scale = $scale })" >/dev/null
|
||||
else
|
||||
hyprctl eval "hl.monitor({ output = \"$internal\", mode = \"preferred\", position = \"auto\", scale = \"auto\" })" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-status}" in
|
||||
status) cmd_status ;;
|
||||
guard) cmd_guard ;;
|
||||
close) cmd_close ;;
|
||||
open) cmd_open ;;
|
||||
-h|--help)
|
||||
cat <<'USAGE'
|
||||
usage: panama-lid [status|guard]
|
||||
usage: panama-lid [status|guard|close|open]
|
||||
|
||||
status what closing the lid would do right now, as JSON
|
||||
guard hold a handle-lid-switch inhibitor while an external display is
|
||||
connected; exits immediately on a machine that needs none
|
||||
close docked lid closed: turn the internal panel off (bound to the lid
|
||||
switch by keybinds.lua); does nothing undocked
|
||||
open lid opened: turn the internal panel back on, restoring the mode
|
||||
and scale chosen in Settings
|
||||
USAGE
|
||||
;;
|
||||
*) printf 'panama-lid: unknown command: %s\n' "$1" >&2; exit 2 ;;
|
||||
|
||||
@@ -240,11 +240,34 @@ media_action() {
|
||||
show_message "$kind" "$label"
|
||||
}
|
||||
|
||||
# Airplane mode: one rfkill state for every radio, with an OSD saying which
|
||||
# way it went. "Any radio unblocked" reads as radios-on, so toggle means
|
||||
# "block everything" from a mixed state -- the direction a person reaching
|
||||
# for airplane mode wants.
|
||||
airplane_action() {
|
||||
case "${1:-toggle}" in
|
||||
toggle)
|
||||
if rfkill list 2>/dev/null | grep -q 'Soft blocked: no'; then
|
||||
rfkill block all 2>/dev/null \
|
||||
&& show_message "airplane-mode-symbolic" "Airplane mode on"
|
||||
else
|
||||
rfkill unblock all 2>/dev/null \
|
||||
&& show_message "network-wireless-symbolic" "Airplane mode off"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
printf 'Usage: panama-osd airplane toggle\n' >&2
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
volume) shift; adjust_volume "$@" ;;
|
||||
microphone) shift; adjust_microphone "$@" ;;
|
||||
brightness) shift; adjust_brightness "$@" ;;
|
||||
media) shift; media_action "$@" ;;
|
||||
airplane) shift; airplane_action "$@" ;;
|
||||
message)
|
||||
shift
|
||||
kind="${1:-}"
|
||||
@@ -256,7 +279,7 @@ case "${1:-}" in
|
||||
show_message "$kind" "$*"
|
||||
;;
|
||||
*)
|
||||
printf 'Usage: panama-osd volume|microphone|brightness|media|message ACTION [value]\n' >&2
|
||||
printf 'Usage: panama-osd volume|microphone|brightness|media|airplane|message ACTION [value]\n' >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -7,6 +7,7 @@ import Quickshell.Bluetooth
|
||||
import Quickshell.Io
|
||||
import Quickshell.Services.Pipewire
|
||||
import QtQuick
|
||||
import qs.config
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
@@ -146,11 +147,38 @@ Singleton {
|
||||
// Running out is not ambient. Published at a priority Do Not Disturb does
|
||||
// not silence, because the one notification you must not miss is the one
|
||||
// saying the machine is about to stop.
|
||||
//
|
||||
// And then, unless told otherwise, the machine is put to sleep: a suspend
|
||||
// at the urgent threshold preserves the session for days, a hard cut at
|
||||
// 0% preserves nothing. The grace timer is what makes the warning above
|
||||
// readable and the action cancelable -- plugging in during it stands
|
||||
// everything down.
|
||||
Timer {
|
||||
id: criticalSuspend
|
||||
interval: 15000
|
||||
onTriggered: {
|
||||
if (Battery.critical && !Battery.acOnline
|
||||
&& DesktopPreferences.get("batteryCriticalAction") === "suspend")
|
||||
Quickshell.execDetached(["systemctl", "suspend"]);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Battery
|
||||
function onAcOnlineChanged(): void {
|
||||
if (Battery.acOnline)
|
||||
criticalSuspend.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Battery
|
||||
function onCriticalChanged(): void {
|
||||
if (!root.powerInitialized || !Battery.critical)
|
||||
return;
|
||||
if (!Battery.acOnline
|
||||
&& DesktopPreferences.get("batteryCriticalAction") === "suspend")
|
||||
criticalSuspend.restart();
|
||||
StatusEvents.publish({
|
||||
key: "battery-critical",
|
||||
glyph: "\u{F0083}",
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
# @vicinae.mode silent
|
||||
# @vicinae.icon ../../icons/hicolor/scalable/apps/panama-settings.svg
|
||||
# @vicinae.description Open Power & Lock in Settings.
|
||||
# @vicinae.keywords ["settings", "warn at", "urgent at", "stop charging at", "turn the screen off after", "lock the screen after", "suspend after", "lock before sleeping", "lock after"]
|
||||
# @vicinae.keywords ["settings", "warn at", "urgent at", "at the urgent level", "stop charging at", "turn the screen off after", "lock the screen after", "suspend after", "lock before sleeping", "lock after"]
|
||||
|
||||
exec "$HOME/.config/quickshell/scripts/panama-action" settings-page power
|
||||
|
||||
+2
-1
@@ -4,7 +4,7 @@
|
||||
Do not edit this file. Run `quickshell/scripts/panama-settings-docs`
|
||||
after changing the schema; a contract fails when this copy is stale.
|
||||
|
||||
149 settings across 30 groups. 70 of them are applied to the compositor and confirmed by reading the value back.
|
||||
150 settings across 30 groups. 70 of them are applied to the compositor and confirmed by reading the value back.
|
||||
|
||||
## accessibility
|
||||
|
||||
@@ -37,6 +37,7 @@ Found on **Power & Lock**.
|
||||
|---|---|---|
|
||||
| **Warn at**<br>`batteryLowPercent` | 20 % | Mention the battery once it drops this low. Range 5–50. |
|
||||
| **Urgent at**<br>`batteryCriticalPercent` | 5 % | Interrupt at this level, even during Do Not Disturb. Range 1–25. |
|
||||
| **At the urgent level**<br>`batteryCriticalAction` | suspend | What happens when the battery reaches the urgent threshold while discharging Choices: Suspend, Only warn. |
|
||||
| **Stop charging at**<br>`batteryChargeLimit` | 100 % | Charging to less than full is easier on the battery over years. Range 50–100. |
|
||||
|
||||
## capture
|
||||
|
||||
@@ -37,6 +37,16 @@ if [[ -f /etc/udev/rules.d/99-panama-gpu.rules ]]; then
|
||||
sudo udevadm trigger --subsystem-match=drm
|
||||
fi
|
||||
|
||||
# The power-key drop-in lands via the same copy; logind reads its config only
|
||||
# at start, so without this the button keeps hard-powering-off until the next
|
||||
# boot. Restarting logind is what Fedora's own updates do and current systemd
|
||||
# preserves sessions across it.
|
||||
if [[ -f /etc/systemd/logind.conf.d/panama-power-key.conf ]]; then
|
||||
log "Reloading logind so the power button opens the menu instead of powering off"
|
||||
sudo systemctl try-restart systemd-logind 2>/dev/null \
|
||||
|| log "Could not restart logind; the power-button change applies at next boot"
|
||||
fi
|
||||
|
||||
# The document-portal drop-in lands via the same copy. A user unit's drop-ins
|
||||
# are read at daemon-reload, so without this the guard applies from the next
|
||||
# login rather than from now -- and the failure it guards against is one you
|
||||
|
||||
@@ -36,7 +36,7 @@ SHELL_WORDS='^(if|then|else|elif|fi|for|while|until|do|done|case|esac|in|functio
|
||||
# authselect is on the list for the same reason: it manages Fedora's PAM and
|
||||
# nsswitch profiles and arrives with fprintd-pam, realmd and nss-mdns, so the
|
||||
# fingerprint aliases in config/bash can rely on it without declaring it.
|
||||
BASELINE='^(sh|bash|cat|cut|sed|awk|gawk|grep|egrep|head|tail|sort|uniq|tr|wc|find|xargs|basename|dirname|mkdir|rm|cp|mv|ln|chmod|chown|stat|df|du|date|sleep|env|id|tee|touch|mktemp|readlink|realpath|seq|comm|join|paste|od|file|nl|fold|column|tput|timeout|flock|install|sha256sum|md5sum|base64|nproc|uptime|free|uname|hostname|whoami|ps|pgrep|pkill|kill|killall|lsblk|mount|umount|sudo|su|rpm|dnf|flatpak|git|python3|ss|ip|lsof|authselect|setsid|nohup|grub2-mkconfig)$'
|
||||
BASELINE='^(sh|bash|cat|cut|sed|awk|gawk|grep|egrep|head|tail|sort|uniq|tr|wc|find|xargs|basename|dirname|mkdir|rm|cp|mv|ln|chmod|chown|stat|df|du|date|sleep|env|id|tee|touch|mktemp|readlink|realpath|seq|comm|join|paste|od|file|nl|fold|column|tput|timeout|flock|install|sha256sum|md5sum|base64|nproc|uptime|free|uname|hostname|whoami|ps|pgrep|pkill|kill|killall|lsblk|mount|umount|sudo|su|rpm|dnf|flatpak|git|python3|ss|ip|ls|rfkill|lsof|authselect|setsid|nohup|grub2-mkconfig)$'
|
||||
|
||||
SESSION='^(systemctl|busctl|journalctl|loginctl|hostnamectl|localectl|systemd-inhibit|systemd-run|udevadm|gsettings|dconf|dbus-send|dbus-monitor|hyprctl|qs|quickshell|gnf|panama|wl-copy|wl-paste)$'
|
||||
|
||||
|
||||
@@ -46,8 +46,12 @@ mkdir -p "$fake/bin"
|
||||
|
||||
# ── 1. Panama never takes the lid over ───────────────────────────────────────
|
||||
|
||||
if compgen -G "$repo_dir/config/copy/etc/systemd/logind.conf.d/*" >/dev/null 2>&1; then
|
||||
note 'a logind drop-in is shipped; the inhibitor approach exists so the lid is never left doing nothing'
|
||||
# Specifically the LID. Other keys may be configured there -- the power-key
|
||||
# drop-in is deliberate policy with a compositor bind behind it -- but a
|
||||
# HandleLidSwitch line would replace the inhibitor design this file protects.
|
||||
if compgen -G "$repo_dir/config/copy/etc/systemd/logind.conf.d/*" >/dev/null 2>&1 \
|
||||
&& sed 's/#.*//' "$repo_dir"/config/copy/etc/systemd/logind.conf.d/* | grep -q 'HandleLidSwitch'; then
|
||||
note 'a logind drop-in sets HandleLidSwitch; the inhibitor approach exists so the lid is never left doing nothing'
|
||||
fi
|
||||
# Comments are stripped first: these files explain at length what they
|
||||
# deliberately do NOT do, and prose naming HandleLidSwitch or lock-session is
|
||||
|
||||
Reference in New Issue
Block a user