Switchable native keyboard input #111

Merged
alufolie91 merged 6 commits from qwerty3 into Saturn-Next 2024-03-17 13:10:34 +01:00
5 changed files with 163 additions and 2 deletions

No files matched your search

+1
View File
@@ -781,6 +781,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_recordmultiplayerdemos);
CV_RegisterVar(&cv_netdemosyncquality);
CV_RegisterVar(&cv_maxdemosize);
CV_RegisterVar(&cv_nativekeyboard);
}
// =========================================================================
+4
View File
@@ -13,6 +13,10 @@
#ifndef __KEYS_H__
#define __KEYS_H__
#include "console.h"
extern consvar_t cv_nativekeyboard;
// These are the key codes as posted by the keyboard handler,
// ascii codes are 0->127,
// scancodes are 0x80 + 0->127
+5 -1
View File
@@ -147,6 +147,8 @@ boolean browselocalskins = false;
boolean menuactive = false;
boolean fromlevelselect = false;
boolean menu_text_input = false;
static INT32 coolalphatimer = 9;
typedef enum
@@ -3514,6 +3516,7 @@ boolean M_Responder(event_t *ev)
// Handle menuitems which need a specific key handling
if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER)
{
menu_text_input = true;
if (shiftdown && ch >= 32 && ch <= 127)
ch = shiftxform[ch];
routine(ch);
@@ -3554,7 +3557,7 @@ boolean M_Responder(event_t *ev)
{
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
{
menu_text_input = true;
if (shiftdown && ch >= 32 && ch <= 127)
ch = shiftxform[ch];
if (M_ChangeStringCvar(ch))
@@ -3749,6 +3752,7 @@ boolean M_Responder(event_t *ev)
case KEY_BACKSPACE:
if ((currentMenu->menuitems[itemOn].status) == IT_CONTROL)
{
menu_text_input = false; //never use native layout for control setup
// detach any keys associated with the game control
G_ClearControlKeys(setupcontrols, currentMenu->menuitems[itemOn].alphaKey);
S_StartSound(NULL, sfx_shldls);
+2
View File
@@ -91,6 +91,8 @@ void M_QuitResponse(INT32 ch);
// Determines whether to show a level in the list
boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
extern boolean menu_text_input;
// flags for items in the menu
// menu handle (what we do when key is pressed
#define IT_TYPE 14 // (2+4+8)
+151 -1
View File
@@ -75,6 +75,7 @@
#include "../command.h"
#include "sdlmain.h"
#include "../i_system.h"
#include "../hu_stuff.h" // for chat_on
#ifdef HWRENDER
#include "../hardware/hw_main.h"
#include "../hardware/hw_drv.h"
@@ -109,6 +110,7 @@ boolean a2c = false;
#endif
boolean highcolor = false;
consvar_t cv_nativekeyboard = {"nativekeyboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static void Impl_SetVsync(void);
@@ -382,6 +384,149 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
return 0;
}
// Get the equivalent ASCII (Unicode?) character for a keypress.
static INT32 GetTypedChar(SDL_Scancode code, SDL_Keysym *sym)
{
SDL_Event next_event;
// Special cases, where we always return a fixed value.
switch (sym->sym)
{
case SDLK_BACKSPACE: return KEY_BACKSPACE;
case SDLK_RETURN: return KEY_ENTER;
default:
break;
}
// The following is a gross hack, but I don't see an easier way
// of doing this within the SDL2 API (in SDL1 it was easier).
// We want to get the fully transformed input character associated
// with this keypress - correct keyboard layout, appropriately
// transformed by any modifier keys, etc. So peek ahead in the SDL
// event queue and see if the key press is immediately followed by
// an SDL_TEXTINPUT event. If it is, it's reasonable to assume the
// key press and the text input are connected. Technically the SDL
// API does not guarantee anything of the sort, but in practice this
// is what happens and I've verified it through manual inspect of
// the SDL source code.
//
// In an ideal world we'd split out ev_keydown into a separate
// ev_textinput event, as SDL2 has done. But this doesn't work
// (I experimented with the idea), because lots of Doom's code is
// based around different responders "eating" events to stop them
// being passed on to another responder. If code is listening for
// a text input, it cannot block the corresponding keydown events
// which can affect other responders.
//
// So we're stuck with this as a rather fragile alternative.
if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT,
SDL_FIRSTEVENT, SDL_LASTEVENT) == 1
&& next_event.type == SDL_TEXTINPUT)
{
// If an SDL_TEXTINPUT event is found, we always assume it
// matches the key press. The input text must be a single
// ASCII character - if it isn't, it's possible the input
// char is a Unicode value instead; better to send a null
// character than the unshifted key.
if (strlen(next_event.text.text) == 1 &&
(next_event.text.text[0] >= ' ' && next_event.text.text[0] <= '~')) {
return next_event.text.text[0];
} else {
return '\0';
}
}
if (code >= SDL_SCANCODE_1 && code <= SDL_SCANCODE_9)
{
return code - SDL_SCANCODE_1 + '1';
}
else if (code == SDL_SCANCODE_0)
{
return '0';
}
if (code >= SDL_SCANCODE_F1 && code <= SDL_SCANCODE_F10)
{
return KEY_F1 + (code - SDL_SCANCODE_F1);
}
switch (code)
{
// F11 and F12 are separated from the rest of the function keys
case SDL_SCANCODE_F11: return KEY_F11;
case SDL_SCANCODE_F12: return KEY_F12;
case SDL_SCANCODE_KP_0: return KEY_KEYPAD0;
case SDL_SCANCODE_KP_1: return KEY_KEYPAD1;
case SDL_SCANCODE_KP_2: return KEY_KEYPAD2;
case SDL_SCANCODE_KP_3: return KEY_KEYPAD3;
case SDL_SCANCODE_KP_4: return KEY_KEYPAD4;
case SDL_SCANCODE_KP_5: return KEY_KEYPAD5;
case SDL_SCANCODE_KP_6: return KEY_KEYPAD6;
case SDL_SCANCODE_KP_7: return KEY_KEYPAD7;
case SDL_SCANCODE_KP_8: return KEY_KEYPAD8;
case SDL_SCANCODE_KP_9: return KEY_KEYPAD9;
case SDL_SCANCODE_RETURN: return KEY_ENTER;
case SDL_SCANCODE_ESCAPE: return KEY_ESCAPE;
case SDL_SCANCODE_BACKSPACE: return KEY_BACKSPACE;
case SDL_SCANCODE_TAB: return KEY_TAB;
case SDL_SCANCODE_SPACE: return KEY_SPACE;
case SDL_SCANCODE_MINUS: return KEY_MINUS;
case SDL_SCANCODE_EQUALS: return KEY_EQUALS;
case SDL_SCANCODE_LEFTBRACKET: return '[';
case SDL_SCANCODE_RIGHTBRACKET: return ']';
case SDL_SCANCODE_BACKSLASH: return '\\';
case SDL_SCANCODE_NONUSHASH: return '#';
case SDL_SCANCODE_SEMICOLON: return ';';
case SDL_SCANCODE_APOSTROPHE: return '\'';
case SDL_SCANCODE_GRAVE: return '`';
case SDL_SCANCODE_COMMA: return ',';
case SDL_SCANCODE_PERIOD: return '.';
case SDL_SCANCODE_SLASH: return '/';
case SDL_SCANCODE_CAPSLOCK: return KEY_CAPSLOCK;
case SDL_SCANCODE_PRINTSCREEN: return 0; // undefined?
case SDL_SCANCODE_SCROLLLOCK: return KEY_SCROLLLOCK;
case SDL_SCANCODE_PAUSE: return KEY_PAUSE;
case SDL_SCANCODE_INSERT: return KEY_INS;
case SDL_SCANCODE_HOME: return KEY_HOME;
case SDL_SCANCODE_PAGEUP: return KEY_PGUP;
case SDL_SCANCODE_DELETE: return KEY_DEL;
case SDL_SCANCODE_END: return KEY_END;
case SDL_SCANCODE_PAGEDOWN: return KEY_PGDN;
case SDL_SCANCODE_RIGHT: return KEY_RIGHTARROW;
case SDL_SCANCODE_LEFT: return KEY_LEFTARROW;
case SDL_SCANCODE_DOWN: return KEY_DOWNARROW;
case SDL_SCANCODE_UP: return KEY_UPARROW;
case SDL_SCANCODE_NUMLOCKCLEAR: return KEY_NUMLOCK;
case SDL_SCANCODE_KP_DIVIDE: return KEY_KPADSLASH;
case SDL_SCANCODE_KP_MULTIPLY: return '*'; // undefined?
case SDL_SCANCODE_KP_MINUS: return KEY_MINUSPAD;
case SDL_SCANCODE_KP_PLUS: return KEY_PLUSPAD;
case SDL_SCANCODE_KP_ENTER: return KEY_ENTER;
case SDL_SCANCODE_KP_PERIOD: return KEY_KPADDEL;
case SDL_SCANCODE_NONUSBACKSLASH: return '\\';
case SDL_SCANCODE_LSHIFT: return KEY_LSHIFT;
case SDL_SCANCODE_RSHIFT: return KEY_RSHIFT;
case SDL_SCANCODE_LCTRL: return KEY_LCTRL;
case SDL_SCANCODE_RCTRL: return KEY_RCTRL;
case SDL_SCANCODE_LALT: return KEY_LALT;
case SDL_SCANCODE_RALT: return KEY_RALT;
case SDL_SCANCODE_LGUI: return KEY_LEFTWIN;
case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN;
default: break;
}
if (code >= SDL_SCANCODE_A && code <= SDL_SCANCODE_Z)
{
// get lowercase ASCII
return code - SDL_SCANCODE_A + 'a';
}
return 0;
}
static void SDLdoGrabMouse(void)
{
SDL_ShowCursor(SDL_DISABLE);
@@ -696,7 +841,12 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
{
return;
}
event.data1 = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
if (cv_nativekeyboard.value && (chat_on || CON_Ready() || (menu_text_input && menuactive))) //only use this this if on chat or console or the current menu wants inputs from us (except if its the control setup menu ig)
event.data1 = GetTypedChar(evt.keysym.scancode, &evt.keysym);
else
event.data1 = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
if (event.data1) D_PostEvent(&event);
}