From 8666ed6b5ec31d81173521b3fc7498e6318c124e Mon Sep 17 00:00:00 2001 From: hughsando Date: Sun, 22 May 2016 10:47:31 +0800 Subject: [PATCH] Sync the text box input between NME and android so that if the box is ever seen, it looks correct (android will show this box if it thinks the display region is too small). This also allows for using the native text box in the future. Only show the text box for TextFields, and allow 'Dumb' keys otherwise. --- project/include/Display.h | 13 ++- project/include/TextField.h | 3 + project/src/android/AndroidFrame.cpp | 36 +++++++- project/src/common/Display.cpp | 4 +- project/src/common/ExternalInterface.cpp | 4 +- project/src/common/Stage.cpp | 14 ++- project/src/common/TextField.cpp | 64 ++++++++++++- project/src/iPhone/UIStageView.mm | 10 +-- project/src/sdl/SDLStage.cpp | 6 +- project/src/sdl2/SDL2Stage.cpp | 5 -- project/src/winrt/WinRTStage.cpp | 5 -- samples/02-Text/Sample.nmml | 1 - .../extension-api/src/org/haxe/nme/NME.java | 1 + .../PROJ/src/org/haxe/nme/GameActivity.java | 55 ++++++++++-- .../PROJ/src/org/haxe/nme/MainView.java | 89 ++++++++++++------- 15 files changed, 237 insertions(+), 73 deletions(-) diff --git a/project/include/Display.h b/project/include/Display.h index 8dbc027de..9f2c9c85b 100644 --- a/project/include/Display.h +++ b/project/include/Display.h @@ -339,6 +339,14 @@ class SimpleButton : public DisplayObjectContainer double GetTimeStamp(); +enum PopupKeyboardMode +{ + pkmOff = 0x0000, + pkmDumb = 0x0001, + pkmSmart = 0x0002, + pkmNative = 0x0003, +}; + class Stage : public DisplayObjectContainer { public: @@ -367,7 +375,8 @@ class Stage : public DisplayObjectContainer virtual void SetScreenMode(ScreenMode mode) { } virtual void ShowCursor(bool inShow) { }; virtual void SetCursor(Cursor inCursor)=0; - virtual void EnablePopupKeyboard(bool inEnable) { } + virtual void PopupKeyboard(PopupKeyboardMode inMode, WString *inValue=0) { }; + virtual void SetPopupTextSelection(int inSel0, int inSel1) { } double GetNextWake() { return mNextWake; } virtual void SetNextWakeDelay(double inNextWake); @@ -378,6 +387,8 @@ class Stage : public DisplayObjectContainer virtual uint32 getBackgroundMask() { return 0xffffffff; } virtual const char *getJoystickName(int id) { return NULL; } + virtual void onTextFieldText(const std::string &inText, int inPos0, int inPos1); + Matrix GetFullMatrix(bool inStageScaling); bool FinishEditOnEnter(); diff --git a/project/include/TextField.h b/project/include/TextField.h index 3bb530e0a..5eba98ef9 100644 --- a/project/include/TextField.h +++ b/project/include/TextField.h @@ -157,6 +157,7 @@ class TextField : public DisplayObject void EndDrag(Event &inEvent); void OnKey(Event &inEvent); void OnScrollWheel(int inDirection); + void onTextUpdate(const std::string &inText, int inPos0, int inPos1); void DeleteSelection(); void ClearSelection(); void CopySelection(); @@ -169,6 +170,8 @@ class TextField : public DisplayObject bool CaretOn(); bool IsCacheDirty(); + void SyncSelection(); + void Focus(); diff --git a/project/src/android/AndroidFrame.cpp b/project/src/android/AndroidFrame.cpp index c92701d25..52b8e349b 100644 --- a/project/src/android/AndroidFrame.cpp +++ b/project/src/android/AndroidFrame.cpp @@ -336,6 +336,7 @@ class AndroidStage : public Stage } } + void OnJoy(int inDeviceId, int inCode, bool inDown) { //__android_log_print(ANDROID_LOG_INFO, "NME", "OnJoy %d %d %d", inDeviceId, inCode, inDown); @@ -451,15 +452,32 @@ class AndroidStage : public Stage //__android_log_print(ANDROID_LOG_INFO, "NME", "Accelerometer %f %f %f", inX, inY, inZ); } - void EnablePopupKeyboard(bool inEnable) + void PopupKeyboard(PopupKeyboardMode inMode,WString *inValue) { JNIEnv *env = GetEnv(); jclass cls = FindClass("org/haxe/nme/GameActivity"); - jmethodID mid = env->GetStaticMethodID(cls, "showKeyboard", "(Z)V"); + jstring str = 0; + if (inValue) + { + std::string cstr = WideToUTF8(*inValue); + str = env->NewStringUTF( cstr.c_str() ); + } + jmethodID mid = env->GetStaticMethodID(cls, "popupKeyboard", "(ILjava/lang/String;)V"); if (mid == 0) return; - env->CallStaticVoidMethod(cls, mid, (jboolean) inEnable); + env->CallStaticVoidMethod(cls, mid, (int)inMode, str); + } + + void SetPopupTextSelection(int inSel0, int inSel1) + { + JNIEnv *env = GetEnv(); + jclass cls = FindClass("org/haxe/nme/GameActivity"); + jmethodID mid = env->GetStaticMethodID(cls, "setPopupSelection", "(II)V"); + if (mid == 0) + return; + + env->CallStaticVoidMethod(cls, mid, inSel0, inSel1); } bool getMultitouchSupported() { return true; } @@ -833,6 +851,18 @@ JAVA_EXPORT int JNICALL Java_org_haxe_nme_NME_onKeyChange(JNIEnv * env, jobject return nme::GetResult(); } + +JAVA_EXPORT int JNICALL Java_org_haxe_nme_NME_onText(JNIEnv * env, jobject obj, jstring inText, int inReplacePos, int inReplaceLen) +{ + AutoHaxe haxe("onText"); + if (nme::sStage) + { + std::string text = JStringToStdString(env, inText, false); + nme::sStage->onTextFieldText(text,inReplacePos,inReplaceLen); + } + return nme::GetResult(); +} + JAVA_EXPORT int JNICALL Java_org_haxe_nme_NME_onJoyChange(JNIEnv * env, jobject obj, int deviceId, int code, bool down) { AutoHaxe haxe("onJoy"); diff --git a/project/src/common/Display.cpp b/project/src/common/Display.cpp index bf28ac1d8..3db01dcd0 100644 --- a/project/src/common/Display.cpp +++ b/project/src/common/Display.cpp @@ -674,7 +674,7 @@ void DisplayObject::Focus() { Stage *stage = getStage(); if (stage) - stage->EnablePopupKeyboard(true); + stage->PopupKeyboard(pkmDumb); } #endif } @@ -686,7 +686,7 @@ void DisplayObject::Unfocus() { Stage *stage = getStage(); if (stage) - stage->EnablePopupKeyboard(false); + stage->PopupKeyboard(pkmOff); } #endif } diff --git a/project/src/common/ExternalInterface.cpp b/project/src/common/ExternalInterface.cpp index e7266868a..15072dd30 100644 --- a/project/src/common/ExternalInterface.cpp +++ b/project/src/common/ExternalInterface.cpp @@ -2296,7 +2296,7 @@ value nme_display_object_request_soft_keyboard(value inObj) if (stage) { // TODO: return whether it pops up - stage->EnablePopupKeyboard(true); + stage->PopupKeyboard(pkmDumb); return alloc_bool(true); } } @@ -2315,7 +2315,7 @@ value nme_display_object_dismiss_soft_keyboard(value inObj) if (stage) { // TODO: return whether it pops up - stage->EnablePopupKeyboard(false); + stage->PopupKeyboard(pkmOff); return alloc_bool(true); } } diff --git a/project/src/common/Stage.cpp b/project/src/common/Stage.cpp index 7b81fbae8..63f9821b3 100644 --- a/project/src/common/Stage.cpp +++ b/project/src/common/Stage.cpp @@ -283,7 +283,7 @@ void Stage::HandleEvent(Event &inEvent) #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN) else { - EnablePopupKeyboard(false); + PopupKeyboard(pkmOff); SetFocusObject(0,fsMouse); } #endif @@ -308,7 +308,7 @@ void Stage::HandleEvent(Event &inEvent) else if (inEvent.type==etMouseClick || inEvent.type==etMouseDown || (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) )) { - EnablePopupKeyboard(false); + PopupKeyboard(pkmOff); SetFocusObject(0); } #endif @@ -318,6 +318,16 @@ void Stage::HandleEvent(Event &inEvent) hit_obj->DecRef(); } +void Stage::onTextFieldText(const std::string &inText, int inPos0, int inPos1) +{ + if (mFocusObject) + { + TextField *field = dynamic_cast(mFocusObject); + if (field) + field->onTextUpdate(inText, inPos0, inPos1); + } +} + void Stage::setOpaqueBackground(uint32 inBG) { opaqueBackground = inBG | 0xff000000; diff --git a/project/src/common/TextField.cpp b/project/src/common/TextField.cpp index 514ebca69..cdba4cccb 100644 --- a/project/src/common/TextField.cpp +++ b/project/src/common/TextField.cpp @@ -542,6 +542,33 @@ void TextField::setSelection(int inStartIndex, int inEndIndex) mCaretDirty = true; mGfxDirty = true; DirtyCache(); + + SyncSelection(); +} + +void TextField::SyncSelection() +{ + Stage *stage = getStage(); + if (stage && stage->GetFocusObject()==this) + { + if (mSelectMinSetPopupTextSelection(mSelectMin, mSelectMax); + else + stage->SetPopupTextSelection(caretIndex,caretIndex); + } +} + + +void TextField::Focus() +{ +#if defined(IPHONE) || defined (ANDROID) || defined(WEBOS) || defined(BLACKBERRY) || defined(TIZEN) + if (needsSoftKeyboard) + { + WString value = getText(); + getStage()->PopupKeyboard(pkmSmart,&value); + SyncSelection(); + } +#endif } @@ -564,9 +591,6 @@ bool TextField::CaptureDown(Event &inEvent) { if (selectable || isInput) { - if (selectable && isInput) - getStage()->EnablePopupKeyboard(true); - UserPoint point = GlobalToLocal(UserPoint( inEvent.x, inEvent.y)); int pos = PointToChar(point); caretIndex = pos; @@ -579,6 +603,14 @@ bool TextField::CaptureDown(Event &inEvent) mGfxDirty = true; DirtyCache(); } + + if (selectable && isInput) + { + WString value = getText(); + getStage()->PopupKeyboard(pkmSmart,&value); + SyncSelection(); + } + } return true; } @@ -620,6 +652,7 @@ void TextField::Drag(Event &inEvent) mTilesDirty = true; mCaretDirty = true; DirtyCache(); + SyncSelection(); } } @@ -675,6 +708,31 @@ void TextField::PasteSelection() InsertString(UTF8ToWide(GetClipboardText())); } +void TextField::onTextUpdate(const std::string &inText, int inPos0, int inPos1) +{ + if (inPos1>inPos0) + { + mSelectMin = inPos0; + mSelectMax = inPos1; + DeleteSelection(); + } + else + caretIndex = inPos0; + + Stage *stage = getStage(); + if (stage) + { + Event onText(etChar); + onText.utf8Text = inText.c_str(); + onText.utf8Length = inText.size(); + onText.id = getID(); + stage->HandleEvent(onText); + } + + InsertString(UTF8ToWide(inText)); +} + + void TextField::OnKey(Event &inEvent) { diff --git a/project/src/iPhone/UIStageView.mm b/project/src/iPhone/UIStageView.mm index 2cb318eb4..33fca0b1e 100644 --- a/project/src/iPhone/UIStageView.mm +++ b/project/src/iPhone/UIStageView.mm @@ -164,7 +164,7 @@ - (void) mainLoop:(id) sender; bool isOpenGL() const { return nmeView->mOGLContext; } Surface *GetPrimarySurface() { return nmeView->mHardwareSurface; } void SetCursor(nme::Cursor) { /* No cursors on iPhone ! */ } - void EnablePopupKeyboard(bool inEnable); + void PopupKeyboard(PopupKeyboardMode inEnable,WString *); double getDPIScale() { return nmeView->dpiScale; } int getWindowFrameBufferId() { return nmeView->defaultFramebuffer; }; @@ -1836,10 +1836,10 @@ -(void)removeMovieNotificationHandlers [nmeView tearDown]; } -void NMEStage::EnablePopupKeyboard(bool inEnable) +void NMEStage::PopupKeyboard(PopupKeyboardMode inMode, WString *) { - popupEnabled = inEnable; - [ nmeView enableKeyboard:inEnable]; + popupEnabled = inEnable!=pkmOff; + [ nmeView enableKeyboard:popupEnabled]; } @@ -2139,7 +2139,7 @@ - (void) dealloc void EnableKeyboard(bool inEnable) { - sgNmeStage->EnablePopupKeyboard(inEnable); + sgNmeStage->PopupKeyboard(inEnable ? pkmDumb : pkmOff); } diff --git a/project/src/sdl/SDLStage.cpp b/project/src/sdl/SDLStage.cpp index 9ba5ec890..cc47d0d6d 100644 --- a/project/src/sdl/SDLStage.cpp +++ b/project/src/sdl/SDLStage.cpp @@ -628,13 +628,13 @@ class SDLStage : public Stage SDL_WarpMouse( inX, inY ); } - void EnablePopupKeyboard (bool enabled) { + void PopupKeyboard(PopupKeyboardMode inMode, WString *) { #ifdef WEBOS if (PDL_GetPDKVersion () >= 300) { - if (enabled) { + if (inMode) { PDL_SetKeyboardState (PDL_TRUE); @@ -650,7 +650,7 @@ class SDLStage : public Stage #ifdef BLACKBERRY - if (enabled) { + if (inMode) { virtualkeyboard_show(); diff --git a/project/src/sdl2/SDL2Stage.cpp b/project/src/sdl2/SDL2Stage.cpp index 06eccc601..8bfebe42d 100644 --- a/project/src/sdl2/SDL2Stage.cpp +++ b/project/src/sdl2/SDL2Stage.cpp @@ -680,11 +680,6 @@ class SDLStage : public Stage } - void EnablePopupKeyboard(bool enabled) - { - - } - bool getMultitouchSupported() { diff --git a/project/src/winrt/WinRTStage.cpp b/project/src/winrt/WinRTStage.cpp index dabe61b2c..9fc8563e0 100644 --- a/project/src/winrt/WinRTStage.cpp +++ b/project/src/winrt/WinRTStage.cpp @@ -407,11 +407,6 @@ class WinRTStage : public Stage, public Direct3DBase } - void EnablePopupKeyboard(bool enabled) - { - } - - bool getMultitouchSupported() { return true; diff --git a/samples/02-Text/Sample.nmml b/samples/02-Text/Sample.nmml index 5a9e48b07..a378b285b 100644 --- a/samples/02-Text/Sample.nmml +++ b/samples/02-Text/Sample.nmml @@ -18,7 +18,6 @@ 1 || count > 1 || (count == 1 && s.charAt(start) == ' '); + for (int i = start; i < start + count; i++) + { + int keyCode = s.charAt(i); + if (keyCode != 0) + { + me.HandleResult(NME.onKeyChange(keyCode, keyCode, true, keyCode == 10 ? false : true)); + me.HandleResult(NME.onKeyChange(keyCode, keyCode, false, false)); + } + } + } + else + { + String replace = count==0 ? "" : s.subSequence(start,start+count).toString(); + //Log.v("VIEW*","replaced " + replace + " at " + start + " (delete =" + before + ")" ); + me.HandleResult(NME.onText(replace,start,start+before)); + } + } } ); + + ignoreTextReset = before > 1 || count > 1 || (count == 1 && s.charAt(start) == ' '); } @Override public void afterTextChanged(Editable s) { - if(!ignoreTextReset) { - // Log.v("VIEW*", "afterTextChanged [" + s + "] "); - if (s.length() != 1) { - ignoreTextReset = true; - mActivity.mKeyInTextView.setText("*"); - mActivity.mKeyInTextView.setSelection(1); - } + if (GameActivity.activity.mIncrementalText) + { + if(!ignoreTextReset) { + // Log.v("VIEW*", "afterTextChanged [" + s + "] "); + if (s.length() != 1) { + ignoreTextReset = true; + mActivity.mKeyInTextView.setText("*"); + mActivity.mKeyInTextView.setSelection(1); + } + } } ignoreTextReset = false; } @@ -265,6 +283,8 @@ public void afterTextChanged(Editable s) { mActivity.mKeyInTextView.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { + if (mActivity.mIncrementalText) + { //if (keyCode == KeyEvent.KEYCODE_ENTER) { if(event.getAction() == KeyEvent.ACTION_DOWN) { final int keyCodeDown = translateKey(keyCode,event,false); @@ -290,6 +310,7 @@ public void run() { } } //} + } return false; } }); @@ -544,7 +565,7 @@ public boolean onKeyDown(final int inKeyCode, KeyEvent event) Log.v("VIEW", "device of event is " + event.getDeviceId()); final MainView me = this; final int keyCode = translateKey(inKeyCode,event,true); - Log.v("VIEW","onKeyDown " + inKeyCode + "->" + keyCode); + // Log.v("VIEW","onKeyDown " + inKeyCode + "->" + keyCode); final int deviceId = event.getDeviceId(); if (keyCode!=0) { queueEvent(new Runnable() { @@ -566,7 +587,7 @@ public boolean onKeyUp(final int inKeyCode, KeyEvent event) Log.v("VIEW", "device of event is " + event.getDeviceId()); final MainView me = this; final int keyCode = translateKey(inKeyCode,event,true); - Log.v("VIEW","onKeyUp " + inKeyCode + "->" + keyCode); + // Log.v("VIEW","onKeyUp " + inKeyCode + "->" + keyCode); final int deviceId = event.getDeviceId(); if (keyCode!=0) {