""" Android hardware.input 组件 — InputManager, InputDevice, MotionRange 等 方法签名完全对齐 Android SDK """ import sys from typing import Any, Callable, Dict, List, Optional from .._core import Stub, AndroidOnlyError # ═══════════════════════════════════════════════════════════════ # InputManager # ═══════════════════════════════════════════════════════════════ class InputManager(Stub): """InputManager — 输入管理器""" ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" # ═══════════════════════════════════════════════════════════ # InputDeviceListener # ═══════════════════════════════════════════════════════════ class InputDeviceListener(Stub): """InputManager.InputDeviceListener — 输入设备监听器""" def onInputDeviceAdded(self, deviceId: int): pass def onInputDeviceRemoved(self, deviceId: int): pass def onInputDeviceChanged(self, deviceId: int): pass def __init__(self): super().__init__() self._devices: Dict[int, InputDevice] = {} self._listeners: Dict[int, InputManager.InputDeviceListener] = {} self._next_id = 1 self._init_default_devices() def _init_default_devices(self): # Keyboard kb = InputDevice( deviceId=0, name="Virtual Keyboard", descriptor="keyboard_v1", sources=InputDevice.SOURCE_KEYBOARD, vendorId=0x1, productId=0x1, keyboardType=InputDevice.KEYBOARD_TYPE_ALPHABETIC, hasMicrophone=False, isVirtual=True ) self._devices[0] = kb # Mouse mouse = InputDevice( deviceId=1, name="Virtual Mouse", descriptor="mouse_v1", sources=InputDevice.SOURCE_MOUSE, vendorId=0x2, productId=0x2, keyboardType=InputDevice.KEYBOARD_TYPE_NONE, hasMicrophone=False, isVirtual=True ) self._devices[1] = mouse # Trackpad tp = InputDevice( deviceId=2, name="Virtual Trackpad", descriptor="trackpad_v1", sources=InputDevice.SOURCE_TOUCHPAD, vendorId=0x3, productId=0x3, keyboardType=InputDevice.KEYBOARD_TYPE_NONE, hasMicrophone=False, isVirtual=False ) self._devices[2] = tp def getDevice(self, deviceId: int) -> Optional["InputDevice"]: return self._devices.get(deviceId) def getDeviceIds(self) -> List[int]: return list(self._devices.keys()) def registerInputDeviceListener(self, listener: InputDeviceListener, handler: Any = None): lid = id(listener) self._listeners[lid] = listener def unregisterInputDeviceListener(self, listener: InputDeviceListener): lid = id(listener) self._listeners.pop(lid, None) def getInputDevice(self, deviceId: int) -> Optional["InputDevice"]: return self.getDevice(deviceId) def isInTabletMode(self) -> bool: return False def getCurrentKeyboardLayoutForInputDevice(self, device: "InputDevice") -> Optional[str]: return None def setKeyboardLayoutForInputDevice(self, device: "InputDevice", keyboardLayoutDescriptor: str): pass # ═══════════════════════════════════════════════════════════════ # InputDevice # ═══════════════════════════════════════════════════════════════ class InputDevice(Stub): """InputDevice — 输入设备""" KEYBOARD_TYPE_ALPHABETIC = 2 KEYBOARD_TYPE_NON_ALPHABETIC = 1 KEYBOARD_TYPE_NONE = 0 SOURCE_CLASS_JOYSTICK = 16 SOURCE_CLASS_MASK = 0x000000FF SOURCE_CLASS_NONE = 0x00000000 SOURCE_CLASS_POINTER = 0x00000002 SOURCE_CLASS_POSITION = 0x00000008 SOURCE_CLASS_TRACKBALL = 0x00000004 SOURCE_CLASS_BUTTON = 0x00000001 SOURCE_GAMEPAD = 0x00000401 SOURCE_HDMI = 0x02000000 SOURCE_JOYSTICK = 0x01000010 SOURCE_KEYBOARD = 0x00000101 SOURCE_MOUSE = 0x00002002 SOURCE_MOUSE_RELATIVE = 0x00002000 SOURCE_ROTARY_ENCODER = 0x00800000 SOURCE_STYLUS = 0x00004002 SOURCE_TOUCHPAD = 0x00100008 SOURCE_TOUCHSCREEN = 0x00001002 SOURCE_TOUCH_NAVIGATION = 0x00200008 SOURCE_TRACKBALL = 0x00010004 SOURCE_UNKNOWN = 0x00000000 SOURCE_ANY = 0xFFFFFFFE # ═══════════════════════════════════════════════════════════ # MotionRange # ═══════════════════════════════════════════════════════════ class MotionRange(Stub): """InputDevice.MotionRange — 运动范围""" def __init__(self, axis: int = 0, source: int = 0, min: float = 0.0, max: float = 1.0, flat: float = 0.0, fuzz: float = 0.0, resolution: float = 0.0): super().__init__() self._axis = axis self._source = source self._min = min self._max = max self._flat = flat self._fuzz = fuzz self._resolution = resolution def getAxis(self) -> int: return self._axis def getSource(self) -> int: return self._source def getMin(self) -> float: return self._min def getMax(self) -> float: return self._max def getFlat(self) -> float: return self._flat def getFuzz(self) -> float: return self._fuzz def getRange(self) -> float: return self._max - self._min def getResolution(self) -> float: return self._resolution def toString(self) -> str: return f"MotionRange(axis={self._axis}, source={self._source}," \ f" range=[{self._min}, {self._max}])" def __init__(self, deviceId: int = 0, name: str = "", descriptor: str = "", sources: int = 0, vendorId: int = 0, productId: int = 0, controllerNumber: int = 0, keyboardType: int = KEYBOARD_TYPE_NONE, hasMicrophone: bool = False, isVirtual: bool = False): super().__init__() self._device_id = deviceId self._name = name self._descriptor = descriptor self._sources = sources self._vendor_id = vendorId self._product_id = productId self._controller_number = controllerNumber self._keyboard_type = keyboardType self._has_microphone = hasMicrophone self._is_virtual = isVirtual self._motion_ranges: List[InputDevice.MotionRange] = [] def getId(self) -> int: return self._device_id def getName(self) -> str: return self._name def getDescriptor(self) -> str: return self._descriptor def getSources(self) -> int: return self._sources def getVendorId(self) -> int: return self._vendor_id def getProductId(self) -> int: return self._product_id def getControllerNumber(self) -> int: return self._controller_number def getKeyCharacterMap(self) -> Any: return None def getMotionRange(self, axis: int = -1, source: int = -1) -> List[MotionRange]: results = [] for mr in self._motion_ranges: if axis >= 0 and mr.getAxis() != axis: continue if source >= 0 and mr.getSource() != source: continue results.append(mr) return results def hasMicrophone(self) -> bool: return self._has_microphone def isVirtual(self) -> bool: return self._is_virtual def toString(self) -> str: return f"InputDevice(id={self._device_id}, name={self._name}," \ f" sources={self._sources:#x})" # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "InputManager", "InputDevice", ]