Preparing to create a new InputConnection for text input on android
This commit is contained in:
parent
8f21dd0a88
commit
1585e0aa67
10 changed files with 585 additions and 17 deletions
|
|
@ -30,6 +30,7 @@ option(MACOS_MAKE_BUNDLE "Package the application as a bundle" ON)
|
|||
set(sources "src/main.cpp"
|
||||
"src/SwitchCWD.cpp"
|
||||
"src/MainProgram.cpp"
|
||||
"src/AndroidJNICalls.cpp"
|
||||
"src/DrawData.cpp"
|
||||
"src/FontData.cpp"
|
||||
"src/ClientData.cpp"
|
||||
|
|
|
|||
4
android-project/app/proguard-rules.pro
vendored
4
android-project/app/proguard-rules.pro
vendored
|
|
@ -16,6 +16,10 @@
|
|||
# public *;
|
||||
#}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class com.erroratline0.infinipaint.InfiniPaint {
|
||||
void startTextInput();
|
||||
}
|
||||
|
||||
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity {
|
||||
java.lang.String nativeGetHint(java.lang.String); # Java-side doesn't use this, so it gets minified, but C-side still tries to register it
|
||||
java.lang.String clipboardGetText();
|
||||
|
|
|
|||
|
|
@ -3,11 +3,17 @@ package com.erroratline0.infinipaint;
|
|||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import org.libsdl.app.SDLActivity;
|
||||
import org.libsdl.app.SDLDummyEdit;
|
||||
import org.libsdl.app.SDLSurface;
|
||||
|
||||
/**
|
||||
|
|
@ -15,6 +21,7 @@ import org.libsdl.app.SDLSurface;
|
|||
*/
|
||||
|
||||
public class InfiniPaint extends SDLActivity {
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Window window = this.getWindow();
|
||||
|
|
@ -31,4 +38,34 @@ public class InfiniPaint extends SDLActivity {
|
|||
protected SDLSurface createSDLSurface(Context context) {
|
||||
return new InfiniPaintSurface(context);
|
||||
}
|
||||
|
||||
static class StartInfiniPaintTextInputTask implements Runnable {
|
||||
public StartInfiniPaintTextInputTask() {}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(1, 1);
|
||||
|
||||
if (mTextEdit == null) {
|
||||
mTextEdit = new InfiniPaintTextBoxView(getContext());
|
||||
mLayout.addView(mTextEdit, params);
|
||||
}
|
||||
else
|
||||
mTextEdit.setLayoutParams(params);
|
||||
|
||||
mTextEdit.setVisibility(View.VISIBLE);
|
||||
mTextEdit.requestFocus();
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(mTextEdit, 0);
|
||||
|
||||
if (imm.isAcceptingText())
|
||||
onNativeScreenKeyboardShown();
|
||||
}
|
||||
}
|
||||
|
||||
static public void startTextInput() {
|
||||
mSingleton.commandHandler.post(new StartInfiniPaintTextInputTask());
|
||||
}
|
||||
|
||||
static InfiniPaintTextBoxView mTextEdit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,330 @@
|
|||
package com.erroratline0.infinipaint;
|
||||
|
||||
import static android.text.TextUtils.CAP_MODE_SENTENCES;
|
||||
|
||||
import android.content.*;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.text.Editable;
|
||||
import android.view.*;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.CorrectionInfo;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.HandwritingGesture;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputContentInfo;
|
||||
import android.view.inputmethod.PreviewableHandwritingGesture;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
import android.view.inputmethod.TextAttribute;
|
||||
import android.view.inputmethod.TextBoundsInfoResult;
|
||||
import android.view.inputmethod.TextSnapshot;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
import android.content.*;
|
||||
import android.os.Build;
|
||||
import android.text.Editable;
|
||||
import android.view.*;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.libsdl.app.SDL;
|
||||
import org.libsdl.app.SDLActivity;
|
||||
|
||||
class InfiniPaintTextBoxInputConnection extends BaseInputConnection
|
||||
{
|
||||
protected EditText mEditText;
|
||||
protected String mCommittedText = "";
|
||||
|
||||
InfiniPaintTextBoxInputConnection(View targetView, boolean fullEditor) {
|
||||
super(targetView, fullEditor);
|
||||
mEditText = new EditText(SDL.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editable getEditable() {
|
||||
return mEditText.getEditableText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendKeyEvent(KeyEvent event) {
|
||||
/*
|
||||
* This used to handle the keycodes from soft keyboard (and IME-translated input from hardkeyboard)
|
||||
* However, as of Ice Cream Sandwich and later, almost all soft keyboard doesn't generate key presses
|
||||
* and so we need to generate them ourselves in commitText. To avoid duplicates on the handful of keys
|
||||
* that still do, we empty this out.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return DOES still generate a key event, however. So rather than using it as the 'click a button' key
|
||||
* as we do with physical keyboards, let's just use it to hide the keyboard.
|
||||
*/
|
||||
|
||||
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
|
||||
if (SDLActivity.onNativeSoftReturnKey()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.sendKeyEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||
if (!super.commitText(text, newCursorPosition)) {
|
||||
return false;
|
||||
}
|
||||
updateText();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
||||
if (!super.setComposingText(text, newCursorPosition)) {
|
||||
return false;
|
||||
}
|
||||
updateText();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
||||
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions>/14560344/android-backspace-in-webview-baseinputconnection
|
||||
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
|
||||
if (beforeLength > 0 && afterLength == 0) {
|
||||
// backspace(s)
|
||||
while (beforeLength-- > 0) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!super.deleteSurroundingText(beforeLength, afterLength)) {
|
||||
return false;
|
||||
}
|
||||
updateText();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updateText() {
|
||||
final Editable content = getEditable();
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String text = content.toString();
|
||||
int compareLength = Math.min(text.length(), mCommittedText.length());
|
||||
int matchLength, offset;
|
||||
|
||||
/* Backspace over characters that are no longer in the string */
|
||||
for (matchLength = 0; matchLength < compareLength; ) {
|
||||
int codePoint = mCommittedText.codePointAt(matchLength);
|
||||
if (codePoint != text.codePointAt(matchLength)) {
|
||||
break;
|
||||
}
|
||||
matchLength += Character.charCount(codePoint);
|
||||
}
|
||||
/* FIXME: This doesn't handle graphemes, like '🌬️' */
|
||||
for (offset = matchLength; offset < mCommittedText.length(); ) {
|
||||
int codePoint = mCommittedText.codePointAt(offset);
|
||||
offset += Character.charCount(codePoint);
|
||||
}
|
||||
|
||||
if (matchLength < text.length()) {
|
||||
String pendingText = text.subSequence(matchLength, text.length()).toString();
|
||||
if (!SDLActivity.dispatchingKeyEvent()) {
|
||||
for (offset = 0; offset < pendingText.length(); ) {
|
||||
int codePoint = pendingText.codePointAt(offset);
|
||||
if (codePoint == '\n') {
|
||||
if (SDLActivity.onNativeSoftReturnKey()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Higher code points don't generate simulated scancodes */
|
||||
if (codePoint > 0 && codePoint < 128) {
|
||||
}
|
||||
offset += Character.charCount(codePoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
mCommittedText = text;
|
||||
}
|
||||
}
|
||||
|
||||
//class InfiniPaintTextBoxInputConnection extends BaseInputConnection {
|
||||
// InfiniPaintTextBoxInputConnection(View targetView, boolean fullEditor) {
|
||||
// super(targetView, fullEditor);
|
||||
// }
|
||||
//
|
||||
// public native void nativeBeginBatchEdit();
|
||||
// public native void nativeClearMetaKeyStates(int states);
|
||||
// public native void nativeSetComposingText(CharSequence text, int newCursorPosition);
|
||||
// public native void nativeSetComposingRegion(int start, int end);
|
||||
// public native void nativeSetSelection(int start, int end);
|
||||
// public native void nativeCommitCorrection(int offset, CharSequence oldText, CharSequence newText);
|
||||
// public native void nativeCommitText(CharSequence text, int newCursorPosition);
|
||||
// public native void nativeDeleteSurroundingText(int beforeLength, int afterLength);
|
||||
// public native void nativeDeleteSurroundingTextInCodePoints(int beforeLength, int afterLength);
|
||||
// public native void nativeEndBatchEdit();
|
||||
// public native void nativeFinishComposingText();
|
||||
// public native CharSequence nativeGetSelectedText();
|
||||
// public native CharSequence nativeGetTextAfterCursor(int n);
|
||||
// public native CharSequence nativeGetTextBeforeCursor(int n);
|
||||
// public native void nativePerformContextMenuAction(int action);
|
||||
// public native void nativePerformEditorAction(int action);
|
||||
//
|
||||
// @Override
|
||||
// public boolean beginBatchEdit() {
|
||||
// nativeBeginBatchEdit();
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean clearMetaKeyStates(int states) {
|
||||
// nativeClearMetaKeyStates(states);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean performSpellCheck() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public TextSnapshot takeSnapshot() {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public CharSequence getTextBeforeCursor(int n, int flags) {
|
||||
// return nativeGetTextBeforeCursor(n);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public CharSequence getTextAfterCursor(int n, int flags) {
|
||||
// return nativeGetTextAfterCursor(n);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public CharSequence getSelectedText(int i) {
|
||||
// return nativeGetSelectedText();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getCursorCapsMode(int i) {
|
||||
// return CAP_MODE_SENTENCES;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ExtractedText getExtractedText(ExtractedTextRequest extractedTextRequest, int i) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean deleteSurroundingText(int i, int i1) {
|
||||
// nativeDeleteSurroundingText(i, i1);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
|
||||
// nativeDeleteSurroundingTextInCodePoints(beforeLength, afterLength);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean setComposingRegion(int i, int i1) {
|
||||
// nativeSetComposingRegion(i, i1);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean finishComposingText() {
|
||||
// nativeFinishComposingText();
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean commitCompletion(CompletionInfo completionInfo) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean commitCorrection(CorrectionInfo correctionInfo) {
|
||||
// nativeCommitCorrection(correctionInfo.getOffset(), correctionInfo.getOldText(), correctionInfo.getNewText());
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean setSelection(int i, int i1) {
|
||||
// nativeSetSelection(i, i1);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean performEditorAction(int i) {
|
||||
// nativePerformEditorAction(i);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean performContextMenuAction(int i) {
|
||||
// nativePerformContextMenuAction(i);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean endBatchEdit() {
|
||||
// nativeEndBatchEdit();
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean sendKeyEvent(KeyEvent keyEvent) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean reportFullscreenMode(boolean b) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean performPrivateCommand(String s, Bundle bundle) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean requestCursorUpdates(int i) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Handler getHandler() {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean commitContent(InputContentInfo inputContentInfo, int i, Bundle bundle) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||
// nativeCommitText(text, newCursorPosition);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
||||
// nativeSetComposingText(text, newCursorPosition);
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.erroratline0.infinipaint;
|
||||
|
||||
import android.content.*;
|
||||
import android.text.InputType;
|
||||
import android.view.*;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
public class InfiniPaintTextBoxView extends View
|
||||
{
|
||||
InputConnection ic;
|
||||
|
||||
InfiniPaintTextBoxView(Context context) {
|
||||
super(context);
|
||||
setFocusableInTouchMode(true);
|
||||
setFocusable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckIsTextEditor() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||
ic = new InfiniPaintTextBoxInputConnection(this, true);
|
||||
|
||||
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
|
||||
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI |
|
||||
EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */ |
|
||||
EditorInfo.IME_ACTION_DONE;
|
||||
|
||||
return ic;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -980,7 +980,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||
}
|
||||
|
||||
// Handler for the messages
|
||||
Handler commandHandler = new SDLCommandHandler();
|
||||
public Handler commandHandler = new SDLCommandHandler();
|
||||
|
||||
// Send a message from the SDLMain thread
|
||||
protected boolean sendCommand(int command, Object data) {
|
||||
|
|
|
|||
148
src/AndroidJNICalls.cpp
Normal file
148
src/AndroidJNICalls.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#ifdef __ANDROID__
|
||||
#include "AndroidJNICalls.hpp"
|
||||
#include <jni.h>
|
||||
#include "InputManager.hpp"
|
||||
#include "MainProgram.hpp"
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <Helpers/Logger.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace AndroidJNICalls {
|
||||
InputManager* globalInputManager;
|
||||
std::mutex globalCallMutex;
|
||||
|
||||
void startTextInput() {
|
||||
JNIEnv* env = static_cast<JNIEnv*>(SDL_GetAndroidJNIEnv());
|
||||
Logger::get().log("INFO", std::to_string((uint64_t)env) + " jni env value");
|
||||
jobject activity = (jobject)SDL_GetAndroidActivity();
|
||||
Logger::get().log("INFO", std::to_string((uint64_t)activity) + " activity value");
|
||||
jclass clazz = env->GetObjectClass(activity);
|
||||
jmethodID method_id = env->GetStaticMethodID(clazz, "startTextInput", "()V");
|
||||
Logger::get().log("INFO", std::to_string((uint64_t)method_id) + " method value");
|
||||
env->CallStaticVoidMethod(clazz, method_id);
|
||||
env->DeleteLocalRef(activity);
|
||||
env->DeleteLocalRef(clazz);
|
||||
}
|
||||
|
||||
void stopTextInput() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
jobject activity;
|
||||
jmethodID startTextInputMethod;
|
||||
JNIEnv* jniEnv;
|
||||
|
||||
using namespace AndroidJNICalls;
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintSurface_nativeInfiniPaintUpdateIMESafeArea(JNIEnv *env, jclass clazz, jint top, jint bottom, jint left, jint right) {
|
||||
if(globalInputManager) {
|
||||
std::scoped_lock a{globalInputManager->safeAreaWithoutIMEMutex};
|
||||
globalInputManager->safeAreaWithoutIME = {{left, top}, {globalInputManager->main.window.size.x() - right, globalInputManager->main.window.size.y() - bottom}};
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeBeginBatchEdit(
|
||||
JNIEnv *env, jobject jobject1) {
|
||||
// TODO: implement nativeBeginBatchEdit()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeClearMetaKeyStates(
|
||||
JNIEnv *env, jobject jobject1, jint states) {
|
||||
// TODO: implement nativeClearMetaKeyStates()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeSetComposingText(
|
||||
JNIEnv *env, jobject jobject1, jobject text, jint new_cursor_position) {
|
||||
// TODO: implement nativeSetComposingText()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeSetComposingRegion(
|
||||
JNIEnv *env, jobject jobject1, jint start, jint end) {
|
||||
// TODO: implement nativeSetComposingRegion()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeSetSelection(JNIEnv *env,
|
||||
jobject jobject1,
|
||||
jint start,
|
||||
jint end) {
|
||||
// TODO: implement nativeSetSelection()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeCommitCorrection(
|
||||
JNIEnv *env, jobject jobject1, jint offset, jobject old_text, jobject new_text) {
|
||||
// TODO: implement nativeCommitCorrection()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeCommitText(JNIEnv *env,
|
||||
jobject jobject1,
|
||||
jobject text,
|
||||
jint new_cursor_position) {
|
||||
// TODO: implement nativeCommitText()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeDeleteSurroundingText(
|
||||
JNIEnv *env, jobject jobject1, jint before_length, jint after_length) {
|
||||
// TODO: implement nativeDeleteSurroundingText()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeDeleteSurroundingTextInCodePoints(
|
||||
JNIEnv *env, jobject jobject1, jint before_length, jint after_length) {
|
||||
// TODO: implement nativeDeleteSurroundingTextInCodePoints()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeEndBatchEdit(JNIEnv *env,
|
||||
jobject jobject1) {
|
||||
// TODO: implement nativeEndBatchEdit()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeFinishComposingText(
|
||||
JNIEnv *env, jobject jobject1) {
|
||||
// TODO: implement nativeFinishComposingText()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeGetSelectedText(
|
||||
JNIEnv *env, jobject jobject1) {
|
||||
// TODO: implement nativeGetSelectedText()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeGetTextAfterCursor(
|
||||
JNIEnv *env, jobject jobject1, jint n) {
|
||||
// TODO: implement nativeGetTextAfterCursor()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativeGetTextBeforeCursor(
|
||||
JNIEnv *env, jobject jobject1, jint n) {
|
||||
// TODO: implement nativeGetTextBeforeCursor()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativePerformContextMenuAction(
|
||||
JNIEnv *env, jobject jobject1, jint action) {
|
||||
// TODO: implement nativePerformContextMenuAction()
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintTextBoxInputConnection_nativePerformEditorAction(
|
||||
JNIEnv *env, jobject jobject1, jint action) {
|
||||
// TODO: implement nativePerformEditorAction()
|
||||
}
|
||||
|
||||
#endif
|
||||
14
src/AndroidJNICalls.hpp
Normal file
14
src/AndroidJNICalls.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#ifdef __ANDROID__
|
||||
#include <mutex>
|
||||
|
||||
struct InputManager;
|
||||
|
||||
namespace AndroidJNICalls {
|
||||
extern InputManager* globalInputManager;
|
||||
extern std::mutex globalCallMutex;
|
||||
|
||||
void startTextInput();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -12,8 +12,7 @@
|
|||
|
||||
#include <Helpers/Logger.hpp>
|
||||
#include "MainProgram.hpp"
|
||||
|
||||
InputManager* globalInputManager = nullptr;
|
||||
#include "AndroidJNICalls.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <include/core/SkStream.h>
|
||||
|
|
@ -32,21 +31,11 @@ extern "C" {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <jni.h>
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_erroratline0_infinipaint_InfiniPaintSurface_nativeInfiniPaintUpdateIMESafeArea(JNIEnv *env, jclass clazz, jint top, jint bottom, jint left, jint right) {
|
||||
if(globalInputManager)
|
||||
globalInputManager->safeAreaWithoutIME = {{left, top}, {globalInputManager->main.window.size.x() - right, globalInputManager->main.window.size.y() - bottom}};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
InputManager::InputManager(MainProgram& initMain):
|
||||
main(initMain) {
|
||||
globalInputManager = this;
|
||||
#ifdef __ANDROID__
|
||||
AndroidJNICalls::globalInputManager = this;
|
||||
#endif
|
||||
|
||||
frame_reset({0, 0});
|
||||
|
||||
|
|
@ -167,7 +156,13 @@ void InputManager::update_accepting_input(SDL_Window* window) {
|
|||
excludeIMEFromSafeArea = false;
|
||||
else
|
||||
excludeIMEFromSafeArea = true;
|
||||
SDL_StartTextInputWithProperties(window, propIDVal);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
AndroidJNICalls::startTextInput();
|
||||
#else
|
||||
SDL_StartTextInputWithProperties(window, propIDVal);
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
isAcceptingInputEmscripten = 1;
|
||||
#endif
|
||||
|
|
@ -875,6 +870,7 @@ void InputManager::update_safe_area() {
|
|||
else
|
||||
main.window.safeArea = SCollision::AABB<float>({0, 0}, {main.window.size.x(), main.window.size.y()});
|
||||
|
||||
std::scoped_lock a{safeAreaWithoutIMEMutex};
|
||||
if(excludeIMEFromSafeArea && safeAreaWithoutIME.has_value())
|
||||
main.window.safeArea = safeAreaWithoutIME.value();
|
||||
}
|
||||
|
|
@ -1148,6 +1144,7 @@ void InputManager::update() {
|
|||
constexpr float PADDING_BETWEEN_TEXTBOX_AND_IME = 15.0f;
|
||||
if(!text.textBoxes.empty()) {
|
||||
auto& r = text.textBoxes.front().rect;
|
||||
std::scoped_lock a{safeAreaWithoutIMEMutex};
|
||||
if(r.has_value() && safeAreaWithoutIME.has_value()) {
|
||||
float bottomY = r.value().max.y();
|
||||
float yLimit = safeAreaWithoutIME.value().max.y() - PADDING_BETWEEN_TEXTBOX_AND_IME;
|
||||
|
|
|
|||
|
|
@ -414,6 +414,7 @@ struct InputManager {
|
|||
float scale;
|
||||
};
|
||||
|
||||
std::mutex safeAreaWithoutIMEMutex;
|
||||
std::optional<SCollision::AABB<float>> safeAreaWithoutIME;
|
||||
bool excludeIMEFromSafeArea = false;
|
||||
Vector2f screenOffset = {0.0f, 0.0f};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue