Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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
(`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.
14 changes: 8 additions & 6 deletions crates/perry-ui-android/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Comment thread
keufcp marked this conversation as resolved.

override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}

// --- Context menu ---

@JvmStatic
Expand Down
Loading