The gesture system in Flutter has two separate layers. The first layer has raw
pointer events, which describe the location and movement of pointers (e.g.,
touches, mice, and styli) across the screen. The second layer has gestures,
which describe semantic actions that consist of one or more pointer movements.

Pointers

Pointers represent raw data about the user’s interaction with the device’s
screen. There are four types of pointer events:

On pointer down, the framework does a hit test on your app to determine what
widgets exists at the location where the pointer contacted the screen. The
pointer down event (and subsequent events for that pointer) are then dispatched
to the innermost widget found by the hit test. From there, the events bubble up
the tree and are dispatched to all the widgets on the path from the innermost
widget to the root of the tree. There is no mechanism for canceling or stopping
pointer events from being dispatched further.

Gestures

Gestures represent semantic actions (e.g., tap, drag, and scale) that are
recognized from multiple individual pointer events, potentially even multiple
individual pointers. Gestures can dispatch multiple events, corresponding to the
lifecycle of the gesture (e.g., drag start, drag update, and drag end):

Gesture disambiguation

At a given location on screen, there might be multiple gesture detectors. All
of these gesture detectors listen to the stream of pointer events as they flow
past and attempt to recognize specific gestures. The
GestureDetector
widget decides which gestures to attempt to recognize based on which of its
callbacks are non-null.

When there is more than one gesture recognizer for a given pointer on the
screen, the framework disambiguates which gesture the user intends by having
each recognizer join the gesture arena. The gesture arena determines which
gesture wins using the following rules:

For example, when disambiguating horizontal and vertical dragging, both
recognizers enter the arena when they receive the pointer down event. The
recognizers observe the pointer move events. If the user moves the pointer more
than a certain number of logical pixels horizontally, the horizontal recognizer
will declare victory and the gesture will be interpreted as a horizontal drag.
Similarly, if the user moves more than a certain number of logical pixels
vertically, the vertical recognizer will declare victory.

The gesture arena is beneficial when there is only a horizontal (or vertical)
drag recognizer. In that case, there will be only one recognizer in the arena
and the horizontal drag will be recognized immediately, which means the first
pixel of horizontal movement can be treated as a drag and the user will not need
to wait for further gesture disambiguation.