Skip to main content

Module text_selection

Module text_selection 

Source
Expand description

Native-grade text selection primitives for BasicTextField.

This module holds the pure, unit-tested building blocks the text field uses to offer Android/iOS-style selection: tap-count classification, word and line/paragraph boundary detection, and the geometry of the draggable teardrop selection handles (their shapes, their hit regions, and the selection math that a handle drag produces).

Keeping these as free functions makes the touch behavior testable without a renderer and keeps TextFieldModifierNode focused on wiring.

Structs§

HandleGrabOffset
Finger-to-handle relationship for one drag. The first phase preserves the captured offset exactly, the second shifts the handle above the finger, and the third preserves that final offset exactly. Progress is based on the furthest displacement from the grab, so event cadence and small reversals cannot change the result.

Enums§

HandleKind
Which selection handle a lollipop represents.
LineAffinity
Which visual line a caret/handle at a soft-wrap boundary belongs to. At a shared boundary byte (the end of one wrapped visual line IS the start of the next — mid-word wraps produce these) the offset alone is ambiguous:
SelectionGranularity
The unit of text a tap gesture selects, growing with the tap count the way mature text editors do (Android TextView, iOS UITextView, VS Code):

Constants§

GRAB_BIAS_VIEW_CLEARANCE
Extra clearance (dp) below the handle dot once fully visible above the finger.
GRAB_DIRECT_FOLLOW_DISTANCE
Downward travel that follows with the original finger-to-handle offset before the visibility drift starts.
GRAB_VISIBILITY_DRIFT_DISTANCE
Additional downward travel over which the handle moves into full view.
HANDLE_DOT_LINE_OVERLAP
How far the dot dips INTO the line box (dp): the reference start dot’s bottom sits ~5 px (1.7 dp) below the line-box top, the end dot’s top ~6 px above the line-box bottom, so dot and stem read as one continuous shape.
HANDLE_GRAB_SLOP
Finger-sized grab slop (px) added around a handle’s drawn teardrop to enlarge its touch target, matching Android’s generous handle hit area. A bare teardrop (~2·HANDLE_RADIUS across) is far smaller than a fingertip, so a touch-DOWN aimed at a handle routinely lands a few px off it; without this slop the press falls through to the field below and places a caret, which collapses the selection. The slop is applied to the sides and BELOW the tip (where the bulb and the grabbing finger sit) but never ABOVE the tip — see crate::widgets::selection_handle, which keeps the box off the glyph line so a double-tap still reaches the field to escalate into a word selection.
HANDLE_RADIUS
Radius of a selection/cursor handle dot in dp (the reference dot is 16.2 physical px at 3x ≈ a 16 dp circle).
HANDLE_STEM_WIDTH
Width of the handle stem in dp (measured 6 px at 3x = 2 dp — the same weight as the caret).
MULTI_TAP_SLOP_PX
Maximum distance (px) between consecutive taps that still counts as a multi-tap. A tap that lands far from the previous one starts a fresh single tap even if it arrives quickly, matching Android’s ViewConfiguration double-tap slop behavior.
MULTI_TAP_TIMEOUT_MS
Maximum time between taps that still counts as a multi-tap, in milliseconds.

Functions§

caret_visual_line
Given the source byte ranges of the visual (wrapped) lines and a caret byte offset, returns the (visual_line_index, line_start_byte) the caret sits on.
classify_tap_count
Classifies a press into a 1-based tap count from the previous tap’s count, the time since it, and the distance from it.
find_line_boundaries
Returns the byte range [start, end) of the line containing pos, delimited by \n (the newline itself is excluded from the range).
find_paragraph_boundaries
Returns the byte range [start, end) of the paragraph containing pos.
grab_bias_full_view
The drift target: bias placing the finger just below the handle dot (tip + dot + clearance), so the whole lollipop stays visible above it.
handle_path_data
SVG path data for a handle lollipop at a text edge.
resolve_selection_tap_count
Resolves the effective tap count for a press, folding in the “tap inside an existing selection” gesture so it drives the same word → line → paragraph granularity ladder (tap_selection_granularity) as a rapid multi-tap.
selection_after_handle_drag
Computes the selection (min, max) that results from dragging one handle to a new text offset, keeping the opposite (fixed) edge anchored.
tap_selection_granularity
Maps a 1-based tap count to the granularity it selects.