Revamp SDL2 key handling, based on how ioquake3 does it.

- Reverted the addition of the interpret_shift param to Key_Event
- Now, SDL_KEYUP/SDL_KEYDOWN are converted from SDL scancodes to quake keys, and passed directly to Key_Event with no extra conditions / logic
- When SDL2 is used, Key_Console/Key_Message no longer convert keys to characters to insert in the typing buffer, but all other functionality is unchanged
- SDL_TEXTINPUT calls a new function, Char_Event. This calls either Char_Console/Char_Message depending on the keydest. These just insert the typed text into the buffer

This is cleaner than before because it maintains a clear separation between key presses and characters, whereas the old code was converting characters from SDL_TEXTINPUT back into fake keys and then feeding those into Key_Event. This also fixes Ctrl+C / Ctrl+V not working in the console

git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1020 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Eric Wasylishen 2014-09-12 04:27:54 +00:00
parent 34f2f6f1ca
commit f44d44d419
3 changed files with 74 additions and 37 deletions

View file

@ -369,11 +369,6 @@ void IN_UpdateForKeydest (void)
} }
#if defined(USE_SDL2) #if defined(USE_SDL2)
static qboolean IN_SDL2_QuakeKeyHandledAsTextInput(int qkey)
{
return (qkey >= 32 && qkey <= 126) && qkey != '`';
}
static inline int IN_SDL2_ScancodeToQuakeKey(SDL_Scancode scancode) static inline int IN_SDL2_ScancodeToQuakeKey(SDL_Scancode scancode)
{ {
switch (scancode) switch (scancode)
@ -500,6 +495,7 @@ void IN_SendKeyEvents (void)
{ {
SDL_Event event; SDL_Event event;
int sym, state, modstate; int sym, state, modstate;
static int lastKeyDown = 0;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
@ -527,17 +523,12 @@ void IN_SendKeyEvents (void)
// SDL2: We use SDL_TEXTINPUT for typing in the console / chat. // SDL2: We use SDL_TEXTINPUT for typing in the console / chat.
// SDL2 uses the local keyboard layout and handles modifiers // SDL2 uses the local keyboard layout and handles modifiers
// (shift for uppercase, etc.) for us. // (shift for uppercase, etc.) for us.
if (lastKeyDown != '`') // don't add a ` to the console when the player brings it down
{ {
char *ch; unsigned char *ch;
for (ch = event.text.text; *ch != '\0'; ch++) for (ch = (unsigned char *)event.text.text; ch[0] != 0 && ch[0] < 128; ch++)
{ {
int qkey = *ch; Char_Event (ch[0]);
if (IN_SDL2_QuakeKeyHandledAsTextInput(qkey) && !gamekey)
{
Key_Event (qkey, true, false);
Key_Event (qkey, false, false);
}
} }
} }
break; break;
@ -563,12 +554,12 @@ void IN_SendKeyEvents (void)
// on the key cap. // on the key cap.
sym = IN_SDL2_ScancodeToQuakeKey(event.key.keysym.scancode); sym = IN_SDL2_ScancodeToQuakeKey(event.key.keysym.scancode);
if (gamekey || !IN_SDL2_QuakeKeyHandledAsTextInput(sym)) if (event.type == SDL_KEYDOWN)
{ lastKeyDown = sym;
state = event.key.state; else
lastKeyDown = 0;
Key_Event (sym, state, true); Key_Event (sym, event.key.state == SDL_PRESSED);
}
break; break;
#else #else
sym = event.key.keysym.sym; sym = event.key.keysym.sym;
@ -796,7 +787,7 @@ void IN_SendKeyEvents (void)
sym = 0; sym = 0;
break; break;
} }
Key_Event (sym, state, true); Key_Event (sym, state);
break; break;
#endif #endif
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
@ -808,20 +799,20 @@ void IN_SendKeyEvents (void)
event.button.button); event.button.button);
break; break;
} }
Key_Event(buttonremap[event.button.button - 1], event.button.state == SDL_PRESSED, true); Key_Event(buttonremap[event.button.button - 1], event.button.state == SDL_PRESSED);
break; break;
#if defined(USE_SDL2) #if defined(USE_SDL2)
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) if (event.wheel.y > 0)
{ {
Key_Event(K_MWHEELUP, false, true); Key_Event(K_MWHEELUP, false);
Key_Event(K_MWHEELUP, true, true); Key_Event(K_MWHEELUP, true);
} }
else if (event.wheel.y < 0) else if (event.wheel.y < 0)
{ {
Key_Event(K_MWHEELDOWN, false, true); Key_Event(K_MWHEELDOWN, false);
Key_Event(K_MWHEELDOWN, true, true); Key_Event(K_MWHEELDOWN, true);
} }
break; break;
#endif #endif

