0
# Mouse Control and Monitoring
1
2
Comprehensive mouse input simulation and monitoring functionality for controlling mouse cursor position, generating button clicks, scroll events, and listening to real-time mouse interactions across multiple operating systems.
3
4
## Capabilities
5
6
### Mouse Controller
7
8
The Controller class provides programmatic control over mouse cursor position and button interactions, enabling automation of mouse-based operations.
9
10
```python { .api }
11
class Controller:
12
"""A controller for sending virtual mouse events to the system."""
13
14
def __init__(self):
15
"""Initialize the mouse controller."""
16
...
17
18
@property
19
def position(self) -> tuple[int, int]:
20
"""
21
The current position of the mouse pointer.
22
23
Returns:
24
tuple[int, int]: The (x, y) coordinates of the mouse pointer
25
"""
26
...
27
28
@position.setter
29
def position(self, pos: tuple[int, int]):
30
"""
31
Set the mouse pointer position.
32
33
Args:
34
pos (tuple[int, int]): The (x, y) coordinates to move the pointer to
35
"""
36
...
37
38
def move(self, dx: int, dy: int):
39
"""
40
Move the mouse pointer relative to its current position.
41
42
Args:
43
dx (int): Horizontal offset in pixels
44
dy (int): Vertical offset in pixels
45
46
Raises:
47
ValueError: If the values are invalid (e.g., out of bounds)
48
"""
49
...
50
51
def click(self, button: Button, count: int = 1):
52
"""
53
Emit button click event(s) at the current position.
54
55
Args:
56
button (Button): The button to click
57
count (int): Number of clicks to perform (default: 1)
58
"""
59
...
60
61
def press(self, button: Button):
62
"""
63
Emit a button press event at the current position.
64
65
Args:
66
button (Button): The button to press
67
"""
68
...
69
70
def release(self, button: Button):
71
"""
72
Emit a button release event at the current position.
73
74
Args:
75
button (Button): The button to release
76
"""
77
...
78
79
def scroll(self, dx: int, dy: int):
80
"""
81
Send scroll events.
82
83
Args:
84
dx (int): Horizontal scroll amount (units undefined, platform-dependent)
85
dy (int): Vertical scroll amount (units undefined, platform-dependent)
86
87
Raises:
88
ValueError: If the values are invalid (e.g., out of bounds)
89
"""
90
...
91
```
92
93
#### Usage Examples
94
95
```python
96
from pynput.mouse import Button, Controller
97
98
# Create controller
99
mouse = Controller()
100
101
# Get current position
102
current_pos = mouse.position
103
print(f"Mouse is at {current_pos}")
104
105
# Move to absolute position
106
mouse.position = (500, 300)
107
108
# Move relatively
109
mouse.move(50, -25)
110
111
# Single click
112
mouse.click(Button.left)
113
114
# Double click
115
mouse.click(Button.left, 2)
116
117
# Right click
118
mouse.click(Button.right)
119
120
# Press and hold, then release
121
mouse.press(Button.left)
122
# ... do something while button is pressed
123
mouse.release(Button.left)
124
125
# Scroll down 3 units
126
mouse.scroll(0, 3)
127
128
# Scroll horizontally
129
mouse.scroll(2, 0)
130
```
131
132
### Mouse Event Listener
133
134
The Listener class monitors mouse events in real-time, providing callbacks for mouse movements, clicks, and scroll events.
135
136
```python { .api }
137
class Listener:
138
"""A listener for mouse events."""
139
140
def __init__(
141
self,
142
on_move: callable = None,
143
on_click: callable = None,
144
on_scroll: callable = None,
145
suppress: bool = False,
146
**kwargs
147
):
148
"""
149
Initialize the mouse event listener.
150
151
Args:
152
on_move (callable): Callback for mouse move events (x, y, injected)
153
on_click (callable): Callback for mouse click events (x, y, button, pressed, injected)
154
on_scroll (callable): Callback for scroll events (x, y, dx, dy, injected)
155
suppress (bool): Whether to suppress events system-wide
156
**kwargs: Platform-specific options (darwin_*, win32_*, xorg_*)
157
"""
158
...
159
160
def start(self):
161
"""Start the listener thread."""
162
...
163
164
def stop(self):
165
"""Stop the listener. Cannot be restarted once stopped."""
166
...
167
168
def wait(self):
169
"""Wait for the listener to become ready."""
170
...
171
172
def join(self, timeout: float = None):
173
"""
174
Wait for the listener thread to complete.
175
176
Args:
177
timeout (float): Maximum time to wait in seconds
178
"""
179
...
180
181
@property
182
def running(self) -> bool:
183
"""Whether the listener is currently running."""
184
...
185
186
@property
187
def suppress(self) -> bool:
188
"""Whether events are being suppressed system-wide."""
189
...
190
```
191
192
#### Usage Examples
193
194
```python
195
from pynput import mouse
196
197
def on_move(x, y, injected):
198
"""Handle mouse move events."""
199
if not injected: # Ignore synthetic events
200
print(f'Mouse moved to ({x}, {y})')
201
202
def on_click(x, y, button, pressed, injected):
203
"""Handle mouse click events."""
204
action = 'Pressed' if pressed else 'Released'
205
print(f'{action} {button} at ({x}, {y})')
206
207
# Stop listener on right button release
208
if button == mouse.Button.right and not pressed:
209
return False
210
211
def on_scroll(x, y, dx, dy, injected):
212
"""Handle mouse scroll events."""
213
direction = 'up' if dy > 0 else 'down'
214
print(f'Scrolled {direction} at ({x}, {y})')
215
216
# Context manager usage (recommended)
217
with mouse.Listener(
218
on_move=on_move,
219
on_click=on_click,
220
on_scroll=on_scroll
221
) as listener:
222
listener.join()
223
224
# Manual control
225
listener = mouse.Listener(
226
on_move=on_move,
227
on_click=on_click,
228
on_scroll=on_scroll
229
)
230
listener.start()
231
listener.join() # Wait for listener to finish
232
233
# Non-blocking usage
234
listener = mouse.Listener(on_click=on_click)
235
listener.start()
236
# ... do other work
237
listener.stop()
238
```
239
240
### Mouse Events Iterator
241
242
The Events class provides synchronous iteration over mouse events, useful for processing events in sequence.
243
244
```python { .api }
245
class Events:
246
"""A mouse event listener supporting synchronous iteration over events."""
247
248
def __init__(self):
249
"""Initialize the events iterator."""
250
...
251
252
def __enter__(self):
253
"""Start the event listener."""
254
...
255
256
def __exit__(self, *args):
257
"""Stop the event listener."""
258
...
259
260
def __iter__(self):
261
"""Return iterator interface."""
262
...
263
264
def __next__(self):
265
"""Get the next event."""
266
...
267
268
def get(self, timeout: float = None):
269
"""
270
Get the next event with optional timeout.
271
272
Args:
273
timeout (float): Maximum time to wait for an event
274
275
Returns:
276
Event or None: The next event, or None if timeout or stopped
277
"""
278
...
279
280
class Move:
281
"""A mouse move event."""
282
def __init__(self, x: int, y: int, injected: bool):
283
self.x = x
284
self.y = y
285
self.injected = injected
286
287
class Click:
288
"""A mouse click event."""
289
def __init__(self, x: int, y: int, button: Button, pressed: bool, injected: bool):
290
self.x = x
291
self.y = y
292
self.button = button
293
self.pressed = pressed
294
self.injected = injected
295
296
class Scroll:
297
"""A mouse scroll event."""
298
def __init__(self, x: int, y: int, dx: int, dy: int, injected: bool):
299
self.x = x
300
self.y = y
301
self.dx = dx
302
self.dy = dy
303
self.injected = injected
304
```
305
306
#### Usage Examples
307
308
```python
309
from pynput.mouse import Events
310
311
# Process events synchronously
312
with Events() as events:
313
for event in events:
314
if isinstance(event, Events.Move):
315
print(f'Mouse moved to ({event.x}, {event.y})')
316
elif isinstance(event, Events.Click):
317
if event.pressed:
318
print(f'Button {event.button} pressed at ({event.x}, {event.y})')
319
else:
320
print(f'Button {event.button} released')
321
break # Exit on button release
322
elif isinstance(event, Events.Scroll):
323
print(f'Scrolled ({event.dx}, {event.dy}) at ({event.x}, {event.y})')
324
325
# Get events with timeout
326
with Events() as events:
327
while True:
328
event = events.get(timeout=1.0)
329
if event is None:
330
print("No event received within timeout")
331
break
332
print(f"Received event: {event}")
333
```
334
335
## Types
336
337
### Button Enumeration
338
339
```python { .api }
340
class Button(enum.Enum):
341
"""Mouse button identifiers."""
342
343
left = 1 # Left mouse button
344
middle = 2 # Middle mouse button (scroll wheel)
345
right = 3 # Right mouse button
346
unknown = 0 # Unknown button
347
```
348
349
## Platform-Specific Features
350
351
### Windows (win32)
352
353
```python
354
# Event filtering
355
def win32_filter(msg, data):
356
"""Filter Windows mouse events."""
357
# Return False to suppress event from reaching listener
358
return True
359
360
listener = mouse.Listener(
361
on_click=on_click,
362
win32_event_filter=win32_filter
363
)
364
```
365
366
### macOS (darwin)
367
368
```python
369
# Event intercepting and modification
370
def darwin_intercept(event_type, event):
371
"""Intercept and modify macOS mouse events."""
372
# Modify event using Quartz functions
373
# Return None to suppress event system-wide
374
return event
375
376
listener = mouse.Listener(
377
on_click=on_click,
378
darwin_intercept=darwin_intercept
379
)
380
```
381
382
### Linux (xorg)
383
384
Platform-specific options are available for X11/Xorg systems, though specific parameters may vary based on system configuration.
385
386
## Error Handling
387
388
### Common Issues
389
390
- **ImportError**: Missing platform dependencies
391
- Windows: Ensure win32 libraries are available
392
- macOS: Requires PyObjC framework bindings
393
- Linux: Requires python-xlib and X11 development libraries
394
395
- **Permission Issues**: Some operations may require elevated privileges
396
- **Display Issues**: Linux requires DISPLAY environment variable to be set
397
398
### Exception Handling
399
400
```python
401
from pynput import mouse
402
403
try:
404
controller = mouse.Controller()
405
controller.position = (100, 100)
406
except Exception as e:
407
print(f"Mouse control error: {e}")
408
409
try:
410
with mouse.Listener(on_click=lambda *args: None) as listener:
411
listener.join()
412
except Exception as e:
413
print(f"Mouse listener error: {e}")
414
```