pub struct TouchSelection { /* private fields */ }Expand description
Turns a direct pointer into a text selection: long press to select a word, handles to adjust it, a magnifier while adjusting, a toolbar when done.
A host owns one of these per text surface, forwards pointer events to it,
and mounts a TextAffordanceLayer fed by affordances.
Implementations§
Source§impl TouchSelection
impl TouchSelection
Sourcepub fn new() -> Self
pub fn new() -> Self
A controller with the shipped Compact metrics, the magnifier on, and motion unrestricted.
Build it in build() and refine it there:
reduced_motion has no accessor on
EventContext, so the value must be captured while a
BuildContext is in hand.
Sourcepub fn metrics(self, metrics: HandleMetrics) -> Self
pub fn metrics(self, metrics: HandleMetrics) -> Self
Use metrics for handle geometry. Pass the ones derived from the same
TextSelectionHandleRecipe the affordance layer paints with.
Sourcepub fn magnifier_metrics(
self,
radius: f32,
half_height: f32,
rise: f32,
scale: f32,
) -> Self
pub fn magnifier_metrics( self, radius: f32, half_height: f32, rise: f32, scale: f32, ) -> Self
Lens geometry, from the active style’s
TextMagnifierRecipe.
Sourcepub fn magnifier(self, enabled: bool) -> Self
pub fn magnifier(self, enabled: bool) -> Self
Turn the magnifier off for this surface — the per-widget opt-out.
A surface whose text layer cannot be replayed purely (see
magnifier) must set this, because there is no way for the framework
to detect that it could not.
Sourcepub fn reduced_motion(self, reduced: bool) -> Self
pub fn reduced_motion(self, reduced: bool) -> Self
Whether the user asked for reduced motion. Gates the magnifier entirely: a lens that appears and then chases the finger is exactly the unbidden movement the preference is about, and the selection works without it.
Sourcepub fn affordances(&self) -> TextAffordances
pub fn affordances(&self) -> TextAffordances
The published geometry. Clone it into the affordance layer.
Sourcepub fn handles(&self) -> Vec<SelectionHandleGeometry>
pub fn handles(&self) -> Vec<SelectionHandleGeometry>
Every handle currently wanted.
Sourcepub fn magnifier_request(&self) -> Option<MagnifierRequest>
pub fn magnifier_request(&self) -> Option<MagnifierRequest>
The magnifier, while one is raised.
Sourcepub fn toolbar(&self) -> Option<SelectionToolbarRequest>
pub fn toolbar(&self) -> Option<SelectionToolbarRequest>
The toolbar the controller wants raised, if any.
Sourcepub fn is_dragging(&self) -> bool
pub fn is_dragging(&self) -> bool
Whether a handle drag is in progress.
Sourcepub fn dismiss(&mut self)
pub fn dismiss(&mut self)
Retract every affordance. The controller owns its own lifetime: the text-affordance band is exempt from outside-press dismissal, so nothing else will do this. Call it when focus leaves, the content changes, the surface becomes read-only, or the window deactivates.
Sourcepub fn refresh(
&mut self,
direction: LayoutDirection,
source: &dyn TextHitSource,
)
pub fn refresh( &mut self, direction: LayoutDirection, source: &dyn TextHitSource, )
Recompute every affordance from source.
Call it after any change the controller did not make — an arrow key, an undo, a scroll that moved the caret — or the handles keep the position the text used to be at.
Sourcepub fn raise(&mut self, direction: LayoutDirection, source: &dyn TextHitSource)
pub fn raise(&mut self, direction: LayoutDirection, source: &dyn TextHitSource)
Raise the affordances for the current selection.
The host calls this when a direct pointer finishes placing a caret: the caret placement itself stays with the host’s own code, which is what keeps a mouse’s path unchanged.
Sourcepub fn on_long_press(
&mut self,
pointer: PointerInfo,
point: Point,
ctx: &mut EventContext<'_>,
source: &mut dyn TextHitSource,
) -> EventResponse
pub fn on_long_press( &mut self, pointer: PointerInfo, point: Point, ctx: &mut EventContext<'_>, source: &mut dyn TextHitSource, ) -> EventResponse
Select the word under point and raise the affordances — the long-press
gesture.
Returns Ignored untouched for an indirect
pointer. That branch is load-bearing: the gesture arena installs a
long-press recognizer on the presence of the handler alone, with no
pointer-kind condition, so without it a half-second mouse hold inside an
editor would select a word.
§Why the device is a parameter here and not read off ctx
handle_pointer and
drag_handle ask ctx.pointer_kind(), and they are
right to: both serve a sample, and the tree installs that sample’s
pointer for the length of the dispatch. A hold serves no sample — it is a
deadline coming due — and the answer a context can give for it is only as
good as the tree’s bookkeeping at tick time. It was wrong for the whole
of this method’s first life: current_input is saved-and-restored around
every dispatch, so the timer path read back InputSnapshot::default()
and this guard refused every genuine touch hold, which made the entry
point dead code and cost its first host a duplicate guard of its own.
The tree now installs the holding contact
(InputSnapshot::for_recognized_gesture), so ctx answers correctly
too — but the gesture already carries the truth on
TapEvent::pointer, and a host that
drives this from anywhere else — an assistive-technology action, its own
hold timer — has no snapshot behind it at all. So the caller names the
device.
point is in window coordinates, like every other point this type
takes — deliberately not TapEvent::position, which the router has
already rewritten into the target’s local space.
Sourcepub fn handle_pointer(
&mut self,
event: &WidgetEvent,
ctx: &mut EventContext<'_>,
source: &mut dyn TextHitSource,
) -> EventResponse
pub fn handle_pointer( &mut self, event: &WidgetEvent, ctx: &mut EventContext<'_>, source: &mut dyn TextHitSource, ) -> EventResponse
Route one pointer event, for a host that paints its own handles.
A host that mounts the TextAffordanceLayer does not call this.
The layer’s handles are widgets in their own right, sitting above the
editor and offered the press first, so such a host wires the pieces
directly instead: on_long_press from its own
long-press handler, raise from its own release arm, and
drag_handle from the layer’s node. All three
stock hosts are of that shape.
What this offers a host that draws the handles itself is the routing
those hosts get from the layer: it claims only what belongs to the
affordances — a press that lands on a handle, and the samples of a drag
it started. Everything else, including every event from an indirect
pointer, is Ignored, so the host’s own caret
placement runs exactly as it did.
Sourcepub fn drag_handle(
&mut self,
kind: SelectionHandleKind,
phase: HandleDragPhase,
point: Point,
ctx: &mut EventContext<'_>,
source: &mut dyn TextHitSource,
) -> EventResponse
pub fn drag_handle( &mut self, kind: SelectionHandleKind, phase: HandleDragPhase, point: Point, ctx: &mut EventContext<'_>, source: &mut dyn TextHitSource, ) -> EventResponse
Drive a handle drag from the affordance layer’s own node.
The layer knows which handle was pressed — it is a widget in its own right — so it names the kind instead of making the controller hit-test for it.
An indirect pointer is refused here as well as at the layer’s node and in
handle_pointer. The three guards cover three
different ways in, and this is the one a caller of the public API reaches
without passing either of the others.
Sourcepub fn handle_at(&self, point: Point) -> Option<SelectionHandleKind>
pub fn handle_at(&self, point: Point) -> Option<SelectionHandleKind>
Which handle, if any, accepts a press at point.
Handles overlap when a selection is short, so this answers with the one whose centre is nearest rather than the first in the list — the same tie-break the hit-test slop pass uses between adjacent grips.