Improve X11 key handling when XKB isn't available + add xvnc scancodes.
authorAlex Baines <alex@abaines.me.uk>
Mon, 03 Oct 2016 11:35:34 +0100
changeset 10494c54de4000f9f
parent 10493 30155a7426c4
child 10495 f732781d7ddc
Improve X11 key handling when XKB isn't available + add xvnc scancodes.

Based on a patch by Bill Lash (see bug 3094).
src/events/scancodes_xfree86.h
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11keyboard.c
src/video/x11/SDL_x11keyboard.h
src/video/x11/SDL_x11sym.h
     1.1 --- a/src/events/scancodes_xfree86.h	Sat Aug 15 00:25:52 2015 -0500
     1.2 +++ b/src/events/scancodes_xfree86.h	Mon Oct 03 11:35:34 2016 +0100
     1.3 @@ -418,4 +418,89 @@
     1.4      /* 238 */   SDL_SCANCODE_UNKNOWN,   /* XF86WLAN */
     1.5  };
     1.6  
     1.7 +/* Xvnc / Xtightvnc scancodes from xmodmap -pk */
     1.8 +static const SDL_Scancode xvnc_scancode_table[] = {
     1.9 +    /*  0 */    SDL_SCANCODE_LCTRL,
    1.10 +    /*  1 */    SDL_SCANCODE_RCTRL,
    1.11 +    /*  2 */    SDL_SCANCODE_LSHIFT,
    1.12 +    /*  3 */    SDL_SCANCODE_RSHIFT,
    1.13 +    /*  4 */    SDL_SCANCODE_UNKNOWN, /* Meta_L */
    1.14 +    /*  5 */    SDL_SCANCODE_UNKNOWN, /* Meta_R */
    1.15 +    /*  6 */    SDL_SCANCODE_LALT,
    1.16 +    /*  7 */    SDL_SCANCODE_RALT,
    1.17 +    /*  8 */    SDL_SCANCODE_SPACE,
    1.18 +    /*  9 */    SDL_SCANCODE_0,
    1.19 +    /*  10 */   SDL_SCANCODE_1,
    1.20 +    /*  11 */   SDL_SCANCODE_2,
    1.21 +    /*  12 */   SDL_SCANCODE_3,
    1.22 +    /*  13 */   SDL_SCANCODE_4,
    1.23 +    /*  14 */   SDL_SCANCODE_5,
    1.24 +    /*  15 */   SDL_SCANCODE_6,
    1.25 +    /*  16 */   SDL_SCANCODE_7,
    1.26 +    /*  17 */   SDL_SCANCODE_8,
    1.27 +    /*  18 */   SDL_SCANCODE_9,
    1.28 +    /*  19 */   SDL_SCANCODE_MINUS,
    1.29 +    /*  20 */   SDL_SCANCODE_EQUALS,
    1.30 +    /*  21 */   SDL_SCANCODE_LEFTBRACKET,
    1.31 +    /*  22 */   SDL_SCANCODE_RIGHTBRACKET,
    1.32 +    /*  23 */   SDL_SCANCODE_SEMICOLON,
    1.33 +    /*  24 */   SDL_SCANCODE_APOSTROPHE,
    1.34 +    /*  25 */   SDL_SCANCODE_GRAVE,
    1.35 +    /*  26 */   SDL_SCANCODE_COMMA,
    1.36 +    /*  27 */   SDL_SCANCODE_PERIOD,
    1.37 +    /*  28 */   SDL_SCANCODE_SLASH,
    1.38 +    /*  29 */   SDL_SCANCODE_BACKSLASH,
    1.39 +    /*  30 */   SDL_SCANCODE_A,
    1.40 +    /*  31 */   SDL_SCANCODE_B,
    1.41 +    /*  32 */   SDL_SCANCODE_C,
    1.42 +    /*  33 */   SDL_SCANCODE_D,
    1.43 +    /*  34 */   SDL_SCANCODE_E,
    1.44 +    /*  35 */   SDL_SCANCODE_F,
    1.45 +    /*  36 */   SDL_SCANCODE_G,
    1.46 +    /*  37 */   SDL_SCANCODE_H,
    1.47 +    /*  38 */   SDL_SCANCODE_I,
    1.48 +    /*  39 */   SDL_SCANCODE_J,
    1.49 +    /*  40 */   SDL_SCANCODE_K,
    1.50 +    /*  41 */   SDL_SCANCODE_L,
    1.51 +    /*  42 */   SDL_SCANCODE_M,
    1.52 +    /*  43 */   SDL_SCANCODE_N,
    1.53 +    /*  44 */   SDL_SCANCODE_O,
    1.54 +    /*  45 */   SDL_SCANCODE_P,
    1.55 +    /*  46 */   SDL_SCANCODE_Q,
    1.56 +    /*  47 */   SDL_SCANCODE_R,
    1.57 +    /*  48 */   SDL_SCANCODE_S,
    1.58 +    /*  49 */   SDL_SCANCODE_T,
    1.59 +    /*  50 */   SDL_SCANCODE_U,
    1.60 +    /*  51 */   SDL_SCANCODE_V,
    1.61 +    /*  52 */   SDL_SCANCODE_W,
    1.62 +    /*  53 */   SDL_SCANCODE_X,
    1.63 +    /*  54 */   SDL_SCANCODE_Y,
    1.64 +    /*  55 */   SDL_SCANCODE_Z,
    1.65 +    /*  56 */   SDL_SCANCODE_BACKSPACE,
    1.66 +    /*  57 */   SDL_SCANCODE_RETURN,
    1.67 +    /*  58 */   SDL_SCANCODE_TAB,
    1.68 +    /*  59 */   SDL_SCANCODE_ESCAPE,
    1.69 +    /*  60 */   SDL_SCANCODE_DELETE,
    1.70 +    /*  61 */   SDL_SCANCODE_HOME,
    1.71 +    /*  62 */   SDL_SCANCODE_END,
    1.72 +    /*  63 */   SDL_SCANCODE_PAGEUP,
    1.73 +    /*  64 */   SDL_SCANCODE_PAGEDOWN,
    1.74 +    /*  65 */   SDL_SCANCODE_UP,
    1.75 +    /*  66 */   SDL_SCANCODE_DOWN,
    1.76 +    /*  67 */   SDL_SCANCODE_LEFT,
    1.77 +    /*  68 */   SDL_SCANCODE_RIGHT,
    1.78 +    /*  69 */   SDL_SCANCODE_F1,
    1.79 +    /*  70 */   SDL_SCANCODE_F2,
    1.80 +    /*  71 */   SDL_SCANCODE_F3,
    1.81 +    /*  72 */   SDL_SCANCODE_F4,
    1.82 +    /*  73 */   SDL_SCANCODE_F5,
    1.83 +    /*  74 */   SDL_SCANCODE_F6,
    1.84 +    /*  75 */   SDL_SCANCODE_F7,
    1.85 +    /*  76 */   SDL_SCANCODE_F8,
    1.86 +    /*  77 */   SDL_SCANCODE_F9,
    1.87 +    /*  78 */   SDL_SCANCODE_F10,
    1.88 +    /*  79 */   SDL_SCANCODE_F11,
    1.89 +    /*  80 */   SDL_SCANCODE_F12,
    1.90 +};
    1.91 +
    1.92  /* *INDENT-ON* */
     2.1 --- a/src/video/x11/SDL_x11events.c	Sat Aug 15 00:25:52 2015 -0500
     2.2 +++ b/src/video/x11/SDL_x11events.c	Mon Oct 03 11:35:34 2016 +0100
     2.3 @@ -766,11 +766,7 @@
     2.4              if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
     2.5                  int min_keycode, max_keycode;
     2.6                  X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
     2.7 -#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
     2.8 -                keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
     2.9 -#else
    2.10 -                keysym = X11_XKeycodeToKeysym(display, keycode, 0);
    2.11 -#endif
    2.12 +                keysym = X11_KeyCodeToSym(_this, keycode, xevent.xkey.state >> 13);
    2.13                  fprintf(stderr,
    2.14                          "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
    2.15                          keycode, keycode - min_keycode, keysym,
     3.1 --- a/src/video/x11/SDL_x11keyboard.c	Sat Aug 15 00:25:52 2015 -0500
     3.2 +++ b/src/video/x11/SDL_x11keyboard.c	Mon Oct 03 11:35:34 2016 +0100
     3.3 @@ -154,21 +154,18 @@
     3.4      { darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
     3.5      { xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
     3.6      { xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
     3.7 +    { xvnc_scancode_table, SDL_arraysize(xvnc_scancode_table) },
     3.8  };
     3.9  /* *INDENT-OFF* */
    3.10  
    3.11  /* This function only works for keyboards in US QWERTY layout */
    3.12  static SDL_Scancode
    3.13 -X11_KeyCodeToSDLScancode(Display *display, KeyCode keycode)
    3.14 +X11_KeyCodeToSDLScancode(_THIS, KeyCode keycode)
    3.15  {
    3.16      KeySym keysym;
    3.17      int i;
    3.18  
    3.19 -#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    3.20 -    keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
    3.21 -#else
    3.22 -    keysym = X11_XKeycodeToKeysym(display, keycode, 0);
    3.23 -#endif
    3.24 +    keysym = X11_KeyCodeToSym(_this, keycode, 0);
    3.25      if (keysym == NoSymbol) {
    3.26          return SDL_SCANCODE_UNKNOWN;
    3.27      }
    3.28 @@ -196,8 +193,21 @@
    3.29  }
    3.30  
    3.31  static Uint32
    3.32 -X11_KeyCodeToUcs4(SDL_VideoData *data, KeyCode keycode, unsigned char group)
    3.33 +X11_KeyCodeToUcs4(_THIS, KeyCode keycode, unsigned char group)
    3.34  {
    3.35 +    KeySym keysym = X11_KeyCodeToSym(_this, keycode, group);
    3.36 +
    3.37 +    if (keysym == NoSymbol) {
    3.38 +        return 0;
    3.39 +    }
    3.40 +
    3.41 +    return X11_KeySymToUcs4(keysym);
    3.42 +}
    3.43 +
    3.44 +KeySym
    3.45 +X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group)
    3.46 +{
    3.47 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    3.48      KeySym keysym;
    3.49  
    3.50  #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    3.51 @@ -219,19 +229,15 @@
    3.52                  group %= num_groups;
    3.53              }
    3.54          }
    3.55 +        keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
    3.56      } else {
    3.57 -        group = 0;
    3.58 +        keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
    3.59      }
    3.60 -
    3.61 -    keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
    3.62  #else
    3.63      keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
    3.64  #endif
    3.65 -    if (keysym == NoSymbol) {
    3.66 -        return 0;
    3.67 -    }
    3.68  
    3.69 -    return X11_KeySymToUcs4(keysym);
    3.70 +    return keysym;
    3.71  }
    3.72  
    3.73  int
    3.74 @@ -259,6 +265,16 @@
    3.75  
    3.76      X11_XAutoRepeatOn(data->display);
    3.77  
    3.78 +#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    3.79 +    {
    3.80 +	    int xkb_major = XkbMajorVersion;
    3.81 +	    int xkb_minor = XkbMinorVersion;
    3.82 +	    if (X11_XkbQueryExtension(data->display, NULL, NULL, NULL, &xkb_major, &xkb_minor)) {
    3.83 +	        data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd);
    3.84 +	    }
    3.85 +	}
    3.86 +#endif
    3.87 +
    3.88      /* Try to determine which scancodes are being used based on fingerprint */
    3.89      best_distance = SDL_arraysize(fingerprint) + 1;
    3.90      best_index = -1;
    3.91 @@ -303,16 +319,12 @@
    3.92          SDL_GetDefaultKeymap(keymap);
    3.93          for (i = min_keycode; i <= max_keycode; ++i) {
    3.94              KeySym sym;
    3.95 -#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    3.96 -            sym = X11_XkbKeycodeToKeysym(data->display, i, 0, 0);
    3.97 -#else
    3.98 -            sym = X11_XKeycodeToKeysym(data->display, i, 0);
    3.99 -#endif
   3.100 +            sym = X11_KeyCodeToSym(_this, (KeyCode) i, 0);
   3.101              if (sym != NoSymbol) {
   3.102                  SDL_Scancode scancode;
   3.103                  printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
   3.104                         (unsigned int) sym, X11_XKeysymToString(sym));
   3.105 -                scancode = X11_KeyCodeToSDLScancode(data->display, i);
   3.106 +                scancode = X11_KeyCodeToSDLScancode(_this, i);
   3.107                  data->key_layout[i] = scancode;
   3.108                  if (scancode == SDL_SCANCODE_UNKNOWN) {
   3.109                      printf("scancode not found\n");
   3.110 @@ -344,16 +356,11 @@
   3.111      unsigned char group = 0;
   3.112  
   3.113      SDL_GetDefaultKeymap(keymap);
   3.114 -    
   3.115 +
   3.116  #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
   3.117 -    {
   3.118 +    if (data->xkb) {
   3.119          XkbStateRec state;
   3.120 -
   3.121 -        if (data->xkb) {
   3.122 -            X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
   3.123 -        } else {
   3.124 -            data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd);
   3.125 -        }
   3.126 +        X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
   3.127  
   3.128          if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) {
   3.129              group = state.group;
   3.130 @@ -372,11 +379,11 @@
   3.131          }
   3.132  
   3.133          /* See if there is a UCS keycode for this scancode */
   3.134 -        key = X11_KeyCodeToUcs4(data, (KeyCode)i, group);
   3.135 +        key = X11_KeyCodeToUcs4(_this, (KeyCode)i, group);
   3.136          if (key) {
   3.137              keymap[scancode] = key;
   3.138          } else {
   3.139 -            SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(data->display, (KeyCode)i);
   3.140 +            SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(_this, (KeyCode)i);
   3.141  
   3.142              switch (keyScancode) {
   3.143                  case SDL_SCANCODE_RETURN:
   3.144 @@ -411,6 +418,7 @@
   3.145  #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
   3.146      if (data->xkb) {
   3.147          X11_XkbFreeClientMap(data->xkb, 0, True);
   3.148 +        data->xkb = NULL;
   3.149      }
   3.150  #endif
   3.151  
     4.1 --- a/src/video/x11/SDL_x11keyboard.h	Sat Aug 15 00:25:52 2015 -0500
     4.2 +++ b/src/video/x11/SDL_x11keyboard.h	Mon Oct 03 11:35:34 2016 +0100
     4.3 @@ -29,6 +29,7 @@
     4.4  extern void X11_StartTextInput(_THIS);
     4.5  extern void X11_StopTextInput(_THIS);
     4.6  extern void X11_SetTextInputRect(_THIS, SDL_Rect *rect);
     4.7 +extern KeySym X11_KeyCodeToSym(_THIS, KeyCode, unsigned char group);
     4.8  
     4.9  #endif /* _SDL_x11keyboard_h */
    4.10  
     5.1 --- a/src/video/x11/SDL_x11sym.h	Sat Aug 15 00:25:52 2015 -0500
     5.2 +++ b/src/video/x11/SDL_x11sym.h	Mon Oct 03 11:35:34 2016 +0100
     5.3 @@ -169,6 +169,7 @@
     5.4  #endif
     5.5  
     5.6  #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
     5.7 +SDL_X11_SYM(Bool,XkbQueryExtension,(Display* a,int * b,int * c,int * d,int * e, int *f),(a,b,c,d,e,f),return)
     5.8  #if NeedWidePrototypes
     5.9  SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,unsigned int b,int c,int d),(a,b,c,d),return)
    5.10  #else