From cd3e7845344a413a73d2649e3e99d51f14eb12fb Mon Sep 17 00:00:00 2001 From: ndren Date: Sat, 18 Feb 2023 15:16:17 +0000 Subject: [PATCH] Refactor SDL input code to fix menu exit (#146) --- source/Irrlicht/CIrrDeviceSDL.cpp | 107 ++++++++++++++++++++++++++++-- source/Irrlicht/CIrrDeviceSDL.h | 9 +++ 2 files changed, 109 insertions(+), 7 deletions(-) diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index 83c763c6..23f00d25 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -8,6 +8,8 @@ #include "CIrrDeviceSDL.h" #include "IEventReceiver.h" +#include "IGUIElement.h" +#include "IGUIEnvironment.h" #include "os.h" #include "CTimer.h" #include "irrString.h" @@ -105,6 +107,98 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv } #endif + +bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key) +{ + switch ( key ) + { + // keys which are known to have safe special character interpretation + // could need changes over time (removals and additions!) + case KEY_RETURN: + case KEY_PAUSE: + case KEY_ESCAPE: + case KEY_PRIOR: + case KEY_NEXT: + case KEY_HOME: + case KEY_END: + case KEY_LEFT: + case KEY_UP: + case KEY_RIGHT: + case KEY_DOWN: + case KEY_TAB: + case KEY_PRINT: + case KEY_SNAPSHOT: + case KEY_INSERT: + case KEY_BACK: + case KEY_DELETE: + case KEY_HELP: + case KEY_APPS: + case KEY_SLEEP: + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + case KEY_F11: + case KEY_F12: + case KEY_F13: + case KEY_F14: + case KEY_F15: + case KEY_F16: + case KEY_F17: + case KEY_F18: + case KEY_F19: + case KEY_F20: + case KEY_F21: + case KEY_F22: + case KEY_F23: + case KEY_F24: + case KEY_NUMLOCK: + case KEY_SCROLL: + case KEY_LCONTROL: + case KEY_RCONTROL: + return true; + + default: + return false; + } +} + +int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key) { + // SDL in-place ORs values with no character representation with 1<<30 + // https://wiki.libsdl.org/SDL2/SDLKeycodeLookup + if (assumedChar & (1<<30)) + return 0; + + switch (key) { + case KEY_PRIOR: + case KEY_NEXT: + case KEY_HOME: + case KEY_END: + case KEY_LEFT: + case KEY_UP: + case KEY_RIGHT: + case KEY_DOWN: + case KEY_NUMLOCK: + return 0; + default: + return assumedChar; + } +} + +void CIrrDeviceSDL::resetReceiveTextInputEvents() { + gui::IGUIElement *elem = GUIEnvironment->getFocus(); + if (elem && elem->acceptsIME()) + SDL_StartTextInput(); + else + SDL_StopTextInput(); +} + //! constructor CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) : CIrrDeviceStub(param), @@ -611,6 +705,10 @@ bool CIrrDeviceSDL::run() else key = (EKEY_CODE)KeyMap[idx].Win32Key; + // Make sure to only input special characters if something is in focus, as SDL_TEXTINPUT handles normal unicode already + if (SDL_IsTextInputActive() && !keyIsKnownSpecial(key) && (SDL_event.key.keysym.mod & KMOD_CTRL) == 0) + break; + #ifdef _IRR_WINDOWS_API_ // handle alt+f4 in Windows, because SDL seems not to if ( (SDL_event.key.keysym.mod & KMOD_LALT) && key == KEY_F4) @@ -624,12 +722,7 @@ bool CIrrDeviceSDL::run() irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN); irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0; irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL ) != 0; - // These keys are handled differently in CGUIEditBox.cpp (may become out of date!) - // Control key is used in special character combinations, so keep that too - // Pass through the keysym only then so no extra text gets input - irrevent.KeyInput.Char = 0; - if (mp.SDLKey == SDLK_DELETE || mp.SDLKey == SDLK_RETURN || mp.SDLKey == SDLK_BACKSPACE || irrevent.KeyInput.Control) - irrevent.KeyInput.Char = mp.SDLKey; + irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key); postEventFromUser(irrevent); } break; @@ -663,7 +756,7 @@ bool CIrrDeviceSDL::run() default: break; } // end switch - + resetReceiveTextInputEvents(); } // end while #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) diff --git a/source/Irrlicht/CIrrDeviceSDL.h b/source/Irrlicht/CIrrDeviceSDL.h index 29927182..7657718f 100644 --- a/source/Irrlicht/CIrrDeviceSDL.h +++ b/source/Irrlicht/CIrrDeviceSDL.h @@ -264,6 +264,15 @@ namespace irr static EM_BOOL MouseLeaveCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); #endif + // Check if a key is a known special character with no side effects on text boxes. + static bool keyIsKnownSpecial(EKEY_CODE key); + + // Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0). + static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key); + + // Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus. + void resetReceiveTextInputEvents(); + //! create the driver void createDriver();