Redo keyboardlayout

Based on this commit from Saturn: 423ca0eca0
This commit is contained in:
NepDisk 2026-02-20 16:30:29 -05:00
parent 516a05c4bf
commit 085ffd8185
6 changed files with 177 additions and 42 deletions

View file

@ -727,6 +727,8 @@ void CON_ToggleOff(void)
I_UpdateMouseGrab();
I_SetTextInput(false);
Unlock_state();
}
@ -767,17 +769,24 @@ void CON_Ticker(void)
con_destlines = 0;
CON_ClearHUD();
I_UpdateMouseGrab();
I_SetTextInput(false);
}
else
{
CON_ChangeHeight();
I_SetTextInput(true);
}
}
// check if console ready for prompt
if (con_destlines >= minheight)
{
consoleready = true;
}
else
{
consoleready = false;
}
// make overlay messages disappear after a while
for (i = 0; i < con_hudlines; i++)
{

View file

@ -1155,6 +1155,7 @@ void HU_clearChatChars(void)
chat_on = false;
I_UpdateMouseGrab();
I_SetTextInput(false);
}
//
@ -1200,6 +1201,7 @@ boolean HU_Responder(event_t *ev)
teamtalk = false;
chat_scrollmedown = true;
typelines = 1;
I_SetTextInput(true);
return true;
}
if (G_ControlBoundToKey(0, gc_teamkey, ev->data1, false)
@ -1212,6 +1214,7 @@ boolean HU_Responder(event_t *ev)
teamtalk = G_GametypeHasTeams(); // Don't teamtalk if we don't have teams.
chat_scrollmedown = true;
typelines = 1;
I_SetTextInput(true);
return true;
}
}
@ -1241,6 +1244,7 @@ boolean HU_Responder(event_t *ev)
chat_on = false;
chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :)
I_SetTextInput(false);
I_UpdateMouseGrab();
}
else if (c == KEY_ESCAPE
@ -1249,6 +1253,7 @@ boolean HU_Responder(event_t *ev)
&& c >= NUMKEYS)) // If it's not a keyboard key, then the chat button is used as a toggle.
{
chat_on = false;
I_SetTextInput(false);
I_UpdateMouseGrab();
}
else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0 && !OLDCHAT) // CHAT SCROLLING YAYS!

View file

