fully automatic keymap generation
If a key is not listed in keymap.cfg but SDL provides a good enough name for the corresponding scancode, a keymap entry is generated automatically. If a key can't be found when adding a bind, it is checked, if SDL can resolve the key name. The resolved keybind is then used to recreate the keymap entry - and the bind can succeed. Some SDL names for scancodes may not be usable as keymap names: if the name contains (, ), $ or ", it will be rejected. Also, SDL does not provide names for all scancodes. Scancode names provided by SDL can be platform-dependant, therefore recreating the bind may fail on a different platform. However, the feature should work fine with most nonstandard keys - and the information written to clientlog can be used to amend keymap.cfg
This commit is contained in:
+29
-1
@@ -153,7 +153,6 @@ void keymap(int *code, char *key)
|
||||
km.code = *code;
|
||||
km.name = newstring(key);
|
||||
}
|
||||
|
||||
COMMAND(keymap, "is");
|
||||
|
||||
keym *findbind(const char *key)
|
||||
@@ -176,6 +175,21 @@ keym *findbindc(int code)
|
||||
return keyms.access(code);
|
||||
}
|
||||
|
||||
keym *autokeymap(int keycode, int scancode)
|
||||
{
|
||||
static bool scdone[SDL_NUM_SCANCODES] = { false };
|
||||
int sc = keycode <= SDLK_SCANCODE_MASK ? scancode : (keycode & (SDLK_SCANCODE_MASK - 1));
|
||||
if(sc < 0 || sc >= SDL_NUM_SCANCODES || scdone[sc]) return NULL;
|
||||
scdone[sc] = true;
|
||||
string text;
|
||||
filtertext(text, SDL_GetScancodeName((SDL_Scancode) sc), FTXT__AUTOKEYMAPNAME);
|
||||
if(!*text || (int)SDL_GetScancodeFromName(text) != sc || findbind(text)) return NULL; // name is not unique (collision probably caused by filtertext) or can't be properly resolved in reverse
|
||||
clientlogf("autokeymap: create keymap entry for scancode %d, \"%s\"", sc, text);
|
||||
sc |= SDLK_SCANCODE_MASK;
|
||||
keymap(&sc, text);
|
||||
return keyms.access(sc);
|
||||
}
|
||||
|
||||
void findkey(int *code)
|
||||
{
|
||||
const char *res = "-255";
|
||||
@@ -228,6 +242,19 @@ bool bindkey(keym *km, const char *action, int type)
|
||||
void bindk(const char *key, const char *action, int type)
|
||||
{
|
||||
keym *km = findbind(key);
|
||||
if(!km)
|
||||
{
|
||||
string text;
|
||||
filtertext(text, key, FTXT__AUTOKEYMAPNAME);
|
||||
int sc = *text && !strcmp(key, text) ? (int)SDL_GetScancodeFromName(text) : SDL_SCANCODE_UNKNOWN;
|
||||
if(sc != SDL_SCANCODE_UNKNOWN)
|
||||
{
|
||||
clientlogf("autokeymap: re-create keymap entry for scancode %d, \"%s\"", sc, text);
|
||||
sc |= SDLK_SCANCODE_MASK;
|
||||
keymap(&sc, text);
|
||||
km = findbind(key);
|
||||
}
|
||||
}
|
||||
if(!km) { conoutf("unknown key \"%s\"", key); return; }
|
||||
bindkey(km, action, type);
|
||||
}
|
||||
@@ -567,6 +594,7 @@ void keypress(int keycode, int scancode, bool isdown, SDL_Keymod mod)
|
||||
{
|
||||
keym *haskey = keyms.access(keycode);
|
||||
if(!haskey && !(keycode & SDLK_SCANCODE_MASK) && scancode) haskey = keyms.access(scancode | SDLK_SCANCODE_MASK); // keycode not found: maybe we know the scancode
|
||||
if(!haskey && isdown) haskey = autokeymap(keycode, scancode);
|
||||
if(haskey && haskey->pressed) execbind(*haskey, isdown); // allow pressed keys to release
|
||||
else if(saycommandon) consolekey(keycode, isdown, mod); // keystrokes go to commandline
|
||||
else if(!menukey(keycode, isdown)) // keystrokes go to menu
|
||||
|
||||
@@ -223,3 +223,4 @@ enum
|
||||
#define FTXT__ZIPDESC (FTXT_NOWHITE | FTXT_ALLOWBLANKS | FTXT_TABTOBLANK | FTXT_NOCOLOR | FTXT_SAFECS)
|
||||
#define FTXT__CERTFILENAME (FTXT_MAPNAME | FTXT_TOLOWER)
|
||||
#define FTXT__CONSOLEPASTE (FTXT_TABTOBLANK)
|
||||
#define FTXT__AUTOKEYMAPNAME (FTXT_SAFECS)
|
||||
|
||||
Reference in New Issue
Block a user