From 4ddee931b5c1bc2b41ed245aafcb5da9a59b3b9c Mon Sep 17 00:00:00 2001 From: agra Date: Tue, 19 May 2026 23:13:51 +0300 Subject: [PATCH] ffi 1.29: retire the C sx_android_query_safe_insets body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the Phase 1D migration for the safe-insets JNI chain. The C function and its `#foreign` declaration in `android.sx` are gone; all dispatch now goes through the sx-side `#jni_call` machinery plus the JavaVM helpers landed in 1.26. What's gone from `library/vendors/sx_android_jni/sx_android_jni.c`: - `#include ` and `` (no longer needed without the JNI body). - `sx_android_query_safe_insets` — 55 lines of `(*env)->Foo` chain with manual `goto done` early-exit. Migrated to `library/modules/platform/android.sx::sx_query_safe_insets_jni` in 1.25 (15 lines of `#jni_call`). What stays: - `sx_android_install_input_handler` — non-JNI; struct-field assignment against `struct android_app`'s `onInputEvent` slot. No sx equivalent yet (would need to either land a `#android_app`- style intrinsic or hand-roll the offset, neither of which is Phase 1 scope). - `` and the `struct sx_android_app_min` mirror needed by the input-handler installer. Net diff: -55 lines in the .c file, -1 line `#foreign` decl in android.sx. Phase 2 (declarative JNI imports) will revisit whether the .c file can be deleted entirely (the input-handler hop may move into a different shape). Verification: - zig build + zig test + run_examples + cross_compile all green. Notable: the previously-failing `ffi-objc-call-12-rect-u64-returns` also passes now — looks like the working-tree `#import c` work was tidied up alongside. - chess Android APK rebuilt + reinstalled + launched on Pixel device; safe-insets behavior unchanged (board top edge sits below the status bar correctly, all pieces in starting positions, no status-bar overlap). --- library/modules/platform/android.sx | 7 +- .../vendors/sx_android_jni/sx_android_jni.c | 74 ++----------------- 2 files changed, 12 insertions(+), 69 deletions(-) diff --git a/library/modules/platform/android.sx b/library/modules/platform/android.sx index 8bd1d17..180dd4d 100644 --- a/library/modules/platform/android.sx +++ b/library/modules/platform/android.sx @@ -51,8 +51,11 @@ AMotionEvent_getAction :: (event: *void) -> s32 #foreign; AMotionEvent_getX :: (event: *void, pointer_index: u64) -> f32 #foreign; AMotionEvent_getY :: (event: *void, pointer_index: u64) -> f32 #foreign; -// JNI/glue bridges from vendors/sx_android_jni/sx_android_jni.c. -sx_android_query_safe_insets :: (activity: *void, top: *s32, left: *s32, bottom: *s32, right: *s32) -> void #foreign; +// Glue bridge from vendors/sx_android_jni/sx_android_jni.c. The +// safe-insets JNI chain that used to live in that file was migrated +// to sx (see `sx_query_safe_insets_jni` below) — what remains is the +// input-handler installer, which is plain struct-field plumbing +// rather than JNI dispatch. sx_android_install_input_handler :: (app: *void, handler: (*void, *void) -> s32) -> void #foreign; // JavaVM vtable indirection — used to attach the calling thread to diff --git a/library/vendors/sx_android_jni/sx_android_jni.c b/library/vendors/sx_android_jni/sx_android_jni.c index cc1edb9..c1f77cc 100644 --- a/library/vendors/sx_android_jni/sx_android_jni.c +++ b/library/vendors/sx_android_jni/sx_android_jni.c @@ -2,11 +2,16 @@ // so consumers don't need to vendor an identically-named copy. The sx // compiler resolves `#source "vendors/..."` against the stdlib search // paths in addition to the consumer's project root. +// +// The safe-insets JNI chain that used to live here was migrated to +// sx in Phase 1D of the FFI plan (see `library/modules/platform/ +// android.sx::sx_query_safe_insets_jni` and the JavaVM helpers +// alongside it). What remains is the input-handler installer, which +// is a plain C struct-field assignment rather than JNI dispatch and +// has no sx equivalent yet. #ifdef __ANDROID__ -#include #include -#include // Mirror of struct android_app (NDK 29 / arm64) up to the fields we touch. // Avoids depending on the glue header in the sx library compile path. @@ -26,69 +31,4 @@ void sx_android_install_input_handler(void* app, struct sx_android_app_min* a = (struct sx_android_app_min*)app; a->onInputEvent = (int (*)(struct sx_android_app_min*, AInputEvent*))handler; } - -// Query system-bar insets (status bar, nav bar) via JNI: -// activity → getWindow() → getDecorView() -// → getRootWindowInsets() -// → getSystemWindowInset[Top|Left|Bottom|Right]() -// Out params receive physical-pixel insets; the sx caller divides by -// dpi_scale to convert to logical units. Falls back to zeros if the -// view isn't attached yet (e.g. called before the first frame). -void sx_android_query_safe_insets(void* activity_ptr, - int* out_top, int* out_left, - int* out_bottom, int* out_right) { - *out_top = 0; *out_left = 0; *out_bottom = 0; *out_right = 0; - if (activity_ptr == 0) return; - - ANativeActivity* act = (ANativeActivity*)activity_ptr; - JavaVM* vm = act->vm; - if (vm == 0) return; - - JNIEnv* env = 0; - int already_attached = 1; - if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { - already_attached = 0; - if ((*vm)->AttachCurrentThread(vm, &env, 0) != 0) return; - } - - jobject activity_obj = act->clazz; - jclass activity_cls = (*env)->GetObjectClass(env, activity_obj); - - jmethodID m_getWindow = (*env)->GetMethodID(env, activity_cls, - "getWindow", "()Landroid/view/Window;"); - if (m_getWindow == 0) goto done; - jobject window = (*env)->CallObjectMethod(env, activity_obj, m_getWindow); - if (window == 0) goto done; - - jclass window_cls = (*env)->GetObjectClass(env, window); - jmethodID m_getDecorView = (*env)->GetMethodID(env, window_cls, - "getDecorView", "()Landroid/view/View;"); - if (m_getDecorView == 0) goto done; - jobject decor = (*env)->CallObjectMethod(env, window, m_getDecorView); - if (decor == 0) goto done; - - jclass view_cls = (*env)->GetObjectClass(env, decor); - jmethodID m_getRootInsets = (*env)->GetMethodID(env, view_cls, - "getRootWindowInsets", "()Landroid/view/WindowInsets;"); - if (m_getRootInsets == 0) goto done; - jobject insets = (*env)->CallObjectMethod(env, decor, m_getRootInsets); - if (insets == 0) goto done; - - jclass insets_cls = (*env)->GetObjectClass(env, insets); - jmethodID m_top = (*env)->GetMethodID(env, insets_cls, - "getSystemWindowInsetTop", "()I"); - jmethodID m_left = (*env)->GetMethodID(env, insets_cls, - "getSystemWindowInsetLeft", "()I"); - jmethodID m_bottom = (*env)->GetMethodID(env, insets_cls, - "getSystemWindowInsetBottom", "()I"); - jmethodID m_right = (*env)->GetMethodID(env, insets_cls, - "getSystemWindowInsetRight", "()I"); - if (m_top) *out_top = (*env)->CallIntMethod(env, insets, m_top); - if (m_left) *out_left = (*env)->CallIntMethod(env, insets, m_left); - if (m_bottom) *out_bottom = (*env)->CallIntMethod(env, insets, m_bottom); - if (m_right) *out_right = (*env)->CallIntMethod(env, insets, m_right); - -done: - if (!already_attached) (*vm)->DetachCurrentThread(vm); -} #endif