Preparing to create a new InputConnection for text input on android

This commit is contained in:
Yousef Khadadeh 2026-05-05 18:51:10 +03:00
parent 8f21dd0a88
commit 1585e0aa67
10 changed files with 585 additions and 17 deletions

148
src/AndroidJNICalls.cpp Normal file
View 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
View 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

View file

@ -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;

View file

@ -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};