mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-26 22:31:17 +00:00
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with Shift+Esc, not `/^/whatever, so you can easily type whatever character is on your "console key" into the game, or even bind that key. Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the newly added K_CONSOLE. in_kbd has a new (SDL2-only) "auto" mode which tries to detect the keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ). Wherever Sys_GetConsoleKey() is called, I now take the current state of Shift into account, so we don't discard more chars than necessary, esp. when they keyboard-layout (in_kbd) is *not* correctly set. (TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore the char generated by the "console key" in the console..)
This commit is contained in:
parent
786e5a3694
commit
78ab625edd
4 changed files with 111 additions and 54 deletions
|
@ -797,8 +797,9 @@ bool idConsoleLocal::ProcessEvent( const sysEvent_t *event, bool forceAccept ) {
|
||||||
bool consoleKey = false;
|
bool consoleKey = false;
|
||||||
if(event->evType == SE_KEY)
|
if(event->evType == SE_KEY)
|
||||||
{
|
{
|
||||||
if( event->evValue == Sys_GetConsoleKey( false ) || event->evValue == Sys_GetConsoleKey( true )
|
bool shiftPressed = idKeyInput::IsDown( K_SHIFT );
|
||||||
|| (event->evValue == K_ESCAPE && idKeyInput::IsDown( K_SHIFT )) ) // shift+esc should also open console
|
if( event->evValue == K_CONSOLE || event->evValue == Sys_GetConsoleKey( shiftPressed )
|
||||||
|
|| (event->evValue == K_ESCAPE && shiftPressed) ) // shift+esc should also open console
|
||||||
{
|
{
|
||||||
consoleKey = true;
|
consoleKey = true;
|
||||||
}
|
}
|
||||||
|
@ -850,7 +851,7 @@ bool idConsoleLocal::ProcessEvent( const sysEvent_t *event, bool forceAccept ) {
|
||||||
// handle key and character events
|
// handle key and character events
|
||||||
if ( event->evType == SE_CHAR ) {
|
if ( event->evType == SE_CHAR ) {
|
||||||
// never send the console key as a character
|
// never send the console key as a character
|
||||||
if ( event->evValue != Sys_GetConsoleKey( false ) && event->evValue != Sys_GetConsoleKey( true ) ) {
|
if ( event->evValue != Sys_GetConsoleKey( idKeyInput::IsDown( K_SHIFT ) ) ) {
|
||||||
consoleField.CharEvent( event->evValue );
|
consoleField.CharEvent( event->evValue );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -267,6 +267,7 @@ typedef enum {
|
||||||
|
|
||||||
K_LAST_SCANCODE = K_SC_CURRENCYSUBUNIT, // TODO: keep up to date!
|
K_LAST_SCANCODE = K_SC_CURRENCYSUBUNIT, // TODO: keep up to date!
|
||||||
|
|
||||||
|
K_CONSOLE, // special keycode used for the "console key" and only to open/close the console (not bindable)
|
||||||
|
|
||||||
// FIXME: maybe move everything joystick related here
|
// FIXME: maybe move everything joystick related here
|
||||||
|
|
||||||
|
|
|
@ -60,10 +60,16 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char *kbdNames[] = {
|
static const char *kbdNames[] = {
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0) // auto-detection is only available for SDL2
|
||||||
|
"auto",
|
||||||
|
#endif
|
||||||
"english", "french", "german", "italian", "spanish", "turkish", "norwegian", "brazilian", NULL
|
"english", "french", "german", "italian", "spanish", "turkish", "norwegian", "brazilian", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static idCVar in_kbd("in_kbd", "english", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "keyboard layout", kbdNames, idCmdSystem::ArgCompletion_String<kbdNames> );
|
static idCVar in_kbd("in_kbd", kbdNames[0], CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "keyboard layout", kbdNames, idCmdSystem::ArgCompletion_String<kbdNames> );
|
||||||
|
// TODO: I'd really like to make in_ignoreConsoleKey default to 1, but I guess there would be too much confusion :-/
|
||||||
|
static idCVar in_ignoreConsoleKey("in_ignoreConsoleKey", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
|
||||||
|
"Console only opens with Shift+Esc, not ` or ^ etc");
|
||||||
|
|
||||||
static idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
|
static idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
|
||||||
"if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work)");
|
"if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work)");
|
||||||
|
@ -451,6 +457,7 @@ void Sys_InitInput() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
in_kbd.SetModified();
|
in_kbd.SetModified();
|
||||||
|
Sys_GetConsoleKey(false); // initialize consoleKeymappingIdx from in_kbd
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
const char* grabKeyboardEnv = SDL_getenv(SDL_HINT_GRAB_KEYBOARD);
|
const char* grabKeyboardEnv = SDL_getenv(SDL_HINT_GRAB_KEYBOARD);
|
||||||
if ( grabKeyboardEnv ) {
|
if ( grabKeyboardEnv ) {
|
||||||
|
@ -485,46 +492,89 @@ void Sys_InitScanTable() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct ConsoleKeyMapping {
|
||||||
|
const char* langName;
|
||||||
|
unsigned char key;
|
||||||
|
unsigned char keyShifted;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ConsoleKeyMapping consoleKeyMappings[] = {
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
{ "auto", 0 , 0 }, // special case: set current keycode for SDL_SCANCODE_GRAVE (no shifted keycode, though)
|
||||||
|
#endif
|
||||||
|
{ "english", '`', '~' },
|
||||||
|
{ "french", '<', '>' },
|
||||||
|
{ "german", '^', 176 }, // °
|
||||||
|
{ "italian", '\\', '|' },
|
||||||
|
{ "spanish", 186, 170 }, // º ª
|
||||||
|
{ "turkish", '"', 233 }, // é
|
||||||
|
{ "norwegian", 124, 167 }, // | §
|
||||||
|
{ "brazilian", '\'', '"' },
|
||||||
|
};
|
||||||
|
static int consoleKeyMappingIdx = 0;
|
||||||
|
|
||||||
|
static void initConsoleKeyMapping() {
|
||||||
|
const int numMappings = sizeof(consoleKeyMappings)/sizeof(consoleKeyMappings[0]);
|
||||||
|
|
||||||
|
idStr lang = in_kbd.GetString();
|
||||||
|
consoleKeyMappingIdx = 0;
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
consoleKeyMappings[0].key = 0;
|
||||||
|
if ( lang.Length() == 0 || lang.Icmp( "auto") == 0 ) {
|
||||||
|
// auto-detection (SDL2-only)
|
||||||
|
int keycode = SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE );
|
||||||
|
if ( keycode > 0 && keycode <= 0xFF ) {
|
||||||
|
// the SDL keycode and dhewm3 keycode should be identical for the mappings,
|
||||||
|
// as it's ISO-8859-1 ("High ASCII") chars
|
||||||
|
for( int i=1; i<numMappings; ++i ) {
|
||||||
|
if ( consoleKeyMappings[i].key == keycode ) {
|
||||||
|
consoleKeyMappingIdx = i;
|
||||||
|
common->Printf( "Detected keyboard layout as \"%s\"\n", consoleKeyMappings[i].langName );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( consoleKeyMappingIdx == 0 ) { // not found in known mappings
|
||||||
|
consoleKeyMappings[0].key = keycode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
for( int i=1; i<numMappings; ++i ) {
|
||||||
|
if( lang.Icmp( consoleKeyMappings[i].langName ) == 0 ) {
|
||||||
|
consoleKeyMappingIdx = i;
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
int keycode = SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE );
|
||||||
|
if ( keycode && keycode != consoleKeyMappings[i].key ) {
|
||||||
|
common->Warning( "in_kbd is set to \"%s\", but the actual keycode of the 'console key' is %c (%d), not %c (%d), so this might not work that well..\n",
|
||||||
|
lang.c_str(), (unsigned char)keycode, keycode, consoleKeyMappings[i].key, consoleKeyMappings[i].key );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
Sys_GetConsoleKey
|
Sys_GetConsoleKey
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
unsigned char Sys_GetConsoleKey(bool shifted) {
|
unsigned char Sys_GetConsoleKey( bool shifted ) {
|
||||||
static unsigned char keys[2] = { '`', '~' };
|
|
||||||
|
|
||||||
if (in_kbd.IsModified()) {
|
if ( in_ignoreConsoleKey.GetBool() ) {
|
||||||
idStr lang = in_kbd.GetString();
|
return 0;
|
||||||
|
}
|
||||||
if (lang.Length()) {
|
|
||||||
if (!lang.Icmp("french")) {
|
|
||||||
keys[0] = '<';
|
|
||||||
keys[1] = '>';
|
|
||||||
} else if (!lang.Icmp("german")) {
|
|
||||||
keys[0] = '^';
|
|
||||||
keys[1] = 176; // °
|
|
||||||
} else if (!lang.Icmp("italian")) {
|
|
||||||
keys[0] = '\\';
|
|
||||||
keys[1] = '|';
|
|
||||||
} else if (!lang.Icmp("spanish")) {
|
|
||||||
keys[0] = 186; // º
|
|
||||||
keys[1] = 170; // ª
|
|
||||||
} else if (!lang.Icmp("turkish")) {
|
|
||||||
keys[0] = '"';
|
|
||||||
keys[1] = 233; // é
|
|
||||||
} else if (!lang.Icmp("norwegian")) {
|
|
||||||
keys[0] = 124; // |
|
|
||||||
keys[1] = 167; // §
|
|
||||||
} else if (!lang.Icmp("brazilian")) {
|
|
||||||
keys[0] = '\'';
|
|
||||||
keys[1] = '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ( in_kbd.IsModified() ) {
|
||||||
|
initConsoleKeyMapping();
|
||||||
in_kbd.ClearModified();
|
in_kbd.ClearModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
return shifted ? keys[1] : keys[0];
|
return shifted ? consoleKeyMappings[consoleKeyMappingIdx].keyShifted : consoleKeyMappings[consoleKeyMappingIdx].key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -665,15 +715,17 @@ sysEvent_t Sys_GetEvent() {
|
||||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
key = mapkey(ev.key.keysym.sym);
|
key = mapkey(ev.key.keysym.sym);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
unsigned char c;
|
if ( !in_ignoreConsoleKey.GetBool() ) {
|
||||||
// check if its an unmapped console key
|
// check if its an unmapped console key
|
||||||
if (ev.key.keysym.unicode == (c = Sys_GetConsoleKey(false))) {
|
int c = Sys_GetConsoleKey( (ev.key.keysym.mod & KMOD_SHIFT) != 0 );
|
||||||
key = c;
|
if (ev.key.keysym.unicode == c) {
|
||||||
} else if (ev.key.keysym.unicode == (c = Sys_GetConsoleKey(true))) {
|
key = c;
|
||||||
key = c;
|
}
|
||||||
} else {
|
}
|
||||||
|
if (!key) {
|
||||||
if (ev.type == SDL_KEYDOWN)
|
if (ev.type == SDL_KEYDOWN)
|
||||||
common->Warning("unmapped SDL key %d (0x%x)", ev.key.keysym.sym, ev.key.keysym.unicode);
|
common->Warning( "unmapped SDL key %d (0x%x) - if possible use SDL2 for better keyboard support",
|
||||||
|
ev.key.keysym.sym, ev.key.keysym.unicode );
|
||||||
continue; // handle next event
|
continue; // handle next event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,18 +751,19 @@ sysEvent_t Sys_GetEvent() {
|
||||||
key = mapkey(ev.key.keysym.sym);
|
key = mapkey(ev.key.keysym.sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!key) {
|
if ( !in_ignoreConsoleKey.GetBool() && ev.key.keysym.scancode == SDL_SCANCODE_GRAVE ) {
|
||||||
if (ev.key.keysym.scancode == SDL_SCANCODE_GRAVE) { // TODO: always do this check?
|
// that key between Esc, Tab and 1 is the console key
|
||||||
key = Sys_GetConsoleKey(true);
|
key = K_CONSOLE;
|
||||||
} else {
|
}
|
||||||
// if the key couldn't be mapped so far, try to map the scancode to K_SC_*
|
|
||||||
key = getKeynumForSDLscancode(sc);
|
if ( !key ) {
|
||||||
if(!key) {
|
// if the key couldn't be mapped so far, try to map the scancode to K_SC_*
|
||||||
if (ev.type == SDL_KEYDOWN) {
|
key = getKeynumForSDLscancode(sc);
|
||||||
common->Warning("unmapped SDL key %d (scancode %d)", ev.key.keysym.sym, (int)sc);
|
if(!key) {
|
||||||
}
|
if (ev.type == SDL_KEYDOWN) {
|
||||||
continue; // handle next event
|
common->Warning("unmapped SDL key %d (scancode %d)", ev.key.keysym.sym, (int)sc);
|
||||||
}
|
}
|
||||||
|
continue; // handle next event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -738,6 +791,8 @@ sysEvent_t Sys_GetEvent() {
|
||||||
res.evType = SE_CHAR;
|
res.evType = SE_CHAR;
|
||||||
res.evValue = ev.text.text[0];
|
res.evValue = ev.text.text[0];
|
||||||
|
|
||||||
|
// TODO: translate to "ISO-8859-1" with SDL_iconv() ?
|
||||||
|
|
||||||
if (ev.text.text[1] != '\0')
|
if (ev.text.text[1] != '\0')
|
||||||
{
|
{
|
||||||
memcpy(s, ev.text.text, SDL_TEXTINPUTEVENT_TEXT_SIZE);
|
memcpy(s, ev.text.text, SDL_TEXTINPUTEVENT_TEXT_SIZE);
|
||||||
|
|
|
@ -210,7 +210,7 @@ const char *idEditWindow::HandleEvent(const sysEvent_t *event, bool *updateVisua
|
||||||
int len = text.Length();
|
int len = text.Length();
|
||||||
|
|
||||||
if ( event->evType == SE_CHAR ) {
|
if ( event->evType == SE_CHAR ) {
|
||||||
if ( event->evValue == Sys_GetConsoleKey( false ) || event->evValue == Sys_GetConsoleKey( true ) ) {
|
if ( event->evValue == Sys_GetConsoleKey( idKeyInput::IsDown( K_SHIFT ) ) ) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue