evdev-binary 1.9.3__cp314-cp314t-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ # pylint: disable=undefined-variable
2
+ """
3
+ This modules exposes the integer constants defined in ``linux/input.h`` and
4
+ ``linux/input-event-codes.h``.
5
+
6
+ Exposed constants::
7
+
8
+ KEY, ABS, REL, SW, MSC, LED, BTN, REP, SND, ID, EV,
9
+ BUS, SYN, FF, FF_STATUS, INPUT_PROP
10
+
11
+ This module also provides reverse and forward mappings of the names and values
12
+ of the above mentioned constants::
13
+
14
+ >>> evdev.ecodes.KEY_A
15
+ 30
16
+
17
+ >>> evdev.ecodes.ecodes['KEY_A']
18
+ 30
19
+
20
+ >>> evdev.ecodes.KEY[30]
21
+ 'KEY_A'
22
+
23
+ >>> evdev.ecodes.REL[0]
24
+ 'REL_X'
25
+
26
+ >>> evdev.ecodes.EV[evdev.ecodes.EV_KEY]
27
+ 'EV_KEY'
28
+
29
+ >>> evdev.ecodes.bytype[evdev.ecodes.EV_REL][0]
30
+ 'REL_X'
31
+
32
+ Keep in mind that values in reverse mappings may point to one or more event
33
+ codes. For example::
34
+
35
+ >>> evdev.ecodes.FF[80]
36
+ ('FF_EFFECT_MIN', 'FF_RUMBLE')
37
+
38
+ >>> evdev.ecodes.FF[81]
39
+ 'FF_PERIODIC'
40
+ """
41
+
42
+ from inspect import getmembers
43
+
44
+ from . import _ecodes
45
+
46
+ #: Mapping of names to values.
47
+ ecodes = {}
48
+
49
+ prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP UI_FF".split()
50
+ prev_prefix = ""
51
+ g = globals()
52
+
53
+ # eg. code: 'REL_Z', val: 2
54
+ for code, val in getmembers(_ecodes):
55
+ for prefix in prefixes: # eg. 'REL'
56
+ if code.startswith(prefix):
57
+ ecodes[code] = val
58
+ # FF_STATUS codes should not appear in the FF reverse mapping
59
+ if not code.startswith(prev_prefix):
60
+ d = g.setdefault(prefix, {})
61
+ # codes that share the same value will be added to a list. eg:
62
+ # >>> ecodes.FF_STATUS
63
+ # {0: 'FF_STATUS_STOPPED', 1: ['FF_STATUS_MAX', 'FF_STATUS_PLAYING']}
64
+ if val in d:
65
+ if isinstance(d[val], list):
66
+ d[val].append(code)
67
+ else:
68
+ d[val] = [d[val], code]
69
+ else:
70
+ d[val] = code
71
+
72
+ prev_prefix = prefix
73
+
74
+
75
+ # Convert lists to tuples.
76
+ k, v = None, None
77
+ for prefix in prefixes:
78
+ for k, v in g[prefix].items():
79
+ if isinstance(v, list):
80
+ g[prefix][k] = tuple(v)
81
+
82
+
83
+ #: Keys are a combination of all BTN and KEY codes.
84
+ keys = {}
85
+ keys.update(BTN)
86
+ keys.update(KEY)
87
+
88
+ # make keys safe to use for the default list of uinput device
89
+ # capabilities
90
+ del keys[_ecodes.KEY_MAX]
91
+ del keys[_ecodes.KEY_CNT]
92
+
93
+ #: Mapping of event types to other value/name mappings.
94
+ bytype = {
95
+ _ecodes.EV_KEY: keys,
96
+ _ecodes.EV_ABS: ABS,
97
+ _ecodes.EV_REL: REL,
98
+ _ecodes.EV_SW: SW,
99
+ _ecodes.EV_MSC: MSC,
100
+ _ecodes.EV_LED: LED,
101
+ _ecodes.EV_REP: REP,
102
+ _ecodes.EV_SND: SND,
103
+ _ecodes.EV_SYN: SYN,
104
+ _ecodes.EV_FF: FF,
105
+ _ecodes.EV_FF_STATUS: FF_STATUS,
106
+ }
107
+
108
+ from evdev._ecodes import *
109
+
110
+ # cheaper than whitelisting in an __all__
111
+ del code, val, prefix, getmembers, g, d, k, v, prefixes, prev_prefix
evdev/eventio.py ADDED
@@ -0,0 +1,152 @@
1
+ import fcntl
2
+ import functools
3
+ import os
4
+ import select
5
+ from typing import Iterator, Union
6
+
7
+ from . import _input, _uinput, ecodes
8
+ from .events import InputEvent
9
+
10
+
11
+ # --------------------------------------------------------------------------
12
+ class EvdevError(Exception):
13
+ pass
14
+
15
+
16
+ class EventIO:
17
+ """
18
+ Base class for reading and writing input events.
19
+
20
+ This class is used by :class:`InputDevice` and :class:`UInput`.
21
+
22
+ - On, :class:`InputDevice` it used for reading user-generated events (e.g.
23
+ key presses, mouse movements) and writing feedback events (e.g. leds,
24
+ beeps).
25
+
26
+ - On, :class:`UInput` it used for writing user-generated events (e.g.
27
+ key presses, mouse movements) and reading feedback events (e.g. leds,
28
+ beeps).
29
+ """
30
+
31
+ def fileno(self):
32
+ """
33
+ Return the file descriptor to the open event device. This makes
34
+ it possible to pass instances directly to :func:`select.select()` and
35
+ :class:`asyncore.file_dispatcher`.
36
+ """
37
+ return self.fd
38
+
39
+ def read_loop(self) -> Iterator[InputEvent]:
40
+ """
41
+ Enter an endless :func:`select.select()` loop that yields input events.
42
+ """
43
+
44
+ while True:
45
+ r, w, x = select.select([self.fd], [], [])
46
+ for event in self.read():
47
+ yield event
48
+
49
+ def read_one(self) -> Union[InputEvent, None]:
50
+ """
51
+ Read and return a single input event as an instance of
52
+ :class:`InputEvent <evdev.events.InputEvent>`.
53
+
54
+ Return ``None`` if there are no pending input events.
55
+ """
56
+
57
+ # event -> (sec, usec, type, code, val)
58
+ event = _input.device_read(self.fd)
59
+
60
+ if event:
61
+ return InputEvent(*event)
62
+
63
+ def read(self) -> Iterator[InputEvent]:
64
+ """
65
+ Read multiple input events from device. Return a generator object that
66
+ yields :class:`InputEvent <evdev.events.InputEvent>` instances. Raises
67
+ `BlockingIOError` if there are no available events at the moment.
68
+ """
69
+
70
+ # events -> ((sec, usec, type, code, val), ...)
71
+ events = _input.device_read_many(self.fd)
72
+
73
+ for event in events:
74
+ yield InputEvent(*event)
75
+
76
+ # pylint: disable=no-self-argument
77
+ def need_write(func):
78
+ """
79
+ Decorator that raises :class:`EvdevError` if there is no write access to the
80
+ input device.
81
+ """
82
+
83
+ @functools.wraps(func)
84
+ def wrapper(*args):
85
+ fd = args[0].fd
86
+ if fcntl.fcntl(fd, fcntl.F_GETFL) & os.O_RDWR:
87
+ # pylint: disable=not-callable
88
+ return func(*args)
89
+ msg = 'no write access to device "%s"' % args[0].path
90
+ raise EvdevError(msg)
91
+
92
+ return wrapper
93
+
94
+ def write_event(self, event):
95
+ """
96
+ Inject an input event into the input subsystem. Events are
97
+ queued until a synchronization event is received.
98
+
99
+ Arguments
100
+ ---------
101
+ event: InputEvent
102
+ InputEvent instance or an object with an ``event`` attribute
103
+ (:class:`KeyEvent <evdev.events.KeyEvent>`, :class:`RelEvent
104
+ <evdev.events.RelEvent>` etc).
105
+
106
+ Example
107
+ -------
108
+ >>> ev = InputEvent(1334414993, 274296, ecodes.EV_KEY, ecodes.KEY_A, 1)
109
+ >>> ui.write_event(ev)
110
+ """
111
+
112
+ if hasattr(event, "event"):
113
+ event = event.event
114
+
115
+ self.write(event.type, event.code, event.value)
116
+
117
+ @need_write
118
+ def write(self, etype: int, code: int, value: int):
119
+ """
120
+ Inject an input event into the input subsystem. Events are
121
+ queued until a synchronization event is received.
122
+
123
+ Arguments
124
+ ---------
125
+ etype
126
+ event type (e.g. ``EV_KEY``).
127
+
128
+ code
129
+ event code (e.g. ``KEY_A``).
130
+
131
+ value
132
+ event value (e.g. 0 1 2 - depends on event type).
133
+
134
+ Example
135
+ ---------
136
+ >>> ui.write(e.EV_KEY, e.KEY_A, 1) # key A - down
137
+ >>> ui.write(e.EV_KEY, e.KEY_A, 0) # key A - up
138
+ """
139
+
140
+ _uinput.write(self.fd, etype, code, value)
141
+
142
+ def syn(self):
143
+ """
144
+ Inject a ``SYN_REPORT`` event into the input subsystem. Events
145
+ queued by :func:`write()` will be fired. If possible, events
146
+ will be merged into an 'atomic' event.
147
+ """
148
+
149
+ self.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0)
150
+
151
+ def close(self):
152
+ pass
evdev/eventio_async.py ADDED
@@ -0,0 +1,106 @@
1
+ import asyncio
2
+ import select
3
+ import sys
4
+
5
+ from . import eventio
6
+ from .events import InputEvent
7
+
8
+ # needed for compatibility
9
+ from .eventio import EvdevError
10
+
11
+ if sys.version_info >= (3, 11):
12
+ from typing import Self
13
+ else:
14
+ from typing import Any as Self
15
+
16
+
17
+ class ReadIterator:
18
+ def __init__(self, device):
19
+ self.current_batch = iter(())
20
+ self.device = device
21
+
22
+ # Standard iterator protocol.
23
+ def __iter__(self) -> Self:
24
+ return self
25
+
26
+ def __next__(self) -> InputEvent:
27
+ try:
28
+ # Read from the previous batch of events.
29
+ return next(self.current_batch)
30
+ except StopIteration:
31
+ r, w, x = select.select([self.device.fd], [], [])
32
+ self.current_batch = self.device.read()
33
+ return next(self.current_batch)
34
+
35
+ def __aiter__(self) -> Self:
36
+ return self
37
+
38
+ def __anext__(self) -> "asyncio.Future[InputEvent]":
39
+ future = asyncio.Future()
40
+ try:
41
+ # Read from the previous batch of events.
42
+ future.set_result(next(self.current_batch))
43
+ except StopIteration:
44
+
45
+ def next_batch_ready(batch):
46
+ try:
47
+ self.current_batch = batch.result()
48
+ future.set_result(next(self.current_batch))
49
+ except Exception as e:
50
+ future.set_exception(e)
51
+
52
+ self.device.async_read().add_done_callback(next_batch_ready)
53
+ return future
54
+
55
+
56
+ class EventIO(eventio.EventIO):
57
+ def _do_when_readable(self, callback):
58
+ loop = asyncio.get_event_loop()
59
+
60
+ def ready():
61
+ loop.remove_reader(self.fileno())
62
+ callback()
63
+
64
+ loop.add_reader(self.fileno(), ready)
65
+
66
+ def _set_result(self, future, cb):
67
+ try:
68
+ future.set_result(cb())
69
+ except Exception as error:
70
+ future.set_exception(error)
71
+
72
+ def async_read_one(self):
73
+ """
74
+ Asyncio coroutine to read and return a single input event as
75
+ an instance of :class:`InputEvent <evdev.events.InputEvent>`.
76
+ """
77
+ future = asyncio.Future()
78
+ self._do_when_readable(lambda: self._set_result(future, self.read_one))
79
+ return future
80
+
81
+ def async_read(self):
82
+ """
83
+ Asyncio coroutine to read multiple input events from device. Return
84
+ a generator object that yields :class:`InputEvent <evdev.events.InputEvent>`
85
+ instances.
86
+ """
87
+ future = asyncio.Future()
88
+ self._do_when_readable(lambda: self._set_result(future, self.read))
89
+ return future
90
+
91
+ def async_read_loop(self) -> ReadIterator:
92
+ """
93
+ Return an iterator that yields input events. This iterator is
94
+ compatible with the ``async for`` syntax.
95
+
96
+ """
97
+ return ReadIterator(self)
98
+
99
+ def close(self):
100
+ try:
101
+ loop = asyncio.get_event_loop()
102
+ loop.remove_reader(self.fileno())
103
+ except RuntimeError:
104
+ # no event loop present, so there is nothing to
105
+ # remove the reader from. Ignore
106
+ pass
evdev/events.py ADDED
@@ -0,0 +1,192 @@
1
+ """
2
+ This module provides the :class:`InputEvent` class, which closely
3
+ resembles the ``input_event`` struct defined in ``linux/input.h``:
4
+
5
+ .. code-block:: c
6
+
7
+ struct input_event {
8
+ struct timeval time;
9
+ __u16 type;
10
+ __u16 code;
11
+ __s32 value;
12
+ };
13
+
14
+ This module also defines several :class:`InputEvent` sub-classes that
15
+ know more about the different types of events (key, abs, rel etc). The
16
+ :data:`event_factory` dictionary maps event types to these classes.
17
+
18
+ Assuming you use the :func:`evdev.util.categorize()` function to
19
+ categorize events according to their type, adding or replacing a class
20
+ for a specific event type becomes a matter of modifying
21
+ :data:`event_factory`.
22
+
23
+ All classes in this module have reasonable ``str()`` and ``repr()``
24
+ methods::
25
+
26
+ >>> print(event)
27
+ event at 1337197425.477827, code 04, type 04, val 458792
28
+ >>> print(repr(event))
29
+ InputEvent(1337197425L, 477827L, 4, 4, 458792L)
30
+
31
+ >>> print(key_event)
32
+ key event at 1337197425.477835, 28 (KEY_ENTER), up
33
+ >>> print(repr(key_event))
34
+ KeyEvent(InputEvent(1337197425L, 477835L, 1, 28, 0L))
35
+ """
36
+
37
+ # event type descriptions have been taken mot-a-mot from:
38
+ # http://www.kernel.org/doc/Documentation/input/event-codes.txt
39
+
40
+ # pylint: disable=no-name-in-module
41
+ from typing import Final
42
+ from .ecodes import ABS, EV_ABS, EV_KEY, EV_REL, EV_SYN, KEY, REL, SYN, keys
43
+
44
+
45
+ class InputEvent:
46
+ """A generic input event."""
47
+
48
+ __slots__ = "sec", "usec", "type", "code", "value"
49
+
50
+ def __init__(self, sec, usec, type, code, value):
51
+ #: Time in seconds since epoch at which event occurred.
52
+ self.sec: int = sec
53
+
54
+ #: Microsecond portion of the timestamp.
55
+ self.usec: int = usec
56
+
57
+ #: Event type - one of ``ecodes.EV_*``.
58
+ self.type: int = type
59
+
60
+ #: Event code related to the event type.
61
+ self.code: int = code
62
+
63
+ #: Event value related to the event type.
64
+ self.value: int = value
65
+
66
+ def timestamp(self) -> float:
67
+ """Return event timestamp as a float."""
68
+ return self.sec + (self.usec / 1000000.0)
69
+
70
+ def __str__(self):
71
+ msg = "event at {:f}, code {:02d}, type {:02d}, val {:02d}"
72
+ return msg.format(self.timestamp(), self.code, self.type, self.value)
73
+
74
+ def __repr__(self):
75
+ msg = "{}({!r}, {!r}, {!r}, {!r}, {!r})"
76
+ return msg.format(self.__class__.__name__, self.sec, self.usec, self.type, self.code, self.value)
77
+
78
+
79
+ class KeyEvent:
80
+ """An event generated by a keyboard, button or other key-like devices."""
81
+
82
+ key_up: Final[int] = 0x0
83
+ key_down: Final[int] = 0x1
84
+ key_hold: Final[int] = 0x2
85
+
86
+ __slots__ = "scancode", "keycode", "keystate", "event"
87
+
88
+ def __init__(self, event: InputEvent, allow_unknown: bool = False):
89
+ """
90
+ The ``allow_unknown`` argument determines what to do in the event of an event code
91
+ for which a key code cannot be found. If ``False`` a ``KeyError`` will be raised.
92
+ If ``True`` the keycode will be set to the hex value of the event code.
93
+ """
94
+
95
+ self.scancode: int = event.code
96
+
97
+ if event.value == 0:
98
+ self.keystate = KeyEvent.key_up
99
+ elif event.value == 2:
100
+ self.keystate = KeyEvent.key_hold
101
+ elif event.value == 1:
102
+ self.keystate = KeyEvent.key_down
103
+
104
+ try:
105
+ self.keycode = keys[event.code]
106
+ except KeyError:
107
+ if allow_unknown:
108
+ self.keycode = "0x{:02X}".format(event.code)
109
+ else:
110
+ raise
111
+
112
+ #: Reference to an :class:`InputEvent` instance.
113
+ self.event: InputEvent = event
114
+
115
+ def __str__(self):
116
+ try:
117
+ ks = ("up", "down", "hold")[self.keystate]
118
+ except IndexError:
119
+ ks = "unknown"
120
+
121
+ msg = "key event at {:f}, {} ({}), {}"
122
+ return msg.format(self.event.timestamp(), self.scancode, self.keycode, ks)
123
+
124
+ def __repr__(self):
125
+ return "{}({!r})".format(self.__class__.__name__, self.event)
126
+
127
+
128
+ class RelEvent:
129
+ """A relative axis event (e.g moving the mouse 5 units to the left)."""
130
+
131
+ __slots__ = "event"
132
+
133
+ def __init__(self, event: InputEvent):
134
+ #: Reference to an :class:`InputEvent` instance.
135
+ self.event: InputEvent = event
136
+
137
+ def __str__(self):
138
+ msg = "relative axis event at {:f}, {}"
139
+ return msg.format(self.event.timestamp(), REL[self.event.code])
140
+
141
+ def __repr__(self):
142
+ return "{}({!r})".format(self.__class__.__name__, self.event)
143
+
144
+
145
+ class AbsEvent:
146
+ """An absolute axis event (e.g the coordinates of a tap on a touchscreen)."""
147
+
148
+ __slots__ = "event"
149
+
150
+ def __init__(self, event: InputEvent):
151
+ #: Reference to an :class:`InputEvent` instance.
152
+ self.event: InputEvent = event
153
+
154
+ def __str__(self):
155
+ msg = "absolute axis event at {:f}, {}"
156
+ return msg.format(self.event.timestamp(), ABS[self.event.code])
157
+
158
+ def __repr__(self):
159
+ return "{}({!r})".format(self.__class__.__name__, self.event)
160
+
161
+
162
+ class SynEvent:
163
+ """
164
+ A synchronization event. Used as markers to separate events. Events may be
165
+ separated in time or in space, such as with the multitouch protocol.
166
+ """
167
+
168
+ __slots__ = "event"
169
+
170
+ def __init__(self, event: InputEvent):
171
+ #: Reference to an :class:`InputEvent` instance.
172
+ self.event: InputEvent = event
173
+
174
+ def __str__(self):
175
+ msg = "synchronization event at {:f}, {}"
176
+ return msg.format(self.event.timestamp(), SYN[self.event.code])
177
+
178
+ def __repr__(self):
179
+ return "{}({!r})".format(self.__class__.__name__, self.event)
180
+
181
+
182
+ #: A mapping of event types to :class:`InputEvent` sub-classes. Used
183
+ #: by :func:`evdev.util.categorize()`
184
+ event_factory = {
185
+ EV_KEY: KeyEvent,
186
+ EV_REL: RelEvent,
187
+ EV_ABS: AbsEvent,
188
+ EV_SYN: SynEvent,
189
+ }
190
+
191
+
192
+ __all__ = ("InputEvent", "KeyEvent", "RelEvent", "SynEvent", "AbsEvent", "event_factory")