View file

@ -50,6 +50,12 @@ qboolean consolekeys[256]; // if true, can't be rebound while in console
qboolean menubound[256]; // if true, can't be rebound while in menu qboolean menubound[256]; // if true, can't be rebound while in menu
qboolean keydown[256]; qboolean keydown[256];
#if defined(USE_SDL2)
const qboolean backend_sends_char_events = true;
#else
const qboolean backend_sends_char_events = false;
#endif
typedef struct typedef struct
{ {
const char *name; const char *name;
@ -230,6 +236,8 @@ Interactive line editing and console scrollback
extern char *con_text, key_tabpartial[MAXCMDLINE]; extern char *con_text, key_tabpartial[MAXCMDLINE];
extern int con_current, con_linewidth, con_vislines; extern int con_current, con_linewidth, con_vislines;
void Char_Console (int key);
void Key_Console (int key) void Key_Console (int key)
{ {
static char current[MAXCMDLINE] = ""; static char current[MAXCMDLINE] = "";
@ -434,6 +442,15 @@ void Key_Console (int key)
break; break;
} }
if (!backend_sends_char_events)
Char_Console (key);
}
void Char_Console (int key)
{
size_t len;
char *workline = key_lines[edit_line];
if (key < 32 || key > 127) if (key < 32 || key > 127)
return; // non printable return; // non printable
@ -486,6 +503,8 @@ void Key_EndChat (void)
chat_buffer[0] = 0; chat_buffer[0] = 0;
} }
void Char_Message (int key);
void Key_Message (int key) void Key_Message (int key)
{ {
if (key == K_ENTER) if (key == K_ENTER)
@ -514,6 +533,12 @@ void Key_Message (int key)
return; return;
} }
if (!backend_sends_char_events)
Char_Message (key);
}
void Char_Message (int key)
{
if (key < 32 || key > 127) if (key < 32 || key > 127)
return; // non printable return; // non printable
@ -888,14 +913,9 @@ Key_Event
Called by the system between frames for both key up and key down events Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt! Should NOT be called during an interrupt!
If interpret_shift is true, and the shift key is currently down, handles
mapping to the shifted version of a key following the US keyboard layout
(e.g. '5' -> '%'). We pass false for SDL_TEXTINPUT events; SDL has already
processed the shift mapping for these.
=================== ===================
*/ */
void Key_Event (int key, qboolean down, qboolean interpret_shift) void Key_Event (int key, qboolean down)
{ {
char *kb; char *kb;
char cmd[1024]; char cmd[1024];
@ -1006,7 +1026,7 @@ void Key_Event (int key, qboolean down, qboolean interpret_shift)
if (!down) if (!down)
return; // other systems only care about key down events return; // other systems only care about key down events
if (shift_down && interpret_shift) if (shift_down)
key = keyshift[key]; key = keyshift[key];
switch (key_dest) switch (key_dest)
@ -1027,6 +1047,31 @@ void Key_Event (int key, qboolean down, qboolean interpret_shift)
} }
} }
/*
===================
Char_Event
Called by the backend when the user has input a character, e.g. coming from
the SDL_TEXTINPUT event.
The backend_sends_char_events variable indicates whether the backend calls this
function.
===================
*/
void Char_Event (int key)
{
switch (key_dest)
{
case key_message:
Char_Message (key);
break;
case key_console:
Char_Console (key);
break;
default:
break;
}
}
/* /*
=================== ===================
Key_ClearStates Key_ClearStates
@ -1039,7 +1084,7 @@ void Key_ClearStates (void)
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
if (keydown[i]) if (keydown[i])
Key_Event (i, false, true); Key_Event (i, false);
} }
} }

View file

@ -164,7 +164,8 @@ void Key_Init (void);
void Key_ClearStates (void); void Key_ClearStates (void);
void Key_UpdateForDest (void); void Key_UpdateForDest (void);
void Key_Event (int key, qboolean down, qboolean interpret_shift); void Key_Event (int key, qboolean down);
void Char_Event (int key);
void Key_SetBinding (int keynum, const char *binding); void Key_SetBinding (int keynum, const char *binding);
const char *Key_KeynumToString (int keynum); const char *Key_KeynumToString (int keynum);