0
# Hotkeys
1
2
Registration and management of complex keyboard shortcuts, including multi-step hotkey sequences, global hotkey detection, and advanced hotkey remapping capabilities. The keyboard package provides comprehensive hotkey functionality that works system-wide regardless of application focus.
3
4
## Capabilities
5
6
### Hotkey Registration
7
8
Register callbacks to be executed when specific key combinations are pressed.
9
10
```python { .api }
11
def add_hotkey(hotkey, callback, args=(), suppress=False, timeout=1, trigger_on_release=False):
12
"""
13
Invokes a callback every time a hotkey is pressed. The hotkey must be in
14
the format 'ctrl+shift+a, s'. This would trigger when the user holds ctrl,
15
shift and "a" at once, releases, and then presses "s".
16
17
Parameters:
18
- hotkey: Hotkey string (e.g., 'ctrl+c', 'ctrl+shift+a, s')
19
- callback: Function to call when hotkey is triggered
20
- args: Optional arguments to pass to callback
21
- suppress: If True, prevent hotkey from reaching other applications
22
- timeout: Seconds allowed between steps in multi-step hotkeys
23
- trigger_on_release: If True, trigger on key release instead of press
24
25
Returns:
26
Function to remove the hotkey
27
28
Examples:
29
- add_hotkey('ctrl+c', copy_function)
30
- add_hotkey('f1', show_help)
31
- add_hotkey('ctrl+shift+s, ctrl+v', special_paste)
32
"""
33
34
def register_hotkey(hotkey, callback, args=(), suppress=False, timeout=1, trigger_on_release=False):
35
"""Alias for add_hotkey()."""
36
```
37
38
### Hotkey Removal
39
40
Remove previously registered hotkeys by hotkey string or callback reference.
41
42
```python { .api }
43
def remove_hotkey(hotkey_or_callback):
44
"""
45
Removes a previously hooked hotkey. Must be called with the hotkey string
46
used in add_hotkey() or the callback function.
47
48
Parameters:
49
- hotkey_or_callback: Hotkey string or callback function to remove
50
"""
51
52
def clear_hotkey(hotkey_or_callback):
53
"""Alias for remove_hotkey()."""
54
55
def unregister_hotkey(hotkey_or_callback):
56
"""Alias for remove_hotkey()."""
57
58
def unhook_all_hotkeys():
59
"""
60
Removes all keyboard hotkeys in use, including abbreviations, word listeners,
61
recorders and waits.
62
"""
63
64
def clear_all_hotkeys():
65
"""Alias for unhook_all_hotkeys()."""
66
67
def remove_all_hotkeys():
68
"""Alias for unhook_all_hotkeys()."""
69
70
def unregister_all_hotkeys():
71
"""Alias for unhook_all_hotkeys()."""
72
```
73
74
### Hotkey Remapping
75
76
Remap hotkeys to other hotkey combinations with optional suppression.
77
78
```python { .api }
79
def remap_hotkey(src, dst, suppress=True, trigger_on_release=False):
80
"""
81
Whenever the hotkey src is pressed, suppress it and send dst instead.
82
83
Parameters:
84
- src: Source hotkey to remap
85
- dst: Destination hotkey to send instead
86
- suppress: If True, suppress the original hotkey
87
- trigger_on_release: If True, trigger on key release
88
89
Returns:
90
Function to remove the remapping
91
92
Example:
93
remap_hotkey('alt+w', 'ctrl+up') # Remap Alt+W to Ctrl+Up
94
"""
95
96
def unremap_hotkey(hotkey):
97
"""Alias for remove_hotkey()."""
98
```
99
100
### Hotkey Utilities
101
102
Utility functions for working with hotkey strings and current key states.
103
104
```python { .api }
105
def get_hotkey_name(names=None):
106
"""
107
Returns a string representation of hotkey from the given key names, or
108
the currently pressed keys if not given.
109
110
Parameters:
111
- names: List of key names (optional, uses currently pressed keys if None)
112
113
Returns:
114
str: Standardized hotkey string
115
116
Example:
117
get_hotkey_name(['ctrl', 'shift', 'a']) # Returns 'ctrl+shift+a'
118
"""
119
120
def parse_hotkey_combinations(hotkey):
121
"""
122
Parses a user-provided hotkey. Instead of each step being a list of the
123
different scan codes for each key, each step is a list of all possible
124
combinations of those scan codes.
125
126
Parameters:
127
- hotkey: Hotkey string to parse
128
129
Returns:
130
tuple: All possible scan code combinations for the hotkey
131
"""
132
```
133
134
## Usage Examples
135
136
### Basic Hotkey Registration
137
138
```python
139
import keyboard
140
141
def on_ctrl_c():
142
print('Ctrl+C was pressed!')
143
144
def on_f1():
145
print('F1 Help key pressed!')
146
147
def on_custom_hotkey():
148
print('Custom hotkey Ctrl+Shift+H pressed!')
149
150
# Register hotkeys
151
keyboard.add_hotkey('ctrl+c', on_ctrl_c)
152
keyboard.add_hotkey('f1', on_f1)
153
keyboard.add_hotkey('ctrl+shift+h', on_custom_hotkey)
154
155
print('Hotkeys registered. Press ESC to exit.')
156
keyboard.wait('esc')
157
158
# Clean up
159
keyboard.unhook_all_hotkeys()
160
```
161
162
### Hotkeys with Arguments
163
164
```python
165
import keyboard
166
167
def show_message(msg, count=1):
168
for i in range(count):
169
print(f'{msg} ({i+1})')
170
171
# Hotkey with arguments
172
keyboard.add_hotkey('f2', show_message, args=('Hello from F2!', 3))
173
keyboard.add_hotkey('f3', show_message, args=('Quick message',))
174
175
keyboard.wait('esc')
176
keyboard.unhook_all_hotkeys()
177
```
178
179
### Multi-Step Hotkeys
180
181
```python
182
import keyboard
183
184
def konami_code():
185
print('Konami code activated!')
186
187
def quick_save():
188
print('Quick save sequence activated!')
189
190
# Multi-step hotkey sequences
191
keyboard.add_hotkey('up, up, down, down, left, right, left, right, b, a', konami_code)
192
keyboard.add_hotkey('ctrl+s, ctrl+s', quick_save, timeout=2) # Double Ctrl+S within 2 seconds
193
194
keyboard.wait('esc')
195
keyboard.unhook_all_hotkeys()
196
```
197
198
### Hotkey Suppression
199
200
```python
201
import keyboard
202
203
def custom_alt_f4():
204
print('Alt+F4 intercepted! Custom close behavior.')
205
# Could implement custom confirmation dialog here
206
return False # Suppress the original Alt+F4
207
208
# Suppress Alt+F4 and replace with custom behavior
209
keyboard.add_hotkey('alt+f4', custom_alt_f4, suppress=True)
210
211
print('Alt+F4 is now intercepted. Press ESC to exit.')
212
keyboard.wait('esc')
213
keyboard.unhook_all_hotkeys()
214
```
215
216
### Dynamic Hotkey Management
217
218
```python
219
import keyboard
220
221
hotkey_callbacks = {}
222
223
def register_dynamic_hotkey(hotkey_str, message):
224
def callback():
225
print(f'Dynamic hotkey: {message}')
226
227
remove_func = keyboard.add_hotkey(hotkey_str, callback)
228
hotkey_callbacks[hotkey_str] = remove_func
229
print(f'Registered: {hotkey_str}')
230
231
def unregister_dynamic_hotkey(hotkey_str):
232
if hotkey_str in hotkey_callbacks:
233
hotkey_callbacks[hotkey_str]() # Call remove function
234
del hotkey_callbacks[hotkey_str]
235
print(f'Unregistered: {hotkey_str}')
236
237
# Register some dynamic hotkeys
238
register_dynamic_hotkey('f5', 'Refresh action')
239
register_dynamic_hotkey('f6', 'Toggle action')
240
register_dynamic_hotkey('ctrl+1', 'Workspace 1')
241
242
print('Dynamic hotkeys registered. Press F9 to remove F5, F10 to exit.')
243
244
def remove_f5():
245
unregister_dynamic_hotkey('f5')
246
247
keyboard.add_hotkey('f9', remove_f5)
248
keyboard.wait('f10')
249
250
# Clean up all remaining hotkeys
251
for remove_func in hotkey_callbacks.values():
252
remove_func()
253
```
254
255
### Hotkey Remapping
256
257
```python
258
import keyboard
259
260
# Remap Windows key combinations for different workflow
261
remove_remap1 = keyboard.remap_hotkey('win+l', 'ctrl+alt+l') # Custom lock
262
remove_remap2 = keyboard.remap_hotkey('win+d', 'alt+tab') # Show desktop -> Alt+Tab
263
264
# Remap for left-handed users
265
remove_remap3 = keyboard.remap_hotkey('ctrl+c', 'ctrl+insert') # Alternative copy
266
remove_remap4 = keyboard.remap_hotkey('ctrl+v', 'shift+insert') # Alternative paste
267
268
print('Hotkey remapping active. Press ESC to exit.')
269
keyboard.wait('esc')
270
271
# Remove all remappings
272
remove_remap1()
273
remove_remap2()
274
remove_remap3()
275
remove_remap4()
276
```
277
278
### Context-Sensitive Hotkeys
279
280
```python
281
import keyboard
282
283
class HotkeyManager:
284
def __init__(self):
285
self.mode = 'normal'
286
self.hotkeys = {}
287
self.setup_mode_hotkeys()
288
289
def setup_mode_hotkeys(self):
290
# Mode switching
291
self.hotkeys['f12'] = keyboard.add_hotkey('f12', self.toggle_mode)
292
293
# Context-sensitive hotkeys
294
self.hotkeys['1'] = keyboard.add_hotkey('1', self.handle_1_key)
295
self.hotkeys['2'] = keyboard.add_hotkey('2', self.handle_2_key)
296
297
def toggle_mode(self):
298
self.mode = 'editing' if self.mode == 'normal' else 'normal'
299
print(f'Switched to {self.mode} mode')
300
301
def handle_1_key(self):
302
if self.mode == 'normal':
303
print('Normal mode: Action 1')
304
else:
305
print('Editing mode: Edit action 1')
306
307
def handle_2_key(self):
308
if self.mode == 'normal':
309
print('Normal mode: Action 2')
310
else:
311
print('Editing mode: Edit action 2')
312
313
def cleanup(self):
314
for remove_func in self.hotkeys.values():
315
remove_func()
316
317
# Usage
318
manager = HotkeyManager()
319
print('Context-sensitive hotkeys active. F12 to toggle mode, ESC to exit.')
320
keyboard.wait('esc')
321
manager.cleanup()
322
```
323
324
## Advanced Hotkey Features
325
326
### Timeout Control
327
328
```python
329
import keyboard
330
331
def slow_sequence():
332
print('Slow sequence completed!')
333
334
def fast_sequence():
335
print('Fast sequence completed!')
336
337
# Different timeout values for different sequences
338
keyboard.add_hotkey('ctrl+a, ctrl+b', slow_sequence, timeout=5) # 5 seconds allowed
339
keyboard.add_hotkey('ctrl+x, ctrl+y', fast_sequence, timeout=0.5) # 0.5 seconds allowed
340
341
keyboard.wait('esc')
342
keyboard.unhook_all_hotkeys()
343
```
344
345
### Release-Triggered Hotkeys
346
347
```python
348
import keyboard
349
350
def on_key_release():
351
print('Hotkey triggered on release!')
352
353
def on_key_press():
354
print('Hotkey triggered on press!')
355
356
# Compare press vs release triggering
357
keyboard.add_hotkey('f7', on_key_press, trigger_on_release=False)
358
keyboard.add_hotkey('f8', on_key_release, trigger_on_release=True)
359
360
keyboard.wait('esc')
361
keyboard.unhook_all_hotkeys()
362
```
363
364
## Hotkey String Format
365
366
### Single Key Hotkeys
367
- `'f1'` - Function keys
368
- `'a'` - Letter keys
369
- `'space'` - Named keys
370
- `'enter'` - Special keys
371
372
### Modifier Combinations
373
- `'ctrl+c'` - Single modifier
374
- `'ctrl+shift+a'` - Multiple modifiers
375
- `'alt+f4'` - Case insensitive
376
377
### Multi-Step Sequences
378
- `'ctrl+k, ctrl+c'` - Visual Studio style
379
- `'ctrl+x, ctrl+c'` - Emacs style
380
- `'g, g'` - Vim style (double key)
381
382
### Special Key Names
383
- `'plus'` for '+' symbol
384
- `'comma'` for ',' symbol
385
- `'space'` for spacebar
386
- `'left ctrl'` / `'right ctrl'` for sided modifiers
387
388
## Error Handling
389
390
Hotkey registration may fail due to:
391
- Invalid hotkey format strings
392
- Platform limitations (Linux requires root for global hotkeys)
393
- Conflicting hotkey registrations
394
- System security restrictions
395
396
The package will raise `ValueError` for invalid hotkey strings and may silently fail to register hotkeys in restricted environments.
397
398
## Performance Considerations
399
400
- Hotkeys with many modifiers are more expensive to detect
401
- Multi-step hotkeys require state tracking and timeout management
402
- Suppressed hotkeys add processing overhead
403
- Large numbers of registered hotkeys can impact system responsiveness
404
405
For optimal performance:
406
- Use specific hotkeys rather than broad key hooks when possible
407
- Remove unused hotkeys promptly
408
- Avoid overlapping hotkey patterns that could cause conflicts