Pārlūkot izejas kodu

Better android input handling: sending notifications about CInputText changes to java so that we can display textinput overlay there; (#354)

Fay 8 gadi atpakaļ
vecāks
revīzija
80f149e296

+ 41 - 0
client/widgets/TextControls.cpp

@@ -18,6 +18,10 @@
 
 
 #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
 #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff
 
 
+#ifdef VCMI_ANDROID
+#include "lib/CAndroidVMHelper.h"
+#endif
+
 std::string CLabel::visibleText()
 std::string CLabel::visibleText()
 {
 {
 	return text;
 	return text;
@@ -427,6 +431,9 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
 void CTextInput::focusGot()
 void CTextInput::focusGot()
 {
 {
 	CSDL_Ext::startTextInput(&pos);
 	CSDL_Ext::startTextInput(&pos);
+#ifdef VCMI_ANDROID
+	notifyAndroidTextInputChanged(text);
+#endif
 }
 }
 
 
 void CTextInput::focusLost()
 void CTextInput::focusLost()
@@ -485,6 +492,9 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key )
 	{
 	{
 		redraw();
 		redraw();
 		cb(text);
 		cb(text);
+#ifdef VCMI_ANDROID
+		notifyAndroidTextInputChanged(text);
+#endif
 	}
 	}
 }
 }
 
 
@@ -493,6 +503,10 @@ void CTextInput::setText( const std::string &nText, bool callCb )
 	CLabel::setText(nText);
 	CLabel::setText(nText);
 	if(callCb)
 	if(callCb)
 		cb(text);
 		cb(text);
+
+#ifdef VCMI_ANDROID
+	notifyAndroidTextInputChanged(text);
+#endif
 }
 }
 
 
 bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key)
 bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key)
@@ -518,6 +532,10 @@ void CTextInput::textInputed(const SDL_TextInputEvent & event)
 		cb(text);
 		cb(text);
 	}
 	}
 	newText = "";
 	newText = "";
+
+#ifdef VCMI_ANDROID
+	notifyAndroidTextInputChanged(text);
+#endif
 }
 }
 
 
 void CTextInput::textEdited(const SDL_TextEditingEvent & event)
 void CTextInput::textEdited(const SDL_TextEditingEvent & event)
@@ -528,6 +546,11 @@ void CTextInput::textEdited(const SDL_TextEditingEvent & event)
 	newText = event.text;
 	newText = event.text;
 	redraw();
 	redraw();
 	cb(text+newText);
 	cb(text+newText);
+
+#ifdef VCMI_ANDROID
+	auto editedText = text + newText;
+	notifyAndroidTextInputChanged(editedText);
+#endif
 }
 }
 
 
 void CTextInput::filenameFilter(std::string & text, const std::string &)
 void CTextInput::filenameFilter(std::string & text, const std::string &)
@@ -574,6 +597,24 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i
 	}
 	}
 }
 }
 
 
+#ifdef VCMI_ANDROID
+void CTextInput::notifyAndroidTextInputChanged(std::string & text)
+{
+	if (!focus)
+		return;
+
+	auto fun = [&text](JNIEnv * env, jclass cls, jmethodID method)
+	{
+		auto jtext = env->NewStringUTF(text.c_str());
+		env->CallStaticObjectMethod(cls, method, jtext);
+		env->DeleteLocalRef(jtext);
+	};
+	CAndroidVMHelper vmHelper;
+	vmHelper.callCustomMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "notifyTextInputChanged",
+		"(Ljava/lang/String;)V", fun);
+}
+#endif //VCMI_ANDROID
+
 CFocusable::CFocusable()
 CFocusable::CFocusable()
 {
 {
 	focus = false;
 	focus = false;

+ 4 - 0
client/widgets/TextControls.h

@@ -160,6 +160,10 @@ protected:
 
 
 	void focusGot() override;
 	void focusGot() override;
 	void focusLost() override;
 	void focusLost() override;
+
+#ifdef VCMI_ANDROID
+	void notifyAndroidTextInputChanged(std::string & text);
+#endif
 public:
 public:
 	CFunctionList<void(const std::string &)> cb;
 	CFunctionList<void(const std::string &)> cb;
 	CFunctionList<void(std::string &, const std::string &)> filters;
 	CFunctionList<void(std::string &, const std::string &)> filters;

+ 10 - 0
lib/CAndroidVMHelper.cpp

@@ -83,6 +83,16 @@ std::string CAndroidVMHelper::callStaticStringMethod(const std::string & cls, co
 	return std::string(env->GetStringUTFChars(jres, nullptr));
 	return std::string(env->GetStringUTFChars(jres, nullptr));
 }
 }
 
 
+void CAndroidVMHelper::callCustomMethod(const std::string & cls, const std::string & method,
+										const std::string & signature,
+										std::function<void(JNIEnv *, jclass, jmethodID)> fun, bool classloaded)
+{
+	auto env = get();
+	auto javaHelper = findClass(cls, classloaded);
+	auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), signature.c_str());
+	fun(env, javaHelper, methodId);
+}
+
 jclass CAndroidVMHelper::findClass(const std::string & name, bool classloaded)
 jclass CAndroidVMHelper::findClass(const std::string & name, bool classloaded)
 {
 {
 	if(classloaded)
 	if(classloaded)

+ 4 - 0
lib/CAndroidVMHelper.h

@@ -12,6 +12,7 @@
 #include "Global.h"
 #include "Global.h"
 
 
 #ifdef VCMI_ANDROID
 #ifdef VCMI_ANDROID
+
 #include <jni.h>
 #include <jni.h>
 #include <string>
 #include <string>
 
 
@@ -36,6 +37,9 @@ public:
 
 
 	std::string callStaticStringMethod(const std::string & cls, const std::string & method, bool classloaded = false);
 	std::string callStaticStringMethod(const std::string & cls, const std::string & method, bool classloaded = false);
 
 
+	void callCustomMethod(const std::string & cls, const std::string & method, const std::string & signature,
+						  std::function<void(JNIEnv *, jclass, jmethodID)> fun, bool classloaded = false);
+
 	static void cacheVM(JNIEnv * env);
 	static void cacheVM(JNIEnv * env);
 
 
 	static void cacheVM(JavaVM * vm);
 	static void cacheVM(JavaVM * vm);