From e965414d34b7c51196bafbe5f45983d6c3a8ffc8 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Fri, 25 Sep 2015 19:49:50 +0200 Subject: [PATCH] Rewritten text input to SDL2 --- src/app/app.cpp | 43 +++++++++++++++++++++++++++++++++++----- src/app/app.h | 11 +++++++--- src/common/event.cpp | 2 ++ src/common/event.h | 23 +++++++++++++++++---- src/ui/controls/edit.cpp | 30 ++++++++++++++++++++-------- src/ui/controls/edit.h | 2 ++ 6 files changed, 91 insertions(+), 20 deletions(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index 19b7fe73..c57b6824 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -97,6 +97,7 @@ struct ApplicationPrivate SDL_memset(¤tEvent, 0, sizeof(SDL_Event)); SDL_memset(&lastMouseMotionEvent, 0, sizeof(SDL_Event)); window = nullptr; + glcontext = nullptr; joystick = nullptr; joystickTimer = 0; } @@ -1038,7 +1039,6 @@ Event CApplication::ProcessSystemEvent() data->virt = false; data->key = m_private->currentEvent.key.keysym.sym; - data->unicode = m_private->currentEvent.key.keysym.sym; // TODO: use SDL_TEXTINPUT for this, and remove this field event.kmodState = m_private->currentEvent.key.keysym.mod; // Some keyboards return numerical enter keycode instead of normal enter @@ -1055,6 +1055,13 @@ Event CApplication::ProcessSystemEvent() event.data = std::move(data); } + else if (m_private->currentEvent.type == SDL_TEXTINPUT) + { + event.type = EVENT_TEXT_INPUT; + auto data = MakeUnique(); + data->text = m_private->currentEvent.text.text; + event.data = std::move(data); + } else if (m_private->currentEvent.type == SDL_MOUSEWHEEL) { event.type = EVENT_MOUSE_WHEEL; @@ -1127,11 +1134,17 @@ void CApplication::LogEvent(const Event &event) }; // Print the events in debug mode to test the code - if (IsDebugModeActive(DEBUG_SYS_EVENTS) || IsDebugModeActive(DEBUG_APP_EVENTS)) + if (IsDebugModeActive(DEBUG_SYS_EVENTS) || IsDebugModeActive(DEBUG_UPDATE_EVENTS) || IsDebugModeActive(DEBUG_APP_EVENTS)) { std::string eventType = ParseEventType(event.type); - if (IsDebugModeActive(DEBUG_SYS_EVENTS) && event.type <= EVENT_SYS_MAX) + if (IsDebugModeActive(DEBUG_UPDATE_EVENTS) && event.type == EVENT_FRAME) + { + l->Trace("Update event: %s\n", eventType.c_str()); + PrintEventDetails(); + } + + if (IsDebugModeActive(DEBUG_SYS_EVENTS) && (event.type <= EVENT_SYS_MAX && event.type != EVENT_FRAME)) { l->Trace("System event %s:\n", eventType.c_str()); switch (event.type) @@ -1142,7 +1155,12 @@ void CApplication::LogEvent(const Event &event) auto data = event.GetData(); l->Trace(" virt = %s\n", data->virt ? "true" : "false"); l->Trace(" key = %d\n", data->key); - l->Trace(" unicode = 0x%04x\n", data->unicode); + break; + } + case EVENT_TEXT_INPUT: + { + auto data = event.GetData(); + l->Trace(" text = %s\n", data->text.c_str()); break; } case EVENT_MOUSE_BUTTON_DOWN: @@ -1231,7 +1249,6 @@ Event CApplication::CreateVirtualEvent(const Event& sourceEvent) auto data = MakeUnique(); data->virt = true; data->key = VIRTUAL_JOY(sourceData->button); - data->unicode = 0; virtualEvent.data = std::move(data); } else @@ -1431,6 +1448,10 @@ bool CApplication::ParseDebugModes(const std::string& str, int& debugModes) { debugModes |= DEBUG_SYS_EVENTS; } + else if (modeToken == "update_events") + { + debugModes |= DEBUG_UPDATE_EVENTS; + } else if (modeToken == "app_events") { debugModes |= DEBUG_APP_EVENTS; @@ -1758,3 +1779,15 @@ bool CApplication::GetSceneTestMode() { return m_sceneTest; } + +void CApplication::SetTextInput(bool textInputEnabled) +{ + if (textInputEnabled) + { + SDL_StartTextInput(); + } + else + { + SDL_StopTextInput(); + } +} diff --git a/src/app/app.h b/src/app/app.h index ef737b4e..e8294813 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -125,9 +125,10 @@ enum PerformanceCounter enum DebugMode { DEBUG_SYS_EVENTS = 1 << 0, - DEBUG_APP_EVENTS = 1 << 1, - DEBUG_EVENTS = DEBUG_SYS_EVENTS | DEBUG_APP_EVENTS, - DEBUG_MODELS = 1 << 2, + DEBUG_UPDATE_EVENTS = 1 << 1, + DEBUG_APP_EVENTS = 1 << 2, + DEBUG_EVENTS = DEBUG_SYS_EVENTS | DEBUG_UPDATE_EVENTS | DEBUG_APP_EVENTS, + DEBUG_MODELS = 1 << 3, DEBUG_ALL = DEBUG_SYS_EVENTS | DEBUG_APP_EVENTS | DEBUG_MODELS }; @@ -270,6 +271,10 @@ public: MouseMode GetMouseMode() const; //@} + //! Enable/disable text input, this toggles the on-screen keyboard on some platforms + /** This also allows for writing in CJK languages (not tested!), see https://wiki.libsdl.org/Tutorials/TextInput for detailed explanation */ + void SetTextInput(bool textInputEnabled); + //! Moves (warps) the mouse cursor to the specified position (in interface coords) void MoveMouse(Math::Point pos); diff --git a/src/common/event.cpp b/src/common/event.cpp index 9bd0cff9..de326bb2 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -57,6 +57,8 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_ACTIVE] = "EVENT_ACTIVE"; + EVENT_TYPE_TEXT[EVENT_TEXT_INPUT] = "EVENT_TEXT_INPUT"; + EVENT_TYPE_TEXT[EVENT_JOY_AXIS] = "EVENT_JOY_AXIS"; EVENT_TYPE_TEXT[EVENT_JOY_BUTTON_DOWN] = "EVENT_JOY_BUTTON_DOWN"; EVENT_TYPE_TEXT[EVENT_JOY_BUTTON_UP] = "EVENT_JOY_BUTTON_UP"; diff --git a/src/common/event.h b/src/common/event.h index a905833e..d7230b07 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -70,6 +70,9 @@ enum EventType //! Event sent when application window loses/gains focus EVENT_ACTIVE = 10, + //! Event sent when user inputs some character + EVENT_TEXT_INPUT = 11, + //! Event sent after moving joystick axes EVENT_JOY_AXIS = 12, //! Event sent after pressing a joystick button @@ -569,13 +572,25 @@ struct KeyEventData : public EventData bool virt = false; //! Key symbol: KEY(...) macro value or virtual key VIRTUAL_... (from common/key.h) unsigned int key = 0; - //! Unicode character - //! NOTE: applicable only to EVENT_KEY_DOWN events! - unsigned int unicode = 0; //! Input binding slot for this key - InputSlot slot = INPUT_SLOT_LEFT; + InputSlot slot = INPUT_SLOT_MAX; }; +/** + * \struct TextInputData + * \brief Additional data for text input event + */ + struct TextInputData : public EventData + { + std::unique_ptr Clone() const override + { + return MakeUnique(*this); + } + + //! Text entered by the user (usually one character, UTF-8 encoded) + std::string text = ""; + }; + /** * \enum MouseButton * \brief Mouse button diff --git a/src/ui/controls/edit.cpp b/src/ui/controls/edit.cpp index 07af407b..a5535757 100644 --- a/src/ui/controls/edit.cpp +++ b/src/ui/controls/edit.cpp @@ -143,6 +143,11 @@ CEdit::CEdit() CEdit::~CEdit() { FreeImage(); + + if (m_bFocus) + { + CApplication::GetInstancePointer()->SetTextInput(false); + } } @@ -473,15 +478,12 @@ bool CEdit::EventProcess(const Event &event) } } - if ( event.type == EVENT_KEY_DOWN && !bControl && m_bFocus ) + if ( event.type == EVENT_TEXT_INPUT && !bControl && m_bFocus ) { - auto data = event.GetData(); - if (data->unicode >= ' ') - { - Insert(static_cast(data->unicode)); // TODO: insert utf-8 char - SendModifEvent(); - return true; - } + auto data = event.GetData(); + Insert(data->text[0]); // TODO: insert utf-8 char + SendModifEvent(); + return true; } if ( event.type == EVENT_FOCUS ) @@ -3215,4 +3217,16 @@ void CEdit::UpdateScroll() } } +void CEdit::SetFocus(CControl* control) +{ + bool oldFocus = m_bFocus; + CControl::SetFocus(control); + + if (oldFocus != m_bFocus) + { + // Start/stop text input mode, this toggles the on-screen keyboard + CApplication::GetInstancePointer()->SetTextInput(m_bFocus); + } +} + } diff --git a/src/ui/controls/edit.h b/src/ui/controls/edit.h index 9a33884d..0a453a6c 100644 --- a/src/ui/controls/edit.h +++ b/src/ui/controls/edit.h @@ -227,6 +227,8 @@ protected: void UpdateScroll(); + void SetFocus(CControl* control) override; + protected: std::unique_ptr m_scroll; // vertical scrollbar on the right