projects/shelled/rustdesk-as-ref/flutter/lib/utils/relative_mouse_accumulator.dart
2026-04-06 12:04:19 -07:00

59 lines
1.6 KiB
Dart

/// A small helper for accumulating fractional mouse deltas and emitting integer deltas.
///
/// Relative mouse mode uses integer deltas on the wire, but Flutter pointer deltas
/// are doubles. This accumulator preserves sub-pixel movement by carrying the
/// fractional remainder across events.
class RelativeMouseDelta {
final int x;
final int y;
const RelativeMouseDelta(this.x, this.y);
}
/// Accumulates fractional mouse deltas and returns integer deltas when available.
class RelativeMouseAccumulator {
double _fracX = 0.0;
double _fracY = 0.0;
/// Adds a delta and returns an integer delta when at least one axis reaches a
/// magnitude of 1px (after truncation towards zero).
///
/// If [maxDelta] is > 0, the returned integer delta is clamped to
/// [-maxDelta, maxDelta] on each axis.
RelativeMouseDelta? add(
double dx,
double dy, {
required int maxDelta,
}) {
// Guard against misuse: negative maxDelta would silently disable clamping.
assert(maxDelta >= 0, 'maxDelta must be non-negative');
_fracX += dx;
_fracY += dy;
int intX = _fracX.truncate();
int intY = _fracY.truncate();
if (intX == 0 && intY == 0) {
return null;
}
// Clamp before subtracting so excess movement is preserved in the accumulator
// rather than being permanently discarded during spikes.
if (maxDelta > 0) {
intX = intX.clamp(-maxDelta, maxDelta);
intY = intY.clamp(-maxDelta, maxDelta);
}
_fracX -= intX;
_fracY -= intY;
return RelativeMouseDelta(intX, intY);
}
void reset() {
_fracX = 0.0;
_fracY = 0.0;
}
}