From f6bfb86fa5cfba35aa8e7f7c9a1e760768affcbe Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 18 Oct 2020 19:06:26 +1100 Subject: [PATCH 1/3] Take two at improving android keyboard Still has problems of a) always adding . after space b) backspacing in numeric keyboard crashing --- .../java/com/classicube/MainActivity.java | 112 ++++++++++++++++-- src/Window.c | 29 ++++- 2 files changed, 126 insertions(+), 15 deletions(-) diff --git a/android/app/src/main/java/com/classicube/MainActivity.java b/android/app/src/main/java/com/classicube/MainActivity.java index 693dae018..7dfc29a4b 100644 --- a/android/app/src/main/java/com/classicube/MainActivity.java +++ b/android/app/src/main/java/com/classicube/MainActivity.java @@ -20,6 +20,9 @@ import android.content.res.Configuration; import android.graphics.PixelFormat; import android.net.Uri; import android.os.Bundle; +import android.text.Editable; +import android.text.InputType; +import android.text.SpannableStringBuilder; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; @@ -33,6 +36,10 @@ import android.view.WindowManager; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.Window; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodManager; // implements InputQueue.Callback @@ -42,7 +49,7 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { // ====================================== // -------------- COMMANDS -------------- // ====================================== - class NativeCmdArgs { public int cmd, arg1, arg2, arg3; public Surface sur; } + class NativeCmdArgs { public int cmd, arg1, arg2, arg3; public String str; public Surface sur; } Queue nativeCmds = new ConcurrentLinkedQueue(); Queue freeCmds = new ConcurrentLinkedQueue(); @@ -66,12 +73,19 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { void pushCmd(int cmd, int a1, int a2, int a3) { NativeCmdArgs args = getCmdArgs(); - args.cmd = cmd; + args.cmd = cmd; args.arg1 = a1; args.arg2 = a2; args.arg3 = a3; nativeCmds.add(args); } + + void pushCmd(int cmd, String text) { + NativeCmdArgs args = getCmdArgs(); + args.cmd = cmd; + args.str = text; + nativeCmds.add(args); + } void pushCmd(int cmd, Surface surface) { NativeCmdArgs args = getCmdArgs(); @@ -83,6 +97,7 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { final static int CMD_KEY_DOWN = 0; final static int CMD_KEY_UP = 1; final static int CMD_KEY_CHAR = 2; + final static int CMD_KEY_TEXT = 19; final static int CMD_MOUSE_DOWN = 3; final static int CMD_MOUSE_UP = 4; @@ -108,9 +123,11 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { // --------------- EVENTS --------------- // ====================================== static boolean gameHooked; + InputMethodManager input; @Override protected void onCreate(Bundle savedInstanceState) { + input = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); Log.i("CC_WIN", "CREATE EVENT"); Window window = getWindow(); Log.i("CC_WIN", "GAME RUNNING?" + gameHooked); @@ -248,6 +265,7 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { case CMD_KEY_DOWN: processKeyDown(c.arg1); break; case CMD_KEY_UP: processKeyUp(c.arg1); break; case CMD_KEY_CHAR: processKeyChar(c.arg1); break; + case CMD_KEY_TEXT: processKeyText(c.str); break; case CMD_MOUSE_DOWN: processMouseDown(c.arg1, c.arg2, c.arg3); break; case CMD_MOUSE_UP: processMouseUp(c.arg1, c.arg2, c.arg3); break; @@ -269,7 +287,8 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { //case CMD_CONFIG_CHANGED: processOnConfigChanged(); break; case CMD_LOW_MEMORY: processOnLowMemory(); break; } - + + c.str = null; c.sur = null; // don't keep a reference to it freeCmds.add(c); } @@ -278,6 +297,7 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { native void processKeyDown(int code); native void processKeyUp(int code); native void processKeyChar(int code); + native void processKeyText(String str); native void processMouseDown(int id, int x, int y); native void processMouseUp(int id, int x, int y); @@ -351,15 +371,57 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { setContentView(curView); curView.requestFocus(); } - + class LauncherView extends SurfaceView { - - public LauncherView(Context context) { super(context); } - + public LauncherView(Context context) { + super(context); + setFocusable(true); + setFocusableInTouchMode(true); + } + @Override public boolean dispatchTouchEvent(MotionEvent ev) { return MainActivity.this.handleTouchEvent(ev) || super.dispatchTouchEvent(ev); } + + @Override + public InputConnection onCreateInputConnection(EditorInfo attrs) { + attrs.actionLabel = null; + attrs.inputType = MainActivity.this.getKeyboardType(); + attrs.imeOptions = EditorInfo.IME_ACTION_GO; + + InputConnection ic = new BaseInputConnection(this, true) { + SpannableStringBuilder kbText = new SpannableStringBuilder(MainActivity.this.keyboardText); + void updateText() { MainActivity.this.pushCmd(CMD_KEY_TEXT, kbText.toString()); } + + @Override + public Editable getEditable() { return kbText; } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + boolean success = super.setComposingText(text, newCursorPosition); + updateText(); + return success; + } + + @Override + public boolean deleteSurroundingText(int beforeLength, int afterLength) { + boolean success = super.deleteSurroundingText(beforeLength, afterLength); + updateText(); + return success; + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + boolean success = super.commitText(text, newCursorPosition); + updateText(); + return success; + } + }; + //String text = MainActivity.this.keyboardText; + //if (text != null) ic.setComposingText(text, 0); + return ic; + } } // ====================================== @@ -403,17 +465,43 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { // --------------- WINDOW --------------- // ====================================== public void setWindowTitle(String str) { setTitle(str); } - - public void openKeyboard() { - InputMethodManager input = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - View view = getWindow().getDecorView(); - input.showSoftInput(view, 0); + + volatile int keyboardType; + volatile String keyboardText = ""; + public void openKeyboard(String text, int type) { + keyboardType = type; + keyboardText = text; + //runOnUiThread(new Runnable() { + //public void run() { + // Restart view so it uses the right INPUT_TYPE + if (curView != null) input.restartInput(curView); + if (curView != null) input.showSoftInput(curView, 0); + //} + //}); } public void closeKeyboard() { InputMethodManager input = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); View view = getWindow().getDecorView(); input.hideSoftInputFromWindow(view.getWindowToken(), 0); + keyboardText = ""; + //runOnUiThread(new Runnable() { + //public void run() { + if (curView != null) input.hideSoftInputFromWindow(curView.getWindowToken(), 0); + //} + //}); + } + + public void setKeyboardText(String text) { + keyboardText = text; + // Restart view because text changed externally + if (curView != null) input.restartInput(curView); + } + + public int getKeyboardType() { + if (keyboardType == 2) return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD; + if (keyboardType == 1) return InputType.TYPE_CLASS_NUMBER; + return InputType.TYPE_CLASS_TEXT; /* TODO: This still adds a . after space */ } public String getClipboardText() { diff --git a/src/Window.c b/src/Window.c index f603908e1..dcb41c877 100644 --- a/src/Window.c +++ b/src/Window.c @@ -3684,6 +3684,14 @@ static void JNICALL java_processKeyChar(JNIEnv* env, jobject o, jint code) { } } +static void JNICALL java_processKeyText(JNIEnv* env, jobject o, jstring str) { + cc_string text = JavaGetString(env, str); + Platform_Log1("KEY - TEXT %s", &text); + + Event_RaiseString(&InputEvents.TextChanged, &text); + (*env)->ReleaseStringUTFChars(env, str, text.buffer); +} + static void JNICALL java_processMouseDown(JNIEnv* env, jobject o, jint id, jint x, jint y) { Platform_Log3("MOUSE %i - DOWN %i,%i", &id, &x, &y); Input_AddTouch(id, x, y); @@ -3773,10 +3781,11 @@ static void JNICALL java_onLowMemory(JNIEnv* env, jobject o) { /* TODO: Low memory */ } -static const JNINativeMethod methods[18] = { +static const JNINativeMethod methods[19] = { { "processKeyDown", "(I)V", java_processKeyDown }, { "processKeyUp", "(I)V", java_processKeyUp }, { "processKeyChar", "(I)V", java_processKeyChar }, + { "processKeyText", "(Ljava/lang/String;)V", java_processKeyText }, { "processMouseDown", "(III)V", java_processMouseDown }, { "processMouseUp", "(III)V", java_processMouseUp }, @@ -3959,10 +3968,24 @@ void Window_FreeFramebuffer(struct Bitmap* bmp) { void Window_OpenKeyboard(const cc_string* text, int type) { JNIEnv* env; + jvalue args[2]; JavaGetCurrentEnv(env); - JavaCallVoid(env, "openKeyboard", "()V", NULL); + + args[0].l = JavaMakeString(env, text); + args[1].i = type; + JavaCallVoid(env, "openKeyboard", "(Ljava/lang/String;I)V", args); + (*env)->DeleteLocalRef(env, args[0].l); +} + +void Window_SetKeyboardText(const cc_string* text) { + JNIEnv* env; + jvalue args[1]; + JavaGetCurrentEnv(env); + + args[0].l = JavaMakeString(env, text); + JavaCallVoid(env, "setKeyboardText", "(Ljava/lang/String;)V", args); + (*env)->DeleteLocalRef(env, args[0].l); } -void Window_SetKeyboardText(const cc_string* text) { } void Window_CloseKeyboard(void) { JNIEnv* env; From e93fa93042ff8eec199ac6ada45f7aa24984aae8 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 19 Oct 2020 21:24:45 +1100 Subject: [PATCH 2/3] Android: Fix backspace in numeric keyboard randomly crashing --- .../src/main/java/com/classicube/MainActivity.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/classicube/MainActivity.java b/android/app/src/main/java/com/classicube/MainActivity.java index 7dfc29a4b..d8139a4e7 100644 --- a/android/app/src/main/java/com/classicube/MainActivity.java +++ b/android/app/src/main/java/com/classicube/MainActivity.java @@ -22,6 +22,7 @@ import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.InputType; +import android.text.Selection; import android.text.SpannableStringBuilder; import android.util.DisplayMetrics; import android.util.Log; @@ -392,10 +393,18 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { InputConnection ic = new BaseInputConnection(this, true) { SpannableStringBuilder kbText = new SpannableStringBuilder(MainActivity.this.keyboardText); + boolean inited; void updateText() { MainActivity.this.pushCmd(CMD_KEY_TEXT, kbText.toString()); } @Override - public Editable getEditable() { return kbText; } + public Editable getEditable() { + if (!inited) { + // otherwise random crashes later with backspacing + Selection.setSelection(kbText, 0); + inited = true; + } + return kbText; + } @Override public boolean setComposingText(CharSequence text, int newCursorPosition) { From 53af396dd9fdec4a29777d348648d35fce694066 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 19 Oct 2020 23:32:14 +1100 Subject: [PATCH 3/3] Android: Fix if you leave input field with text in it then select it again, you can't backspace the text anymore --- android/app/src/main/java/com/classicube/MainActivity.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/classicube/MainActivity.java b/android/app/src/main/java/com/classicube/MainActivity.java index d8139a4e7..068db60d7 100644 --- a/android/app/src/main/java/com/classicube/MainActivity.java +++ b/android/app/src/main/java/com/classicube/MainActivity.java @@ -399,8 +399,9 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 { @Override public Editable getEditable() { if (!inited) { - // otherwise random crashes later with backspacing - Selection.setSelection(kbText, 0); + // needed to set selection, otherwise random crashes later with backspacing + // set selection to end, so backspacing after opening keyboard with text still works + Selection.setSelection(kbText, kbText.toString().length()); inited = true; } return kbText;