SDL  2.0
SDL_x11keyboard.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_X11
24 
25 #include "SDL_x11video.h"
26 
27 #include "../../events/SDL_keyboard_c.h"
28 #include "../../events/scancodes_darwin.h"
29 #include "../../events/scancodes_xfree86.h"
30 
31 #include <X11/keysym.h>
32 #include <X11/XKBlib.h>
33 
34 #include "imKStoUCS.h"
35 
36 #ifdef X_HAVE_UTF8_STRING
37 #include <locale.h>
38 #endif
39 
40 /* *INDENT-OFF* */
41 static const struct {
42  KeySym keysym;
43  SDL_Scancode scancode;
44 } KeySymToSDLScancode[] = {
45  { XK_Return, SDL_SCANCODE_RETURN },
46  { XK_Escape, SDL_SCANCODE_ESCAPE },
47  { XK_BackSpace, SDL_SCANCODE_BACKSPACE },
48  { XK_Tab, SDL_SCANCODE_TAB },
49  { XK_Caps_Lock, SDL_SCANCODE_CAPSLOCK },
50  { XK_F1, SDL_SCANCODE_F1 },
51  { XK_F2, SDL_SCANCODE_F2 },
52  { XK_F3, SDL_SCANCODE_F3 },
53  { XK_F4, SDL_SCANCODE_F4 },
54  { XK_F5, SDL_SCANCODE_F5 },
55  { XK_F6, SDL_SCANCODE_F6 },
56  { XK_F7, SDL_SCANCODE_F7 },
57  { XK_F8, SDL_SCANCODE_F8 },
58  { XK_F9, SDL_SCANCODE_F9 },
59  { XK_F10, SDL_SCANCODE_F10 },
60  { XK_F11, SDL_SCANCODE_F11 },
61  { XK_F12, SDL_SCANCODE_F12 },
62  { XK_Print, SDL_SCANCODE_PRINTSCREEN },
63  { XK_Scroll_Lock, SDL_SCANCODE_SCROLLLOCK },
64  { XK_Pause, SDL_SCANCODE_PAUSE },
65  { XK_Insert, SDL_SCANCODE_INSERT },
66  { XK_Home, SDL_SCANCODE_HOME },
67  { XK_Prior, SDL_SCANCODE_PAGEUP },
68  { XK_Delete, SDL_SCANCODE_DELETE },
69  { XK_End, SDL_SCANCODE_END },
70  { XK_Next, SDL_SCANCODE_PAGEDOWN },
71  { XK_Right, SDL_SCANCODE_RIGHT },
72  { XK_Left, SDL_SCANCODE_LEFT },
73  { XK_Down, SDL_SCANCODE_DOWN },
74  { XK_Up, SDL_SCANCODE_UP },
75  { XK_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR },
76  { XK_KP_Divide, SDL_SCANCODE_KP_DIVIDE },
77  { XK_KP_Multiply, SDL_SCANCODE_KP_MULTIPLY },
78  { XK_KP_Subtract, SDL_SCANCODE_KP_MINUS },
79  { XK_KP_Add, SDL_SCANCODE_KP_PLUS },
80  { XK_KP_Enter, SDL_SCANCODE_KP_ENTER },
81  { XK_KP_Delete, SDL_SCANCODE_KP_PERIOD },
82  { XK_KP_End, SDL_SCANCODE_KP_1 },
83  { XK_KP_Down, SDL_SCANCODE_KP_2 },
84  { XK_KP_Next, SDL_SCANCODE_KP_3 },
85  { XK_KP_Left, SDL_SCANCODE_KP_4 },
86  { XK_KP_Begin, SDL_SCANCODE_KP_5 },
87  { XK_KP_Right, SDL_SCANCODE_KP_6 },
88  { XK_KP_Home, SDL_SCANCODE_KP_7 },
89  { XK_KP_Up, SDL_SCANCODE_KP_8 },
90  { XK_KP_Prior, SDL_SCANCODE_KP_9 },
91  { XK_KP_Insert, SDL_SCANCODE_KP_0 },
92  { XK_KP_Decimal, SDL_SCANCODE_KP_PERIOD },
93  { XK_KP_1, SDL_SCANCODE_KP_1 },
94  { XK_KP_2, SDL_SCANCODE_KP_2 },
95  { XK_KP_3, SDL_SCANCODE_KP_3 },
96  { XK_KP_4, SDL_SCANCODE_KP_4 },
97  { XK_KP_5, SDL_SCANCODE_KP_5 },
98  { XK_KP_6, SDL_SCANCODE_KP_6 },
99  { XK_KP_7, SDL_SCANCODE_KP_7 },
100  { XK_KP_8, SDL_SCANCODE_KP_8 },
101  { XK_KP_9, SDL_SCANCODE_KP_9 },
102  { XK_KP_0, SDL_SCANCODE_KP_0 },
103  { XK_KP_Decimal, SDL_SCANCODE_KP_PERIOD },
104  { XK_Hyper_R, SDL_SCANCODE_APPLICATION },
105  { XK_KP_Equal, SDL_SCANCODE_KP_EQUALS },
106  { XK_F13, SDL_SCANCODE_F13 },
107  { XK_F14, SDL_SCANCODE_F14 },
108  { XK_F15, SDL_SCANCODE_F15 },
109  { XK_F16, SDL_SCANCODE_F16 },
110  { XK_F17, SDL_SCANCODE_F17 },
111  { XK_F18, SDL_SCANCODE_F18 },
112  { XK_F19, SDL_SCANCODE_F19 },
113  { XK_F20, SDL_SCANCODE_F20 },
114  { XK_F21, SDL_SCANCODE_F21 },
115  { XK_F22, SDL_SCANCODE_F22 },
116  { XK_F23, SDL_SCANCODE_F23 },
117  { XK_F24, SDL_SCANCODE_F24 },
118  { XK_Execute, SDL_SCANCODE_EXECUTE },
119  { XK_Help, SDL_SCANCODE_HELP },
120  { XK_Menu, SDL_SCANCODE_MENU },
121  { XK_Select, SDL_SCANCODE_SELECT },
122  { XK_Cancel, SDL_SCANCODE_STOP },
123  { XK_Redo, SDL_SCANCODE_AGAIN },
124  { XK_Undo, SDL_SCANCODE_UNDO },
125  { XK_Find, SDL_SCANCODE_FIND },
126  { XK_KP_Separator, SDL_SCANCODE_KP_COMMA },
127  { XK_Sys_Req, SDL_SCANCODE_SYSREQ },
128  { XK_Control_L, SDL_SCANCODE_LCTRL },
129  { XK_Shift_L, SDL_SCANCODE_LSHIFT },
130  { XK_Alt_L, SDL_SCANCODE_LALT },
131  { XK_Meta_L, SDL_SCANCODE_LGUI },
132  { XK_Super_L, SDL_SCANCODE_LGUI },
133  { XK_Control_R, SDL_SCANCODE_RCTRL },
134  { XK_Shift_R, SDL_SCANCODE_RSHIFT },
135  { XK_Alt_R, SDL_SCANCODE_RALT },
136  { XK_ISO_Level3_Shift, SDL_SCANCODE_RALT },
137  { XK_Meta_R, SDL_SCANCODE_RGUI },
138  { XK_Super_R, SDL_SCANCODE_RGUI },
139  { XK_Mode_switch, SDL_SCANCODE_MODE },
140  { XK_period, SDL_SCANCODE_PERIOD },
141  { XK_comma, SDL_SCANCODE_COMMA },
142  { XK_slash, SDL_SCANCODE_SLASH },
143  { XK_backslash, SDL_SCANCODE_BACKSLASH },
144  { XK_minus, SDL_SCANCODE_MINUS },
145  { XK_equal, SDL_SCANCODE_EQUALS },
146  { XK_space, SDL_SCANCODE_SPACE },
147  { XK_grave, SDL_SCANCODE_GRAVE },
148  { XK_apostrophe, SDL_SCANCODE_APOSTROPHE },
149  { XK_bracketleft, SDL_SCANCODE_LEFTBRACKET },
150  { XK_bracketright, SDL_SCANCODE_RIGHTBRACKET },
151 };
152 
153 static const struct
154 {
155  SDL_Scancode const *table;
156  int table_size;
157 } scancode_set[] = {
162 };
163 /* *INDENT-OFF* */
164 
165 /* This function only works for keyboards in US QWERTY layout */
166 static SDL_Scancode
167 X11_KeyCodeToSDLScancode(_THIS, KeyCode keycode)
168 {
169  KeySym keysym;
170  int i;
171 
172  keysym = X11_KeyCodeToSym(_this, keycode, 0);
173  if (keysym == NoSymbol) {
174  return SDL_SCANCODE_UNKNOWN;
175  }
176 
177  if (keysym >= XK_a && keysym <= XK_z) {
178  return SDL_SCANCODE_A + (keysym - XK_a);
179  }
180  if (keysym >= XK_A && keysym <= XK_Z) {
181  return SDL_SCANCODE_A + (keysym - XK_A);
182  }
183 
184  if (keysym == XK_0) {
185  return SDL_SCANCODE_0;
186  }
187  if (keysym >= XK_1 && keysym <= XK_9) {
188  return SDL_SCANCODE_1 + (keysym - XK_1);
189  }
190 
191  for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
192  if (keysym == KeySymToSDLScancode[i].keysym) {
193  return KeySymToSDLScancode[i].scancode;
194  }
195  }
196  return SDL_SCANCODE_UNKNOWN;
197 }
198 
199 static Uint32
200 X11_KeyCodeToUcs4(_THIS, KeyCode keycode, unsigned char group)
201 {
202  KeySym keysym = X11_KeyCodeToSym(_this, keycode, group);
203 
204  if (keysym == NoSymbol) {
205  return 0;
206  }
207 
208  return X11_KeySymToUcs4(keysym);
209 }
210 
211 KeySym
212 X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group)
213 {
215  KeySym keysym;
216 
218  if (data->xkb) {
219  int num_groups = XkbKeyNumGroups(data->xkb, keycode);
220  unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
221 
222  if (num_groups && group >= num_groups) {
223 
224  int action = XkbOutOfRangeGroupAction(info);
225 
226  if (action == XkbRedirectIntoRange) {
227  if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) {
228  group = 0;
229  }
230  } else if (action == XkbClampIntoRange) {
231  group = num_groups - 1;
232  } else {
233  group %= num_groups;
234  }
235  }
236  keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
237  } else {
238  keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
239  }
240 #else
241  keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
242 #endif
243 
244  return keysym;
245 }
246 
247 int
249 {
251  int i = 0;
252  int j = 0;
253  int min_keycode, max_keycode;
254  struct {
255  SDL_Scancode scancode;
256  KeySym keysym;
257  int value;
258  } fingerprint[] = {
259  { SDL_SCANCODE_HOME, XK_Home, 0 },
260  { SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
261  { SDL_SCANCODE_UP, XK_Up, 0 },
262  { SDL_SCANCODE_LEFT, XK_Left, 0 },
263  { SDL_SCANCODE_DELETE, XK_Delete, 0 },
264  { SDL_SCANCODE_KP_ENTER, XK_KP_Enter, 0 },
265  };
266  int best_distance;
267  int best_index;
268  int distance;
269  Bool xkb_repeat = 0;
270 
271  X11_XAutoRepeatOn(data->display);
272 
273 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
274  {
275  int xkb_major = XkbMajorVersion;
276  int xkb_minor = XkbMinorVersion;
277 
278  if (X11_XkbQueryExtension(data->display, NULL, NULL, NULL, &xkb_major, &xkb_minor)) {
279  data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd);
280  }
281 
282  /* This will remove KeyRelease events for held keys */
283  X11_XkbSetDetectableAutoRepeat(data->display, True, &xkb_repeat);
284  }
285 #endif
286 
287  /* Open a connection to the X input manager */
288 #ifdef X_HAVE_UTF8_STRING
289  if (SDL_X11_HAVE_UTF8) {
290  /* Set the locale, and call XSetLocaleModifiers before XOpenIM so that
291  Compose keys will work correctly. */
292  char *prev_locale = setlocale(LC_ALL, NULL);
293  char *prev_xmods = X11_XSetLocaleModifiers(NULL);
294  const char *new_xmods = "";
295  const char *env_xmods = SDL_getenv("XMODIFIERS");
296  SDL_bool has_dbus_ime_support = SDL_FALSE;
297 
298  if (prev_locale) {
299  prev_locale = SDL_strdup(prev_locale);
300  }
301 
302  if (prev_xmods) {
303  prev_xmods = SDL_strdup(prev_xmods);
304  }
305 
306  /* IBus resends some key events that were filtered by XFilterEvents
307  when it is used via XIM which causes issues. Prevent this by forcing
308  @im=none if XMODIFIERS contains @im=ibus. IBus can still be used via
309  the DBus implementation, which also has support for pre-editing. */
310  if (env_xmods && SDL_strstr(env_xmods, "@im=ibus") != NULL) {
311  has_dbus_ime_support = SDL_TRUE;
312  }
313  if (env_xmods && SDL_strstr(env_xmods, "@im=fcitx") != NULL) {
314  has_dbus_ime_support = SDL_TRUE;
315  }
316  if (has_dbus_ime_support || !xkb_repeat) {
317  new_xmods = "@im=none";
318  }
319 
320  setlocale(LC_ALL, "");
321  X11_XSetLocaleModifiers(new_xmods);
322 
323  data->im = X11_XOpenIM(data->display, NULL, data->classname, data->classname);
324 
325  /* Reset the locale + X locale modifiers back to how they were,
326  locale first because the X locale modifiers depend on it. */
327  setlocale(LC_ALL, prev_locale);
328  X11_XSetLocaleModifiers(prev_xmods);
329 
330  if (prev_locale) {
331  SDL_free(prev_locale);
332  }
333 
334  if (prev_xmods) {
335  SDL_free(prev_xmods);
336  }
337  }
338 #endif
339  /* Try to determine which scancodes are being used based on fingerprint */
340  best_distance = SDL_arraysize(fingerprint) + 1;
341  best_index = -1;
342  X11_XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
343  for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
344  fingerprint[i].value =
345  X11_XKeysymToKeycode(data->display, fingerprint[i].keysym) -
346  min_keycode;
347  }
348  for (i = 0; i < SDL_arraysize(scancode_set); ++i) {
349  /* Make sure the scancode set isn't too big */
350  if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
351  continue;
352  }
353  distance = 0;
354  for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
355  if (fingerprint[j].value < 0
356  || fingerprint[j].value >= scancode_set[i].table_size) {
357  distance += 1;
358  } else if (scancode_set[i].table[fingerprint[j].value] != fingerprint[j].scancode) {
359  distance += 1;
360  }
361  }
362  if (distance < best_distance) {
363  best_distance = distance;
364  best_index = i;
365  }
366  }
367  if (best_index >= 0 && best_distance <= 2) {
368 #ifdef DEBUG_KEYBOARD
369  printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", best_index, min_keycode, max_keycode, scancode_set[best_index].table_size);
370 #endif
371  SDL_memcpy(&data->key_layout[min_keycode], scancode_set[best_index].table,
372  sizeof(SDL_Scancode) * scancode_set[best_index].table_size);
373  } else {
375 
376  printf
377  ("Keyboard layout unknown, please report the following to the SDL forums/mailing list (https://discourse.libsdl.org/):\n");
378 
379  /* Determine key_layout - only works on US QWERTY layout */
380  SDL_GetDefaultKeymap(keymap);
381  for (i = min_keycode; i <= max_keycode; ++i) {
382  KeySym sym;
383  sym = X11_KeyCodeToSym(_this, (KeyCode) i, 0);
384  if (sym != NoSymbol) {
385  SDL_Scancode scancode;
386  printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
387  (unsigned int) sym, X11_XKeysymToString(sym));
388  scancode = X11_KeyCodeToSDLScancode(_this, i);
389  data->key_layout[i] = scancode;
390  if (scancode == SDL_SCANCODE_UNKNOWN) {
391  printf("scancode not found\n");
392  } else {
393  printf("scancode = %d (%s)\n", scancode, SDL_GetScancodeName(scancode));
394  }
395  }
396  }
397  }
398 
400 
402 
403 #ifdef SDL_USE_IME
404  SDL_IME_Init();
405 #endif
406 
407  return 0;
408 }
409 
410 void
412 {
414  int i;
415  SDL_Scancode scancode;
417  unsigned char group = 0;
418 
419  SDL_GetDefaultKeymap(keymap);
420 
421 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
422  if (data->xkb) {
423  XkbStateRec state;
424  X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
425 
426  if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) {
427  group = state.group;
428  }
429  }
430 #endif
431 
432 
433  for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
434  Uint32 key;
435 
436  /* Make sure this is a valid scancode */
437  scancode = data->key_layout[i];
438  if (scancode == SDL_SCANCODE_UNKNOWN) {
439  continue;
440  }
441 
442  /* See if there is a UCS keycode for this scancode */
443  key = X11_KeyCodeToUcs4(_this, (KeyCode)i, group);
444  if (key) {
445  keymap[scancode] = key;
446  } else {
447  SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(_this, (KeyCode)i);
448 
449  switch (keyScancode) {
450  case SDL_SCANCODE_RETURN:
451  keymap[scancode] = SDLK_RETURN;
452  break;
453  case SDL_SCANCODE_ESCAPE:
454  keymap[scancode] = SDLK_ESCAPE;
455  break;
457  keymap[scancode] = SDLK_BACKSPACE;
458  break;
459  case SDL_SCANCODE_TAB:
460  keymap[scancode] = SDLK_TAB;
461  break;
462  case SDL_SCANCODE_DELETE:
463  keymap[scancode] = SDLK_DELETE;
464  break;
465  default:
466  keymap[scancode] = SDL_SCANCODE_TO_KEYCODE(keyScancode);
467  break;
468  }
469  }
470  }
471  SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
472 }
473 
474 void
476 {
478 
480  if (data->xkb) {
481  X11_XkbFreeKeyboard(data->xkb, 0, True);
482  data->xkb = NULL;
483  }
484 #endif
485 
486 #ifdef SDL_USE_IME
487  SDL_IME_Quit();
488 #endif
489 }
490 
491 static void
492 X11_ResetXIM(_THIS)
493 {
494 #ifdef X_HAVE_UTF8_STRING
495  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
496  int i;
497 
498  if (videodata && videodata->windowlist) {
499  for (i = 0; i < videodata->numwindows; ++i) {
500  SDL_WindowData *data = videodata->windowlist[i];
501  if (data && data->ic) {
502  /* Clear any partially entered dead keys */
503  char *contents = X11_Xutf8ResetIC(data->ic);
504  if (contents) {
505  X11_XFree(contents);
506  }
507  }
508  }
509  }
510 #endif
511 }
512 
513 void
515 {
516  X11_ResetXIM(_this);
517 }
518 
519 void
521 {
522  X11_ResetXIM(_this);
523 #ifdef SDL_USE_IME
524  SDL_IME_Reset();
525 #endif
526 }
527 
528 void
530 {
531  if (!rect) {
532  SDL_InvalidParamError("rect");
533  return;
534  }
535 
536 #ifdef SDL_USE_IME
538 #endif
539 }
540 
541 #endif /* SDL_VIDEO_DRIVER_X11 */
542 
543 /* vi: set ts=4 sw=4 expandtab: */
void SDL_GetDefaultKeymap(SDL_Keycode *keymap)
Definition: SDL_keyboard.c:588
GLboolean GLuint group
GLenum GLsizei GLenum GLenum const void * table
void X11_QuitKeyboard(_THIS)
void X11_SetTextInputRect(_THIS, SDL_Rect *rect)
static const SDL_Scancode xfree86_scancode_table[]
void SDL_IME_Quit(void)
Definition: SDL_ime.c:109
SDL_Rect rect
Definition: testrelative.c:27
struct wl_display * display
struct xkb_state * state
void SDL_IME_UpdateTextRect(SDL_Rect *rect)
Definition: SDL_ime.c:139
SDL_WindowData ** windowlist
Definition: SDL_x11video.h:83
void X11_StartTextInput(_THIS)
static const SDL_Scancode xfree86_scancode_table2[]
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
Sint32 SDL_Keycode
The SDL virtual key representation.
Definition: SDL_keycode.h:45
GLsizei GLsizei GLfloat distance
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
void SDL_SetKeymap(int start, SDL_Keycode *keys, int length)
Definition: SDL_keyboard.c:594
static const SDL_Scancode darwin_scancode_table[]
#define SDL_memcpy
GLuint64 key
Definition: gl2ext.h:2192
KeySym X11_KeyCodeToSym(_THIS, KeyCode, unsigned char group)
#define _THIS
#define SDL_free
unsigned int X11_KeySymToUcs4(KeySym keysym)
#define SDL_SCANCODE_TO_KEYCODE(X)
Definition: SDL_keycode.h:48
GLsizei const GLfloat * value
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
void X11_UpdateKeymap(_THIS)
void SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
Definition: SDL_keyboard.c:616
#define SDL_getenv
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:161
void X11_StopTextInput(_THIS)
#define SDL_GetScancodeName
int X11_InitKeyboard(_THIS)
void SDL_IME_Reset(void)
Definition: SDL_ime.c:123
#define SDL_strdup
SDL_bool SDL_IME_Init(void)
Definition: SDL_ime.c:86
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
Definition: SDL_config.h:360
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_Scancode
The SDL keyboard scancode representation.
Definition: SDL_scancode.h:43
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
#define SDL_strstr
static const SDL_Scancode xvnc_scancode_table[]