Skip to content

Android: deliver Back once, including the Android 13+ system gesture - #32

Open
ymote wants to merge 1 commit into
mainfrom
feat/rinx-host-services
Open

ymote wants to merge 1 commit into
mainfrom
feat/rinx-host-services

Conversation

@ymote

@ymote ymote commented Sep 26, 2026 •

Copy link
Copy Markdown

Android Back now reaches the native widget tree exactly once, on every API level and for every source: the hardware or navigation-bar Back key, and on Android 13+ the system edge gesture. The activity no longer finishes or backgrounds itself before widgets handle the event.

The Splash half of this PR's original scope landed separately in #35 (widgets/src/splash.rs reapply_text), so this branch has been rebased onto main and cut down to the Android Back change. The manifest extension-class override that used to be in it is gone too; it was unrelated to Back.

What changed

tools/cargo_makepad/src/android/java/dev/makepad/android/MakepadActivity.java

  • One delivery point. All Back sources go through dispatchBackPressed(). It closes an open QR scanner, then offers the event to ApplicationExtension.onBackPressed(), then sends MakepadNative.onBackPressed(). super.onBackPressed() is gone because it finished the activity (or backgrounded it on API 31+) before Rust had seen the event.
  • The surface ignores KEYCODE_BACK. Before, MakepadSurface.onKey forwarded the key to Rust, which turned KeyDown(Back) into BackPressed, and the framework also delivered Back through the activity, so one press produced two navigations. Now the key is left unhandled. Below API 33 it reaches onKeyUp → onBackPressed. On API 33+ the OnBackInvokedCallback receives it.
  • The activity registers an OnBackInvokedCallback on Android 13+. It uses PRIORITY_DEFAULT, so dismissing the IME still comes first, and it is unregistered in onDestroy.
  • ApplicationExtension.usesSystemBackCallback() is a new default method that returns false. An extension that registers its own system callback, as OctoSense's shell extension does, returns true. In that case the activity registers no callback of its own and drops the compatibility Back key in dispatchKeyEvent, so there is still only one delivery.

tools/cargo_makepad/src/android/mod.rs

  • Every generated activity, in both the default and Quest manifests, declares android:enableOnBackInvokedCallback="true". Without that opt-in, Android 13+ ignores the callback.
  • A test checks that every singleTask activity in both variants carries the opt-in.

Relation to OctoSense's makepad-system-back.patch

This PR upstreams OctoSense's tools/runtime-patches/makepad-system-back.patch and goes further than it:

  • It includes all three of the patch's hunks: the usesSystemBackCallback() interface method, the API 33+ compatibility-key drop when the extension owns the callback, and closing the QR scanner from onBackPressed.
  • It also removes super.onBackPressed() and gives plain cargo-makepad apps, which have no extension, the same single-delivery behaviour.

The method name and semantics are unchanged, so MakepadAppExtension.java compiles as-is. When OctoSense repins to a makepad that includes this PR, it should drop the patch, which will no longer apply. Its shell extension can keep its own callback (through usesSystemBackCallback()), or delete its SystemBack helper and rely on the activity's callback plus onBackPressed().

Validation

  • cargo check -p makepad-widgets: clean
  • cargo test -p cargo-makepad android::: passes, including the new manifest test
  • cargo makepad android build -p makepad-example-hello-world (aarch64) with this checkout's cargo-makepad, so the modified MakepadActivity.java is compiled by javac and packaged
  • Earlier device runs on the original branch: OnePlus 6 (Back key and edge swipe through hosted Rinx). The API 33+ extension-owned path is what OctoSense ships today via the runtime patch. This exact rebased build has not been re-run on a device.

🤖 Generated with Claude Code

@ymote

ymote commented Sep 27, 2026

Copy link
Copy Markdown
Author

The Splash part (reapply_text) landed on main as #35 (db4691d). The Android Back changes here remain unmerged; Back handling in ROM Home is being reworked separately, so they should be rebased or re-proposed with that work.

chrislearn pushed a commit to chrislearn/makepad that referenced this pull request Sep 28, 2026
A host that regenerates a Splash body from declarative data (Rinx's L0
mini apps) must keep focus, selection and scroll state in the named
widgets it already has. reapply_text evaluates the new body with
Apply::Reload into the existing view; set_text still tears the instance
down. From OctoSense-org#32 (its Splash part), on main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every Back (key, navigation button, system edge gesture) now goes through
one MakepadActivity.dispatchBackPressed(): an open QR scanner closes, the
application extension may consume it, otherwise MakepadNative.onBackPressed.
super.onBackPressed() no longer finishes or backgrounds the activity before
the widget tree has handled the event.

The surface leaves KEYCODE_BACK unhandled instead of forwarding it to Rust
as KeyDown(Back) (which became a second BackPressed). Below API 33 the
activity's onKeyUp -> onBackPressed delivers it; on API 33+ an
OnBackInvokedCallback (PRIORITY_DEFAULT, so the IME's Back stays first) does,
and cargo-makepad's manifests opt every activity in with
android:enableOnBackInvokedCallback.

ApplicationExtension.usesSystemBackCallback() lets an extension that owns its
own system callback keep it: the activity then registers none and drops the
compatibility Back key. This upstreams OctoSense's
tools/runtime-patches/makepad-system-back.patch with the same interface.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote
ymote force-pushed the feat/rinx-host-services branch from 3fda5b6 to 76311da Compare October 1, 2026 16:07
@ymote ymote changed the title Preserve Splash input state and deliver Android Back once Android: deliver Back once, including the Android 13+ system gesture Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant