0
# Event Processing
1
2
Event classes and utilities for handling input events from Linux input devices. This includes the core event representation, specialized event types, and utilities for event categorization and processing.
3
4
## Capabilities
5
6
### Core Event Representation
7
8
The fundamental InputEvent class represents all input events from the Linux kernel.
9
10
```python { .api }
11
class InputEvent:
12
def __init__(self, sec: int, usec: int, type: int, code: int, value: int) -> None:
13
"""
14
Initialize an input event.
15
16
Parameters:
17
- sec: Seconds since epoch when event occurred
18
- usec: Microsecond portion of timestamp
19
- type: Event type (EV_KEY, EV_REL, EV_ABS, etc.)
20
- code: Event code specific to the event type
21
- value: Event value
22
"""
23
24
def timestamp(self) -> float:
25
"""
26
Return event timestamp as float seconds since epoch.
27
28
Returns:
29
Combined sec + usec as floating point timestamp
30
"""
31
32
# Attributes
33
sec: int # Seconds since epoch
34
usec: int # Microseconds portion
35
type: int # Event type (EV_*)
36
code: int # Event code
37
value: int # Event value
38
```
39
40
### Key Events
41
42
Specialized class for keyboard and button events with enhanced key state information.
43
44
```python { .api }
45
class KeyEvent:
46
# Class constants for key states
47
key_up: int = 0x0 # Key released
48
key_down: int = 0x1 # Key pressed
49
key_hold: int = 0x2 # Key held (repeat)
50
51
def __init__(self, event: InputEvent, allow_unknown: bool = False) -> None:
52
"""
53
Create KeyEvent from InputEvent.
54
55
Parameters:
56
- event: InputEvent with type EV_KEY
57
- allow_unknown: If False, raise KeyError for unknown key codes.
58
If True, use hex value for unknown keys.
59
60
Raises:
61
- KeyError: If key code is unknown and allow_unknown=False
62
"""
63
64
# Attributes
65
scancode: int # Raw scan code from event.code
66
keycode: str # Human-readable key name (e.g., "KEY_A", "BTN_LEFT")
67
keystate: int # Key state (key_up, key_down, or key_hold)
68
event: InputEvent # Reference to original InputEvent
69
```
70
71
### Relative Events
72
73
Events for relative positioning devices like mice and trackballs.
74
75
```python { .api }
76
class RelEvent:
77
def __init__(self, event: InputEvent) -> None:
78
"""
79
Create RelEvent from InputEvent with type EV_REL.
80
81
Parameters:
82
- event: InputEvent with type EV_REL
83
"""
84
85
# Attributes
86
event: InputEvent # Reference to original InputEvent
87
```
88
89
### Absolute Events
90
91
Events for absolute positioning devices like touchscreens and joysticks.
92
93
```python { .api }
94
class AbsEvent:
95
def __init__(self, event: InputEvent) -> None:
96
"""
97
Create AbsEvent from InputEvent with type EV_ABS.
98
99
Parameters:
100
- event: InputEvent with type EV_ABS
101
"""
102
103
# Attributes
104
event: InputEvent # Reference to original InputEvent
105
```
106
107
### Synchronization Events
108
109
Events that mark boundaries between logical input events.
110
111
```python { .api }
112
class SynEvent:
113
def __init__(self, event: InputEvent) -> None:
114
"""
115
Create SynEvent from InputEvent with type EV_SYN.
116
117
Parameters:
118
- event: InputEvent with type EV_SYN
119
"""
120
121
# Attributes
122
event: InputEvent # Reference to original InputEvent
123
```
124
125
### Event Factory
126
127
Dictionary mapping event types to their corresponding event classes.
128
129
```python { .api }
130
event_factory: Dict[int, Type] = {
131
# Maps event type codes to event classes
132
# EV_KEY -> KeyEvent
133
# EV_REL -> RelEvent
134
# EV_ABS -> AbsEvent
135
# EV_SYN -> SynEvent
136
}
137
```
138
139
### Event Categorization
140
141
Utilities for converting generic InputEvent objects to specialized event types.
142
143
```python { .api }
144
def categorize(event: InputEvent) -> Union[InputEvent, KeyEvent, RelEvent, AbsEvent, SynEvent]:
145
"""
146
Categorize InputEvent according to its type.
147
148
Uses event_factory dictionary to map event types to specialized classes.
149
If event type is not found in factory, returns original InputEvent unchanged.
150
151
Parameters:
152
- event: InputEvent to categorize
153
154
Returns:
155
Specialized event object (KeyEvent, RelEvent, etc.) or original InputEvent
156
"""
157
```
158
159
## Usage Examples
160
161
### Basic Event Processing
162
163
```python
164
from evdev import InputDevice, categorize, ecodes
165
166
device = InputDevice('/dev/input/event0')
167
168
for event in device.read_loop():
169
# Categorize event based on type
170
categorized_event = categorize(event)
171
172
if isinstance(categorized_event, KeyEvent):
173
print(f"Key event: {categorized_event.keycode} -> {categorized_event.keystate}")
174
elif isinstance(categorized_event, RelEvent):
175
print(f"Relative event: code={event.code}, value={event.value}")
176
elif isinstance(categorized_event, AbsEvent):
177
print(f"Absolute event: code={event.code}, value={event.value}")
178
else:
179
print(f"Other event: {event}")
180
```
181
182
### Key State Processing
183
184
```python
185
from evdev import InputDevice, categorize, ecodes, KeyEvent
186
187
device = InputDevice('/dev/input/event0')
188
189
for event in device.read_loop():
190
if event.type == ecodes.EV_KEY:
191
key_event = categorize(event)
192
193
if key_event.keystate == KeyEvent.key_down:
194
print(f"Key pressed: {key_event.keycode}")
195
elif key_event.keystate == KeyEvent.key_up:
196
print(f"Key released: {key_event.keycode}")
197
elif key_event.keystate == KeyEvent.key_hold:
198
print(f"Key held: {key_event.keycode}")
199
```
200
201
### Event Filtering by Type
202
203
```python
204
from evdev import InputDevice, categorize, ecodes
205
206
device = InputDevice('/dev/input/event0')
207
208
def process_events():
209
for event in device.read_loop():
210
if event.type == ecodes.EV_KEY:
211
# Process keyboard/button events
212
key_event = categorize(event)
213
handle_key_event(key_event)
214
215
elif event.type == ecodes.EV_REL:
216
# Process mouse movement events
217
rel_event = categorize(event)
218
handle_mouse_movement(rel_event)
219
220
elif event.type == ecodes.EV_ABS:
221
# Process absolute positioning events
222
abs_event = categorize(event)
223
handle_absolute_positioning(abs_event)
224
225
elif event.type == ecodes.EV_SYN:
226
# Synchronization event - marks end of event sequence
227
handle_sync_event(event)
228
229
def handle_key_event(key_event):
230
print(f"Key: {key_event.keycode}, State: {key_event.keystate}")
231
232
def handle_mouse_movement(rel_event):
233
event = rel_event.event
234
if event.code == ecodes.REL_X:
235
print(f"Mouse X movement: {event.value}")
236
elif event.code == ecodes.REL_Y:
237
print(f"Mouse Y movement: {event.value}")
238
239
def handle_absolute_positioning(abs_event):
240
event = abs_event.event
241
if event.code == ecodes.ABS_X:
242
print(f"Touch X position: {event.value}")
243
elif event.code == ecodes.ABS_Y:
244
print(f"Touch Y position: {event.value}")
245
246
def handle_sync_event(event):
247
if event.code == ecodes.SYN_REPORT:
248
print("End of event sequence")
249
250
process_events()
251
```
252
253
### Event Timestamp Processing
254
255
```python
256
from evdev import InputDevice, categorize
257
import time
258
259
device = InputDevice('/dev/input/event0')
260
start_time = time.time()
261
262
for event in device.read_loop():
263
# Get event timestamp
264
event_time = event.timestamp()
265
relative_time = event_time - start_time
266
267
categorized = categorize(event)
268
print(f"[{relative_time:.3f}s] {categorized}")
269
270
# Alternative: access timestamp components directly
271
print(f"Event at {event.sec}.{event.usec:06d}")
272
```
273
274
### Handling Unknown Key Codes
275
276
```python
277
from evdev import InputDevice, categorize, ecodes, KeyEvent
278
279
device = InputDevice('/dev/input/event0')
280
281
for event in device.read_loop():
282
if event.type == ecodes.EV_KEY:
283
try:
284
# Default behavior - raises KeyError for unknown keys
285
key_event = KeyEvent(event)
286
print(f"Known key: {key_event.keycode}")
287
except KeyError:
288
# Handle unknown key codes
289
key_event = KeyEvent(event, allow_unknown=True)
290
print(f"Unknown key: {key_event.keycode} (code: {key_event.scancode})")
291
```
292
293
### Event Stream Buffering
294
295
```python
296
from evdev import InputDevice, categorize
297
from collections import deque
298
299
device = InputDevice('/dev/input/event0')
300
event_buffer = deque(maxlen=100) # Keep last 100 events
301
302
def process_buffered_events():
303
while True:
304
# Read all available events
305
events = device.read()
306
307
# Add to buffer and categorize
308
for event in events:
309
categorized = categorize(event)
310
event_buffer.append(categorized)
311
312
# Process buffer
313
while event_buffer:
314
event = event_buffer.popleft()
315
handle_event(event)
316
317
def handle_event(event):
318
if isinstance(event, KeyEvent):
319
print(f"Buffered key event: {event.keycode}")
320
else:
321
print(f"Buffered event: {event}")
322
323
process_buffered_events()
324
```