github / src / scripting / key.py @ 13e86181
1 |
# Copyright (c) 2016, LE GOFF Vincent |
---|---|
2 |
# All rights reserved.
|
3 |
|
4 |
# Redistribution and use in source and binary forms, with or without
|
5 |
# modification, are permitted provided that the following conditions are met:
|
6 |
|
7 |
# * Redistributions of source code must retain the above copyright notice, this
|
8 |
# list of conditions and the following disclaimer.
|
9 |
|
10 |
# * Redistributions in binary form must reproduce the above copyright notice,
|
11 |
# this list of conditions and the following disclaimer in the documentation
|
12 |
# and/or other materials provided with the distribution.
|
13 |
|
14 |
# * Neither the name of ytranslate nor the names of its
|
15 |
# contributors may be used to endorse or promote products derived from
|
16 |
# this software without specific prior written permission.
|
17 |
|
18 |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19 |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20 |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21 |
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
22 |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23 |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24 |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25 |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26 |
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27 |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28 |
|
29 |
"""Module containing functions to handle the keyboard."""
|
30 |
|
31 |
## Constants
|
32 |
|
33 |
# Modifiers
|
34 |
MOD_ALT = 1
|
35 |
MOD_CTRL = 2
|
36 |
MOD_SHIFT = 4
|
37 |
|
38 |
# Key codes
|
39 |
CODE_TO_KEY = { |
40 |
8: "Backspace", |
41 |
13: "Enter", |
42 |
27: "Escape", |
43 |
32: "Space", |
44 |
310: "Pause", |
45 |
324: "PavNum0", |
46 |
325: "PavNum1", |
47 |
326: "PavNum2", |
48 |
327: "PavNum3", |
49 |
328: "PavNum4", |
50 |
329: "PavNum5", |
51 |
330: "PavNum6", |
52 |
331: "PavNum7", |
53 |
332: "PavNum8", |
54 |
333: "PavNum9", |
55 |
340: "F1", |
56 |
341: "F2", |
57 |
342: "F3", |
58 |
343: "F4", |
59 |
344: "F5", |
60 |
345: "F6", |
61 |
346: "F7", |
62 |
347: "F8", |
63 |
348: "F9", |
64 |
349: "F10", |
65 |
350: "F11", |
66 |
351: "F12", |
67 |
364: "NumLock", |
68 |
387: "PavNum*", |
69 |
388: "PavNum+", |
70 |
390: "PavNum-", |
71 |
391: "PavNum.", |
72 |
392: "PavNum/", |
73 |
398: "PavNum-", |
74 |
} |
75 |
|
76 |
KEY_TO_CODE = {} |
77 |
for code, key in CODE_TO_KEY.items(): |
78 |
KEY_TO_CODE[key.lower()] = code |
79 |
|
80 |
# Add a few keys in the KEY_TO_CODE dictionary, as names may differ
|
81 |
KEY_TO_CODE["esc"] = 27 |
82 |
KEY_TO_CODE["back"] = 8 |
83 |
KEY_TO_CODE["return"] = 13 |
84 |
KEY_TO_CODE["pavnumlock"] = 364 |
85 |
KEY_TO_CODE["pavlock"] = 364 |
86 |
|
87 |
## Functions
|
88 |
def key_name(code, modifiers): |
89 |
"""Return the key name, if found."""
|
90 |
if code in CODE_TO_KEY: |
91 |
name = CODE_TO_KEY[code] |
92 |
elif 0 < code < 256: |
93 |
name = chr(code).upper()
|
94 |
else:
|
95 |
return "" |
96 |
|
97 |
ctrl = modifiers & MOD_CTRL != 0
|
98 |
alt = modifiers & MOD_ALT != 0
|
99 |
shift = modifiers & MOD_SHIFT != 0
|
100 |
if shift:
|
101 |
name = "Shift + " + name
|
102 |
if alt:
|
103 |
name = "Alt + " + name
|
104 |
if ctrl:
|
105 |
name = "Ctrl + " + name
|
106 |
|
107 |
return name
|
108 |
|
109 |
def key_code(name): |
110 |
"""Return the key code as a tuple.
|
111 |
|
112 |
The returned key code is a tuple containing two integers:
|
113 |
code: The key code as present in the constants
|
114 |
modifiers: A binary value of active modifiers
|
115 |
|
116 |
For example:
|
117 |
(8, 0) means Backspace (no modifiers)
|
118 |
(340, 1) means Alt + F1
|
119 |
(13, 6) means Ctrl + Shift + Enter
|
120 |
(107, 2) means Ctrl + K
|
121 |
|
122 |
"""
|
123 |
# Remove spaces
|
124 |
name = name.replace(" ", "").lower() |
125 |
|
126 |
# Scan for modifiers
|
127 |
modifiers = ("shift", "ctrl", "control", "alt") |
128 |
active_modifiers = 0
|
129 |
while name:
|
130 |
found = False
|
131 |
for modifier in modifiers: |
132 |
if name.startswith(modifier):
|
133 |
name = name[len(modifier):]
|
134 |
if modifier == "alt": |
135 |
active_modifiers = active_modifiers | MOD_ALT |
136 |
elif modifier in ("ctrl", "control"): |
137 |
active_modifiers = active_modifiers | MOD_CTRL |
138 |
elif modifier == "shift": |
139 |
active_modifiers = active_modifiers | MOD_SHIFT |
140 |
|
141 |
found = True
|
142 |
break
|
143 |
|
144 |
if name and name[0] in "+-": |
145 |
name = name[1:]
|
146 |
|
147 |
if not found: |
148 |
break
|
149 |
|
150 |
if len(name) == 1: |
151 |
code = ord(name.upper())
|
152 |
elif name not in KEY_TO_CODE: |
153 |
raise ValueError("The key {} cannot be found".format( |
154 |
repr(name)))
|
155 |
else:
|
156 |
code = KEY_TO_CODE[name] |
157 |
|
158 |
return (code, active_modifiers)
|