diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index f7b64beb08..1a975de2d6 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -2,17 +2,145 @@ package org.cocos2dx.lib; import android.content.Context; import android.opengl.GLSurfaceView; +import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodManager; + +class Cocos2dxInputConnection implements InputConnection { + + @Override + public boolean beginBatchEdit() { + return false; + } + + @Override + public boolean clearMetaKeyStates(int states) { + return false; + } + + @Override + public boolean commitCompletion(CompletionInfo text) { + return false; + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + if (null != mView) { + final String insertText = text.toString(); + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean deleteSurroundingText(int leftLength, int rightLength) { + return false; + } + + @Override + public boolean endBatchEdit() { + return false; + } + + @Override + public boolean finishComposingText() { + return false; + } + + @Override + public int getCursorCapsMode(int reqModes) { + return 0; + } + + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, + int flags) { + return null; + } + + @Override + public CharSequence getTextAfterCursor(int n, int flags) { + return null; + } + + @Override + public CharSequence getTextBeforeCursor(int n, int flags) { + return null; + } + + @Override + public boolean performContextMenuAction(int id) { + return false; + } + + @Override + public boolean performEditorAction(int editorAction) { + if (null != mView) { + final String insertText = "\n"; + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean performPrivateCommand(String action, Bundle data) { + return false; + } + + @Override + public boolean reportFullscreenMode(boolean enabled) { + return false; + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + if (null != mView) { + switch (event.getKeyCode()) { + + case KeyEvent.KEYCODE_DEL: + mView.deleteBackward(); + break; + } + } + return false; + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + return false; + } + + @Override + public boolean setSelection(int start, int end) { + return false; + } + + public void setGLSurfaceView(Cocos2dxGLSurfaceView view) { + mView = view; + } + + private Cocos2dxGLSurfaceView mView; +} public class Cocos2dxGLSurfaceView extends GLSurfaceView { - private static final String TAG = Cocos2dxGLSurfaceView.class - .getCanonicalName(); + + static private Cocos2dxGLSurfaceView mainView; + + private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName(); private Cocos2dxRenderer mRenderer; private final boolean debug = false; + /////////////////////////////////////////////////////////////////////////// + // for initialize + /////////////////////////////////////////////////////////////////////////// public Cocos2dxGLSurfaceView(Context context) { super(context); initView(); @@ -27,8 +155,86 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { mRenderer = new Cocos2dxRenderer(); setFocusableInTouchMode(true); setRenderer(mRenderer); + mainView = this; } + /////////////////////////////////////////////////////////////////////////// + // for text input + /////////////////////////////////////////////////////////////////////////// + + public static void openIMEKeyboard() { + if (null == mainView) { + return; + } + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + imm.showSoftInput(mainView, InputMethodManager.SHOW_IMPLICIT); + } + + public static void closeIMEKeyboard() { + if (null != mainView) { + Log.d("Cocos2dxGLSurfaceView", "closeIMEKeyboard"); + } + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0); + } + + @Override + public boolean onCheckIsTextEditor() { + if (null == mainView) + { + return false; + } + return true; + } + + private Cocos2dxInputConnection ic; + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + if (onCheckIsTextEditor()) { + + outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT; + outAttrs.imeOptions = EditorInfo.IME_NULL; + outAttrs.initialSelStart = -1; + outAttrs.initialSelEnd = -1; + outAttrs.initialCapsMode = 0; + + if (null == ic) + { + ic = new Cocos2dxInputConnection(); + ic.setGLSurfaceView(this); + } + return ic; + } + return null; + } + + public void insertText(final String text) { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleInsertText(text); + } + }); + } + + public void deleteBackward() { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleDeleteBackward(); + } + }); + } + /////////////////////////////////////////////////////////////////////////// + // for touch event + /////////////////////////////////////////////////////////////////////////// + public boolean onTouchEvent(final MotionEvent event) { // these data are used in ACTION_MOVE and ACTION_CANCEL final int pointerNumber = event.getPointerCount(); diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java index 4a80d59ac6..90f280614b 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java @@ -67,12 +67,26 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer { public static void setAnimationInterval(double interval){ animationInterval = (long)(interval * NANOSECONDSPERSECOND); } - private static native void nativeTouchesBegin(int id, float x, float y); private static native void nativeTouchesEnd(int id, float x, float y); private static native void nativeTouchesMove(int[] id, float[] x, float[] y); private static native void nativeTouchesCancel(int[] id, float[] x, float[] y); -private static native boolean nativeKeyDown(int keyCode); + private static native boolean nativeKeyDown(int keyCode); private static native void nativeRender(); private static native void nativeInit(int w, int h); + + ///////////////////////////////////////////////////////////////////////////////// + // handle input method edit message + ///////////////////////////////////////////////////////////////////////////////// + + public void handleInsertText(final String text) { + nativeInsertText(text); + } + + public void handleDeleteBackward() { + nativeDeleteBackward(); + } + + private static native void nativeInsertText(String text); + private static native void nativeDeleteBackward(); } diff --git a/cocos2dx/Android.mk b/cocos2dx/Android.mk index af06f10e43..9364f11f8d 100644 --- a/cocos2dx/Android.mk +++ b/cocos2dx/Android.mk @@ -82,6 +82,8 @@ support/image_support/TGAlib.cpp \ support/zip_support/ZipUtils.cpp \ support/zip_support/ioapi.cpp \ support/zip_support/unzip.cpp \ +text_input_node/CCIMEDispatcher.cpp \ +text_input_node/CCTextFieldTTF.cpp \ textures/CCTexture2D.cpp \ textures/CCTextureAtlas.cpp \ textures/CCTextureCache.cpp \ @@ -135,4 +137,4 @@ LOCAL_LDLIBS := -L$(LOCAL_PATH)/platform/third_party/android/libraries \ # define the macro to compile through support/zip_support/ioapi.c LOCAL_CFLAGS := -DUSE_FILE32API -include $(BUILD_SHARED_LIBRARY) \ No newline at end of file +include $(BUILD_SHARED_LIBRARY) diff --git a/cocos2dx/platform/android/CCEGLView_android.cpp b/cocos2dx/platform/android/CCEGLView_android.cpp index b64aa585b0..321b344334 100644 --- a/cocos2dx/platform/android/CCEGLView_android.cpp +++ b/cocos2dx/platform/android/CCEGLView_android.cpp @@ -28,6 +28,7 @@ THE SOFTWARE. #include "CCDirector.h" #include "ccMacros.h" #include "CCTouchDispatcher.h" +#include "Cocos2dJni.h" #include @@ -127,21 +128,21 @@ void CCEGLView::setContentScaleFactor(float contentScaleFactor) void CCEGLView::setViewPortInPoints(float x, float y, float w, float h) { - if (m_bNotHVGA) - { - float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); - glViewport((GLint)(x * factor) + m_rcViewPort.origin.x, - (GLint)(y * factor) + m_rcViewPort.origin.y, - (GLint)(w * factor), - (GLint)(h * factor)); - } - else - { - glViewport((GLint)x, - (GLint)y, - (GLint)w, - (GLint)h); - } + if (m_bNotHVGA) + { + float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); + glViewport((GLint)(x * factor) + m_rcViewPort.origin.x, + (GLint)(y * factor) + m_rcViewPort.origin.y, + (GLint)(w * factor), + (GLint)(h * factor)); + } + else + { + glViewport((GLint)x, + (GLint)y, + (GLint)w, + (GLint)h); + } } CCEGLView& CCEGLView::sharedOpenGLView() @@ -157,15 +158,21 @@ float CCEGLView::getScreenScaleFactor() CCRect CCEGLView::getViewPort() { - if (m_bNotHVGA) - { - return m_rcViewPort; - } - else - { - CCRect rect(0, 0, 0, 0); - return rect; - } + if (m_bNotHVGA) + { + return m_rcViewPort; + } + else + { + CCRect rect(0, 0, 0, 0); + return rect; + } +} + +void CCEGLView::setIMEKeyboardState(bool bOpen) +{ + + setKeyboardStateJNI((int)bOpen); } } // end of namespace cocos2d diff --git a/cocos2dx/platform/android/CCEGLView_android.h b/cocos2dx/platform/android/CCEGLView_android.h index af10c8dfa7..9830cd6611 100644 --- a/cocos2dx/platform/android/CCEGLView_android.h +++ b/cocos2dx/platform/android/CCEGLView_android.h @@ -60,6 +60,7 @@ public: void setViewPortInPoints(float x, float y, float w, float h); CCRect getViewPort(); float getScreenScaleFactor(); + void setIMEKeyboardState(bool bOpen); // static function /** diff --git a/cocos2dx/platform/android/Cocos2dJni.cpp b/cocos2dx/platform/android/Cocos2dJni.cpp index 3beb0f21b5..b0375c7056 100644 --- a/cocos2dx/platform/android/Cocos2dJni.cpp +++ b/cocos2dx/platform/android/Cocos2dJni.cpp @@ -29,6 +29,7 @@ THE SOFTWARE. #include "CCTouchDispatcher.h" #include "CCFileUtils.h" #include "CCGeometry.h" +#include "CCIMEDispatcher.h" #include "platform/android/CCAccelerometer_android.h" #include @@ -43,24 +44,73 @@ using namespace cocos2d; extern "C" { + ////////////////////////////////////////////////////////////////////////// + // java vm helper function + ////////////////////////////////////////////////////////////////////////// - #define MAX_TOUCHES 5 - static CCTouch *s_pTouches[MAX_TOUCHES] = { NULL }; + JavaVM *gJavaVM = NULL; - // handle accelerometer changes + jint JNI_OnLoad(JavaVM *vm, void *reserved) + { + gJavaVM = vm; + return JNI_VERSION_1_4; + } - void Java_org_cocos2dx_lib_Cocos2dxAccelerometer_onSensorChanged(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z, jlong timeStamp) - { - // We need to invert to make it compatible with iOS. - CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort(); - float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor(); - cocos2d::CCAccelerometer::sharedAccelerometer()->update((x - rcRect.origin.x) / fScreenScaleFactor, - (y - rcRect.origin.y) / fScreenScaleFactor, - z, - timeStamp); - } + struct TMethodJNI + { + JNIEnv * env; + jclass classID; + jmethodID methodID; + }; + static bool getMethodID(struct TMethodJNI& t, const char *className, const char *methodName, const char *paramCode) + { + bool ret = 0; + do + { + if (gJavaVM->GetEnv((void**)&t.env, JNI_VERSION_1_4) != JNI_OK) + { + LOGD("Failed to get the environment using GetEnv()"); + break; + } - // handle touch event + if (gJavaVM->AttachCurrentThread(&t.env, 0) < 0) + { + LOGD("Failed to get the environment using AttachCurrentThread()"); + break; + } + + t.classID = t.env->FindClass(className); + if (! t.classID) + { + LOGD("Failed to find class of %s", className); + break; + } + + t.methodID = t.env->GetStaticMethodID(t.classID, methodName, paramCode); + if (! t.methodID) + { + LOGD("Failed to find method id of %s", methodName); + break; + } + ret = true; + } while (0); + + return ret; + } + + ////////////////////////////////////////////////////////////////////////// + // native renderer + ////////////////////////////////////////////////////////////////////////// + + #define MAX_TOUCHES 5 + static CCTouch *s_pTouches[MAX_TOUCHES] = { NULL }; + + void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) + { + cocos2d::CCDirector::sharedDirector()->mainLoop(); + } + + // handle touch event void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv* env, jobject thiz, jint id, jfloat x, jfloat y) { CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort(); @@ -196,6 +246,21 @@ extern "C" return JNI_FALSE; } + ////////////////////////////////////////////////////////////////////////// + // handle accelerometer changes + ////////////////////////////////////////////////////////////////////////// + + void Java_org_cocos2dx_lib_Cocos2dxAccelerometer_onSensorChanged(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z, jlong timeStamp) + { + // We need to invert to make it compatible with iOS. + CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort(); + float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor(); + cocos2d::CCAccelerometer::sharedAccelerometer()->update((x - rcRect.origin.x) / fScreenScaleFactor, + (y - rcRect.origin.y) / fScreenScaleFactor, + z, + timeStamp); + } + void Java_org_cocos2dx_lib_Cocos2dxActivity_nativeSetPaths(JNIEnv* env, jobject thiz, jstring apkPath) { const char* str; @@ -207,72 +272,29 @@ extern "C" } } - // record the java vm - - JavaVM *gJavaVM = NULL; - jclass classOfCocos2dxActivity = 0; - JNIEnv *env = 0; - - jint JNI_OnLoad(JavaVM *vm, void *reserved) - { - gJavaVM = vm; - return JNI_VERSION_1_4; - } - - static jmethodID getMethodID(const char *methodName, const char *paramCode) - { - jmethodID ret = 0; - - // get jni environment and java class for Cocos2dxActivity - if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) - { - LOGD("Failed to get the environment using GetEnv()"); - return 0; - } - - if (gJavaVM->AttachCurrentThread(&env, 0) < 0) - { - LOGD("Failed to get the environment using AttachCurrentThread()"); - return 0; - } - - classOfCocos2dxActivity = env->FindClass("org/cocos2dx/lib/Cocos2dxActivity"); - if (! classOfCocos2dxActivity) - { - LOGD("Failed to find class of org/cocos2dx/lib/Cocos2dxActivity"); - return 0; - } - - if (env != 0 && classOfCocos2dxActivity != 0) - { - ret = env->GetStaticMethodID(classOfCocos2dxActivity, methodName, paramCode); - } - - if (! ret) - { - LOGD("get method id of %s error", methodName); - } - - return ret; - } void enableAccelerometerJNI() { - jmethodID methodID = getMethodID("enableAccelerometer", "()V"); - - if (methodID) + TMethodJNI t; + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxActivity" + , "enableAccelerometer" + , "()V")) { - env->CallStaticVoidMethod(classOfCocos2dxActivity, methodID); + t.env->CallStaticVoidMethod(t.classID, t.methodID); } } void disableAccelerometerJNI() { - jmethodID methodID = getMethodID("disableAccelerometer", "()V"); + TMethodJNI t; - if (methodID) + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxActivity" + , "disableAccelerometer" + , "()V")) { - env->CallStaticVoidMethod(classOfCocos2dxActivity, methodID); + t.env->CallStaticVoidMethod(t.classID, t.methodID); } } @@ -283,30 +305,58 @@ extern "C" return; } - jmethodID methodID = getMethodID("showMessageBox", "(Ljava/lang/String;Ljava/lang/String;)V"); - - if (methodID) + TMethodJNI t; + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxActivity" + , "showMessageBox" + , "(Ljava/lang/String;Ljava/lang/String;)V")) { jstring StringArg1; if (! pszTitle) { - StringArg1 = env->NewStringUTF(""); + StringArg1 = t.env->NewStringUTF(""); } else { - StringArg1 = env->NewStringUTF(pszTitle); + StringArg1 = t.env->NewStringUTF(pszTitle); } - jstring StringArg2 = env->NewStringUTF(pszMsg); - env->CallStaticVoidMethod(classOfCocos2dxActivity, methodID, StringArg1, StringArg2); + jstring StringArg2 = t.env->NewStringUTF(pszMsg); + t.env->CallStaticVoidMethod(t.classID, t.methodID, StringArg1, StringArg2); } } - // native renderer + ////////////////////////////////////////////////////////////////////////// + // handle IME message + ////////////////////////////////////////////////////////////////////////// - void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) - { - cocos2d::CCDirector::sharedDirector()->mainLoop(); - } + void setKeyboardStateJNI(int bOpen) + { + TMethodJNI t; + jint open = bOpen; + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxGLSurfaceView" + , (bOpen) ? "openIMEKeyboard" : "closeIMEKeyboard" + , "()V")) + { + t.env->CallStaticVoidMethod(t.classID, t.methodID); + } + } + + void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText(JNIEnv* env, jobject thiz, jstring text) + { + jboolean isCopy = 0; + const char* pszText = env->GetStringUTFChars(text, &isCopy); + if (isCopy) + { + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); + env->ReleaseStringUTFChars(text, pszText); + } + } + + void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward(JNIEnv* env, jobject thiz) + { + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); + } } diff --git a/cocos2dx/platform/android/Cocos2dJni.h b/cocos2dx/platform/android/Cocos2dJni.h index d83aa73a0e..7cf0d83c98 100644 --- a/cocos2dx/platform/android/Cocos2dJni.h +++ b/cocos2dx/platform/android/Cocos2dJni.h @@ -33,6 +33,7 @@ extern "C" void enableAccelerometerJNI(); void disableAccelerometerJNI(); void showMessageBoxJNI(const char * pszMsg, const char * pszTitle); + void setKeyboardStateJNI(int bOpen); } #endif // __ANDROID_COCOS2D_JNI_H__ diff --git a/cocos2dx/platform/win32/CCEGLView_win32.cpp b/cocos2dx/platform/win32/CCEGLView_win32.cpp index 22c340388f..63af858d3f 100644 --- a/cocos2dx/platform/win32/CCEGLView_win32.cpp +++ b/cocos2dx/platform/win32/CCEGLView_win32.cpp @@ -319,6 +319,10 @@ LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); } + else if (VK_RETURN == wParam) + { + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText("\n", 1); + } else if (VK_TAB == wParam) { // tab input @@ -327,13 +331,19 @@ LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // ESC input } - - break; } - char szUtf8[8] = {0}; - int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL); + else if (wParam < 128) + { + // ascii char + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText((const char *)&wParam, 1); + } + else + { + char szUtf8[8] = {0}; + int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL); - CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen); + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen); + } } break; diff --git a/cocos2dx/text_input_node/CCTextFieldTTF.cpp b/cocos2dx/text_input_node/CCTextFieldTTF.cpp index 65a935b839..5b170b4edd 100644 --- a/cocos2dx/text_input_node/CCTextFieldTTF.cpp +++ b/cocos2dx/text_input_node/CCTextFieldTTF.cpp @@ -155,9 +155,29 @@ void CCTextFieldTTF::detatchWithIME() void CCTextFieldTTF::insertText(const char * text, int len) { + std::string sInsert(text, len); + + // insert \n means input end + int nPos = sInsert.find('\n'); + if (sInsert.npos != nPos) + { + len = nPos; + sInsert.erase(nPos); + } + if (len <= 0) + { + // close keyboard + CCEGLView * pGlView = CCDirector::sharedDirector()->getOpenGLView(); + if (pGlView) + { + pGlView->setIMEKeyboardState(false); + } + return; + } + m_bLock = true; std::string sText(*m_pInputText); - sText.append(text, len); + sText.append(sInsert); m_pLens->push_back((unsigned short)len); setString(sText.c_str()); m_bLock = false; diff --git a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index f7b64beb08..1a975de2d6 100644 --- a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -2,17 +2,145 @@ package org.cocos2dx.lib; import android.content.Context; import android.opengl.GLSurfaceView; +import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodManager; + +class Cocos2dxInputConnection implements InputConnection { + + @Override + public boolean beginBatchEdit() { + return false; + } + + @Override + public boolean clearMetaKeyStates(int states) { + return false; + } + + @Override + public boolean commitCompletion(CompletionInfo text) { + return false; + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + if (null != mView) { + final String insertText = text.toString(); + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean deleteSurroundingText(int leftLength, int rightLength) { + return false; + } + + @Override + public boolean endBatchEdit() { + return false; + } + + @Override + public boolean finishComposingText() { + return false; + } + + @Override + public int getCursorCapsMode(int reqModes) { + return 0; + } + + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, + int flags) { + return null; + } + + @Override + public CharSequence getTextAfterCursor(int n, int flags) { + return null; + } + + @Override + public CharSequence getTextBeforeCursor(int n, int flags) { + return null; + } + + @Override + public boolean performContextMenuAction(int id) { + return false; + } + + @Override + public boolean performEditorAction(int editorAction) { + if (null != mView) { + final String insertText = "\n"; + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean performPrivateCommand(String action, Bundle data) { + return false; + } + + @Override + public boolean reportFullscreenMode(boolean enabled) { + return false; + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + if (null != mView) { + switch (event.getKeyCode()) { + + case KeyEvent.KEYCODE_DEL: + mView.deleteBackward(); + break; + } + } + return false; + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + return false; + } + + @Override + public boolean setSelection(int start, int end) { + return false; + } + + public void setGLSurfaceView(Cocos2dxGLSurfaceView view) { + mView = view; + } + + private Cocos2dxGLSurfaceView mView; +} public class Cocos2dxGLSurfaceView extends GLSurfaceView { - private static final String TAG = Cocos2dxGLSurfaceView.class - .getCanonicalName(); + + static private Cocos2dxGLSurfaceView mainView; + + private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName(); private Cocos2dxRenderer mRenderer; private final boolean debug = false; + /////////////////////////////////////////////////////////////////////////// + // for initialize + /////////////////////////////////////////////////////////////////////////// public Cocos2dxGLSurfaceView(Context context) { super(context); initView(); @@ -27,8 +155,86 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { mRenderer = new Cocos2dxRenderer(); setFocusableInTouchMode(true); setRenderer(mRenderer); + mainView = this; } + /////////////////////////////////////////////////////////////////////////// + // for text input + /////////////////////////////////////////////////////////////////////////// + + public static void openIMEKeyboard() { + if (null == mainView) { + return; + } + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + imm.showSoftInput(mainView, InputMethodManager.SHOW_IMPLICIT); + } + + public static void closeIMEKeyboard() { + if (null != mainView) { + Log.d("Cocos2dxGLSurfaceView", "closeIMEKeyboard"); + } + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0); + } + + @Override + public boolean onCheckIsTextEditor() { + if (null == mainView) + { + return false; + } + return true; + } + + private Cocos2dxInputConnection ic; + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + if (onCheckIsTextEditor()) { + + outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT; + outAttrs.imeOptions = EditorInfo.IME_NULL; + outAttrs.initialSelStart = -1; + outAttrs.initialSelEnd = -1; + outAttrs.initialCapsMode = 0; + + if (null == ic) + { + ic = new Cocos2dxInputConnection(); + ic.setGLSurfaceView(this); + } + return ic; + } + return null; + } + + public void insertText(final String text) { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleInsertText(text); + } + }); + } + + public void deleteBackward() { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleDeleteBackward(); + } + }); + } + /////////////////////////////////////////////////////////////////////////// + // for touch event + /////////////////////////////////////////////////////////////////////////// + public boolean onTouchEvent(final MotionEvent event) { // these data are used in ACTION_MOVE and ACTION_CANCEL final int pointerNumber = event.getPointerCount(); diff --git a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java index 4a80d59ac6..90f280614b 100644 --- a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java +++ b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java @@ -67,12 +67,26 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer { public static void setAnimationInterval(double interval){ animationInterval = (long)(interval * NANOSECONDSPERSECOND); } - private static native void nativeTouchesBegin(int id, float x, float y); private static native void nativeTouchesEnd(int id, float x, float y); private static native void nativeTouchesMove(int[] id, float[] x, float[] y); private static native void nativeTouchesCancel(int[] id, float[] x, float[] y); -private static native boolean nativeKeyDown(int keyCode); + private static native boolean nativeKeyDown(int keyCode); private static native void nativeRender(); private static native void nativeInit(int w, int h); + + ///////////////////////////////////////////////////////////////////////////////// + // handle input method edit message + ///////////////////////////////////////////////////////////////////////////////// + + public void handleInsertText(final String text) { + nativeInsertText(text); + } + + public void handleDeleteBackward() { + nativeDeleteBackward(); + } + + private static native void nativeInsertText(String text); + private static native void nativeDeleteBackward(); }