Files
Cachy-Predator-Keyboard/predator_control/idle.py
T
MrBlakeandClaude Opus 5.5 571cfcca2a Add power settings for the lighting, bump to 1.4.0
New Power page:
- toggle for the firmware's 30 s keyboard backlight timeout
- idle timeout for keyboard and lightbar, separately for AC and battery;
  predatord watches all input devices and restores the lighting on the
  next input
- battery rules: dimmed keyboard brightness, keyboard off, lightbar off

The rules only change what is sent to the hardware; the saved lighting
settings stay untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:59:42 +02:00

57 lines
1.7 KiB
Python

"""Input activity watcher used for the 'turn lighting off when idle' feature."""
import glob
import os
import select
import threading
import time
class IdleWatcher(threading.Thread):
"""Tracks the time of the last keyboard/touchpad/mouse event on any input device."""
RESCAN = 30 # seconds between scans for new devices (hotplug, resume)
def __init__(self, on_activity=None):
super().__init__(daemon=True)
self.last_input = time.monotonic()
self.on_activity = on_activity
def idle_seconds(self):
return time.monotonic() - self.last_input
def _open_all(self, fds):
for path in glob.glob("/dev/input/event*"):
if path in fds.values():
continue
try:
fds[os.open(path, os.O_RDONLY | os.O_NONBLOCK)] = path
except OSError:
pass
def run(self):
fds = {}
next_scan = 0.0
while True:
if time.monotonic() >= next_scan:
self._open_all(fds)
next_scan = time.monotonic() + self.RESCAN
if not fds:
time.sleep(5)
continue
ready, _, _ = select.select(list(fds), [], [], 5)
active = False
for fd in ready:
try:
if os.read(fd, 4096):
active = True
except BlockingIOError:
pass
except OSError:
os.close(fd)
fds.pop(fd, None)
if active:
self.last_input = time.monotonic()
if self.on_activity:
self.on_activity()