Files
Modus/src/services/capslock.py
T

75 lines
2.2 KiB
Python

from pathlib import Path
from fabric.core.service import Property, Service, Signal
from fabric.utils import logger
from utils.utils import EvdevLEDMonitor
# Discover CapsLock LED device
capslock_leds = list(Path("/sys/class/leds").glob("input*::capslock"))
capslock_device = capslock_leds[0] if capslock_leds else None
class CapsLock(Service):
instance = None
@staticmethod
def get_initial():
if CapsLock.instance is None:
CapsLock.instance = CapsLock()
return CapsLock.instance
@Signal
def state_changed(self, is_on: bool) -> None:
"""Signal emitted when CapsLock state changes."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.capslock_led_path = capslock_device
self._last_state = None
self._monitoring_started = False
if capslock_device is None:
logger.warning("CapsLock device not found, CapsLock service disabled")
return
# LED_CAPSL = 1
self._monitor = EvdevLEDMonitor(
self.capslock_led_path, 1, self._on_state_changed
)
def _on_state_changed(self, is_on: bool):
if is_on != self._last_state:
self._last_state = is_on
self.emit("state_changed", is_on)
def stop(self):
if hasattr(self, "_monitor"):
self._monitor.stop()
def _ensure_monitoring_started(self):
if not self._monitoring_started and self.capslock_led_path:
self._monitoring_started = True
# Set initial state before starting monitoring
self._last_state = self._get_current_state()
self._monitor._last_state = self._last_state
self._monitor.start()
def _get_current_state(self) -> bool:
if not self.capslock_led_path:
return False
brightness_path = self.capslock_led_path / "brightness"
if brightness_path.exists():
try:
return bool(int(brightness_path.read_text().strip()))
except (ValueError, OSError):
return False
return False
@Property(bool, "read-write", default_value=False)
def is_on(self) -> bool:
self._ensure_monitoring_started()
return self._get_current_state()