feat(presence-detect): skip the camera entirely during a manual caffeine session

When idle is inhibited manually (a caffeine toggle, not this daemon), the lock
is held regardless of presence, so polling the camera is pointless. Guard the
loop: if the shared idle lock is alive but we don't own it (same test as
caffeine-manual-status.sh), skip the read and leave the camera free for other
apps for the whole manual session. PRESENCE_FLAG is cleared while skipping,
since we're no longer watching — so the widget's presence input reads false
during a manual session instead of showing a stale "camera sees you".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
main
Amir Alexander Abdelbaki 2026-07-11 04:01:16 +02:00
parent bc544898c1
commit 83687764d8
2 changed files with 23 additions and 12 deletions

View File

@ -30,11 +30,12 @@ PID_FILE="/tmp/caffeine-inhibit.pid"
# Marks that *this daemon* (not the manual caffeine toggle) currently holds
# the lock, so a "no motion" tick never releases a manually-started session.
OWNED_FLAG="/tmp/presence-inhibit-owned"
# Records whether the camera currently SEES the user (motion on the last tick),
# INDEPENDENT of who holds the idle lock. Unlike OWNED_FLAG this is set even when
# a manual caffeine session already owns the lock (so the daemon never starts its
# own inhibitor). presence-status.sh reads this so the Eww widget can show the
# presence input as a distinct signal from a manual caffeine toggle.
# Records whether the camera currently SEES the user (motion, or the camera
# being in use by another app, on the last tick). presence-status.sh reads this
# so the Eww widget can show presence as a distinct signal from the idle lock.
# It reflects live camera state only while the daemon is actively watching:
# during a MANUAL caffeine session the daemon stops reading the camera entirely
# (to leave it free) and clears this flag, so presence reads false there.
PRESENCE_FLAG="/tmp/presence-detected"
PRESENCE_CFG="${XDG_CONFIG_HOME:-$HOME/.config}/presence-detect.conf"
@ -133,6 +134,18 @@ trap _cleanup SIGTERM SIGINT SIGHUP
LAST_MOTION=0
while true; do
# When idle is inhibited MANUALLY (a caffeine toggle, not this daemon), the
# lock is already held regardless of presence, so there's no reason to look
# at the camera — skip the read entirely and leave the device free for other
# apps. Detected the same way caffeine-manual-status.sh does it: the shared
# lock is alive but we don't own it. We clear PRESENCE_FLAG because we're no
# longer watching and must not report a stale "camera sees you".
if _inhibit_running && [[ ! -f "$OWNED_FLAG" ]]; then
rm -f "$PRESENCE_FLAG"
sleep "$(_next_interval)"
continue
fi
DEVICE="$(_camera_id)"
# Run the OpenCV motion detector; stderr suppressed to keep the journal clean.
python3 "$PYTHON_DETECT" "$DEVICE" 2>/dev/null
@ -143,9 +156,6 @@ while true; do
# another app (a video call, howdy) is holding the camera, which is
# itself proof you're here, so it keeps the session awake even though we
# can't read frames. Both refresh the grace clock and mark presence.
# PRESENCE_FLAG is updated *independently* of the inhibit lock — it
# reflects "user is present" even during a manual caffeine session (where
# _start_inhibit is a no-op because the lock is already held).
0|3) LAST_MOTION="$now"; touch "$PRESENCE_FLAG"; _start_inhibit ;;
# No motion: only actually release once we've been still for the whole
# grace window. Within it, leave the flag/lock exactly as they were so a

View File

@ -3,10 +3,11 @@
# presence-detect daemon currently sees the user (motion on its last tick),
# INDEPENDENT of whether the idle lock is held or who holds it.
#
# presence-detect.sh writes PRESENCE_FLAG on every "motion" tick and removes it
# on every "no motion" tick, so this is a clean, standalone signal — true even
# during a manual caffeine session (where the daemon never starts its own
# inhibitor). For the MANUAL-inhibit input, see caffeine-manual-status.sh.
# presence-detect.sh writes PRESENCE_FLAG on every "present" tick and removes it
# on every "away" tick, so this is a clean, standalone signal. Note: during a
# MANUAL caffeine session the daemon stops reading the camera (to leave it free)
# and clears the flag, so presence reads false there. For the MANUAL-inhibit
# input, see caffeine-manual-status.sh.
#
# Prints "true" when presence is detected, else "false".
PRESENCE_FLAG="/tmp/presence-detected"