This guide describes a very high-level event plumbing and policy knobs for conveying a mouse device's events to a User Interface (UI) client. For a more general overview of input, beyond mouse, see the User Input architecture RFC.
Background
A mouse device typically has a motion sensor, a number of buttons, and a scroll wheel. Many variations and configurations exist, but this page discusses just the basics.
When the user moves the mouse along a flat surface, its physical motion is used to control the motion of a cursor on a display. When the user clicks a button, its state change (down/up) is used to drive interactions in a UI. When the user moves the scroll wheel, its motion is used to drive motion of graphical content in a UI.
Protocols and event flow
A mouse event starts from a mouse device and flows up the stack, until it reaches a UI client, which reacts to a mouse event. A UI client is typically implemented on top of a UI framework, so when a mouse event reaches this level, it gets exposed in a framework-specific way.
Device
A mouse device connects to a "host" (your computer), and speaks the USB HID protocol. The protocol specifics are defined in a HID usage table. The host waits to be interrupted for HID reports from the device. The mouse sits inert, until there is something to report to the host, such as motion, button press, or scrolling.
Input driver
On the host side, Fuchsia's input driver stack reads the mouse's HID reports and
translates them into a FIDL
MouseInputReport
.
This translation improves ergonomics for the upper layers of the Fuchsia
platform: the components in the upper layers can process events in FIDL, instead
of HID-specific data formats.
Input driver allows higher-level components to read reports from each device
over a Zircon channel. Each device is initially surfaced as a file in
/dev/class/input-report
.
Input pipeline
The Input Pipeline library attaches to a mouse device by discovery in the
/dev/class/input-report
directory. Only platform
components have access to this sensitive capability.
This component provides a centralized location for routing mouse events and for implementing policy decisions.
Physical mouse motion is typically interpreted as cursor motion, and this motion data is sent to the Scenic component via a sensitive pointer injector API. Button events and scroll wheel events also travel on the same injector channel.
The Input Pipeline implements the following centralized policy decisions:
- Choosing which view tree to target for mouse event injection.
- Defining how to interpret a mouse's physical motion. For example, a mouse's physical motion could be set up to control the movement of the cursor, or instead of cursor control, reported to UI clients as relative motion data.
- Defining the mouse's motion resolution.
- Defining the button priority order (primary, secondary, etc). For example, reordering priority allows users to make a mouse's right-side button the primary button.
- Defining the scroll wheel's travel (per detent) and direction.
Generally, these fields may be extended in the future, to support a richer or more precise interpretation of the user's intentions for mouse usage.
Scenic
The Scenic component forwards injected mouse events to UI clients, following policy defined by the injector (Input Pipeline). Scenic performs hit testing in the view tree to determine which UI client should receive mouse events.
When a mouse target is identified, Scenic dispatches mouse events to that UI
client over the
MouseSource
API. UI
clients listen for mouse events with a
hanging-get FIDL pattern.
UI clients and UI frameworks
A UI client can freely make use of the mouse event it received from Scenic. It can read cursor motion, button events, and scroll events as part of creating a user experience.
If the UI client is implemented on top of a UI framework, such as Flutter or
Chromium, the framework code is responsible for implementing Fuchsia-facing code
to receive mouse events. It then must surface these mouse events in a
framework-specific way to the UI client implemented on top of that framework.
For example, in the Flutter framework, mouse events are surfaced to Flutter
programs via the
PointerEvent
Dart class.