47 lines
2.0 KiB
Dart
47 lines
2.0 KiB
Dart
|
|
// lib/editor/input/input_arbiter.dart
|
||
|
|
//
|
||
|
|
// Pure draw-vs-pan/zoom arbitration for the pen-first canvas (P0 step 4 —
|
||
|
|
// extracted verbatim from `pen_canvas.dart` so the make-or-break gesture rules
|
||
|
|
// are decided by ONE testable place rather than inline in a StatefulWidget).
|
||
|
|
//
|
||
|
|
// The model (clean-room from Saber, proven live):
|
||
|
|
// - A DRAW gesture is exactly ONE active pointer that is a stylus / inverted
|
||
|
|
// stylus / mouse, OR (when the finger-drawing toggle is on) a single finger.
|
||
|
|
// - >= 2 active pointers ALWAYS means pan/zoom (pinch); never draw.
|
||
|
|
// - Palm rejection: a finger never draws unless the user explicitly enabled
|
||
|
|
// finger-drawing — so a resting palm pans (or is ignored) instead of marking.
|
||
|
|
// - A hardware pen button mapped to `pan` suppresses drawing so the shared
|
||
|
|
// InteractiveViewer pans instead.
|
||
|
|
//
|
||
|
|
// These are PURE functions (no widget/IO state) so the whole truth table is
|
||
|
|
// unit-tested; `pen_canvas.dart` owns the live pointer map and delegates the
|
||
|
|
// decisions here.
|
||
|
|
|
||
|
|
import 'package:flutter/gestures.dart' show PointerDeviceKind;
|
||
|
|
|
||
|
|
/// Whether [kind] is a pen (tip or flipped eraser end).
|
||
|
|
bool isStylusKind(PointerDeviceKind kind) =>
|
||
|
|
kind == PointerDeviceKind.stylus ||
|
||
|
|
kind == PointerDeviceKind.invertedStylus;
|
||
|
|
|
||
|
|
/// Decide whether the gesture currently forming should DRAW.
|
||
|
|
///
|
||
|
|
/// True iff there is exactly one active pointer, drawing is not suppressed by a
|
||
|
|
/// hardware pan button, and the pointer is a draw device:
|
||
|
|
/// - stylus / inverted stylus → always draws,
|
||
|
|
/// - mouse → always draws (desktop authoring),
|
||
|
|
/// - touch → draws only when [fingerDrawingEnabled] (else it pans / is palm).
|
||
|
|
bool shouldDraw({
|
||
|
|
required int activePointerCount,
|
||
|
|
required PointerDeviceKind kind,
|
||
|
|
required bool fingerDrawingEnabled,
|
||
|
|
required bool hwPanActive,
|
||
|
|
}) {
|
||
|
|
if (activePointerCount != 1) return false;
|
||
|
|
if (hwPanActive) return false;
|
||
|
|
if (isStylusKind(kind)) return true;
|
||
|
|
if (kind == PointerDeviceKind.mouse) return true;
|
||
|
|
if (kind == PointerDeviceKind.touch) return fingerDrawingEnabled;
|
||
|
|
return false;
|
||
|
|
}
|