evdev-binary 1.9.3__cp314-cp314-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.
- evdev/__init__.py +39 -0
- evdev/_ecodes.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/_input.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/_uinput.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/device.py +440 -0
- evdev/ecodes.py +3885 -0
- evdev/ecodes_runtime.py +111 -0
- evdev/eventio.py +152 -0
- evdev/eventio_async.py +106 -0
- evdev/events.py +192 -0
- evdev/evtest.py +181 -0
- evdev/ff.py +198 -0
- evdev/genecodes_c.py +147 -0
- evdev/genecodes_py.py +54 -0
- evdev/input.c +580 -0
- evdev/py.typed +0 -0
- evdev/uinput.c +417 -0
- evdev/uinput.py +375 -0
- evdev/util.py +146 -0
- evdev_binary-1.9.3.dist-info/METADATA +48 -0
- evdev_binary-1.9.3.dist-info/RECORD +24 -0
- evdev_binary-1.9.3.dist-info/WHEEL +5 -0
- evdev_binary-1.9.3.dist-info/licenses/LICENSE +29 -0
- evdev_binary-1.9.3.dist-info/top_level.txt +1 -0
evdev/ecodes_runtime.py
ADDED
|
@@ -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")
|