- SurfaceView windows are always translucent, so adjustResize cannot
resize them: the keyboard overlapped the bottom of the window and the
top bar sat under the status bar. Consume the insets in app instead:
a smali-injected PadInsetsListener (identical block in build_emu.sh
and build_phone.sh) shrinks the GioView to statusBarBottom..keyboardTop
(or ..navBarTop) on every API 30+ insets dispatch, with
setDecorFitsSystemWindows(false) so IME insets are delivered at
targetSdk 34.
- Fix a change-detection bug in the listener: the height write skipped
the topMargin/bottomMargin checks on every IME state transition, so
the margins were never applied while the keyboard animated. All three
params are now checked with a single requestLayout on any change.
- Selection menu now re-anchors to the selected word every frame while
it is visible and hides when the word scrolls out of the viewport
(positionSelectionMenu + regression test).
- Doc: development_plan.md section 14 (invariants, geometry contract,
build-script identity invariant).
Verified on device: top bar below status bar and clickable, bottom bar
flush with keyboard top (view 128..1517 at 1080x2400), BACK dismiss +
re-tap re-raise without a show loop, typing saves, menu tracks scrolls.
Two user-reported bugs in the post-wrap build:
1. Selection 'jumped' when scrolling: frameOf's chunked branch shadowed the
outer start/end with 'start, end, winLine := cb.VisibleByteRange(...)',
leaving IMEWindowStartByte at 0 for chunked files while scrolled, so the
window-relative selection highlight (and IME commits) mis-mapped near the
file top. Fix: declare winLine outside, assign. Mutation-verified
regression tests: real_file_scroll_selection_test.go.
2. Bottom bar hidden behind the keyboard: GioView extends SurfaceView, which
unconditionally marks the window FORMAT_TRANSLUCENT; translucent windows
are never IME-resized, so adjustResize is dead. Fix (build scripts):
smali-patch a PadInsetsListener OnApplyWindowInsetsListener onto the
GioView (shrinks it by the IME inset bottom) + setDecorFitsSystemWindows
(false) on API 30+ so insets are dispatched. targetSdk kept at 34.
3. (Found while fixing 2) Keyboard could not be dismissed: TextField.Draw
issued SoftKeyboardCmd{Show:true} every frame; with insets-driven
resizes, the hide animation triggered redraws that re-showed the keyboard
mid-animation. Fix: ShowIMESeq pulse from the logic layer (open/tap/
double-tap); renderer shows only on pulse change, re-arming on focus
loss — matching widget.Editor.
On-device (emulator): BACK dismisses and stays down; tap re-shows; typing
works; bottom bar above keyboard; word selection anchored across flick
scroll. go test -race ./... green. Phone APK rebuilt with the same patch.
Same pipeline as build_emu.sh (gogio -> apktool MANAGE_EXTERNAL_STORAGE
injection -> debug-sign) for a real phone: -arch arm64,arm (covers any
phone from the last decade; gogio accepts a comma-separated arch list)
and output cmd/pad/pad-phone.apk. Notes in the header: on Android 11+
the user must grant 'All files access' in system settings after
installing (MANAGE_EXTERNAL_STORAGE is app-restricted; the emulator AVD
had it granted, phones do not).