From 5f375edaa5a36ec7d2e26e0616bdc08f0adb51b9 Mon Sep 17 00:00:00 2001 From: keufcp <149170099+keufcp@users.noreply.github.com> Date: Thu, 13 Aug 2026 22:37:36 +0900 Subject: [PATCH 1/3] fix(android): unbreak perry-ui-android build and wire Picker onChange --- ...icker-callback-and-json-extract-pointer.md | 19 +++++++++++ crates/perry-ui-android/src/json.rs | 14 ++++---- .../main/java/com/perry/app/PerryBridge.kt | 32 +++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 changelog.d/0000-android-picker-callback-and-json-extract-pointer.md diff --git a/changelog.d/0000-android-picker-callback-and-json-extract-pointer.md b/changelog.d/0000-android-picker-callback-and-json-extract-pointer.md new file mode 100644 index 0000000000..b0e2941dde --- /dev/null +++ b/changelog.d/0000-android-picker-callback-and-json-extract-pointer.md @@ -0,0 +1,19 @@ +Fixed two Android defects that made `perry-ui-android` unbuildable and left +`Picker` inert. + +`crates/perry-ui-android/src/json.rs` still called the `is_raw_pointer` helper +that #7448 deleted, so the crate failed to compile for any Android target +(`error[E0425]: cannot find function is_raw_pointer`). #7448 converted the +object path to `extract_pointer` but not the array-element path. Routing it +through the same helper also extends the #7447 fix to array elements: the old +bit test is the IEEE-754 positive-subnormal predicate, so every positive +denormal element in a stringified array was classified as a pointer and +dereferenced. + +`PerryBridge.setSpinnerCallback` did not exist. `widgets/picker.rs` has always +called it over JNI and discarded the resulting error with `let _ =`, so +`Picker`'s `onChange` could never fire on Android — the widget rendered and +selected, and the app was simply never told. + +Neither showed up in CI because the Android jobs in `feature-matrix.yml` are +`continue-on-error: true` and push-only. diff --git a/crates/perry-ui-android/src/json.rs b/crates/perry-ui-android/src/json.rs index e251b2fa43..b69183ed83 100644 --- a/crates/perry-ui-android/src/json.rs +++ b/crates/perry-ui-android/src/json.rs @@ -552,12 +552,14 @@ unsafe fn stringify_array(ptr: *const u8, buf: &mut String) { buf.push_str("true"); } else if elem_bits == TAG_FALSE { buf.push_str("false"); - } else if elem_tag == POINTER_TAG || is_raw_pointer(elem_bits) { - let elem_ptr = if elem_tag == POINTER_TAG { - (elem_bits & POINTER_MASK) as *const u8 - } else { - elem_bits as *const u8 - }; + // #7448 converted the object path to `extract_pointer` but left this + // array-element path calling the `is_raw_pointer` it deleted, so + // perry-ui-android stopped compiling for any Android target. Routing + // it through the same helper also gives array elements the fix the + // object path already had: the old bit test was the IEEE-754 + // positive-subnormal predicate, so every positive denormal element was + // classified as a pointer and dereferenced (#7447). + } else if let Some(elem_ptr) = extract_pointer(elem_bits) { if is_object_pointer(elem_ptr) { stringify_object(elem_ptr, buf); } else { diff --git a/crates/perry-ui-android/template/app/src/main/java/com/perry/app/PerryBridge.kt b/crates/perry-ui-android/template/app/src/main/java/com/perry/app/PerryBridge.kt index 2fe2fbfad5..9076814ad9 100644 --- a/crates/perry-ui-android/template/app/src/main/java/com/perry/app/PerryBridge.kt +++ b/crates/perry-ui-android/template/app/src/main/java/com/perry/app/PerryBridge.kt @@ -426,6 +426,38 @@ object PerryBridge { seekBar.progress = progress } + // --- Spinner (Picker) callback --- + + // `perry-ui-android`'s picker.rs has always called this, but it was never + // defined here and the Rust side discarded the resulting JNI error with + // `let _ =` — so `Picker`'s onChange could not fire on Android at all. + @JvmStatic + fun setSpinnerCallback(spinner: Spinner, callbackKey: Long) { + // Spinner calls the listener once when an adapter installs the initial + // selection, and again for every later `setAdapter` — `pickerAddItem` + // rebuilds the adapter per item. None of those is a user choice, so + // report only actual changes, with the first one taken as the baseline. + var reported = -1 + spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>?, + view: View?, + position: Int, + id: Long + ) { + if (reported == -1) { + reported = position + return + } + if (position == reported) return + reported = position + nativeInvokeCallback1(callbackKey, position.toDouble()) + } + + override fun onNothingSelected(parent: AdapterView<*>?) {} + } + } + // --- Context menu --- @JvmStatic From 1fa16e9396d3320021e49aa608498647efe7db38 Mon Sep 17 00:00:00 2001 From: keufcp <149170099+keufcp@users.noreply.github.com> Date: Fri, 14 Aug 2026 16:02:52 +0900 Subject: [PATCH 2/3] docs(changelog): key the fragment to PR #8080 --- ...d => 8080-android-picker-callback-and-json-extract-pointer.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{0000-android-picker-callback-and-json-extract-pointer.md => 8080-android-picker-callback-and-json-extract-pointer.md} (100%) diff --git a/changelog.d/0000-android-picker-callback-and-json-extract-pointer.md b/changelog.d/8080-android-picker-callback-and-json-extract-pointer.md similarity index 100% rename from changelog.d/0000-android-picker-callback-and-json-extract-pointer.md rename to changelog.d/8080-android-picker-callback-and-json-extract-pointer.md From 800b3767049a685b95e0207612ba95978b470486 Mon Sep 17 00:00:00 2001 From: keufcp <149170099+keufcp@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:15:43 +0900 Subject: [PATCH 3/3] docs(changelog): say onChange stopped firing rather than Picker being inert --- .../8080-android-picker-callback-and-json-extract-pointer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.d/8080-android-picker-callback-and-json-extract-pointer.md b/changelog.d/8080-android-picker-callback-and-json-extract-pointer.md index b0e2941dde..51eae83bc3 100644 --- a/changelog.d/8080-android-picker-callback-and-json-extract-pointer.md +++ b/changelog.d/8080-android-picker-callback-and-json-extract-pointer.md @@ -1,5 +1,5 @@ -Fixed two Android defects that made `perry-ui-android` unbuildable and left -`Picker` inert. +Fixed two Android defects that made `perry-ui-android` unbuildable and stopped +`Picker` from reporting selection changes. `crates/perry-ui-android/src/json.rs` still called the `is_raw_pointer` helper that #7448 deleted, so the crate failed to compile for any Android target