diversion: treat evdev as an optional dependency

evdev was imported unconditionally on every OS except macOS and Windows,
i.e. the code assumed "not macOS and not Windows" means Linux. On any
other platform the import is a hard failure at startup.

evdev is also genuinely optional: setup.py only installs it when
platform_system == "Linux", and packagers may make it optional. Select on
whether the module imports rather than on the OS name.

click_uinput() dereferenced evdev.ecodes before calling simulate_uinput(),
so it raised AttributeError rather than degrading; click() has no handler,
so that escaped to the caller. Bail out early there and in setup_uinput()
when evdev is absent. simulate_scroll() was already safe, but only because
setup_uinput()'s blanket except swallowed the AttributeError.
This commit is contained in:
Nick Price 2026-07-11 17:42:52 -07:00
parent b7fbca06e0
commit 057f7533b1
No known key found for this signature in database
1 changed files with 10 additions and 6 deletions

View File

@ -21,7 +21,6 @@ import logging
import math
import numbers
import os
import platform
import socket
import struct
import subprocess
@ -39,12 +38,13 @@ import yaml
from keysyms import keysymdef
# There is no evdev on macOS or Windows. Diversion will not work without
# it but other Solaar functionality is available.
if platform.system() in ("Darwin", "Windows"):
evdev = None
else:
# evdev is not available on every platform, and is an optional dependency
# elsewhere. Diversion will not work without it but other Solaar
# functionality is available.
try:
import evdev
except ImportError:
evdev = None
from .common import NamedInt
from .hidpp20 import SupportedFeature
@ -257,6 +257,8 @@ else:
def setup_uinput():
global udevice
if evdev is None:
return False
if udevice is not None:
return udevice
try:
@ -337,6 +339,8 @@ def simulate_key(code, event): # X11 keycode but Solaar event code
def click_uinput(button, count):
if evdev is None:
return False
if isinstance(count, int):
for _ in range(count):
if not simulate_uinput(evdev.ecodes.EV_KEY, button[1], 1):