Last active
June 3, 2025 16:11
-
-
Save psqq/bed97027e52d602adc9982c7482ac273 to your computer and use it in GitHub Desktop.
alternative AutoRun for linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# alternative https://github.com/divisionind/AutoRun for linux | |
# usage examples: | |
# sudo KEYBOARD_DEVICE_NAME="AT Translated Set 2 keyboard" ./.venv/bin/python main.py | |
# or | |
# sudo KEYBOARD_DEVICE=/dev/input/event3 ./.venv/bin/python main.py | |
# better by name | |
import evdev | |
import os | |
import time | |
class RunLoop: | |
def __init__(self, uinput: evdev.UInput) -> None: | |
self.held = False | |
self.keys = [] | |
self.counter = dict() | |
self.counter_max_value = 2 | |
# Get keyboard device by name or path | |
device_path = os.environ.get("KEYBOARD_DEVICE") | |
device_name = os.environ.get("KEYBOARD_DEVICE_NAME") | |
done = False | |
i = 0 | |
while not done: | |
if device_name: | |
devices = [evdev.InputDevice(path) for path in evdev.list_devices()] | |
for device in devices: | |
if device.name == device_name: | |
self.kb_dev = device | |
done = True | |
break | |
else: | |
if i == 10: | |
raise ValueError(f"Device with name '{device_name}' not found") | |
else: | |
time.sleep(0.5) | |
elif device_path: | |
self.kb_dev = evdev.InputDevice(device_path) | |
done = True | |
else: | |
raise ValueError("Either KEYBOARD_DEVICE or KEYBOARD_DEVICE_NAME must be set") | |
self.uinput = uinput | |
def start_hold_keys(self): | |
self.held = True | |
self.counter = dict() | |
self.keys = self.kb_dev.active_keys(verbose=True) | |
self.keys = list(filter(lambda k: k[0] != "KEY_PAUSE", self.keys)) | |
print("Start holding keys", self.keys) | |
for k in self.keys: | |
self.uinput.write(evdev.ecodes.EV_KEY, k[1], 1) | |
self.uinput.syn() | |
def finish_hold_keys(self): | |
print("Finish holding keys", self.keys) | |
self.held = False | |
for k in self.keys: | |
self.uinput.write(evdev.ecodes.EV_KEY, k[1], 0) | |
self.uinput.syn() | |
def on_pause(self): | |
if self.held: | |
self.finish_hold_keys() | |
else: | |
self.start_hold_keys() | |
def on_keyboard_event(self, scancode, keystate): | |
if scancode == evdev.ecodes.KEY_PAUSE and keystate == 1: | |
self.on_pause() | |
return | |
if self.held and keystate == 0: | |
is_hold_again = False | |
for paused_key in self.keys: | |
if scancode == paused_key[1]: | |
self.uinput.write(evdev.ecodes.EV_KEY, paused_key[1], 1) | |
self.uinput.syn() | |
is_hold_again = True | |
if is_hold_again: | |
counter_value = self.counter.get(scancode, 0) | |
counter_value += 1 | |
self.counter[scancode] = counter_value | |
if counter_value >= self.counter_max_value: | |
self.finish_hold_keys() | |
def run(self): | |
for event in self.kb_dev.read_loop(): | |
if event.type == evdev.ecodes.EV_KEY: | |
key_event = evdev.categorize(event) | |
if isinstance(key_event, evdev.events.KeyEvent): | |
self.on_keyboard_event( | |
scancode=key_event.scancode, keystate=key_event.keystate | |
) | |
def main(): | |
while True: | |
try: | |
with evdev.UInput() as uinput: | |
RunLoop(uinput).run() | |
except IOError as e: | |
if e.errno == 19: | |
print("restart on", e) | |
else: | |
raise e | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment