From 500723614b8a726b05b2fc8f6331d5ef182edd8a Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 7 Nov 2025 17:50:47 +1100 Subject: [PATCH] Android: Get surface width/height from Java side instead --- android/app/CMakeLists.txt | 3 +- .../java/com/classicube/MainActivity.java | 25 ++-- src/android/Platform_Android.c | 129 +++++++++--------- src/android/Window_Android.c | 43 +++--- src/android/interop_android.h | 13 -- 5 files changed, 106 insertions(+), 107 deletions(-) diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt index e80340188..912f74f96 100644 --- a/android/app/CMakeLists.txt +++ b/android/app/CMakeLists.txt @@ -232,5 +232,4 @@ target_link_libraries(classicube android EGL GLESv2 - log - jnigraphics) + log) diff --git a/android/app/src/main/java/com/classicube/MainActivity.java b/android/app/src/main/java/com/classicube/MainActivity.java index ec9885fdb..4d77de4c5 100644 --- a/android/app/src/main/java/com/classicube/MainActivity.java +++ b/android/app/src/main/java/com/classicube/MainActivity.java @@ -26,6 +26,7 @@ import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.PixelFormat; +import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.provider.OpenableColumns; @@ -120,10 +121,14 @@ public class MainActivity extends Activity pending.add(args); } - public void pushCmd(int cmd, Surface surface) { + public void pushCmd(int cmd, SurfaceHolder holder) { NativeCmdArgs args = getCmdArgs(); - args.cmd = cmd; - args.sur = surface; + Rect rect = holder.getSurfaceFrame(); + + args.cmd = cmd; + args.sur = holder.getSurface(); + args.arg1 = rect.width(); + args.arg2 = rect.height(); pending.add(args); } @@ -350,9 +355,9 @@ public class MainActivity extends Activity case CMD_GPAD_AXISL: processJoystickL(c.arg1, c.arg2); break; case CMD_GPAD_AXISR: processJoystickR(c.arg1, c.arg2); break; - case CMD_WIN_CREATED: processSurfaceCreated(c.sur); break; + case CMD_WIN_CREATED: processSurfaceCreated(c.sur, c.arg1, c.arg2); break; case CMD_WIN_DESTROYED: processSurfaceDestroyed(); break; - case CMD_WIN_RESIZED: processSurfaceResized(c.sur); break; + case CMD_WIN_RESIZED: processSurfaceResized(c.arg1, c.arg2); break; case CMD_WIN_REDRAW: processSurfaceRedrawNeeded(); break; case CMD_APP_START: processOnStart(); break; @@ -387,9 +392,9 @@ public class MainActivity extends Activity native void processJoystickL(int x, int y); native void processJoystickR(int x, int y); - native void processSurfaceCreated(Surface sur); + native void processSurfaceCreated(Surface sur, int w, int h); native void processSurfaceDestroyed(); - native void processSurfaceResized(Surface sur); + native void processSurfaceResized(int w, int h); native void processSurfaceRedrawNeeded(); native void processOnStart(); @@ -444,13 +449,15 @@ public class MainActivity extends Activity public void surfaceCreated(SurfaceHolder holder) { // getSurface - API level 1 Log.i("CC_WIN", "win created " + holder.getSurface()); - MainActivity.this.pushCmd(CMD_WIN_CREATED, holder.getSurface()); + Rect r = holder.getSurfaceFrame(); + MainActivity.this.pushCmd(CMD_WIN_CREATED, holder); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // getSurface - API level 1 Log.i("CC_WIN", "win changed " + holder.getSurface()); - MainActivity.this.pushCmd(CMD_WIN_RESIZED, holder.getSurface()); + Rect r = holder.getSurfaceFrame(); + MainActivity.this.pushCmd(CMD_WIN_RESIZED, holder); } public void surfaceDestroyed(SurfaceHolder holder) { diff --git a/src/android/Platform_Android.c b/src/android/Platform_Android.c index c96b5e609..9c99f1ea1 100644 --- a/src/android/Platform_Android.c +++ b/src/android/Platform_Android.c @@ -12,6 +12,14 @@ #include #include +static jmethodID JAVA_getApkUpdateTime; +static jmethodID JAVA_shareScreenshot; +static jmethodID JAVA_getGameDataDir; +static jmethodID JAVA_getGameCacheDir; +static jmethodID JAVA_startOpen; +static jmethodID JAVA_getUUID; + + /*########################################################################################################################* *-----------------------------------------------------Main entrypoint-----------------------------------------------------* *#########################################################################################################################*/ @@ -43,8 +51,15 @@ void Platform_Log(const char* msg, int len) { /*########################################################################################################################* *-----------------------------------------------------Process/Module------------------------------------------------------* *#########################################################################################################################*/ -cc_result Process_StartOpen(const cc_string* args) { - JavaCall_String_Void("startOpen", args); +cc_result Process_StartOpen(const cc_string* open_args) { + JNIEnv* env; + jvalue args[1]; + Java_GetCurrentEnv(env); + + args[0].l = Java_AllocString(env, open_args); + Java_ICall_Void(env, JAVA_startOpen, args); + + Java_DeleteLocalRef(env, args[0].l); return 0; } @@ -60,7 +75,8 @@ cc_bool Updater_Clean(void) { return true; } cc_result Updater_GetBuildTime(cc_uint64* t) { JNIEnv* env; Java_GetCurrentEnv(env); - *t = JavaCallLong(env, "getApkUpdateTime", "()J", NULL); + + *t = Java_ICall_Long(env, JAVA_getApkUpdateTime, NULL); return 0; } @@ -87,19 +103,34 @@ void Platform_TryLogJavaError(void) { } void Platform_ShareScreenshot(const cc_string* filename) { - cc_string path; char pathBuffer[FILENAME_SIZE]; - String_InitArray(path, pathBuffer); + cc_string errMsg; char buffer[FILENAME_SIZE]; + String_InitArray(errMsg, buffer); + + JNIEnv* env; + jobject obj; + jvalue args[1]; + Java_GetCurrentEnv(env); - JavaCall_String_String("shareScreenshot", filename, &path); - if (!path.length) return; + args[0].l = Java_AllocString(env, filename); + obj = Java_ICall_Obj(env, JAVA_shareScreenshot, args); + Java_DecodeString(env, obj, &errMsg); + + Java_DeleteLocalRef(env, args[0].l); + Java_DeleteLocalRef(env, obj); + if (!errMsg.length) return; Chat_AddRaw("&cError sharing screenshot"); - Chat_Add1(" &c%s", &path); + Chat_Add1(" &c%s", &errMsg); } void Directory_GetCachePath(cc_string* path) { - // TODO cache method ID - JavaCall_Void_String("getGameCacheDirectory", path); + JNIEnv* env; + Java_GetCurrentEnv(env); + + jobject obj = Java_ICall_Obj(env, JAVA_getGameCacheDir, NULL); + Java_DecodeString(env, obj, path); + + Java_DeleteLocalRef(env, obj); } /* All threads using JNI must detach BEFORE they exit */ @@ -120,8 +151,14 @@ void* ExecThread(void* param) { cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { cc_string dir; char dirBuffer[FILENAME_SIZE + 1]; String_InitArray_NT(dir, dirBuffer); + JNIEnv* env; + Java_GetCurrentEnv(env); - JavaCall_Void_String("getGameDataDirectory", &dir); + jobject obj = Java_ICall_Obj(env, JAVA_getGameDataDir, NULL); + Java_DecodeString(env, obj, &dir); + + Java_DeleteLocalRef(env, obj); + // TODO should be raw path dir.buffer[dir.length] = '\0'; Platform_Log1("DATA DIR: %s|", &dir); @@ -135,7 +172,13 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { } void GetDeviceUUID(cc_string* str) { - JavaCall_Void_String("getUUID", str); + JNIEnv* env; + Java_GetCurrentEnv(env); + + jobject obj = Java_ICall_Obj(env, JAVA_getUUID, NULL); + Java_DecodeString(env, obj, str); + + Java_DeleteLocalRef(env, obj); } @@ -165,6 +208,7 @@ cc_string JavaGetString(JNIEnv* env, jstring str, char* buffer) { void Java_DecodeString(JNIEnv* env, jstring str, cc_string* dst) { const jchar* src; jsize len; + if (!str) return; src = (*env)->GetStringChars(env, str, NULL); len = (*env)->GetStringLength(env, str); @@ -193,57 +237,6 @@ jbyteArray Java_AllocBytes(JNIEnv* env, const void* src, cc_uint32 len) { return arr; } -void JavaCallVoid(JNIEnv* env, const char* name, const char* sig, jvalue* args) { - jmethodID method = (*env)->GetMethodID(env, App_Class, name, sig); - (*env)->CallVoidMethodA(env, App_Instance, method, args); -} - -jlong JavaCallLong(JNIEnv* env, const char* name, const char* sig, jvalue* args) { - jmethodID method = (*env)->GetMethodID(env, App_Class, name, sig); - return (*env)->CallLongMethodA(env, App_Instance, method, args); -} - -jobject JavaCallObject(JNIEnv* env, const char* name, const char* sig, jvalue* args) { - jmethodID method = (*env)->GetMethodID(env, App_Class, name, sig); - return (*env)->CallObjectMethodA(env, App_Instance, method, args); -} - -void JavaCall_String_Void(const char* name, const cc_string* value) { - JNIEnv* env; - jvalue args[1]; - Java_GetCurrentEnv(env); - - args[0].l = Java_AllocString(env, value); - JavaCallVoid(env, name, "(Ljava/lang/String;)V", args); - - Java_DeleteLocalRef(env, args[0].l); -} - -void JavaCall_Void_String(const char* name, cc_string* dst) { - JNIEnv* env; - jobject obj; - Java_GetCurrentEnv(env); - - obj = JavaCallObject(env, name, "()Ljava/lang/String;", NULL); - if (obj) Java_DecodeString(env, obj, dst); - - Java_DeleteLocalRef(env, obj); -} - -void JavaCall_String_String(const char* name, const cc_string* arg, cc_string* dst) { - JNIEnv* env; - jobject obj; - jvalue args[1]; - Java_GetCurrentEnv(env); - - args[0].l = Java_AllocString(env, arg); - obj = JavaCallObject(env, name, "(Ljava/lang/String;)Ljava/lang/String;", args); - if (obj) Java_DecodeString(env, obj, dst); - - Java_DeleteLocalRef(env, args[0].l); - Java_DeleteLocalRef(env, obj); -} - /*########################################################################################################################* *----------------------------------------------------Initialisation-------------------------------------------------------* @@ -271,6 +264,15 @@ static const JNINativeMethod methods[] = { { "runGameAsync", "()V", java_runGameAsync } }; +static void CacheJavaMethodRefs(JNIEnv* env) { + JAVA_getApkUpdateTime = Java_GetIMethod(env, "getApkUpdateTime", "()J"); + JAVA_shareScreenshot = Java_GetIMethod(env, "shareScreenshot", "(Ljava/lang/String;)Ljava/lang/String;"); + JAVA_getGameDataDir = Java_GetIMethod(env, "getGameDataDirectory", "()Ljava/lang/String;"); + JAVA_getGameCacheDir = Java_GetIMethod(env, "getGameCacheDirectory", "()Ljava/lang/String;"); + JAVA_startOpen = Java_GetIMethod(env, "startOpen", "(Ljava/lang/String;)V"); + JAVA_getUUID = Java_GetIMethod(env, "getUUID", "()Ljava/lang/String;"); +} + /* This method is automatically called by the Java VM when the */ /* activity java class calls 'System.loadLibrary("classicube");' */ CC_API jint JNI_OnLoad(JavaVM* vm, void* reserved) { @@ -283,5 +285,6 @@ CC_API jint JNI_OnLoad(JavaVM* vm, void* reserved) { App_Class = (*env)->NewGlobalRef(env, klass); Java_RegisterNatives(env, methods); + CacheJavaMethodRefs(env); return JNI_VERSION_1_4; } diff --git a/src/android/Window_Android.c b/src/android/Window_Android.c index 61e8a0f1c..b66c331d4 100644 --- a/src/android/Window_Android.c +++ b/src/android/Window_Android.c @@ -16,15 +16,15 @@ static ANativeWindow* win_handle; static cc_bool winCreated; static jmethodID JAVA_openKeyboard, JAVA_setKeyboardText, JAVA_closeKeyboard; static jmethodID JAVA_getWindowState, JAVA_enterFullscreen, JAVA_exitFullscreen; -static jmethodID JAVA_showAlert, JAVA_setRequestedOrientation; +static jmethodID JAVA_showAlert, JAVA_setRequestedOri; static jmethodID JAVA_openFileDialog, JAVA_saveFileDialog; static jmethodID JAVA_processedSurfaceDestroyed, JAVA_processEvents; static jmethodID JAVA_getDpiX, JAVA_getDpiY, JAVA_setupForGame; static jmethodID JAVA_getClipboardText, JAVA_setClipboardText; -static void RefreshWindowBounds(void) { - Window_Main.Width = ANativeWindow_getWidth(win_handle); - Window_Main.Height = ANativeWindow_getHeight(win_handle); +static void SetWindowBounds(int width, int height) { + Window_Main.Width = width; + Window_Main.Height = height; Platform_Log2("SCREEN BOUNDS: %i,%i", &Window_Main.Width, &Window_Main.Height); Event_RaiseVoid(&WindowEvents.Resized); } @@ -174,13 +174,13 @@ static void JNICALL java_processJoystickR(JNIEnv* env, jobject o, jint x, jint y Gamepad_SetAxis(port, PAD_AXIS_RIGHT, x / 4096.0f, y / 4096.0f, 1.0f / 60); } -static void JNICALL java_processSurfaceCreated(JNIEnv* env, jobject o, jobject surface) { +static void JNICALL java_processSurfaceCreated(JNIEnv* env, jobject o, jobject surface, jint w, jint h) { Platform_LogConst("WIN - CREATED"); win_handle = ANativeWindow_fromSurface(env, surface); winCreated = true; Window_Main.Handle.ptr = win_handle; - RefreshWindowBounds(); + SetWindowBounds(w, h); /* TODO: Restore context */ Event_RaiseVoid(&WindowEvents.Created); } @@ -198,9 +198,9 @@ static void JNICALL java_processSurfaceDestroyed(JNIEnv* env, jobject o) { Java_ICall_Void(env, JAVA_processedSurfaceDestroyed, NULL); } -static void JNICALL java_processSurfaceResized(JNIEnv* env, jobject o, jobject surface) { +static void JNICALL java_processSurfaceResized(JNIEnv* env, jobject o, jint w, jint h) { Platform_LogConst("WIN - RESIZED"); - RefreshWindowBounds(); + SetWindowBounds(w, h); } static void JNICALL java_processSurfaceRedrawNeeded(JNIEnv* env, jobject o) { @@ -267,10 +267,10 @@ static const JNINativeMethod methods[] = { { "processJoystickL", "(II)V", java_processJoystickL }, { "processJoystickR", "(II)V", java_processJoystickR }, - { "processSurfaceCreated", "(Landroid/view/Surface;)V", java_processSurfaceCreated }, - { "processSurfaceDestroyed", "()V", java_processSurfaceDestroyed }, - { "processSurfaceResized", "(Landroid/view/Surface;)V", java_processSurfaceResized }, - { "processSurfaceRedrawNeeded", "()V", java_processSurfaceRedrawNeeded }, + { "processSurfaceCreated", "(Landroid/view/Surface;II)V", java_processSurfaceCreated }, + { "processSurfaceDestroyed", "()V", java_processSurfaceDestroyed }, + { "processSurfaceResized", "(II)V", java_processSurfaceResized }, + { "processSurfaceRedrawNeeded", "()V", java_processSurfaceRedrawNeeded }, { "processOnStart", "()V", java_onStart }, { "processOnStop", "()V", java_onStop }, @@ -301,16 +301,21 @@ static void CacheJavaMethodRefs(JNIEnv* env) { JAVA_processedSurfaceDestroyed = Java_GetIMethod(env, "processedSurfaceDestroyed", "()V"); JAVA_processEvents = Java_GetIMethod(env, "processEvents", "()V"); - JAVA_showAlert = Java_GetIMethod(env, "showAlert", "(Ljava/lang/String;Ljava/lang/String;)V"); - JAVA_setRequestedOrientation = Java_GetIMethod(env, "setRequestedOrientation", "(I)V"); - JAVA_openFileDialog = Java_GetIMethod(env, "openFileDialog", "(Ljava/lang/String;)I"); - JAVA_saveFileDialog = Java_GetIMethod(env, "saveFileDialog", "(Ljava/lang/String;Ljava/lang/String;)I"); + JAVA_showAlert = Java_GetIMethod(env, "showAlert", "(Ljava/lang/String;Ljava/lang/String;)V"); + JAVA_setRequestedOri = Java_GetIMethod(env, "setRequestedOrientation", "(I)V"); + JAVA_openFileDialog = Java_GetIMethod(env, "openFileDialog", "(Ljava/lang/String;)I"); + JAVA_saveFileDialog = Java_GetIMethod(env, "saveFileDialog", "(Ljava/lang/String;Ljava/lang/String;)I"); JAVA_getClipboardText = Java_GetIMethod(env, "getClipboardText", "()Ljava/lang/String;"); JAVA_setClipboardText = Java_GetIMethod(env, "setClipboardText", "(Ljava/lang/String;)V"); } -void Window_PreInit(void) { +void Window_PreInit(void) { + JNIEnv* env; + Java_GetCurrentEnv(env); + Java_RegisterNatives(env, methods); + CacheJavaMethodRefs(env); + DisplayInfo.CursorVisible = true; } @@ -319,8 +324,6 @@ void Window_Init(void) { JNIEnv* env; /* TODO: ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0); */ Java_GetCurrentEnv(env); - Java_RegisterNatives(env, methods); - CacheJavaMethodRefs(env); Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; Input_SetTouchMode(true); @@ -608,7 +611,7 @@ void Window_LockLandscapeOrientation(cc_bool lock) { /* SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 0x00000006 */ /* SCREEN_ORIENTATION_UNSPECIFIED = 0xffffffff */ args[0].i = lock ? 0x00000006 : 0xffffffff; - Java_ICall_Void(env, JAVA_setRequestedOrientation, args); + Java_ICall_Void(env, JAVA_setRequestedOri, args); } void Window_EnableRawMouse(void) { DefaultEnableRawMouse(); } diff --git a/src/android/interop_android.h b/src/android/interop_android.h index 34fd12d5f..65f1c11d9 100644 --- a/src/android/interop_android.h +++ b/src/android/interop_android.h @@ -22,19 +22,6 @@ void Java_DecodeString(JNIEnv* env, jstring str, cc_string* dst); /* Creates a string from the given java string. buffer must be at least NATIVE_STR_LEN long. */ //cc_string Java_DecodeRaw(JNIEnv* env, jstring str, char* buffer); -/* Calls a method in the activity class that returns nothing. */ -void JavaCallVoid(JNIEnv* env, const char* name, const char* sig, jvalue* args); -/* Calls a method in the activity class that returns a jint. */ -jlong JavaCallLong(JNIEnv* env, const char* name, const char* sig, jvalue* args); -/* Calls a method in the activity class that returns a jobject. */ -jobject JavaCallObject(JNIEnv* env, const char* name, const char* sig, jvalue* args); -/* Calls a method in the activity class that takes a string and returns nothing. */ -void JavaCall_String_Void(const char* name, const cc_string* value); -/* Calls a method in the activity class that takes no arguments and returns a string. */ -void JavaCall_Void_String(const char* name, cc_string* dst); -/* Calls a method in the activity class that takes a string and returns a string. */ -void JavaCall_String_String(const char* name, const cc_string* arg, cc_string* dst); - /* Calls an instance method in the activity class that returns nothing */ #define Java_ICall_Void(env, method, args) (*env)->CallVoidMethodA(env, App_Instance, method, args) /* Calls an instance method in the activity class that returns a jint */