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) {