FreeRDP
SDL2/sdl_kbd.cpp
1 
20 #include "sdl_kbd.hpp"
21 #include "sdl_disp.hpp"
22 #include "sdl_freerdp.hpp"
23 #include "sdl_utils.hpp"
24 #include "sdl_prefs.hpp"
25 
26 #include <map>
27 
28 #include <freerdp/utils/string.h>
29 #include <freerdp/scancode.h>
30 
31 #include <freerdp/log.h>
32 #define TAG CLIENT_TAG("SDL.kbd")
33 
34 using scancode_entry_t = struct
35 {
36  Uint32 sdl;
37  const char* sdl_name;
38  UINT32 rdp;
39  const char* rdp_name;
40 };
41 
42 #define STR(x) #x
43 #define ENTRY(x, y) \
44  { \
45  x, STR(x), y, #y \
46  }
47 static const scancode_entry_t map[] = {
48  ENTRY(SDL_SCANCODE_UNKNOWN, RDP_SCANCODE_UNKNOWN),
49  ENTRY(SDL_SCANCODE_A, RDP_SCANCODE_KEY_A),
50  ENTRY(SDL_SCANCODE_B, RDP_SCANCODE_KEY_B),
51  ENTRY(SDL_SCANCODE_C, RDP_SCANCODE_KEY_C),
52  ENTRY(SDL_SCANCODE_D, RDP_SCANCODE_KEY_D),
53  ENTRY(SDL_SCANCODE_E, RDP_SCANCODE_KEY_E),
54  ENTRY(SDL_SCANCODE_F, RDP_SCANCODE_KEY_F),
55  ENTRY(SDL_SCANCODE_G, RDP_SCANCODE_KEY_G),
56  ENTRY(SDL_SCANCODE_H, RDP_SCANCODE_KEY_H),
57  ENTRY(SDL_SCANCODE_I, RDP_SCANCODE_KEY_I),
58  ENTRY(SDL_SCANCODE_J, RDP_SCANCODE_KEY_J),
59  ENTRY(SDL_SCANCODE_K, RDP_SCANCODE_KEY_K),
60  ENTRY(SDL_SCANCODE_L, RDP_SCANCODE_KEY_L),
61  ENTRY(SDL_SCANCODE_M, RDP_SCANCODE_KEY_M),
62  ENTRY(SDL_SCANCODE_N, RDP_SCANCODE_KEY_N),
63  ENTRY(SDL_SCANCODE_O, RDP_SCANCODE_KEY_O),
64  ENTRY(SDL_SCANCODE_P, RDP_SCANCODE_KEY_P),
65  ENTRY(SDL_SCANCODE_Q, RDP_SCANCODE_KEY_Q),
66  ENTRY(SDL_SCANCODE_R, RDP_SCANCODE_KEY_R),
67  ENTRY(SDL_SCANCODE_S, RDP_SCANCODE_KEY_S),
68  ENTRY(SDL_SCANCODE_T, RDP_SCANCODE_KEY_T),
69  ENTRY(SDL_SCANCODE_U, RDP_SCANCODE_KEY_U),
70  ENTRY(SDL_SCANCODE_V, RDP_SCANCODE_KEY_V),
71  ENTRY(SDL_SCANCODE_W, RDP_SCANCODE_KEY_W),
72  ENTRY(SDL_SCANCODE_X, RDP_SCANCODE_KEY_X),
73  ENTRY(SDL_SCANCODE_Y, RDP_SCANCODE_KEY_Y),
74  ENTRY(SDL_SCANCODE_Z, RDP_SCANCODE_KEY_Z),
75  ENTRY(SDL_SCANCODE_1, RDP_SCANCODE_KEY_1),
76  ENTRY(SDL_SCANCODE_2, RDP_SCANCODE_KEY_2),
77  ENTRY(SDL_SCANCODE_3, RDP_SCANCODE_KEY_3),
78  ENTRY(SDL_SCANCODE_4, RDP_SCANCODE_KEY_4),
79  ENTRY(SDL_SCANCODE_5, RDP_SCANCODE_KEY_5),
80  ENTRY(SDL_SCANCODE_6, RDP_SCANCODE_KEY_6),
81  ENTRY(SDL_SCANCODE_7, RDP_SCANCODE_KEY_7),
82  ENTRY(SDL_SCANCODE_8, RDP_SCANCODE_KEY_8),
83  ENTRY(SDL_SCANCODE_9, RDP_SCANCODE_KEY_9),
84  ENTRY(SDL_SCANCODE_0, RDP_SCANCODE_KEY_0),
85  ENTRY(SDL_SCANCODE_RETURN, RDP_SCANCODE_RETURN),
86  ENTRY(SDL_SCANCODE_ESCAPE, RDP_SCANCODE_ESCAPE),
87  ENTRY(SDL_SCANCODE_BACKSPACE, RDP_SCANCODE_BACKSPACE),
88  ENTRY(SDL_SCANCODE_TAB, RDP_SCANCODE_TAB),
89  ENTRY(SDL_SCANCODE_SPACE, RDP_SCANCODE_SPACE),
90  ENTRY(SDL_SCANCODE_MINUS, RDP_SCANCODE_OEM_MINUS),
91  ENTRY(SDL_SCANCODE_CAPSLOCK, RDP_SCANCODE_CAPSLOCK),
92  ENTRY(SDL_SCANCODE_F1, RDP_SCANCODE_F1),
93  ENTRY(SDL_SCANCODE_F2, RDP_SCANCODE_F2),
94  ENTRY(SDL_SCANCODE_F3, RDP_SCANCODE_F3),
95  ENTRY(SDL_SCANCODE_F4, RDP_SCANCODE_F4),
96  ENTRY(SDL_SCANCODE_F5, RDP_SCANCODE_F5),
97  ENTRY(SDL_SCANCODE_F6, RDP_SCANCODE_F6),
98  ENTRY(SDL_SCANCODE_F7, RDP_SCANCODE_F7),
99  ENTRY(SDL_SCANCODE_F8, RDP_SCANCODE_F8),
100  ENTRY(SDL_SCANCODE_F9, RDP_SCANCODE_F9),
101  ENTRY(SDL_SCANCODE_F10, RDP_SCANCODE_F10),
102  ENTRY(SDL_SCANCODE_F11, RDP_SCANCODE_F11),
103  ENTRY(SDL_SCANCODE_F12, RDP_SCANCODE_F12),
104  ENTRY(SDL_SCANCODE_F13, RDP_SCANCODE_F13),
105  ENTRY(SDL_SCANCODE_F14, RDP_SCANCODE_F14),
106  ENTRY(SDL_SCANCODE_F15, RDP_SCANCODE_F15),
107  ENTRY(SDL_SCANCODE_F16, RDP_SCANCODE_F16),
108  ENTRY(SDL_SCANCODE_F17, RDP_SCANCODE_F17),
109  ENTRY(SDL_SCANCODE_F18, RDP_SCANCODE_F18),
110  ENTRY(SDL_SCANCODE_F19, RDP_SCANCODE_F19),
111  ENTRY(SDL_SCANCODE_F20, RDP_SCANCODE_F20),
112  ENTRY(SDL_SCANCODE_F21, RDP_SCANCODE_F21),
113  ENTRY(SDL_SCANCODE_F22, RDP_SCANCODE_F22),
114  ENTRY(SDL_SCANCODE_F23, RDP_SCANCODE_F23),
115  ENTRY(SDL_SCANCODE_F24, RDP_SCANCODE_F24),
116  ENTRY(SDL_SCANCODE_NUMLOCKCLEAR, RDP_SCANCODE_NUMLOCK),
117  ENTRY(SDL_SCANCODE_KP_DIVIDE, RDP_SCANCODE_DIVIDE),
118  ENTRY(SDL_SCANCODE_KP_MULTIPLY, RDP_SCANCODE_MULTIPLY),
119  ENTRY(SDL_SCANCODE_KP_MINUS, RDP_SCANCODE_SUBTRACT),
120  ENTRY(SDL_SCANCODE_KP_PLUS, RDP_SCANCODE_ADD),
121  ENTRY(SDL_SCANCODE_KP_ENTER, RDP_SCANCODE_RETURN_KP),
122  ENTRY(SDL_SCANCODE_KP_1, RDP_SCANCODE_NUMPAD1),
123  ENTRY(SDL_SCANCODE_KP_2, RDP_SCANCODE_NUMPAD2),
124  ENTRY(SDL_SCANCODE_KP_3, RDP_SCANCODE_NUMPAD3),
125  ENTRY(SDL_SCANCODE_KP_4, RDP_SCANCODE_NUMPAD4),
126  ENTRY(SDL_SCANCODE_KP_5, RDP_SCANCODE_NUMPAD5),
127  ENTRY(SDL_SCANCODE_KP_6, RDP_SCANCODE_NUMPAD6),
128  ENTRY(SDL_SCANCODE_KP_7, RDP_SCANCODE_NUMPAD7),
129  ENTRY(SDL_SCANCODE_KP_8, RDP_SCANCODE_NUMPAD8),
130  ENTRY(SDL_SCANCODE_KP_9, RDP_SCANCODE_NUMPAD9),
131  ENTRY(SDL_SCANCODE_KP_0, RDP_SCANCODE_NUMPAD0),
132  ENTRY(SDL_SCANCODE_KP_PERIOD, RDP_SCANCODE_OEM_PERIOD),
133  ENTRY(SDL_SCANCODE_LCTRL, RDP_SCANCODE_LCONTROL),
134  ENTRY(SDL_SCANCODE_LSHIFT, RDP_SCANCODE_LSHIFT),
135  ENTRY(SDL_SCANCODE_LALT, RDP_SCANCODE_LMENU),
136  ENTRY(SDL_SCANCODE_LGUI, RDP_SCANCODE_LWIN),
137  ENTRY(SDL_SCANCODE_RCTRL, RDP_SCANCODE_RCONTROL),
138  ENTRY(SDL_SCANCODE_RSHIFT, RDP_SCANCODE_RSHIFT),
139  ENTRY(SDL_SCANCODE_RALT, RDP_SCANCODE_RMENU),
140  ENTRY(SDL_SCANCODE_RGUI, RDP_SCANCODE_RWIN),
141  ENTRY(SDL_SCANCODE_MODE, RDP_SCANCODE_APPS),
142  ENTRY(SDL_SCANCODE_MUTE, RDP_SCANCODE_VOLUME_MUTE),
143  ENTRY(SDL_SCANCODE_VOLUMEUP, RDP_SCANCODE_VOLUME_UP),
144  ENTRY(SDL_SCANCODE_VOLUMEDOWN, RDP_SCANCODE_VOLUME_DOWN),
145  ENTRY(SDL_SCANCODE_GRAVE, RDP_SCANCODE_OEM_3),
146  ENTRY(SDL_SCANCODE_COMMA, RDP_SCANCODE_OEM_COMMA),
147  ENTRY(SDL_SCANCODE_PERIOD, RDP_SCANCODE_OEM_PERIOD),
148  ENTRY(SDL_SCANCODE_SLASH, RDP_SCANCODE_OEM_2),
149  ENTRY(SDL_SCANCODE_BACKSLASH, RDP_SCANCODE_OEM_5),
150  ENTRY(SDL_SCANCODE_SCROLLLOCK, RDP_SCANCODE_SCROLLLOCK),
151  ENTRY(SDL_SCANCODE_INSERT, RDP_SCANCODE_INSERT),
152  ENTRY(SDL_SCANCODE_PRINTSCREEN, RDP_SCANCODE_PRINTSCREEN),
153  ENTRY(SDL_SCANCODE_HOME, RDP_SCANCODE_HOME),
154  ENTRY(SDL_SCANCODE_DELETE, RDP_SCANCODE_DELETE),
155  ENTRY(SDL_SCANCODE_RIGHT, RDP_SCANCODE_RIGHT),
156  ENTRY(SDL_SCANCODE_LEFT, RDP_SCANCODE_LEFT),
157  ENTRY(SDL_SCANCODE_DOWN, RDP_SCANCODE_DOWN),
158  ENTRY(SDL_SCANCODE_UP, RDP_SCANCODE_UP),
159  ENTRY(SDL_SCANCODE_SEMICOLON, RDP_SCANCODE_OEM_1),
160  ENTRY(SDL_SCANCODE_PAUSE, RDP_SCANCODE_PAUSE),
161  ENTRY(SDL_SCANCODE_PAGEUP, RDP_SCANCODE_PRIOR),
162  ENTRY(SDL_SCANCODE_END, RDP_SCANCODE_END),
163  ENTRY(SDL_SCANCODE_PAGEDOWN, RDP_SCANCODE_NEXT),
164  ENTRY(SDL_SCANCODE_AUDIONEXT, RDP_SCANCODE_MEDIA_NEXT_TRACK),
165  ENTRY(SDL_SCANCODE_AUDIOPREV, RDP_SCANCODE_MEDIA_PREV_TRACK),
166  ENTRY(SDL_SCANCODE_AUDIOSTOP, RDP_SCANCODE_MEDIA_STOP),
167  ENTRY(SDL_SCANCODE_AUDIOPLAY, RDP_SCANCODE_MEDIA_PLAY_PAUSE),
168  ENTRY(SDL_SCANCODE_AUDIOMUTE, RDP_SCANCODE_VOLUME_MUTE),
169  ENTRY(SDL_SCANCODE_MEDIASELECT, RDP_SCANCODE_LAUNCH_MEDIA_SELECT),
170  ENTRY(SDL_SCANCODE_MAIL, RDP_SCANCODE_LAUNCH_MAIL),
171  ENTRY(SDL_SCANCODE_APP1, RDP_SCANCODE_LAUNCH_APP1),
172  ENTRY(SDL_SCANCODE_APP2, RDP_SCANCODE_LAUNCH_APP2),
173  ENTRY(SDL_SCANCODE_SYSREQ, RDP_SCANCODE_SYSREQ),
174  ENTRY(SDL_SCANCODE_WWW, RDP_SCANCODE_BROWSER_HOME),
175  ENTRY(SDL_SCANCODE_LEFTBRACKET, RDP_SCANCODE_OEM_4),
176  ENTRY(SDL_SCANCODE_RIGHTBRACKET, RDP_SCANCODE_OEM_6),
177  ENTRY(SDL_SCANCODE_APOSTROPHE, RDP_SCANCODE_OEM_7),
178  ENTRY(SDL_SCANCODE_NONUSBACKSLASH, RDP_SCANCODE_OEM_102),
179  ENTRY(SDL_SCANCODE_SLEEP, RDP_SCANCODE_SLEEP),
180  ENTRY(SDL_SCANCODE_EQUALS, RDP_SCANCODE_OEM_PLUS),
181  ENTRY(SDL_SCANCODE_KP_COMMA, RDP_SCANCODE_DECIMAL),
182  ENTRY(SDL_SCANCODE_FIND, RDP_SCANCODE_BROWSER_SEARCH),
183  ENTRY(SDL_SCANCODE_RETURN2, RDP_SCANCODE_RETURN_KP),
184  ENTRY(SDL_SCANCODE_AC_SEARCH, RDP_SCANCODE_BROWSER_SEARCH),
185  ENTRY(SDL_SCANCODE_AC_HOME, RDP_SCANCODE_BROWSER_HOME),
186  ENTRY(SDL_SCANCODE_AC_BACK, RDP_SCANCODE_BROWSER_BACK),
187  ENTRY(SDL_SCANCODE_AC_FORWARD, RDP_SCANCODE_BROWSER_FORWARD),
188  ENTRY(SDL_SCANCODE_AC_STOP, RDP_SCANCODE_BROWSER_STOP),
189 
190 #if 1 // TODO: unmapped
191  ENTRY(SDL_SCANCODE_NONUSHASH, RDP_SCANCODE_UNKNOWN),
192  ENTRY(SDL_SCANCODE_APPLICATION, RDP_SCANCODE_UNKNOWN),
193  ENTRY(SDL_SCANCODE_POWER, RDP_SCANCODE_UNKNOWN),
194  ENTRY(SDL_SCANCODE_KP_EQUALS, RDP_SCANCODE_UNKNOWN),
195  ENTRY(SDL_SCANCODE_EXECUTE, RDP_SCANCODE_UNKNOWN),
196  ENTRY(SDL_SCANCODE_HELP, RDP_SCANCODE_UNKNOWN),
197  ENTRY(SDL_SCANCODE_MENU, RDP_SCANCODE_UNKNOWN),
198  ENTRY(SDL_SCANCODE_SELECT, RDP_SCANCODE_UNKNOWN),
199  ENTRY(SDL_SCANCODE_STOP, RDP_SCANCODE_UNKNOWN),
200  ENTRY(SDL_SCANCODE_AGAIN, RDP_SCANCODE_UNKNOWN),
201  ENTRY(SDL_SCANCODE_UNDO, RDP_SCANCODE_UNKNOWN),
202  ENTRY(SDL_SCANCODE_CUT, RDP_SCANCODE_UNKNOWN),
203  ENTRY(SDL_SCANCODE_COPY, RDP_SCANCODE_UNKNOWN),
204  ENTRY(SDL_SCANCODE_PASTE, RDP_SCANCODE_UNKNOWN),
205  ENTRY(SDL_SCANCODE_KP_EQUALSAS400, RDP_SCANCODE_UNKNOWN),
206  ENTRY(SDL_SCANCODE_INTERNATIONAL1, RDP_SCANCODE_UNKNOWN),
207  ENTRY(SDL_SCANCODE_INTERNATIONAL2, RDP_SCANCODE_UNKNOWN),
208  ENTRY(SDL_SCANCODE_INTERNATIONAL3, RDP_SCANCODE_UNKNOWN),
209  ENTRY(SDL_SCANCODE_INTERNATIONAL4, RDP_SCANCODE_UNKNOWN),
210  ENTRY(SDL_SCANCODE_INTERNATIONAL5, RDP_SCANCODE_UNKNOWN),
211  ENTRY(SDL_SCANCODE_INTERNATIONAL6, RDP_SCANCODE_UNKNOWN),
212  ENTRY(SDL_SCANCODE_INTERNATIONAL7, RDP_SCANCODE_UNKNOWN),
213  ENTRY(SDL_SCANCODE_INTERNATIONAL8, RDP_SCANCODE_UNKNOWN),
214  ENTRY(SDL_SCANCODE_INTERNATIONAL9, RDP_SCANCODE_UNKNOWN),
215  ENTRY(SDL_SCANCODE_LANG1, RDP_SCANCODE_UNKNOWN),
216  ENTRY(SDL_SCANCODE_LANG2, RDP_SCANCODE_UNKNOWN),
217  ENTRY(SDL_SCANCODE_LANG3, RDP_SCANCODE_UNKNOWN),
218  ENTRY(SDL_SCANCODE_LANG4, RDP_SCANCODE_UNKNOWN),
219  ENTRY(SDL_SCANCODE_LANG5, RDP_SCANCODE_UNKNOWN),
220  ENTRY(SDL_SCANCODE_LANG6, RDP_SCANCODE_UNKNOWN),
221  ENTRY(SDL_SCANCODE_LANG7, RDP_SCANCODE_UNKNOWN),
222  ENTRY(SDL_SCANCODE_LANG8, RDP_SCANCODE_UNKNOWN),
223  ENTRY(SDL_SCANCODE_LANG9, RDP_SCANCODE_UNKNOWN),
224  ENTRY(SDL_SCANCODE_ALTERASE, RDP_SCANCODE_UNKNOWN),
225  ENTRY(SDL_SCANCODE_CANCEL, RDP_SCANCODE_UNKNOWN),
226  ENTRY(SDL_SCANCODE_CLEAR, RDP_SCANCODE_UNKNOWN),
227  ENTRY(SDL_SCANCODE_PRIOR, RDP_SCANCODE_UNKNOWN),
228  ENTRY(SDL_SCANCODE_SEPARATOR, RDP_SCANCODE_UNKNOWN),
229  ENTRY(SDL_SCANCODE_OUT, RDP_SCANCODE_UNKNOWN),
230  ENTRY(SDL_SCANCODE_OPER, RDP_SCANCODE_UNKNOWN),
231  ENTRY(SDL_SCANCODE_CLEARAGAIN, RDP_SCANCODE_UNKNOWN),
232  ENTRY(SDL_SCANCODE_CRSEL, RDP_SCANCODE_UNKNOWN),
233  ENTRY(SDL_SCANCODE_EXSEL, RDP_SCANCODE_UNKNOWN),
234  ENTRY(SDL_SCANCODE_KP_00, RDP_SCANCODE_UNKNOWN),
235  ENTRY(SDL_SCANCODE_KP_000, RDP_SCANCODE_UNKNOWN),
236  ENTRY(SDL_SCANCODE_THOUSANDSSEPARATOR, RDP_SCANCODE_UNKNOWN),
237  ENTRY(SDL_SCANCODE_DECIMALSEPARATOR, RDP_SCANCODE_UNKNOWN),
238  ENTRY(SDL_SCANCODE_CURRENCYUNIT, RDP_SCANCODE_UNKNOWN),
239  ENTRY(SDL_SCANCODE_CURRENCYSUBUNIT, RDP_SCANCODE_UNKNOWN),
240  ENTRY(SDL_SCANCODE_KP_LEFTPAREN, RDP_SCANCODE_UNKNOWN),
241  ENTRY(SDL_SCANCODE_KP_RIGHTPAREN, RDP_SCANCODE_UNKNOWN),
242  ENTRY(SDL_SCANCODE_KP_LEFTBRACE, RDP_SCANCODE_UNKNOWN),
243  ENTRY(SDL_SCANCODE_KP_RIGHTBRACE, RDP_SCANCODE_UNKNOWN),
244  ENTRY(SDL_SCANCODE_KP_TAB, RDP_SCANCODE_UNKNOWN),
245  ENTRY(SDL_SCANCODE_KP_BACKSPACE, RDP_SCANCODE_UNKNOWN),
246  ENTRY(SDL_SCANCODE_KP_A, RDP_SCANCODE_UNKNOWN),
247  ENTRY(SDL_SCANCODE_KP_B, RDP_SCANCODE_UNKNOWN),
248  ENTRY(SDL_SCANCODE_KP_C, RDP_SCANCODE_UNKNOWN),
249  ENTRY(SDL_SCANCODE_KP_D, RDP_SCANCODE_UNKNOWN),
250  ENTRY(SDL_SCANCODE_KP_E, RDP_SCANCODE_UNKNOWN),
251  ENTRY(SDL_SCANCODE_KP_F, RDP_SCANCODE_UNKNOWN),
252  ENTRY(SDL_SCANCODE_KP_XOR, RDP_SCANCODE_UNKNOWN),
253  ENTRY(SDL_SCANCODE_KP_POWER, RDP_SCANCODE_UNKNOWN),
254  ENTRY(SDL_SCANCODE_KP_PERCENT, RDP_SCANCODE_UNKNOWN),
255  ENTRY(SDL_SCANCODE_KP_LESS, RDP_SCANCODE_UNKNOWN),
256  ENTRY(SDL_SCANCODE_KP_GREATER, RDP_SCANCODE_UNKNOWN),
257  ENTRY(SDL_SCANCODE_KP_AMPERSAND, RDP_SCANCODE_UNKNOWN),
258  ENTRY(SDL_SCANCODE_KP_DBLAMPERSAND, RDP_SCANCODE_UNKNOWN),
259  ENTRY(SDL_SCANCODE_KP_VERTICALBAR, RDP_SCANCODE_UNKNOWN),
260  ENTRY(SDL_SCANCODE_KP_DBLVERTICALBAR, RDP_SCANCODE_UNKNOWN),
261  ENTRY(SDL_SCANCODE_KP_COLON, RDP_SCANCODE_UNKNOWN),
262  ENTRY(SDL_SCANCODE_KP_HASH, RDP_SCANCODE_UNKNOWN),
263  ENTRY(SDL_SCANCODE_KP_SPACE, RDP_SCANCODE_UNKNOWN),
264  ENTRY(SDL_SCANCODE_KP_AT, RDP_SCANCODE_UNKNOWN),
265  ENTRY(SDL_SCANCODE_KP_EXCLAM, RDP_SCANCODE_UNKNOWN),
266  ENTRY(SDL_SCANCODE_KP_MEMSTORE, RDP_SCANCODE_UNKNOWN),
267  ENTRY(SDL_SCANCODE_KP_MEMRECALL, RDP_SCANCODE_UNKNOWN),
268  ENTRY(SDL_SCANCODE_KP_MEMCLEAR, RDP_SCANCODE_UNKNOWN),
269  ENTRY(SDL_SCANCODE_KP_MEMADD, RDP_SCANCODE_UNKNOWN),
270  ENTRY(SDL_SCANCODE_KP_MEMSUBTRACT, RDP_SCANCODE_UNKNOWN),
271  ENTRY(SDL_SCANCODE_KP_MEMMULTIPLY, RDP_SCANCODE_UNKNOWN),
272  ENTRY(SDL_SCANCODE_KP_MEMDIVIDE, RDP_SCANCODE_UNKNOWN),
273  ENTRY(SDL_SCANCODE_KP_PLUSMINUS, RDP_SCANCODE_UNKNOWN),
274  ENTRY(SDL_SCANCODE_KP_CLEAR, RDP_SCANCODE_UNKNOWN),
275  ENTRY(SDL_SCANCODE_KP_CLEARENTRY, RDP_SCANCODE_UNKNOWN),
276  ENTRY(SDL_SCANCODE_KP_BINARY, RDP_SCANCODE_UNKNOWN),
277  ENTRY(SDL_SCANCODE_KP_OCTAL, RDP_SCANCODE_UNKNOWN),
278  ENTRY(SDL_SCANCODE_KP_DECIMAL, RDP_SCANCODE_UNKNOWN),
279  ENTRY(SDL_SCANCODE_KP_HEXADECIMAL, RDP_SCANCODE_UNKNOWN),
280  ENTRY(SDL_SCANCODE_CALCULATOR, RDP_SCANCODE_UNKNOWN),
281  ENTRY(SDL_SCANCODE_COMPUTER, RDP_SCANCODE_UNKNOWN),
282  ENTRY(SDL_SCANCODE_AC_REFRESH, RDP_SCANCODE_UNKNOWN),
283  ENTRY(SDL_SCANCODE_AC_BOOKMARKS, RDP_SCANCODE_UNKNOWN),
284  ENTRY(SDL_SCANCODE_BRIGHTNESSDOWN, RDP_SCANCODE_UNKNOWN),
285  ENTRY(SDL_SCANCODE_BRIGHTNESSUP, RDP_SCANCODE_UNKNOWN),
286  ENTRY(SDL_SCANCODE_DISPLAYSWITCH, RDP_SCANCODE_UNKNOWN),
287  ENTRY(SDL_SCANCODE_KBDILLUMTOGGLE, RDP_SCANCODE_UNKNOWN),
288  ENTRY(SDL_SCANCODE_KBDILLUMDOWN, RDP_SCANCODE_UNKNOWN),
289  ENTRY(SDL_SCANCODE_KBDILLUMUP, RDP_SCANCODE_UNKNOWN),
290  ENTRY(SDL_SCANCODE_EJECT, RDP_SCANCODE_UNKNOWN),
291  ENTRY(SDL_SCANCODE_AUDIOREWIND, RDP_SCANCODE_UNKNOWN),
292  ENTRY(SDL_SCANCODE_AUDIOFASTFORWARD, RDP_SCANCODE_UNKNOWN)
293 #endif
294 };
295 
296 static UINT32 sdl_get_kbd_flags()
297 {
298  UINT32 flags = 0;
299 
300  SDL_Keymod mod = SDL_GetModState();
301  if ((mod & KMOD_NUM) != 0)
302  flags |= KBD_SYNC_NUM_LOCK;
303  if ((mod & KMOD_CAPS) != 0)
304  flags |= KBD_SYNC_CAPS_LOCK;
305 #if SDL_VERSION_ATLEAST(2, 0, 18)
306  if ((mod & KMOD_SCROLL) != 0)
307  flags |= KBD_SYNC_SCROLL_LOCK;
308 #endif
309 
310  // TODO: KBD_SYNC_KANA_LOCK
311 
312  return flags;
313 }
314 
315 BOOL sdlInput::keyboard_sync_state()
316 {
317  const UINT32 syncFlags = sdl_get_kbd_flags();
318  return freerdp_input_send_synchronize_event(_sdl->context()->input, syncFlags);
319 }
320 
321 BOOL sdlInput::keyboard_focus_in()
322 {
323  auto input = _sdl->context()->input;
324  WINPR_ASSERT(input);
325 
326  auto syncFlags = sdl_get_kbd_flags();
327  freerdp_input_send_focus_in_event(input, syncFlags);
328 
329  /* finish with a mouse pointer position like mstsc.exe if required */
330 #if 0
331  if (xfc->remote_app)
332  return;
333 
334  if (XQueryPointer(xfc->display, xfc->window->handle, &w, &w, &d, &d, &x, &y, &state))
335  {
336  if ((x >= 0) && (x < xfc->window->width) && (y >= 0) && (y < xfc->window->height))
337  {
338  xf_event_adjust_coordinates(xfc, &x, &y);
339  freerdp_client_send_button_event(&xfc->common, FALSE, PTR_FLAGS_MOVE, x, y);
340  }
341  }
342 #endif
343  return TRUE;
344 }
345 
346 /* This function is called to update the keyboard indicator LED */
347 BOOL sdlInput::keyboard_set_indicators(rdpContext* context, UINT16 led_flags)
348 {
349  WINPR_UNUSED(context);
350 
351  int state = KMOD_NONE;
352 
353  if ((led_flags & KBD_SYNC_NUM_LOCK) != 0)
354  state |= KMOD_NUM;
355  if ((led_flags & KBD_SYNC_CAPS_LOCK) != 0)
356  state |= KMOD_CAPS;
357 #if SDL_VERSION_ATLEAST(2, 0, 18)
358  if ((led_flags & KBD_SYNC_SCROLL_LOCK) != 0)
359  state |= KMOD_SCROLL;
360 #endif
361 
362  // TODO: KBD_SYNC_KANA_LOCK
363 
364  SDL_SetModState(static_cast<SDL_Keymod>(state));
365 
366  return TRUE;
367 }
368 
369 /* This function is called to set the IME state */
370 BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
371  UINT32 imeConvMode)
372 {
373  if (!context)
374  return FALSE;
375 
376  WLog_WARN(TAG,
377  "KeyboardSetImeStatus(unitId=%04" PRIx16 ", imeState=%08" PRIx32
378  ", imeConvMode=%08" PRIx32 ") ignored",
379  imeId, imeState, imeConvMode);
380  return TRUE;
381 }
382 
383 uint32_t sdlInput::prefToMask()
384 {
385  const std::map<std::string, uint32_t> mapping = {
386  { "KMOD_LSHIFT", KMOD_LSHIFT },
387  { "KMOD_RSHIFT", KMOD_RSHIFT },
388  { "KMOD_LCTRL", KMOD_LCTRL },
389  { "KMOD_RCTRL", KMOD_RCTRL },
390  { "KMOD_LALT", KMOD_LALT },
391  { "KMOD_RALT", KMOD_RALT },
392  { "KMOD_LGUI", KMOD_LGUI },
393  { "KMOD_RGUI", KMOD_RGUI },
394  { "KMOD_NUM", KMOD_NUM },
395  { "KMOD_CAPS", KMOD_CAPS },
396  { "KMOD_MODE", KMOD_MODE },
397 #if SDL_VERSION_ATLEAST(2, 0, 18)
398  { "KMOD_SCROLL", KMOD_SCROLL },
399 #endif
400  { "KMOD_CTRL", KMOD_CTRL },
401  { "KMOD_SHIFT", KMOD_SHIFT },
402  { "KMOD_ALT", KMOD_ALT },
403  { "KMOD_GUI", KMOD_GUI }
404  };
405  uint32_t mod = KMOD_NONE;
406  for (const auto& val : SdlPref::instance()->get_array("SDL_KeyModMask", { "KMOD_RSHIFT" }))
407  {
408  auto it = mapping.find(val);
409  if (it != mapping.end())
410  {
411  mod |= it->second;
412  }
413  }
414  return mod;
415 }
416 
417 static const char* sdl_scancode_name(Uint32 scancode)
418 {
419  for (const auto& cur : map)
420  {
421  if (cur.sdl == scancode)
422  return cur.sdl_name;
423  }
424 
425  return "SDL_SCANCODE_UNKNOWN";
426 }
427 
428 static Uint32 sdl_scancode_val(const char* scancodeName)
429 {
430  for (const auto& cur : map)
431  {
432  if (strcmp(cur.sdl_name, scancodeName) == 0)
433  return cur.sdl;
434  }
435 
436  return SDL_SCANCODE_UNKNOWN;
437 }
438 
439 static const char* sdl_rdp_scancode_name(UINT32 scancode)
440 {
441  for (const auto& cur : map)
442  {
443  if (cur.rdp == scancode)
444  return cur.rdp_name;
445  }
446 
447  return "RDP_SCANCODE_UNKNOWN";
448 }
449 
450 static UINT32 sdl_rdp_scancode_val(const char* scancodeName)
451 {
452  for (const auto& cur : map)
453  {
454  if (strcmp(cur.rdp_name, scancodeName) == 0)
455  return cur.rdp;
456  }
457 
458  return RDP_SCANCODE_UNKNOWN;
459 }
460 
461 static UINT32 sdl_scancode_to_rdp(Uint32 scancode)
462 {
463  UINT32 rdp = RDP_SCANCODE_UNKNOWN;
464 
465  for (const auto& cur : map)
466  {
467  if (cur.sdl == scancode)
468  {
469  rdp = cur.rdp;
470  break;
471  }
472  }
473 
474 #if defined(WITH_DEBUG_SDL_KBD_EVENTS)
475  auto code = static_cast<SDL_Scancode>(scancode);
476  WLog_DBG(TAG, "got %s [%s] -> [%s]", SDL_GetScancodeName(code), sdl_scancode_name(scancode),
477  sdl_rdp_scancode_name(rdp));
478 #endif
479  return rdp;
480 }
481 
482 uint32_t sdlInput::prefKeyValue(const std::string& key, uint32_t fallback)
483 {
484  auto item = SdlPref::instance()->get_string(key);
485  if (item.empty())
486  return fallback;
487  auto val = sdl_scancode_val(item.c_str());
488  if (val == SDL_SCANCODE_UNKNOWN)
489  return fallback;
490  return val;
491 }
492 
493 std::list<std::string> sdlInput::tokenize(const std::string& data, const std::string& delimiter)
494 {
495  size_t lastpos = 0;
496  size_t pos = 0;
497  std::list<std::string> list;
498  while ((pos = data.find(delimiter, lastpos)) != std::string::npos)
499  {
500  auto token = data.substr(lastpos, pos);
501  lastpos = pos + 1;
502  list.push_back(token);
503  }
504  auto token = data.substr(lastpos);
505  list.push_back(token);
506  return list;
507 }
508 
509 bool sdlInput::extract(const std::string& token, uint32_t& key, uint32_t& value)
510 {
511  return freerdp_extract_key_value(token.c_str(), &key, &value);
512 }
513 
514 uint32_t sdlInput::remapScancode(uint32_t scancode)
515 {
516  if (!_remapInitialized.exchange(true))
517  remapInitialize();
518  auto it = _remapList.find(scancode);
519  if (it != _remapList.end())
520  return it->second;
521  return scancode;
522 }
523 
524 void sdlInput::remapInitialize()
525 {
526  WINPR_ASSERT(_sdl);
527 
528  auto context = _sdl->context();
529  WINPR_ASSERT(context);
530  auto KeyboardRemappingList =
531  freerdp_settings_get_string(context->settings, FreeRDP_KeyboardRemappingList);
532  if (!KeyboardRemappingList)
533  return;
534 
535  auto list = tokenize(KeyboardRemappingList);
536  for (auto& token : list)
537  {
538  uint32_t key = 0;
539  uint32_t value = 0;
540  if (!extract(token, key, value))
541  continue;
542  _remapList.emplace(key, value);
543  }
544 }
545 
546 BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev)
547 {
548  WINPR_ASSERT(ev);
549  const UINT32 rdp_scancode = sdl_scancode_to_rdp(ev->keysym.scancode);
550  const SDL_Keymod mods = SDL_GetModState();
551 
552  if ((mods & _hotkeyModmask) == _hotkeyModmask)
553  {
554  if (ev->type == SDL_KEYDOWN)
555  {
556  if (ev->keysym.scancode == _hotkeyFullscreen)
557  {
558  _sdl->update_fullscreen(!_sdl->fullscreen);
559  return TRUE;
560  }
561  if (ev->keysym.scancode == _hotkeyResizable)
562  {
563  _sdl->update_resizeable(!_sdl->resizeable);
564  return TRUE;
565  }
566 
567  if (ev->keysym.scancode == _hotkeyGrab)
568  {
569  _sdl->grab_kbd_enabled = !_sdl->grab_kbd_enabled;
570  keyboard_grab(ev->windowID, _sdl->grab_kbd ? SDL_FALSE : SDL_TRUE);
571  return TRUE;
572  }
573  if (ev->keysym.scancode == _hotkeyDisconnect)
574  {
575  freerdp_abort_connect_context(_sdl->context());
576  return TRUE;
577  }
578  if (ev->keysym.scancode == _hotkeyMinimize)
579  {
580  _sdl->update_minimize();
581  return TRUE;
582  }
583  }
584  }
585 
586  auto scancode = remapScancode(rdp_scancode);
587  return freerdp_input_send_keyboard_event_ex(_sdl->context()->input, ev->type == SDL_KEYDOWN,
588  ev->repeat, scancode);
589 }
590 
591 BOOL sdlInput::keyboard_grab(Uint32 windowID, SDL_bool enable)
592 {
593  auto it = _sdl->windows.find(windowID);
594  if (it == _sdl->windows.end())
595  return FALSE;
596 
597  auto status = enable && _sdl->grab_kbd_enabled;
598  _sdl->grab_kbd = status;
599  return it->second.grabKeyboard(status);
600 }
601 
602 BOOL sdlInput::mouse_focus(Uint32 windowID)
603 {
604  if (_lastWindowID != windowID)
605  {
606  _lastWindowID = windowID;
607  auto it = _sdl->windows.find(windowID);
608  if (it == _sdl->windows.end())
609  return FALSE;
610 
611  it->second.raise();
612  }
613  return TRUE;
614 }
615 
616 BOOL sdlInput::mouse_grab(Uint32 windowID, SDL_bool enable)
617 {
618  auto it = _sdl->windows.find(windowID);
619  if (it == _sdl->windows.end())
620  return FALSE;
621  _sdl->grab_mouse = enable;
622  return it->second.grabMouse(enable);
623 }
624 
625 sdlInput::sdlInput(SdlContext* sdl)
626  : _sdl(sdl), _lastWindowID(UINT32_MAX), _hotkeyModmask(prefToMask())
627 {
628 
629  _hotkeyFullscreen = prefKeyValue("SDL_Fullscreen", SDL_SCANCODE_RETURN);
630  _hotkeyResizable = prefKeyValue("SDL_Resizeable", SDL_SCANCODE_R);
631  _hotkeyGrab = prefKeyValue("SDL_Grab", SDL_SCANCODE_G);
632  _hotkeyDisconnect = prefKeyValue("SDL_Disconnect", SDL_SCANCODE_D);
633  _hotkeyMinimize = prefKeyValue("SDL_Minimize", SDL_SCANCODE_M);
634 }
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.