Hit Testing

Overview

A hit is the point of interaction between a pointer event and a graphical view.

Hit testing is the process where Scenic determines which hits should be routed to which clients.

Hit regions

Client-submitted graphical content is not in and of itself hittable. Rather, it is the rectangular hit regions attached to Flatland transforms that enable content views to receive input events.

To ease the use of the Flatland API for developers, each view has a default hit region. These hit regions act as normal hit regions but are added implicitly to the root transform in the SetRootView() call. See the default hit regions section for more information.

Semantic visibility

There are two types of hit regions Flatland clients may attach to transforms: semantically visible and semantically invisible hit regions. The property of semantic visibility can be ignored by most clients, as its only used in rare accessibility-specific use cases. See the semantic visibility page for more information.

High level overview of algorithm

Given a hit at point (x,y), the View containing the geographically top-most (topologically last) semantically-compatible hit region which intersects (x,y) receives the hit. Let’s break down the requirements into its component parts.

Top most

Given a parent and child transform with content, the child transform is drawn on top of the parent transform, and is also topologically after the parent.

Given two sibling transforms with the same parent, the child added last via AddChild() is topologically after its sibling.

Semantic compatibility

Semantic hit tests do not interact with semantically invisible hit regions.

See the semantic visibility page for more information.

Overlap

A hit that is on the border of a hit region is considered to be included in that hit region.

If two or more transforms share a border, the tie-breaker goes to the topologically last transform.

Default hit regions

While a View itself is not by default hittable, API clients tend to expect content to be interactable when created, so Flatland creates a full screen default hit region (DHR) for Views when they install their root transform via a SetRootTransform() call, unless the client manually specifies their own hit region.

DHRs are maximally sized, so resizing the View to be larger should not lead to a part of the screen becoming unhittable.

The semantics of default hit regions can be summarized in the following rules:

  1. A DHR is added to the root transform, T, during a SetRootTransform(T) call if and only if no SetHitRegions(T) calls were made prior.
  2. Calling SetHitRegions(T, hit_region_vector) after a SetRootTransform(T) call overrides the DHR, even if |hit_region_vector| is empty.
  3. A DHR is only installed for a given root transform so long as it is the root View.
  4. A DHR for a given transform T is unaffected by any hit region operation on any other transform, U.

To help illustrate the semantics, let’s consider some examples.

Scenario 1

SetRootTransform(T)

End state: T has a DHR.

Scenario 2

SetRootTransform(T)

SetRootTransform(U)

End state: T has no hit regions, U has a DHR.

Scenario 3

Scenario 3A

SetRootTransform(T)

SetHitRegions(T, {HR1})

Scenario 3B

SetHitRegions(T, {HR1})

SetRootTransform(T)

End state for 3A and 3B: T has one hit region, HR1. There is no DHR.

Scenario 4

SetRootTransform(T)

SetHitRegions(T, { {} })

End state: T has no hit regions

Scenario 5

SetRootTransform(T)

SetRootTransform(U)

SetHitRegions(T, {HR1, HR2})

End state: T has two hit regions, HR1 and HR2. U has a DHR.