From dfdfd26bb8b031a803a3428be6d9780b94617ef8 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 5 Feb 2024 21:58:26 -0800 Subject: monitor input availability through udev events --- panel.py | 61 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/panel.py b/panel.py index 34beed3..9efef29 100755 --- a/panel.py +++ b/panel.py @@ -3,6 +3,7 @@ # Copyright 2024 David Vazgenovich Shakaryan import glob +import os import subprocess import threading import time @@ -150,26 +151,52 @@ class ModHLWM(Mod): def process_cmd(self, cmd): subprocess.run(('herbstclient', *cmd.split())) -class ModNoKBD(Mod): - def __init__(self): +class ModInputUnavail(Mod): + def __init__(self, path, label=''): super().__init__() - self.prev = True + self.path = path + self.label = label def work(self): - while True: - has_kbd = bool(glob.glob('/dev/input/by-id/*-kbd')) - if has_kbd != self.prev: - if has_kbd: - buf = None - else: - buf = f'%{{B#a03000}}{spacing()}NO KBD{spacing()}%{{B-}}' + p = subprocess.Popen( + ('udevadm', 'monitor', '-ups', 'input'), + stdout=subprocess.PIPE, text=True) - self.prev = has_kbd - with self.cv: - self.out = buf - self.cv.notify() + self._update_state(os.path.exists(self.path)) - time.sleep(1) + building = False + for line in iter(p.stdout.readline, ''): + line = line.rstrip() + + if not building and line.startswith('UDEV'): + building = True + e = {} + elif building: + if '=' in line: + k, v = line.split('=', 1) + e[k] = v + else: + building = False + if e: + self._process_event(e) + + def _process_event(self, e): + if (action := e.get('ACTION')) and (paths := e.get('DEVLINKS')): + if self.path in paths.split(' '): + if action == 'add': + self._update_state(True) + elif action == 'remove': + self._update_state(False) + + def _update_state(self, avail): + if avail: + buf = None + else: + buf = f'%{{B#a03000}}{spacing()}{self.label}{spacing()}%{{B-}}' + + with self.cv: + self.out = buf + self.cv.notify() class Bar: def __init__(self, *mods): @@ -216,7 +243,9 @@ class Bar: Bar( ModHLWM(), ModRight(), - ModNoKBD(), + ModInputUnavail( + '/dev/input/by-id/usb-HID_Keyboard_HID_Keyboard-event-kbd', + label='NO KEYBOARD'), ModSpacer(n=2), ModDate( fmts=('%Y-%m-%d %H:%M:%S', '%H:%M'), -- cgit v1.2.3-70-g09d2