diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 018f51feb8..d4b06b2ab6 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -10,6 +10,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/inputmanager.hpp" namespace MWGui { @@ -126,7 +127,7 @@ namespace MWGui // always update input before rendering something, otherwise mygui goes crazy when something was entered in the frame before // (e.g. when using "coc" console command, it would enter an infinite loop and crash due to overflow) - //MWBase::Environment::get().getInputManager()->update(0, true); + MWBase::Environment::get().getInputManager()->update(0, true); Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0)); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index f53508f86d..2fd8b40853 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -23,6 +23,65 @@ using namespace ICS; +namespace +{ + std::vector utf8ToUnicode(const std::string& utf8) + { + std::vector unicode; + size_t i = 0; + while (i < utf8.size()) + { + unsigned long uni; + size_t todo; + unsigned char ch = utf8[i++]; + if (ch <= 0x7F) + { + uni = ch; + todo = 0; + } + else if (ch <= 0xBF) + { + throw std::logic_error("not a UTF-8 string"); + } + else if (ch <= 0xDF) + { + uni = ch&0x1F; + todo = 1; + } + else if (ch <= 0xEF) + { + uni = ch&0x0F; + todo = 2; + } + else if (ch <= 0xF7) + { + uni = ch&0x07; + todo = 3; + } + else + { + throw std::logic_error("not a UTF-8 string"); + } + for (size_t j = 0; j < todo; ++j) + { + if (i == utf8.size()) + throw std::logic_error("not a UTF-8 string"); + unsigned char ch = utf8[i++]; + if (ch < 0x80 || ch > 0xBF) + throw std::logic_error("not a UTF-8 string"); + uni <<= 6; + uni += ch & 0x3F; + } + if (uni >= 0xD800 && uni <= 0xDFFF) + throw std::logic_error("not a UTF-8 string"); + if (uni > 0x10FFFF) + throw std::logic_error("not a UTF-8 string"); + unicode.push_back(uni); + } + return unicode; + } +} + namespace MWInput { InputManager::InputManager(OEngine::Render::OgreRenderer &ogre, @@ -422,11 +481,19 @@ namespace MWInput OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); - MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), text); - + if (kc != OIS::KC_UNASSIGNED) + MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); return true; } + void InputManager::textInput(const SDL_TextInputEvent &arg) + { + const char* text = &arg.text[0]; + std::vector unicode = utf8ToUnicode(std::string(text)); + for (std::vector::iterator it = unicode.begin(); it != unicode.end(); ++it) + MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::None, *it); + } + bool InputManager::keyReleased(const SDL_KeyboardEvent &arg ) { mInputBinder->keyReleased (arg); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 57c367bde9..788f116acd 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -88,6 +88,7 @@ namespace MWInput public: virtual bool keyPressed(const SDL_KeyboardEvent &arg ); virtual bool keyReleased( const SDL_KeyboardEvent &arg ); + virtual void textInput (const SDL_TextInputEvent &arg); virtual bool mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ); virtual bool mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ); diff --git a/extern/sdl4ogre/events.h b/extern/sdl4ogre/events.h index 5a0146635f..13f8b31011 100644 --- a/extern/sdl4ogre/events.h +++ b/extern/sdl4ogre/events.h @@ -35,6 +35,7 @@ class KeyListener { public: virtual ~KeyListener() {} + virtual void textInput (const SDL_TextInputEvent& arg) {} virtual bool keyPressed(const SDL_KeyboardEvent &arg) = 0; virtual bool keyReleased(const SDL_KeyboardEvent &arg) = 0; }; diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index a6d4640274..5c1df52c60 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -67,12 +67,15 @@ namespace SFO break; case SDL_KEYDOWN: if (!evt.key.repeat) - _handleKeyPress(evt.key); + mKeyboardListener->keyPressed(evt.key); break; case SDL_KEYUP: if (!evt.key.repeat) mKeyboardListener->keyReleased(evt.key); break; + case SDL_TEXTINPUT: + mKeyboardListener->textInput(evt.text); + break; case SDL_WINDOWEVENT: handleWindowEvent(evt); break; @@ -220,74 +223,6 @@ namespace SFO return pack_evt; } - void InputWrapper::_handleKeyPress(SDL_KeyboardEvent &evt) - { - //SDL keyboard events are followed by the actual text those keys would generate - //to account for languages that require multiple keystrokes to produce a key. - //Look for an event immediately following ours, assuming each key produces exactly - //one character or none at all. - - //TODO: Check if this works properly for multibyte symbols - //do we have to worry about endian-ness? - //for that matter, check if we even need to do any of this. - - SDL_Event text_evts[1]; - if(SDL_PeepEvents(text_evts, 1, SDL_GETEVENT, SDL_TEXTINPUT, SDL_TEXTINPUT) != 0) - { - if(strlen(text_evts[0].text.text) != 0) - { - const unsigned char* symbol = reinterpret_cast(&(text_evts[0].text.text[0])); - evt.keysym.unicode = _UTF8ToUTF32(symbol); - } - } - - mKeyboardListener->keyPressed(evt); - } - - //Lifted from OIS' LinuxKeyboard.cpp - Uint32 InputWrapper::_UTF8ToUTF32(const unsigned char *buf) - { - unsigned char FirstChar = buf[0]; - - //it's an ascii char, bail out early. - if(FirstChar < 128) - return FirstChar; - - Uint32 val = 0; - Sint32 len = 0; - - if((FirstChar & 0xE0) == 0xC0) //2 Chars - { - len = 2; - val = FirstChar & 0x1F; - } - else if((FirstChar & 0xF0) == 0xE0) //3 Chars - { - len = 3; - val = FirstChar & 0x0F; - } - else if((FirstChar & 0xF8) == 0xF0) //4 Chars - { - len = 4; - val = FirstChar & 0x07; - } - else if((FirstChar & 0xFC) == 0xF8) //5 Chars - { - len = 5; - val = FirstChar & 0x03; - } - else // if((FirstChar & 0xFE) == 0xFC) //6 Chars - { - len = 6; - val = FirstChar & 0x01; - } - - for(int i = 1; i < len; i++) - val = (val << 6) | (buf[i] & 0x3F); - - return val; - } - OIS::KeyCode InputWrapper::sdl2OISKeyCode(SDL_Keycode code) { OIS::KeyCode kc = OIS::KC_UNASSIGNED; @@ -296,8 +231,6 @@ namespace SFO if(ois_equiv != mKeyMap.end()) kc = ois_equiv->second; - else - std::cerr << "Couldn't find OIS key for " << code << std::endl; return kc; } diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index cb9804d548..08b329925f 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -42,8 +42,6 @@ namespace SFO void _wrapMousePointer(const SDL_MouseMotionEvent &evt); MouseMotionEvent _packageMouseMotion(const SDL_Event& evt); - void _handleKeyPress(SDL_KeyboardEvent& evt); - Uint32 _UTF8ToUTF32(const unsigned char *buf); void _setupOISKeys(); SFO::MouseListener* mMouseListener;