From 294788a31476d9a2b069bbb4fcd8f631931794c8 Mon Sep 17 00:00:00 2001 From: Uyanide Date: Mon, 20 Apr 2026 18:59:18 +0200 Subject: [PATCH] led_monitor -> led-monitor --- .../quickshell/Services/CapslockService.qml | 2 +- .../scripts/{led_monitor => led-monitor} | 38 +++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) rename config/scripts/.local/scripts/{led_monitor => led-monitor} (88%) diff --git a/config/quickshell/.config/quickshell/Services/CapslockService.qml b/config/quickshell/.config/quickshell/Services/CapslockService.qml index 69fdd37..ff1e880 100644 --- a/config/quickshell/.config/quickshell/Services/CapslockService.qml +++ b/config/quickshell/.config/quickshell/Services/CapslockService.qml @@ -18,7 +18,7 @@ Singleton { id: capslockMonitorProcess running: true - command: ["led_monitor", "-l", "capslock"] + command: ["led-monitor", "-l", "capslock"] stdout: SplitParser { splitMarker: "\n" diff --git a/config/scripts/.local/scripts/led_monitor b/config/scripts/.local/scripts/led-monitor similarity index 88% rename from config/scripts/.local/scripts/led_monitor rename to config/scripts/.local/scripts/led-monitor index 40a4250..cfb1040 100755 --- a/config/scripts/.local/scripts/led_monitor +++ b/config/scripts/.local/scripts/led-monitor @@ -4,21 +4,17 @@ import glob import argparse import select import os -import fcntl import struct # struct input_event: struct timeval (typically 2 longs), type (uint16), code (uint16), value (int32) # '@' ensures native byte order, size, and alignment. -EVENT_FORMAT = '@llHHi' +EVENT_FORMAT = "@llHHi" EVENT_SIZE = struct.calcsize(EVENT_FORMAT) EV_LED = 0x11 -LED_CODES = { - 'numlock': 0x00, - 'capslock': 0x01, - 'scrolllock': 0x02 -} +LED_CODES = {"numlock": 0x00, "capslock": 0x01, "scrolllock": 0x02} + def get_led_state(led_type: str) -> int: pattern = f"/sys/class/leds/*::{led_type}/brightness" @@ -27,24 +23,26 @@ def get_led_state(led_type: str) -> int: return 0 for path in paths: try: - with open(path, 'r') as f: + with open(path, "r") as f: if int(f.read().strip()) > 0: return 1 except (IOError, ValueError, OSError): continue return 0 + def has_led_capability(event_path: str) -> bool: try: basename = os.path.basename(event_path) cap_path = f"/sys/class/input/{basename}/device/capabilities/led" if os.path.exists(cap_path): - with open(cap_path, 'r') as f: + with open(cap_path, "r") as f: return f.read().strip() != "0" except OSError: pass return False + class DeviceMonitor: def __init__(self, target_led: str): self.target_led = target_led @@ -62,7 +60,7 @@ class DeviceMonitor: def scan_devices(self) -> None: current_fds = set(self.active_fds.keys()) - paths = glob.glob('/dev/input/event*') + paths = glob.glob("/dev/input/event*") found_fds = set() for path in paths: @@ -134,9 +132,14 @@ class DeviceMonitor: events_count = len(data) // EVENT_SIZE for i in range(events_count): chunk = data[i * EVENT_SIZE : (i + 1) * EVENT_SIZE] - _, _, ev_type, ev_code, _ = struct.unpack(EVENT_FORMAT, chunk) + _, _, ev_type, ev_code, _ = struct.unpack( + EVENT_FORMAT, chunk + ) - if ev_type == EV_LED and ev_code == self.target_led_code: + if ( + ev_type == EV_LED + and ev_code == self.target_led_code + ): # Instead of acting immediately on the value, we just flag it. # This prevents state bouncing between multiple kernel devices. led_event_triggered = True @@ -166,19 +169,22 @@ class DeviceMonitor: except Exception: pass + def main(): parser = argparse.ArgumentParser(description="Keyboard LED monitor.") parser.add_argument( - '-l', '--led', + "-l", + "--led", type=str, - default='capslock', - choices=['capslock', 'numlock', 'scrolllock'], - help="Target LED to monitor" + default="capslock", + choices=["capslock", "numlock", "scrolllock"], + help="Target LED to monitor", ) args = parser.parse_args() monitor = DeviceMonitor(args.led) monitor.run() + if __name__ == "__main__": main()