diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 9366d5b46..310a3cadb 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -45,8 +45,12 @@ class InputModel { var command = false; // trackpad - var trackpadScrollDistance = Offset.zero; + final _trackpadSpeed = 0.02; + var _trackpadLastDelta = Offset.zero; + var _trackpadScrollUnsent = Offset.zero; + var _stopFling = true; Timer? _flingTimer; + final _flingBaseDelay = 10; // mouse final isPhysicalMouse = false.obs; @@ -307,6 +311,7 @@ class InputModel { } void onPointHoverImage(PointerHoverEvent e) { + _stopFling = true; if (e.kind != ui.PointerDeviceKind.mouse) return; if (!isPhysicalMouse.value) { isPhysicalMouse.value = true; @@ -324,17 +329,33 @@ class InputModel { } } - void onPointerPanZoomStart(PointerPanZoomStartEvent e) {} + void onPointerPanZoomStart(PointerPanZoomStartEvent e) { + _stopFling = true; + } // https://docs.flutter.dev/release/breaking-changes/trackpad-gestures // TODO(support zoom in/out) void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent e) { var delta = e.panDelta; - trackpadScrollDistance += delta; + _trackpadLastDelta = delta; + _trackpadScrollUnsent += (delta * _trackpadSpeed); + var x = _trackpadScrollUnsent.dx.truncate(); + var y = _trackpadScrollUnsent.dy.truncate(); + _trackpadScrollUnsent -= Offset(_trackpadScrollUnsent.dx - x.toDouble(), + _trackpadScrollUnsent.dy - y.toDouble()); + + if (x == 0 && y == 0) { + x = delta.dx > 1 ? 1 : (delta.dx < -1 ? -1 : 0); + y = delta.dy > 1 ? 1 : (delta.dy < -1 ? -1 : 0); + if (x.abs() > y.abs()) { + y = 0; + } else { + x = 0; + } + } + bind.sessionSendMouse( - id: id, - msg: - '{"type": "trackpad", "x": "${delta.dx.toInt()}", "y": "${delta.dy.toInt()}"}'); + id: id, msg: '{"type": "trackpad", "x": "$x", "y": "$y"}'); } // Simple simulation for fling. @@ -357,18 +378,67 @@ class InputModel { }); } - void onPointerPanZoomEnd(PointerPanZoomEndEvent e) { - var x = _signOrZero(trackpadScrollDistance.dx); - var y = _signOrZero(trackpadScrollDistance.dy); - var dx = trackpadScrollDistance.dx.abs() ~/ 40; - var dy = trackpadScrollDistance.dy.abs() ~/ 40; - _scheduleFling(x, y, dx, dy); + void _scheduleFling2(double x, double y, int delay) { + if ((x ==0 && y == 0) || _stopFling) { + return; + } - trackpadScrollDistance = Offset.zero; + _flingTimer = Timer(Duration(milliseconds: delay), () { + if (_stopFling) { + return; + } + + final d = 0.95; + x *= d; + y *= d; + final dx0 = x * _trackpadSpeed * 2; + final dy0 = y * _trackpadSpeed * 2; + + // Try set delta (x,y) and delay. + var dx = dx0.toInt(); + var dy = dy0.toInt(); + var delay = _flingBaseDelay; + + // Try set min delta (x,y), and increase delay. + if (dx == 0 && dy == 0) { + final thr = 25; + var vx = thr; + var vy = thr; + if (dx0 != 0) { + vx = 1.0 ~/ dx0.abs(); + } + if (dy0 != 0) { + vy = 1.0 ~/ dy0.abs(); + } + if (vx < vy && vx < thr) { + delay *= vx; + dx = dx0 > 0 ? 1 : (dx0 < 0 ? -1 : 0); + } else if (vy < thr) { + delay *= vy; + dy = dy0 > 0 ? 1 : (dy0 < 0 ? -1 : 0); + } + } + + if (dx == 0 && dy == 0) { + return; + } + + bind.sessionSendMouse( + id: id, msg: '{"type": "trackpad", "x": "$dx", "y": "$dy"}'); + _scheduleFling2(x, y, delay); + }); + } + + void onPointerPanZoomEnd(PointerPanZoomEndEvent e) { + _stopFling = false; + _trackpadScrollUnsent = Offset.zero; + _scheduleFling2(_trackpadLastDelta.dx, _trackpadLastDelta.dy, _flingBaseDelay); + _trackpadLastDelta = Offset.zero; } void onPointDownImage(PointerDownEvent e) { debugPrint("onPointDownImage"); + _stopFling = true; if (e.kind != ui.PointerDeviceKind.mouse) { if (isPhysicalMouse.value) { isPhysicalMouse.value = false;