Browse Source

fix SDL text events from generating a ~ key when opening the console

Jeff Hutchinson 8 years ago
parent
commit
f6b8ef126d

+ 5 - 3
Engine/source/windowManager/sdl/sdlWindow.cpp

@@ -607,8 +607,10 @@ const UTF16 *PlatformWindowSDL::getCurtainWindowClassName()
 void PlatformWindowSDL::setKeyboardTranslation(const bool enabled)
 {
    mEnableKeyboardTranslation = enabled;
-   if (mEnableKeyboardTranslation)
-      SDL_StartTextInput();
+
+   // Flag for update. Let SDL know what kind of input state we are changing to.
+   if (enabled)
+      mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::TEXT_INPUT);
    else
-      SDL_StopTextInput();
+      mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::RAW_INPUT);
 }

+ 27 - 0
Engine/source/windowManager/sdl/sdlWindowMgr.cpp

@@ -59,6 +59,8 @@ PlatformWindowManagerSDL::PlatformWindowManagerSDL()
    mDisplayWindow = true;
    mOffscreenRender = false;
 
+   mInputState = KeyboardInputState::NONE;
+
    buildMonitorsList();
 }
 
@@ -262,6 +264,21 @@ void PlatformWindowManagerSDL::_process()
       }
    }
 
+   // After the event loop is processed, we can now see if we have to notify
+   // SDL that we want text based events. This fixes a bug where text based
+   // events would be generated while key presses would still be happening.
+   // See KeyboardInputState for further documentation.
+   if (mInputState != KeyboardInputState::NONE)
+   {
+      // Update text mode toggling.
+      if (mInputState == KeyboardInputState::TEXT_INPUT)
+         SDL_StartTextInput();
+      else
+         SDL_StopTextInput();
+
+      // Done until we need to update it again.
+      mInputState = KeyboardInputState::NONE;
+   }
 }
 
 PlatformWindow * PlatformWindowManagerSDL::getWindowById( WindowId id )
@@ -343,6 +360,12 @@ void PlatformWindowManagerSDL::raiseCurtain()
    // TODO SDL
 }
 
+void PlatformWindowManagerSDL::updateSDLTextInputState(KeyboardInputState state)
+{
+   // Force update state. This will respond at the end of the event loop.
+   mInputState = state;
+}
+
 void Platform::openFolder(const char* path )
 {
     AssertFatal(0, "Not Implemented");
@@ -369,4 +392,8 @@ AFTER_MODULE_INIT(gfx)
 {   
    int res = SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE );
    AssertFatal(res != -1, "SDL init error");
+
+   // By default, SDL enables text input. We disable it on initialization, and
+   // we will enable it whenever the time is right.
+   SDL_StopTextInput();
 }

+ 34 - 0
Engine/source/windowManager/sdl/sdlWindowMgr.h

@@ -34,6 +34,30 @@ class FileDialog; // TODO SDL REMOVE
 /// SDL2 implementation of the window manager interface.
 class PlatformWindowManagerSDL : public PlatformWindowManager
 {
+public:
+   /// An enum that holds an event loop frame of the state of the
+   /// keyboard for how the keyboard is interpreted inside of Torque.
+   ///
+   /// SDL has a concept of text editing events as well as raw input
+   /// events. Because of this, SDL needs notified whenever it needs
+   /// to fire text based events. SDL will continue firing raw input
+   /// events as well during this time.
+   ///
+   /// The reason why this was created is because we needed time to
+   /// transition between raw input to raw input + text based events.
+   /// If we take a raw input and notify SDL we wanted text during the
+   /// event loop, SDL will issue a text input event as well. This was
+   /// causing issues with the console, where the console key would be
+   /// appended to the console buffer upon opening it. We fix this by
+   /// delaying the notification to SDL until the event loop is complete.
+   enum class KeyboardInputState
+   {
+      NONE = 0,       /// < No state change during this event loop cycle.
+      TEXT_INPUT = 1, /// < We want to change to text based events & raw input.
+      RAW_INPUT = 2   /// < We only want raw input.
+   };
+
+protected:
    friend class PlatformWindowSDL;
    friend class FileDialog; // TODO SDL REMOVE
 
@@ -69,6 +93,10 @@ class PlatformWindowManagerSDL : public PlatformWindowManager
 
    SignalSlot<void()> mOnProcessSignalSlot;
 
+   /// The input state that will change whenever SDL needs notified.
+   /// After it is handled, it will return to state NONE.
+   KeyboardInputState mInputState;
+
 public:
    PlatformWindowManagerSDL();
    ~PlatformWindowManagerSDL();
@@ -100,6 +128,12 @@ public:
    virtual void raiseCurtain();
 
    virtual void setDisplayWindow(bool set) { mDisplayWindow = set; }
+
+   /// Stores the input state so that the event loop will fire a check if we need
+   /// to change how keyboard input is being handled.
+   /// @param state The state of the keyboard input, either being raw input or text
+   ///  based input.
+   void updateSDLTextInputState(KeyboardInputState state);
 };
 
 #endif