iris/android: composing text sync, tap-vs-swipe focus, composer rebuild, atlas reset on app-switch
Four fixes from Iris's phone report on the dc01f88 build, plus her same-day
follow-up on swipe-vs-tap:
- android/ime.rs: InputConnection now calls InputMethodManager.updateSelection
after every edit (new update_ime_selection, called from after_input) -- Gboard
was holding keystrokes back with nothing telling it the app's selection/
composing region had moved, which read as "doesn't enter it until I hit
space, doesn't move the caret". New unit tests in widget/text/edit.rs cover
the buffer-level composing/commit/delete/selection operations directly.
- attr.rs: Selector/Selectable rewritten around a shared on_press dispatcher
over PressStart/Pressing/PressEnd instead of click_or_drag(), so a field
that isn't already focused only grants focus (and requests the IME) on a
completed tap -- press and release with no frame past DRAG_SLOP. A drag
is never consumed, so whatever is behind the field still sees it. New
FocusHost::is_focused (both platform impls) and TextEdit::press_origin
back this. Verified on the emulator: dumpsys input_method's mInputShown
stays false after a swipe over the composer, true after a tap.
- iris_core: GlyphAtlas::clear()/Textures::reset(), called together from
android/view.rs's surface_changed exactly when a genuinely new renderer is
built (app-switch, not the keyboard-resize path that already reuses the
renderer) -- both CPU-side caches otherwise kept pointing at the old,
destroyed device's textures. Verified on the emulator: home, reopen, every
glyph still on screen.
- transcript-ui/composer.rs: rebuilt as one widget (unchanged Stack{rect,
span} idiom, capped at ~6 lines via MaxSize + .scrollable(), wrapped in one
Pad whose bottom Composer::set_bottom_inset rewrites in place so the bar
sits on the IME or nav-bar inset with no rebuild -- rebuilding would drop
focus/selection/in-progress text). Wired from bench_client.rs's existing
on_insets_changed.
A second, deeper bug found while verifying the composing fix is NOT fixed
this pass: composed text never becomes visible at all. A new layout_tests.rs
test proves the widget tree's own region math is correct across a keyboard
resize, ruling that out; RUST.md's P0 box has the full writeup and what to
check next (UiRenderState::redraw's single-widget path, or something
force-gles-specific -- this AVD has no Vulkan adapter to rule that out with).
cargo fmt/clippy/test --workspace and cargo ndk clippy all clean.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
dc01f88d75
commit
20b12255e1
14 files changed
+628
-15
No files matched your search
@@ -141,6 +141,27 @@ impl Textures {
|
||||
self.updates.push(Update::Patch(handle.slot, rect));
|
||||
}
|
||||
|
||||
/// Forget every image, page and pending update -- what a genuinely new
|
||||
/// GPU device needs alongside [`crate::render::atlas::GlyphAtlas::
|
||||
/// clear`], which this module's own doc references: every slot number
|
||||
/// and every queued [`Update`] here describes the *old* device's
|
||||
/// textures (an `Update::Push`/`Update::Patch` already drained into a
|
||||
/// renderer that no longer exists is gone for good, and a fresh
|
||||
/// `UiRenderNode`'s own texture manager starts with none of them
|
||||
/// applied), so nothing is lost by starting this bookkeeping over too.
|
||||
/// Any `TextureHandle` a caller still holds across the reset (none in
|
||||
/// the transcript screen this reset is wired up for today -- confirmed
|
||||
/// by grep, the only standalone (non-atlas) image anywhere in this
|
||||
/// workspace is `iris/widget/image.rs`'s `Image`, used by the separate
|
||||
/// `tabs-ui` example) is left pointing at a slot this instance no
|
||||
/// longer recognises and needs reinserting via `add`/`add_page` again
|
||||
/// -- the same pre-existing gap a renderer restart already left for
|
||||
/// such a handle before this method existed, just named rather than
|
||||
/// silent now.
|
||||
pub fn reset(&mut self) {
|
||||
*self = Self::new();
|
||||
}
|
||||
|
||||
pub fn free(&mut self) {
|
||||
for (kind, idx) in self.recv.try_iter() {
|
||||
self.images[idx as usize] = None;
|
||||
|
||||
@@ -173,6 +173,25 @@ impl GlyphAtlas {
|
||||
pub fn glyph_count(&self) -> usize {
|
||||
self.entries.len()
|
||||
}
|
||||
|
||||
/// Forget every page and every rasterised entry -- what a genuinely new
|
||||
/// GPU device needs (`android::view::IrisViewPeer::surface_changed`'s
|
||||
/// "not already live" branch, e.g. after backgrounding): the pages this
|
||||
/// atlas remembers are `TextureHandle`s into the *old* device's
|
||||
/// textures, which no longer exist, and every `GlyphEntry`'s `uv_min`/
|
||||
/// `uv_max`/`layer` point into them. Without this, a glyph already
|
||||
/// cached here is treated as "already placed" and never re-inserted
|
||||
/// into the fresh (empty) atlas the new renderer actually has --
|
||||
/// exactly the "rectangles stay, glyphs disappear" bug the resize path
|
||||
/// (`AndroidRenderer::resize`) was built to avoid for the reuse case;
|
||||
/// this is its counterpart for the case where the renderer really is
|
||||
/// new. Dropping `pages` also drops its `TextureHandle`s, which send a
|
||||
/// free message back through their `Textures`; see `Textures::reset`'s
|
||||
/// doc for why that is harmless here.
|
||||
pub fn clear(&mut self) {
|
||||
self.pages.clear();
|
||||
self.entries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn fits(page: &Page, need_w: u32, need_h: u32) -> bool {
|
||||
|
||||
Reference in new issue
Block a user