Skip to content

Two-thumb: drop the word-joining layer if thumbs are genuinely simultaneous #143

Description

@AsafMah

The observation

From daily use: "if we always have simultaneous typing, we never need to join together parts of words, right?"

That's correct, and it's a stronger statement than it first appears.

Every piece of the multi-part machinery exists for one reason: the code assumes the gesture decoder accepts one trail, so two thumbs must be spliced into one. That assumption produced:

  • connector-point synthesis (StrokeAligner CONNECTOR mode)
  • the merged-trail extend base (WordComposer.setExtendBatchInputBase)
  • the ideal-prefix builder (IdealPrefixTrailBuilder, tap → micro-stroke)
  • stroke re-timing knobs
  • fragment stitching and fragment backspace

The research in #141 established that the assumption is false: the AOSP decoder models two pointer tracks (MAX_POINTER_COUNT_G == 2) and partitions points by pointer id, not by timing. InputPointers.appendAll hardcoded id 0, which is the sole reason the splicing layer had to exist.

So if both thumbs are handed over as two tracks, there is nothing to join, and that entire layer can be deleted rather than tuned.

Proposal

For the experimental build: stop synthesising, and pass the two thumbs through as what they are.

  • Remove connector synthesis, ideal-prefix promotion, and the re-timing controls from the active path.
  • Keep the first-seen pointer-id normalisation from Two-thumb experimental build (upstream v4.1.2 merged, installs side by side) #141 — that fixed a real bug where a stroke carrying no id 0 returned zero suggestions.
  • Simplify word assembly: a word is whatever the decoder returns for the concurrent tracks, with no extend-base and no fragment stitching.
  • Retain only the part of the combining timer that decides when the word is finished, which is a separate job from gluing.

Two things that must be settled first

1. This is native-decoder only. sHaveNativeGestureLib is true only for a user-supplied or system glide library; the bundled one is dictionary-only and sets it false. The Java fallback engine ignores pointer ids entirely and scores a single trail. Simplifying this way makes two-thumb typing a native-decoder feature, and leaves fallback users with either the old machinery or nothing. That's a product decision, not a code one.

2. Two tracks is a hard ceiling. Genuinely concurrent thumbs fit in two tracks. A word built from three or more sequential fragments does not, and that is precisely what the current machinery was built to handle. Whether that case matters in practice is a question about how people actually type, and it is the thing to measure before deleting anything.

What would settle it

Real use of the experimental build with Joining word parts → Two separate thumb tracks, comparing against One joined trail. Specifically: are both thumbs on the screen at overlapping times, or is it more alternating? If overlapping dominates, the joining layer is dead weight and should go. If alternating dominates, two tracks are not enough and the layer earns its place.

Related

Note on the gesture library

Worth recording, since it cost real confusion: the library lives in the app's private files/libjni_latinime.so, not in preferences. A separately-packaged build (.exp, or a fresh install of the release package) therefore starts without it, and exporting/importing settings does not carry it across. Until it is loaded, every recognition setting in this area is inert — and one of them was actively harmful, which #141 fixes by gating the whole group and saying why.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions