Event Handling & messaging
Relevant source files
The following files were used as context for generating this wiki page:
- src/app/script/app/kl-app.ts
- src/app/script/app/kl-app-events.ts
- src/app/script/bb/bb.ts
- src/app/script/bb/base/browser.ts
- src/app/script/bb/base/cross-tab-channel.ts (Referenced via usage in
kl-app.ts) - src/app/script/bb/input/event-chain/event-chain.ts (Referenced via usage in
kl-app.ts)
The Rocreate project utilizes a sophisticated event handling architecture designed to manage high-frequency pointer data, multi-touch gestures, and cross-tab communication. The system is centered around an "Event Chain" pattern that allows for modular processing of input events—such as smoothing, sanitization, and gesture detection—before they reach the rendering engine. This ensures that the drawing experience remains performant and responsive across various hardware form factors including desktop, tablet, and mobile.
Messaging within the application is handled through internal service subscriptions and specialized channels for inter-tab coordination. This allows the application to maintain state consistency when multiple instances of the project are open and provides a robust mechanism for UI updates based on internal state changes, such as brush settings or layer modifications.
Input Event Processing
The core of the input system is the EventChain, which processes TPointerEvent data through a series of specialized elements. In the KlApp implementation, the chain is configured to handle drawing events by passing them through sequential filters including the LineSanitizer, AssistModeSanitizer, and LineSmoothing.
Event Chain Architecture
The EventChain follows a pipe-and-filter pattern where input events are "chained in" and processed results are "chained out" to a final handler.
The diagram shows the flow of pointer data through modular sanitizers and smoothers before reaching the final output.
Sources: src/app/script/app/kl-app.ts:466-470, src/app/script/app/kl-app.ts:634-712
Key Input Components
| Component | Role | File Reference |
|---|---|---|
PointerListener | Low-level listener for mouse, touch, and pen events. | src/app/script/bb/bb.ts:167 |
EventChain | Orchestrates the flow of events through multiple processors. | src/app/script/app/kl-app.ts:466 |
LineSanitizer | Validates input state and manages drawing lifecycle (down/move/up). | src/app/script/app/kl-app.ts:463 |
LineSmoothing | Applies presets and algorithms to reduce input jitter. | src/app/script/app/kl-app.ts:462 |
AssistModeSanitizer | Snaps input to perspective or symmetry guides. | src/app/script/app/kl-app.ts:464 |
Inter-component Messaging
Messaging between the central controller (KlApp) and its sub-components is achieved through a mix of direct method calls and a subscription-based BrushSettingService.
Brush Setting Service
The BrushSettingService acts as a central hub for brush-related state changes. UI components like the ProcreateLayout subscribe to this service to update color previews, size indicators, and opacity sliders in real-time.
Sequence illustrating how brush setting changes are propagated to the UI.
Sources: src/app/script/app/kl-app.ts:420-457, src/app/script/app/kl-app.ts:1335-1343
Specialized Gesture Handling
The system includes dedicated handlers for complex gestures that go beyond simple pointer clicks, specifically for the Procreate-style interface.
- Long Press Eyedropper: Triggered when a user holds a finger on the canvas. It calculates the canvas-space coordinates and samples the color at that point.
- Four-Finger Tap: Opens the
QuickMenu, a radial action menu. - Quick Shape Detection: A
QuickShapeHandlermonitors strokes and snaps freehand drawings into geometric primitives (lines, circles, triangles) if a "hold-at-end" gesture is detected.
Flow of specialized gestures from the Easel viewport to their respective handlers.
Sources: src/app/script/app/kl-app.ts:543-565, src/app/script/app/kl-app.ts:585-630
Cross-Tab Communication
Rocreate implements a CrossTabChannel to prevent data corruption when the same project is opened in multiple browser tabs. This is particularly relevant for the ProjectStore and KlRecoveryManager.
When a project is opened, the application broadcasts a request for project IDs to other tabs. If a collision is detected (i.e., another tab reports the same Project ID), a warning modal is displayed to the user.
| Message Type | Direction | Payload |
|---|---|---|
request-project-ids | Broadcast | None |
response-project-id | Response | id: string |
Sources: src/app/script/app/kl-app.ts:983-1002
Browser Event Utilities
The project includes several utilities in src/app/script/bb/base/browser.ts to normalize browser behavior and handle legacy environment quirks:
- High-Resolution Timestamps: The
EVENT_USES_HIGH_RES_TIMESTAMPutility detects if the browser'sEvent.timeStampuses high-resolution (sub-millisecond) values or unix epoch milliseconds. - Feature Detection: Constants like
HAS_POINTER_EVENTSandIS_CSS_MIN_MAX_SUPPORTEDare used throughout the application to toggle between modern and fallback event listeners or UI styles. - Event Cleaning:
unsetEventHandleris used to safely nullify event handlers (e.g.,onclick,onkeyup) on DOM elements during destruction to prevent memory leaks.
Sources: src/app/script/bb/base/browser.ts:3-13, src/app/script/bb/base/browser.ts:44-49
Summary
Event handling in Rocreate is a layered system that balances low-level browser normalization with high-level artistic features like line smoothing and gesture recognition. By using a modular EventChain, the application ensures that complex input processing remains decoupled from the core rendering logic, while the BrushSettingService and CrossTabChannel provide necessary messaging infrastructure for a consistent user experience.