@ -20,6 +20,9 @@
extern "C" {
#endif
boolean I_UseNativeKeyboard(void);
void I_SetTextInput(boolean enable);
typedef enum
{
/// Software
@ -153,8 +156,6 @@ void I_EndRead(void);
UINT32 I_GetRefreshRate(void);
boolean I_UseNativeKeyboard(void);
extern consvar_t cv_keyboardlayout;
void I_SetBorderlessWindow(void);

View file

@ -30,6 +30,14 @@ extern "C" {
#define KEY_MINUS 45
#define KEY_EQUALS 61
//azerty special keys support
//(necessary for being able to print 'regular' chars in azerty)
#define KEY_FR_E_AIGUE (0x80+2)
#define KEY_FR_E_GRAVE (0x80+10)
#define KEY_FR_C_CEDILLE (0x80+7)
#define KEY_FR_A_GRAVE (0x80+5)
#define KEY_FR_U_GRAVE (0x80+13)
#define KEY_NUMLOCK (0x80+69)
#define KEY_SCROLLLOCK (0x80+70)

View file

@ -147,7 +147,6 @@ const char *quitmsg[NUM_QUITMESSAGES];
boolean fromlevelselect = false;
boolean menu_text_input = false;
static char menu_text_input_buf[MAXSTRINGLENGTH];
static textinput_t menuinput;
@ -363,6 +362,11 @@ static void M_RawSetItemOn(menu_t *menu, INT16 index)
{
M_TextInputInit(&menuinput, menu_text_input_buf, M_StringCvarLength(cv));
M_TextInputSetString(&menuinput, cv->string);
I_SetTextInput(true);
}
else
{
I_SetTextInput(false);
}
}
@ -1970,6 +1974,8 @@ void M_StartControlPanel(void)
//
void M_ClearMenus(boolean callexitmenufunc)
{
I_SetTextInput(false);
if (currentMenu)
{
if (currentMenu->quitroutine && callexitmenufunc)
@ -1991,7 +1997,6 @@ void M_ClearMenus(boolean callexitmenufunc)
currentMenu = NULL;
messagebox.active = false;
hidetitlemap = false;
menu_text_input = false;
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
if (gamestate == GS_TIMEATTACK)
@ -2161,7 +2166,6 @@ void M_EnterMenu(menutype_t menunum, boolean callexit, INT32 arg)
if (menustack[0] == MN_NONE)
menustack[0] = menunum; // M_ClearMenus got called, put it back on the stack
menu_text_input = true;
M_SetupNextMenu(menunum, callexit);
}

View file

@ -87,12 +87,7 @@
rendermode_t rendermode = render_soft;
rendermode_t chosenrendermode = render_none; // set by command line arguments
boolean I_UseNativeKeyboard(void)
{
return cv_keyboardlayout.value == 2 && (chat_on || CON_Ready() || (menu_text_input && menustack[0]));
}
static CV_PossibleValue_t keyboardlayout_cons_t[] = {{1,"Default US"}, {2, "Native"}, {0, NULL}};
static CV_PossibleValue_t keyboardlayout_cons_t[] = {{1,"Default US"}, {2, "Native"}, {3, "AZERTY"}, {0, NULL}};
consvar_t cv_keyboardlayout = CVAR_INIT ("keyboardlayout", "Default US", CV_SAVE, keyboardlayout_cons_t, NULL);
boolean highcolor = false;
@ -464,35 +459,6 @@ 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_KeyboardEvent *evt)
{
SDL_Event next_event;
SDL_Keycode keycode = evt->key;
SDL_Scancode scancode = evt->scancode;
const boolean Text_Input_Only = (chat_on || CON_Ready() || (menu_text_input && menustack[0])); // 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)
// Special cases, where we always return a fixed value.
switch (keycode)
{
case SDLK_BACKSPACE: return KEY_BACKSPACE;
case SDLK_RETURN: return KEY_ENTER;
default:
break;
}
if (Text_Input_Only)
{
if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) == 1 && next_event.type == SDL_EVENT_TEXT_INPUT)
{
if (next_event.text.text[1] == '\0') // limit to ASCII
return next_event.text.text[0];
}
}
return Impl_SDL_Scancode_To_Keycode(scancode); // fallback
}
static boolean IgnoreMouse(void)
{
if (cv_alwaysgrabmouse.value)
@ -677,6 +643,145 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
}
}
static INT32 Impl_SDL_Keysym_To_Keycode(SDL_KeyboardEvent evt)
{
SDL_Keycode keycode = evt.key;
SDL_Scancode scancode = evt.scancode;
if (keycode >= SDLK_A && keycode <= SDLK_Z)
{
// get lowercase ASCII
return keycode;
}
if (keycode >= SDLK_F1 && keycode <= SDLK_F10)
{
return KEY_F1 + (keycode - SDLK_F1);
}
switch (scancode)
{
case SDL_SCANCODE_APOSTROPHE: return KEY_FR_U_GRAVE;
case SDL_SCANCODE_LEFTBRACKET: return '^';
default: break;
}
switch (keycode)
{
// F11 and F12 are separated from the rest of the function keys
case SDLK_F11: return KEY_F11;
case SDLK_F12: return KEY_F12;
case SDLK_RETURN: return KEY_ENTER;
case SDLK_ESCAPE: return KEY_ESCAPE;
case SDLK_BACKSPACE: return KEY_BACKSPACE;
case SDLK_TAB: return KEY_TAB;
case SDLK_SPACE: return KEY_SPACE;
case SDLK_EQUALS: return KEY_EQUALS;
case SDLK_SEMICOLON: return ';';
case SDLK_COMMA: return ',';
case SDLK_COLON: return ':';
case SDLK_EXCLAIM: return '!';
case SDLK_DOLLAR: return '$';
case SDLK_ASTERISK: return '*';
case SDLK_PERCENT: return '%';
case SDLK_0: return KEY_FR_A_GRAVE;
case SDLK_1:
case SDLK_AMPERSAND: return '&';
case SDLK_2: return KEY_FR_E_AIGUE;
case SDLK_3:
case SDLK_DBLAPOSTROPHE: return '"';
case SDLK_4: return '\'';
case SDLK_5:
case SDLK_LEFTPAREN: return '(';
case SDLK_6:
case SDLK_MINUS: return KEY_MINUS;
case SDLK_7: return KEY_FR_E_GRAVE;
case SDLK_8:
case SDLK_UNDERSCORE: return '_';
case SDLK_9: return KEY_FR_C_CEDILLE;
case SDLK_RIGHTPAREN: return ')';
case SDLK_SLASH: return '/';
case SDLK_LESS: return '<';
case SDLK_KP_0: return KEY_KEYPAD0;
case SDLK_KP_1: return KEY_KEYPAD1;
case SDLK_KP_2: return KEY_KEYPAD2;
case SDLK_KP_3: return KEY_KEYPAD3;
case SDLK_KP_4: return KEY_KEYPAD4;
case SDLK_KP_5: return KEY_KEYPAD5;
case SDLK_KP_6: return KEY_KEYPAD6;
case SDLK_KP_7: return KEY_KEYPAD7;
case SDLK_KP_8: return KEY_KEYPAD8;
case SDLK_KP_9: return KEY_KEYPAD9;
default: break;
}
return Impl_SDL_Scancode_To_Keycode(scancode);
}
static boolean native_input_active = false;
// used to supress the games shift/alt handling
boolean I_UseNativeKeyboard(void)
{
return (cv_keyboardlayout.value == 2 && native_input_active);
}
void I_SetTextInput(boolean enable)
{
if (!window)
return;
if (enable && !native_input_active)
{
SDL_StartTextInput(window);
native_input_active = true;
}
else if (!enable && native_input_active)
{
SDL_StopTextInput(window);
native_input_active = false;
}
}
// Get the equivalent ASCII (Unicode?) character for a keypress.
static INT32 GetTypedChar(SDL_KeyboardEvent evt)
{
SDL_Event next_event;
SDL_Keycode keycode = evt.key;
SDL_Scancode scancode = evt.scancode;
// 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)
if (native_input_active)
{
// Special cases, where we always return a fixed value.
switch (keycode)
{
case SDLK_BACKSPACE: return KEY_BACKSPACE;
case SDLK_RETURN: return KEY_ENTER;
default:
break;
}
// Special case for console key
if (scancode == SDL_SCANCODE_GRAVE)
return '`';
if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) == 1 && next_event.type == SDL_EVENT_TEXT_INPUT)
{
if (next_event.text.text[1] == '\0') // limit to ASCII
{
return next_event.text.text[0];
}
}
}
// otherwise fallback to scancodes
return Impl_SDL_Scancode_To_Keycode(scancode);
}
static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
{
event_t event;
@ -699,7 +804,10 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
switch (cv_keyboardlayout.value)
{
case 2: // "native"
event.data1 = GetTypedChar(&evt);
event.data1 = GetTypedChar(evt);
break;
case 3: // AZERTY
event.data1 = Impl_SDL_Keysym_To_Keycode(evt);
break;
default:
event.data1 = Impl_SDL_Scancode_To_Keycode(evt.scancode);