Files
Michał Pierzchała 3394d5b89c fix(android): keep a scroll's swipe out of the IME window (#2514)
* fix(android): keep a scroll's swipe out of the IME window

Android is the case the clip exists for beyond iOS: an `adjustPan` or `adjustNothing` activity keeps a
window whose recorded bounds already run under the IME, so a plan built from them aims at the keys.
The helper now reports the largest input method window beside the application window, in absolute
screen pixels like the window next to it, and `scroll` clips its band with the shared rule or refuses
when the keyboard owns the surface.

An older helper reports no keyboard keys, and a provider-supplied viewport has no IME channel at all.
Both read as "nothing to avoid", which is what the shared rule already does with a missing frame;
neither turns into a refusal.

`UiAutomation.getWindows()` answers with an empty list until the service asks for interactive windows,
so the read applies the seam the tree capture already uses rather than depending on a snapshot capture
having run first in the same instrumentation; the one-shot fallback below it has no such neighbour.
Measured on a Pixel 7 emulator with an `adjust=pan` contact editor, the application window keeps its
full 2400px height while the IME window reports `[0,1517][1080,2400]`, and `scroll down` answers with
`referenceHeight: 1505`, `keyboardMinY: 1517`, `keyboardAvoided: true` and a swipe ending at 301
instead of starting at 1920 under the keys.

* fix(android): clear the composer, not just the key plane, before a scroll swipes

The helper kept the largest `TYPE_INPUT_METHOD` rectangle as the keyboard. A composer bar and its key
plane can arrive as separate windows and the key plane is the larger one, so the earlier top edge was
discarded and the clipped band still ended inside the composer: the swipe landed on keys the rule
exists to keep it off.

The read now copies every input method window and unions the ones the swipe's centre line crosses,
which is the same line the shared clip rule tests. A candidate strip at the edge of the screen that the
swipe can never reach no longer shortens the band either. The selection runs on plain window edges,
because `Rect` is a device type whose constructors throw off-device, so the two-window case is a unit
test rather than a simulator-only path.

* refactor(android): pass the measured occlusion explicitly and drop the duplicate rect check

The clip rule already fails open on a keyboard frame it cannot measure,
so the helper reader no longer needs its own copy of the check, and the
gesture-viewport validator goes back to its original body. The refusal
names its three numbers instead of spreading the clip variant, so the
discriminator never leaks into error details.
2026-09-13 13:55:38 +02:00
..