示例#1
0
static bool _al_xwin_get_keyboard_mapping(void)
{
    int i;
    int count;
    int missing = 0;

    ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver();

    memset(used, 0, sizeof used);
    memset(keycode_to_scancode, 0, sizeof keycode_to_scancode);

    XDisplayKeycodes(system->x11display, &min_keycode, &max_keycode);
    count = 1 + max_keycode - min_keycode;

    if (keysyms) {
        XFree(keysyms);
    }
    keysyms = XGetKeyboardMapping(system->x11display, min_keycode,
                                  count, &sym_per_key);

    ALLEGRO_INFO("%i keys, %i symbols per key.\n", count, sym_per_key);

    if (sym_per_key <= 0) {
        return false;
    }

    missing = 0;

    for (i = min_keycode; i <= max_keycode; i++) {
        KeySym sym = keysyms[sym_per_key * (i - min_keycode)];
        KeySym sym2 =  keysyms[sym_per_key * (i - min_keycode) + 1];
        char *sym_str, *sym2_str;
        int allegro_key = 0;
        char str[1024];

        sym_str = XKeysymToString(sym);
        sym2_str = XKeysymToString(sym2);

        snprintf(str, sizeof str, "key [%i: %s %s]", i,
                 sym_str ? sym_str : "NULL", sym2_str ? sym2_str : "NULL");

        /* Hack for French keyboards, to correctly map ALLEGRO_KEY_0 to ALLEGRO_KEY_9. */
        if (sym2 >= XK_0 && sym2 <= XK_9) {
            allegro_key = find_allegro_key(sym2);
        }

        if (!allegro_key) {
            if (sym != NoSymbol) {
                allegro_key = find_allegro_key(sym);

                if (allegro_key == 0) {
                    missing++;
                    ALLEGRO_DEBUG("%s defering.\n", str);
                }
            }
            else {
                /* No KeySym for this key - ignore it. */
                keycode_to_scancode[i] = -1;
                ALLEGRO_DEBUG("%s not assigned.\n", str);
            }
        }

        if (allegro_key) {
            bool is_double = false;
            if (used[allegro_key]) {
                is_double = true;
            }
            keycode_to_scancode[i] = allegro_key;
            key_names[allegro_key] =
                XKeysymToString(keysyms[sym_per_key * (i - min_keycode)]);
            used[allegro_key] = 1;
            ALLEGRO_DEBUG("%s%s assigned to %i.\n", str,
                          is_double ? " *double*" : "", allegro_key);
        }
    }

    if (missing) {
        /* The keys still not assigned are just assigned arbitrarily now. */
        for (i = min_keycode; i <= max_keycode; i++) {
            if (keycode_to_scancode[i] == 0) {
                find_unknown_key_assignment(i);
            }
        }
    }

    if (xmodmap)
        XFreeModifiermap(xmodmap);
    xmodmap = XGetModifierMapping(system->x11display);
    for (i = 0; i < 8; i++) {
        int j;
        char str[1024];
        sprintf(str, "Modifier %d:", i + 1);
        for (j = 0; j < xmodmap->max_keypermod; j++) {
            KeyCode keycode = xmodmap->modifiermap[i * xmodmap->max_keypermod + j];
            // XKeycodeToKeysym is deprecated
            //KeySym sym = XKeycodeToKeysym(system->x11display, keycode, 0);
            KeySym sym = XkbKeycodeToKeysym(system->x11display, keycode, 0, 0);

            char *sym_str = XKeysymToString(sym);
            sprintf(str + strlen(str), " %s", sym_str ? sym_str : "NULL");
        }
        ALLEGRO_DEBUG("%s\n", str);
    }

    /* The [xkeymap] section can be useful, e.g. if trying to play a
     * game which has X and Y hardcoded as ALLEGRO_KEY_X and ALLEGRO_KEY_Y to mean
     * left/right movement, but on the X11 keyboard X and Y are far apart.
     * For normal use, a user never should have to touch [xkeymap] anymore
     * though, and proper written programs will not hardcode such mappings.
     */
    ALLEGRO_CONFIG *c = al_get_system_config();

    char const *key;
    ALLEGRO_CONFIG_ENTRY *it;
    key = al_get_first_config_entry(c, "xkeymap", &it);
    while (key) {
        char const *val;
        val = al_get_config_value(c, "xkeymap", key);
        int keycode = strtol(key, NULL, 10);
        int scancode = strtol(val, NULL, 10);
        if (keycode > 0 && scancode > 0) {
            keycode_to_scancode[keycode] = scancode;
            ALLEGRO_WARN("User override: KeySym %i assigned to %i.\n",
                         keycode, scancode);
        }
        key = al_get_next_config_entry(&it);
    }

    return true;
}
示例#2
0
/* x_get_keyboard_mapping:
 *  Generate a mapping from X11 keycodes to Allegro KEY_* codes. We have
 *  two goals: Every keypress should be mapped to a distinct Allegro KEY_*
 *  code. And we want the KEY_* codes to match the pressed
 *  key to some extent. To do the latter, the X11 KeySyms produced by a key
 *  are examined. If a match is found in the table above, the mapping is
 *  added to the mapping table. If no known KeySym is found for a key (or
 *  the same KeySym is found for more keys) - the remaining keys are
 *  distributed arbitrarily to the remaining KEY_* codes.
 *
 *  In a future version, this could be simplified by mapping *all* the X11
 *  KeySyms to KEY_* codes.
 */
void _xwin_get_keyboard_mapping(void)
{
   int i;
   int count;
   int missing = 0;

   memset(used, 0, sizeof used);
   memset(_xwin.keycode_to_scancode, 0, sizeof _xwin.keycode_to_scancode);

   XLOCK();

   XDisplayKeycodes(_xwin.display, &min_keycode, &max_keycode);
   count = 1 + max_keycode - min_keycode;

   if (keysyms) {
      XFree(keysyms);
   }
   keysyms = XGetKeyboardMapping(_xwin.display, min_keycode,
      count, &sym_per_key);

   TRACE (PREFIX_I "%i keys, %i symbols per key.\n", count, sym_per_key);

   missing = 0;

   for (i = min_keycode; i <= max_keycode; i++) {
      KeySym sym = keysyms[sym_per_key * (i - min_keycode)];
      KeySym sym2 =  keysyms[sym_per_key * (i - min_keycode) + 1];
      char *sym_str, *sym2_str;
      int allegro_key = 0;

      sym_str = XKeysymToString(sym);
      sym2_str = XKeysymToString(sym2);

      TRACE (PREFIX_I "key [%i: %s %s]", i, sym_str ? sym_str : "NULL", sym2_str ?
         sym2_str : "NULL");

      /* Hack for French keyboards, to correctly map KEY_0 to KEY_9. */
      if (sym2 >= XK_0 && sym2 <= XK_9) {
	 allegro_key = find_allegro_key(sym2);
      }

      if (!allegro_key) {
	 if (sym != NoSymbol) {
	    allegro_key = find_allegro_key(sym);

	    if (allegro_key == 0) {
	       missing++;
	       TRACE (" defering.\n");
	    }
	 }
	 else {
	    /* No KeySym for this key - ignore it. */
	    _xwin.keycode_to_scancode[i] = -1;
	    TRACE (" not assigned.\n");
	 }
      }

      if (allegro_key) {
	 if (used[allegro_key]) {
	    TRACE(" *double*");
	 }
	 _xwin.keycode_to_scancode[i] = allegro_key;
	 key_names[allegro_key] =
	    XKeysymToString(keysyms[sym_per_key * (i - min_keycode)]);
	 used[allegro_key] = 1;
	 TRACE(" assigned to %i.\n", allegro_key);
      }
   }

   if (missing) {
      /* The keys still not assigned are just assigned arbitrarily now. */
      for (i = min_keycode; i <= max_keycode; i++) {
	 if (_xwin.keycode_to_scancode[i] == 0) {
	    find_unknown_key_assignment(i);
	 }
      }
   }

   if (xmodmap)
      XFreeModifiermap(xmodmap);
   xmodmap = XGetModifierMapping(_xwin.display);
   for (i = 0; i < 8; i++) {
      int j;

      TRACE (PREFIX_I "Modifier %d:", i + 1);
      for (j = 0; j < xmodmap->max_keypermod; j++) {
	 KeySym sym = XKeycodeToKeysym(_xwin.display,
	    xmodmap->modifiermap[i * xmodmap->max_keypermod + j], 0);
         char *sym_str = XKeysymToString(sym);
         TRACE(" %s", sym_str ? sym_str : "NULL");
      }
      TRACE("\n");
   }

   /* The [xkeymap] section can be useful, e.g. if trying to play a
    * game which has X and Y hardcoded as KEY_X and KEY_Y to mean
    * left/right movement, but on the X11 keyboard X and Y are far apart.
    * For normal use, a user never should have to touch [xkeymap] anymore
    * though, and proper written programs will not hardcode such mappings.
    */
   {
      char *section, *option_format;
      char option[128], tmp1[128], tmp2[128];

      section = uconvert_ascii("xkeymap", tmp1);
      option_format = uconvert_ascii("keycode%d", tmp2);

      for (i = min_keycode; i <= max_keycode; i++) {
	 int scancode;

	 uszprintf(option, sizeof(option), option_format, i);
	 scancode = get_config_int(section, option, -1);
	 if (scancode > 0) {
	    _xwin.keycode_to_scancode[i] = scancode;
	    TRACE(PREFIX_I "User override: KeySym %i assigned to %i.\n", i, scancode);
	 }
      }
   }

   XUNLOCK();
}