Skip to content

Commit 76e0d95

Browse files
Add internal_filesystem/lib/mpos/indev/mpos_sdl_keyboard.py
1 parent 832ffb1 commit 76e0d95

File tree

1 file changed

+376
-0
lines changed

1 file changed

+376
-0
lines changed
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
import lvgl as lv
2+
from micropython import const # NOQA
3+
import micropython # NOQA # NOQA
4+
import keypad_framework
5+
6+
KEY_UNKNOWN = 0
7+
KEY_BACKSPACE = 8 # LV_KEY_BACKSPACE
8+
KEY_TAB = 9 # LV_KEY_NEXT
9+
KEY_CLEAR = 12
10+
KEY_RETURN = 13 # LV_KEY_ENTER
11+
KEY_PAUSE = 19 #
12+
KEY_ESCAPE = 27 # LV_KEY_ESC
13+
KEY_SPACE = 32 # " "
14+
KEY_EXCLAIM = 33 # !
15+
KEY_QUOTEDBL = 34 # "
16+
KEY_HASH = 35 # #
17+
KEY_DOLLAR = 36 # $
18+
KEY_AMPERSAND = 38 # &
19+
KEY_QUOTE = 39 # '
20+
KEY_LEFTPAREN = 40 # (
21+
KEY_RIGHTPAREN = 41 # )
22+
KEY_ASTERISK = 42 # *
23+
KEY_PLUS = 43 # +
24+
KEY_COMMA = 44 # ,
25+
KEY_MINUS = 45 # -
26+
KEY_PERIOD = 46 # .
27+
KEY_SLASH = 47 # /
28+
29+
KEY_0 = 48 # 0
30+
KEY_1 = 49 # 1
31+
KEY_2 = 50 # 2
32+
KEY_3 = 51 # 3
33+
KEY_4 = 52 # 4
34+
KEY_5 = 53 # 5
35+
KEY_6 = 54 # 6
36+
KEY_7 = 55 # 7
37+
KEY_8 = 56 # 8
38+
KEY_9 = 57 # 9
39+
40+
KEY_COLON = 58 # :
41+
KEY_SEMICOLON = 59 # ;
42+
KEY_LESS = 60 # <
43+
KEY_EQUALS = 61 # =
44+
KEY_GREATER = 62 # >
45+
KEY_QUESTION = 63 # ?
46+
KEY_AT = 64 # @
47+
KEY_LEFTBRACKET = 91 # [
48+
KEY_BACKSLASH = 92 # \
49+
KEY_RIGHTBRACKET = 93 # ]
50+
KEY_CARET = 94 # ^
51+
KEY_UNDERSCORE = 95 # _
52+
KEY_BACKQUOTE = 96 # `
53+
KEY_a = 97 # a
54+
KEY_z = 122 # z
55+
KEY_DELETE = 127 # LV_KEY_DEL
56+
57+
# Numeric keypad
58+
# if MOD_KEY_NUM then it's numbers.
59+
60+
KEYPAD_0 = 256 # 0/INS
61+
KEYPAD_1 = 257 # 1/END LV_KEY_END
62+
KEYPAD_2 = 258 # 2/DOWN LV_KEY_DOWN
63+
KEYPAD_3 = 259 # 3/PAGEDOWN
64+
KEYPAD_4 = 260 # 4/LEFT LV_KEY_LEFT
65+
KEYPAD_5 = 261 # 5
66+
KEYPAD_6 = 262 # 6/RIGHT LV_KEY_RIGHT
67+
KEYPAD_7 = 263 # 7/HOME LV_KEY_HOME
68+
KEYPAD_8 = 264 # 8/UP LV_KEY_UP
69+
KEYPAD_9 = 265 # 9/PAGEUP
70+
KEYPAD_PERIOD = 266 # ./DEL LV_KEY_DEL
71+
KEYPAD_DIVIDE = 267 # /
72+
KEYPAD_MULTIPLY = 268 # *
73+
KEYPAD_MINUS = 269 # -
74+
KEYPAD_PLUS = 270 # +
75+
KEYPAD_ENTER = 271 # LV_KEY_ENTER
76+
KEYPAD_EQUALS = 272 # =
77+
78+
# Arrows + Home/End pad
79+
80+
KEY_UP = 273 # LV_KEY_UP
81+
KEY_DOWN = 274 # LV_KEY_DOWN
82+
KEY_RIGHT = 275 # LV_KEY_RIGHT
83+
KEY_LEFT = 276 # LV_KEY_LEFT
84+
KEY_INSERT = 277
85+
KEY_HOME = 278 # LV_KEY_HOME
86+
KEY_END = 279 # LV_KEY_END
87+
KEY_PAGEUP = 280
88+
KEY_PAGEDOWN = 281
89+
90+
KEY_F1 = 282
91+
KEY_F2 = 283
92+
KEY_F3 = 284
93+
KEY_F4 = 285
94+
KEY_F5 = 286
95+
KEY_F6 = 287
96+
KEY_F7 = 288
97+
KEY_F8 = 289
98+
KEY_F9 = 290
99+
KEY_F10 = 291
100+
KEY_F11 = 292
101+
KEY_F12 = 293
102+
KEY_F13 = 294
103+
KEY_F14 = 295
104+
KEY_F15 = 296
105+
106+
KEY_NUMLOCK = 300
107+
KEY_CAPSLOCK = 301
108+
KEY_SCROLLOCK = 302
109+
KEY_RSHIFT = 303
110+
KEY_LSHIFT = 304
111+
KEY_RCTRL = 305
112+
KEY_LCTRL = 306
113+
KEY_RALT = 307
114+
KEY_LALT = 308
115+
KEY_RMETA = 309
116+
KEY_LMETA = 310
117+
118+
# Left "Windows" key
119+
KEY_LSUPER = 311
120+
121+
# Right "Windows" key
122+
KEY_RSUPER = 312
123+
124+
# Alt Gr" key
125+
KEY_MODE = 313
126+
# Multi-key compose key
127+
KEY_COMPOSE = 314
128+
129+
KEY_HELP = 315
130+
KEY_PRINT = 316
131+
KEY_SYSREQ = 317
132+
KEY_BREAK = 318
133+
KEY_MENU = 319
134+
# Power Macintosh power key
135+
KEY_POWER = 320
136+
# Some european keyboards
137+
KEY_EURO = 321
138+
# Atari keyboard has Undo
139+
KEY_UNDO = 322
140+
141+
MOD_KEY_NONE = 0x0000
142+
MOD_KEY_LSHIFT = 0x0001
143+
MOD_KEY_RSHIFT = 0x0002
144+
MOD_KEY_LCTRL = 0x0040
145+
MOD_KEY_RCTRL = 0x0080
146+
MOD_KEY_LALT = 0x0100
147+
MOD_KEY_RALT = 0x0200
148+
MOD_KEY_LMETA = 0x0400
149+
MOD_KEY_RMETA = 0x0800
150+
MOD_KEY_NUM = 0x1000
151+
MOD_KEY_CAPS = 0x2000
152+
MOD_KEY_MODE = 0x4000
153+
MOD_KEY_CTRL = MOD_KEY_LCTRL | MOD_KEY_RCTRL
154+
MOD_KEY_SHIFT = MOD_KEY_LSHIFT | MOD_KEY_RSHIFT
155+
MOD_KEY_ALT = MOD_KEY_LALT | MOD_KEY_RALT
156+
MOD_KEY_META = MOD_KEY_LMETA | MOD_KEY_RMETA
157+
158+
# SDL keycode ranges
159+
SDL_NAV_KEY_START = 1073741897 # Insert
160+
SDL_NAV_KEY_END = 1073741906 # Down Arrow
161+
SDL_FUNC_KEY_START = 1073741882 # F1
162+
SDL_FUNC_KEY_END = 1073741893 # F12
163+
SDL_KEYPAD_KEY_START = 1073741908 # Keypad /
164+
SDL_KEYPAD_KEY_END = 1073741923 # Keypad .
165+
166+
# Shift key mappings for QWERTY layout
167+
SHIFT_KEY_MAP = {
168+
KEY_1: KEY_EXCLAIM, # 1 -> !
169+
KEY_2: KEY_AT, # 2 -> @
170+
KEY_3: KEY_HASH, # 3 -> #
171+
KEY_4: KEY_DOLLAR, # 4 -> $
172+
KEY_5: 37, # 5 -> % (ASCII 37)
173+
KEY_6: KEY_CARET, # 6 -> ^
174+
KEY_7: KEY_AMPERSAND, # 7 -> &
175+
KEY_8: KEY_ASTERISK, # 8 -> *
176+
KEY_9: KEY_LEFTPAREN, # 9 -> (
177+
KEY_0: KEY_RIGHTPAREN, # 0 -> )
178+
KEY_MINUS: KEY_UNDERSCORE, # - -> _
179+
KEY_EQUALS: KEY_PLUS, # = -> +
180+
KEY_LEFTBRACKET: 123, # [ -> { (ASCII 123)
181+
KEY_RIGHTBRACKET: 125, # ] -> } (ASCII 125)
182+
KEY_BACKSLASH: 124, # \ -> | (ASCII 124)
183+
KEY_SEMICOLON: KEY_COLON, # ; -> :
184+
KEY_QUOTE: KEY_QUOTEDBL, # ' -> "
185+
KEY_COMMA: KEY_LESS, # , -> <
186+
KEY_PERIOD: KEY_GREATER, # . -> >
187+
KEY_SLASH: KEY_QUESTION, # / -> ?
188+
KEY_BACKQUOTE: 126, # ` -> ~ (ASCII 126)
189+
}
190+
191+
192+
class MposSDLKeyboard(keypad_framework.KeypadDriver):
193+
194+
def __init__(self, *args, **kwargs): # NOQA
195+
super().__init__()
196+
self.__last_key = -1
197+
self.__current_state = self.RELEASED
198+
199+
self.group = lv.group_create()
200+
self.group.set_default() # NOQA
201+
self.set_group(self.group)
202+
self.set_mode(lv.INDEV_MODE.EVENT) # NOQA
203+
204+
self._py_disp_drv._data_bus.register_keypad_callback(self._keypad_cb) # NOQA
205+
206+
self.paste_text_callback = None
207+
208+
def set_paste_text_callback(self, callback):
209+
self.paste_text_callback = callback
210+
211+
def set_mode(self, mode):
212+
self._indev_drv.set_mode(mode) # NOQA
213+
214+
def _keypad_cb(self, *args):
215+
if len(args) == 5: # Special case for paste
216+
_, state, key, mod, clipboard_text = args
217+
print(f"got clipboard paste arg: {clipboard_text}")
218+
if self.paste_text_callback and state == 1 and key == 118 and mod & MOD_KEY_CTRL: # CTRL-V
219+
self.paste_text_callback(clipboard_text)
220+
return
221+
else:
222+
_, state, key, mod = args
223+
print(f"sdl_keyboard.py _keypad_cb got {_}, {state} {key} {mod}")
224+
225+
# Skip modifier keys and SDL-specific large keycodes (>= 2^30), except keypad, nav, and func keys
226+
if (key in {KEY_LSHIFT, KEY_RSHIFT, KEY_LCTRL, KEY_RCTRL, KEY_LALT, KEY_RALT,
227+
KEY_LMETA, KEY_RMETA, KEY_LSUPER, KEY_RSUPER, KEY_MODE, KEY_COMPOSE,
228+
KEY_NUMLOCK, KEY_CAPSLOCK, KEY_SCROLLOCK} or
229+
(key >= 1 << 30 and not (SDL_NAV_KEY_START <= key <= SDL_NAV_KEY_END or
230+
SDL_FUNC_KEY_START <= key <= SDL_FUNC_KEY_END or
231+
SDL_KEYPAD_KEY_START <= key <= SDL_KEYPAD_KEY_END))):
232+
self.__last_key = -1 # Do not send modifier keys to LVGL
233+
return
234+
235+
if key == KEY_PAUSE:
236+
return
237+
238+
# Handle numeric keypad keys (SDL keycodes and original KEYPAD_* range)
239+
if (KEYPAD_0 <= key <= KEYPAD_EQUALS or
240+
SDL_KEYPAD_KEY_START <= key <= SDL_KEYPAD_KEY_END):
241+
if mod & MOD_KEY_NUM:
242+
mapping = {
243+
KEYPAD_0: KEY_0,
244+
KEYPAD_1: KEY_1,
245+
KEYPAD_2: KEY_2,
246+
KEYPAD_3: KEY_3,
247+
KEYPAD_4: KEY_4,
248+
KEYPAD_5: KEY_5,
249+
KEYPAD_6: KEY_6,
250+
KEYPAD_7: KEY_7,
251+
KEYPAD_8: KEY_8,
252+
KEYPAD_9: KEY_9,
253+
KEYPAD_PERIOD: KEY_PERIOD,
254+
KEYPAD_DIVIDE: KEY_SLASH,
255+
KEYPAD_MULTIPLY: KEY_ASTERISK,
256+
KEYPAD_MINUS: KEY_MINUS,
257+
KEYPAD_PLUS: KEY_PLUS,
258+
KEYPAD_ENTER: KEY_EQUALS,
259+
KEYPAD_EQUALS: KEY_EQUALS,
260+
1073741908: KEY_SLASH, # Keypad /
261+
1073741909: KEY_ASTERISK, # Keypad *
262+
1073741910: KEY_MINUS, # Keypad -
263+
1073741911: KEY_PLUS, # Keypad +
264+
1073741912: lv.KEY.ENTER, # Keypad ENTER
265+
1073741913: KEY_1, # Keypad 1
266+
1073741914: KEY_2, # Keypad 2
267+
1073741915: KEY_3, # Keypad 3
268+
1073741916: KEY_4, # Keypad 4
269+
1073741917: KEY_5, # Keypad 5
270+
1073741918: KEY_6, # Keypad 6
271+
1073741919: KEY_7, # Keypad 7
272+
1073741920: KEY_8, # Keypad 8
273+
1073741921: KEY_9, # Keypad 9
274+
1073741922: KEY_0, # Keypad 0
275+
1073741923: KEY_PERIOD # Keypad .
276+
}
277+
else:
278+
mapping = {
279+
KEYPAD_0: KEY_INSERT,
280+
KEYPAD_1: lv.KEY.END, # NOQA
281+
KEYPAD_2: lv.KEY.DOWN, # NOQA
282+
KEYPAD_3: lv.KEY.PREV, # NOQA
283+
KEYPAD_4: lv.KEY.LEFT, # NOQA
284+
KEYPAD_5: KEY_5,
285+
KEYPAD_6: lv.KEY.RIGHT, # NOQA
286+
KEYPAD_7: lv.KEY.HOME, # NOQA
287+
KEYPAD_8: lv.KEY.UP, # NOQA
288+
KEYPAD_9: lv.KEY.NEXT, # NOQA
289+
KEYPAD_PERIOD: lv.KEY.DEL, # NOQA
290+
KEYPAD_DIVIDE: KEY_SLASH,
291+
KEYPAD_MULTIPLY: KEY_ASTERISK,
292+
KEYPAD_MINUS: KEY_MINUS,
293+
KEYPAD_PLUS: KEY_PLUS,
294+
KEYPAD_ENTER: lv.KEY.ENTER, # NOQA
295+
KEYPAD_EQUALS: KEY_EQUALS,
296+
1073741908: KEY_SLASH, # Keypad /
297+
1073741909: KEY_ASTERISK, # Keypad *
298+
1073741910: KEY_MINUS, # Keypad -
299+
1073741911: KEY_PLUS, # Keypad +
300+
1073741912: lv.KEY.ENTER, # Keypad ENTER
301+
1073741913: lv.KEY.END, # Keypad 1
302+
1073741914: lv.KEY.DOWN, # Keypad 2
303+
1073741915: lv.KEY.PREV, # Keypad 3
304+
1073741916: lv.KEY.LEFT, # Keypad 4
305+
1073741917: KEY_5, # Keypad 5
306+
1073741918: lv.KEY.RIGHT, # Keypad 6
307+
1073741919: lv.KEY.HOME, # Keypad 7
308+
1073741920: lv.KEY.UP, # Keypad 8
309+
1073741921: lv.KEY.NEXT, # Keypad 9
310+
1073741922: KEY_INSERT, # Keypad 0
311+
1073741923: lv.KEY.DEL # Keypad .
312+
}
313+
314+
self.__last_key = mapping[key]
315+
# Apply Shift for keypad symbols if applicable
316+
if mod & MOD_KEY_SHIFT and self.__last_key in SHIFT_KEY_MAP:
317+
self.__last_key = SHIFT_KEY_MAP[self.__last_key]
318+
else:
319+
mapping = {
320+
KEY_BACKSPACE: lv.KEY.BACKSPACE, # NOQA
321+
KEY_TAB: lv.KEY.NEXT, # NOQA
322+
KEY_RETURN: lv.KEY.ENTER, # NOQA
323+
KEY_ESCAPE: lv.KEY.ESC, # NOQA
324+
KEY_DELETE: lv.KEY.DEL, # NOQA
325+
KEY_UP: lv.KEY.UP, # NOQA
326+
KEY_DOWN: lv.KEY.DOWN, # NOQA
327+
KEY_RIGHT: lv.KEY.RIGHT, # NOQA
328+
KEY_LEFT: lv.KEY.LEFT, # NOQA
329+
KEY_HOME: lv.KEY.HOME, # NOQA
330+
KEY_END: lv.KEY.END, # NOQA
331+
KEY_PAGEDOWN: lv.KEY.PREV, # NOQA
332+
KEY_PAGEUP: lv.KEY.NEXT, # NOQA
333+
1073741897: KEY_INSERT, # SDL Insert
334+
1073741898: lv.KEY.HOME, # SDL Home
335+
1073741899: lv.KEY.PREV, # SDL PageUp
336+
1073741900: lv.KEY.DEL, # SDL Delete (unconfirmed)
337+
1073741901: lv.KEY.END, # SDL End
338+
1073741902: lv.KEY.NEXT, # SDL PageDown
339+
1073741903: lv.KEY.RIGHT, # SDL Right Arrow
340+
1073741904: lv.KEY.LEFT, # SDL Left Arrow
341+
1073741905: lv.KEY.UP, # SDL Up Arrow
342+
1073741906: lv.KEY.DOWN, # SDL Down Arrow
343+
1073741882: KEY_F1, # SDL F1
344+
1073741883: KEY_F2, # SDL F2
345+
1073741884: KEY_F3, # SDL F3
346+
1073741885: KEY_F4, # SDL F4
347+
1073741886: KEY_F5, # SDL F5
348+
1073741887: KEY_F6, # SDL F6
349+
1073741888: KEY_F7, # SDL F7
350+
1073741889: KEY_F8, # SDL F8
351+
1073741890: KEY_F9, # SDL F9
352+
1073741891: KEY_F10, # SDL F10
353+
1073741892: KEY_F11, # SDL F11
354+
1073741893: KEY_F12 # SDL F12
355+
}
356+
357+
# Handle Shift or Caps Lock for letters and symbols
358+
if mod & (MOD_KEY_SHIFT | MOD_KEY_CAPS) and KEY_a <= key <= KEY_z:
359+
# Convert lowercase to uppercase
360+
self.__last_key = key - 32 # ASCII lowercase to uppercase
361+
elif mod & MOD_KEY_SHIFT and key in SHIFT_KEY_MAP:
362+
# Apply Shift mapping for numbers and punctuation
363+
self.__last_key = SHIFT_KEY_MAP[key]
364+
else:
365+
# Use standard mapping or key as-is
366+
self.__last_key = mapping.get(key, key)
367+
368+
if state:
369+
self.__current_state = self.PRESSED
370+
else:
371+
self.__current_state = self.RELEASED
372+
373+
micropython.schedule(MposSDLKeyboard.read, self)
374+
375+
def _get_key(self):
376+
return self.__current_state, self.__last_key

0 commit comments

Comments
 (0)