sample method
Converts globalPointer into every coordinate the drag pipeline
needs, or null when the scrollable is unmounted (or its viewport
box is detached mid-teardown).
Every path that resolves a target samples first, so this is also the
correctness floor for the scroll subscription: a swapped position is
re-bound here even with no widget layer above the controller (the
widget's didChangeDependencies edge trigger only removes the
latency until the next event).
Implementation
PointerSample? sample(Offset globalPointer) {
syncScrollSubscription();
if (!_scrollable.mounted) {
return null;
}
final box = _scrollable.context.findRenderObject();
if (box is! RenderBox || !box.attached) {
return null;
}
final local = box.globalToLocal(globalPointer);
return (
sliverX: globalPointer.dx - _renderPort.crossAxisGlobalOrigin,
sliverY:
_scrollable.position.pixels +
local.dy -
_renderPort.precedingScrollExtent,
viewportDy: local.dy,
viewportHeight: box.size.height,
);
}