diff --git a/android/src/main/java/STKEditText.java b/android/src/main/java/STKEditText.java index 5044fe20e..93645abd5 100644 --- a/android/src/main/java/STKEditText.java +++ b/android/src/main/java/STKEditText.java @@ -10,6 +10,7 @@ import android.view.inputmethod.InputMethodManager; import android.view.KeyEvent; import android.view.View; import android.widget.EditText; +import android.widget.TextView; // We need to extend EditText instead of view to allow copying to our STK // editbox @@ -34,6 +35,8 @@ public class STKEditText extends EditText int composing_start, int composing_end); // ------------------------------------------------------------------------ + private native static void handleActionNext(int widget_id); + // ------------------------------------------------------------------------ public STKEditText(Context context) { super(context); @@ -43,6 +46,21 @@ public class STKEditText extends EditText m_stk_widget_id = -1; m_from_stk_editbox = false; m_stk_input_connection = null; + setOnEditorActionListener(new EditText.OnEditorActionListener() + { + @Override + public boolean onEditorAction(TextView v, int action_id, + KeyEvent event) + { + if (action_id == EditorInfo.IME_ACTION_NEXT) + { + handleActionNext(m_stk_widget_id); + // STK will handle the closing of the screen keyboard + return true; + } + return false; + } + }); } // ------------------------------------------------------------------------ @Override diff --git a/src/guiengine/event_handler.hpp b/src/guiengine/event_handler.hpp index 55f02fcac..3f6dad9e5 100644 --- a/src/guiengine/event_handler.hpp +++ b/src/guiengine/event_handler.hpp @@ -73,8 +73,6 @@ namespace GUIEngine EventPropagation onWidgetActivated(Widget* w, const int playerID); void sendNavigationEvent(const NavigationDirection nav, const int playerID); void navigate(const NavigationDirection nav, const int playerID); - int findIDClosestWidget(const NavigationDirection nav, const int playerID, - Widget* w, bool ignore_disabled, int recursion_counter=1); /** \brief send an event to the GUI module user's event callback * \param widget the widget that triggerred this event @@ -115,6 +113,8 @@ namespace GUIEngine static void deallocate(); void setAcceptEvents(bool value) { m_accept_events = value; } + int findIDClosestWidget(const NavigationDirection nav, const int playerID, + Widget* w, bool ignore_disabled, int recursion_counter=1); }; } diff --git a/src/guiengine/widgets/text_box_widget.cpp b/src/guiengine/widgets/text_box_widget.cpp index 14e022acd..676aec9f5 100644 --- a/src/guiengine/widgets/text_box_widget.cpp +++ b/src/guiengine/widgets/text_box_widget.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace irr; @@ -53,34 +54,41 @@ public: m_listeners.clearWithoutDeleting(); } + void handleTextUpdated() + { + for (unsigned n = 0; n < m_listeners.size(); n++) + m_listeners[n].onTextUpdated(); + } + + bool handleEnterPressed() + { + bool handled = false; + for (unsigned n = 0; n < m_listeners.size(); n++) + { + if (m_listeners[n].onEnterPressed(Text)) + { + handled = true; + Text = L""; + CursorPos = MarkBegin = MarkEnd = 0; + } + } + return handled; + } + virtual bool OnEvent(const SEvent& event) { bool out = CGUIEditBox::OnEvent(event); - if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) - { - for (unsigned int n=0; n& - getListeners() { return m_listeners; } - }; using namespace GUIEngine; @@ -280,9 +288,61 @@ ANDROID_EDITTEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME) eb->fromAndroidEditText(to_editbox, start, end, composing_start, composing_end); if (old_text != eb->getText()) + eb->handleTextUpdated(); + }); +} + +#define MAKE_HANDLE_ACTION_NEXT_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_STKEditText_handleActionNext(JNIEnv* env, jobject this_obj, jint widget_id) +#define ANDROID_HANDLE_ACTION_NEXT_CALLBACK(PKG_NAME) MAKE_HANDLE_ACTION_NEXT_CALLBACK(PKG_NAME) + +extern "C" +ANDROID_HANDLE_ACTION_NEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME) +{ + GUIEngine::addGUIFunctionBeforeRendering([widget_id]() + { + TextBoxWidget* tb = + dynamic_cast(getFocusForPlayer(0)); + if (!tb || (int)widget_id != tb->getID()) + return; + MyCGUIEditBox* eb = tb->getIrrlichtElement(); + if (!eb) + return; + + // First test for onEnterPressed, if true then close keyboard + if (eb->handleEnterPressed()) { - for (unsigned n = 0; n < eb->getListeners().size(); n++) - eb->getListeners()[n].onTextUpdated(); + GUIEngine::getDevice()->toggleOnScreenKeyboard(false); + return; + } + + // As it's action "next", check if below widget is a text box, if + // so focus it and keep the screen keyboard, so user can keep + // typing + int id = GUIEngine::EventHandler::get()->findIDClosestWidget( + NAV_DOWN, 0, tb, true/*ignore_disabled*/); + TextBoxWidget* closest_tb = NULL; + if (id != -1) + { + closest_tb = + dynamic_cast(GUIEngine::getWidget(id)); + } + + if (closest_tb) + { + closest_tb->setFocusForPlayer(0); + } + else + { + // Post an enter event and close the keyboard + SEvent enter_event; + enter_event.EventType = EET_KEY_INPUT_EVENT; + enter_event.KeyInput.Char = 0; + enter_event.KeyInput.PressedDown = true; + enter_event.KeyInput.Key = IRR_KEY_RETURN; + GUIEngine::getDevice()->postEventFromUser(enter_event); + enter_event.KeyInput.PressedDown = false; + GUIEngine::getDevice()->postEventFromUser(enter_event); + GUIEngine::getDevice()->toggleOnScreenKeyboard(false); } }); }