Input & Stylus Handling
Relevant source files
The following files were used as context for generating this wiki page:
Input and Stylus Handling in Rocreate is a multi-layered system designed to translate raw hardware events—ranging from mouse clicks to pressure-sensitive stylus strokes and multi-touch gestures—into precise drawing actions. The system prioritizes low-latency feedback and high-fidelity input capture to support professional-grade creative workflows.
The architecture relies on a chain of event processors that normalize hardware-specific data, handle complex gestures, and apply smoothing algorithms to raw coordinates. This ensures that the drawing experience remains consistent across various devices, including desktop tablets and mobile touch screens.
Architecture Overview
The input system follows a pipeline architecture where raw browser events are captured by low-level listeners, processed into internal data structures, and then passed through an "Event Chain" for refinement.
The diagram above illustrates the sequential flow of input data from hardware capture to the final drawing engine.
Sources: src/app/script/app/kl-app.ts:503-512, src/app/script/klecks/ui/easel/easel.ts:468-475
Core Components
PointerListener
The PointerListener is the primary entry point for all pointer-based input (mouse, touch, pen). It abstracts the complexities of the browser's Pointer Events API, providing a unified interface for tracking pointer movement, button states, and specialized stylus data like pressure and tilt.
Key capabilities include:
- Coordinate Normalization: Translates global screen coordinates into local element coordinates.
- Pressure Handling: Captures stylus pressure and utilizes a
PressureNormalizerto account for hardware variations. - Multi-pointer Support: Tracks up to 4 simultaneous pointers, distinguishing between primary and secondary inputs.
- Corruption Recovery: Implements
cleanupCorruptedPointerto reset state if events are missed (e.g., apointerupthat never fired).
Sources: src/app/script/bb/input/pointer-listener.ts:15-40, src/app/script/bb/bb.ts:167-172
PressureNormalizer
Hardware often reports pressure inconsistently. The PressureNormalizer ensures that pressure values are mapped to a predictable [0, 1] range. It tracks the maximum pressure seen during a session to scale values appropriately, preventing "dead zones" on various tablet brands.
Sources: src/app/script/bb/input/pressure-normalizer.ts:1-20
GestureListener & Preprocessing
For multi-touch environments, the system utilizes specialized listeners to detect high-level intents.
| Component | Responsibility | Relevant Files |
|---|---|---|
| GestureListener | Detects native browser gestures like pinch and rotation. | gesture-listener.ts |
| EaselPointerPreprocessor | Handles complex Rocreate-specific gestures, such as the 4-finger tap for the Quick Menu and Long Press for the Eyedropper. | easel.ts, kl-app.ts |
| PinchZoomer | Part of the event chain; manages canvas scaling and rotation via two-finger input. | bb.ts |
Sources: src/app/script/klecks/ui/easel/easel.ts:468-550, src/app/script/app/kl-app.ts:635-645
Input Refinement Pipeline
Once raw pointer data is captured, it is processed through the EventChain to ensure visual quality.
Line Smoothing
The LineSmoothing module implements algorithms to reduce jitter and create clean curves. It supports multiple modes:
- Basic: Standard averaging of recent points.
- StreamLine: A Procreate-inspired algorithm that pulls the path toward the current pointer position with momentum.
- Pulled String: The drawing only occurs when the pointer exceeds a certain distance from the last point, as if pulling a string.
Sequence of smoothing application during a single pointer move event.
Sources: src/app/script/klecks/events/line-smoothing.ts:1-50, src/app/script/app/kl-app.ts:503-505
Line Sanitizer
This component acts as a safety filter in the pipeline. It prevents "stray" events from reaching the drawing engine, such as movement events that occur without a preceding "down" event or duplicated coordinates that could cause rendering artifacts.
Sources: src/app/script/app/kl-app.ts:506, src/app/script/app/kl-app.ts:795-800
Specialized Stylus Interactions
The system leverages stylus-specific data to drive advanced brush dynamics. These are mapped in KlApp to the current brush configuration.
- Pressure to Size/Opacity: Stylus pressure can dynamically scale the brush radius or alpha channel.
- Tilt Support:
tiltXandtiltYare captured byPointerListenerand can be used to adjust the angle or shape of "calligraphy" or "flat" brushes. - Quick Shape Detection: Input points are tracked during a stroke; if the user holds at the end of a stroke, the
QuickShapeHandleranalyzes the point buffer to snap the freehand line into a perfect geometric shape (circle, ellipse, triangle, etc.).
Sources: src/app/script/app/kl-app.ts:803-825, src/app/script/app/kl-app.ts:910-985
Summary
Input & Stylus Handling in this project is characterized by a robust, multi-stage pipeline. By decoupling hardware listeners from the drawing logic and inserting a configurable refinement chain, the system achieves high precision and professional feel across a wide array of input devices. This architecture allows for advanced features like Procreate-style gestures and real-time stroke stabilization while maintaining low-latency performance.