From 28f41d6c938a9d228e12c89f92f21ecaa7af51b0 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 20 Mar 2023 18:42:03 +0800 Subject: [PATCH] maybe better touchpad control Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 101 +++++++++++++++++++++------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 38402216d..310a3cadb 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -45,11 +45,12 @@ class InputModel { var command = false; // trackpad - final _trackpadSpeed = 0.01; - var trackpadScrollDistance = Offset.zero; + final _trackpadSpeed = 0.02; + var _trackpadLastDelta = Offset.zero; var _trackpadScrollUnsent = Offset.zero; - var _newScroll = true; + var _stopFling = true; Timer? _flingTimer; + final _flingBaseDelay = 10; // mouse final isPhysicalMouse = false.obs; @@ -310,6 +311,7 @@ class InputModel { } void onPointHoverImage(PointerHoverEvent e) { + _stopFling = true; if (e.kind != ui.PointerDeviceKind.mouse) return; if (!isPhysicalMouse.value) { isPhysicalMouse.value = true; @@ -327,29 +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); - final x = _trackpadScrollUnsent.dx.truncate(); - final y = _trackpadScrollUnsent.dy.truncate(); + var x = _trackpadScrollUnsent.dx.truncate(); + var y = _trackpadScrollUnsent.dy.truncate(); _trackpadScrollUnsent -= Offset(_trackpadScrollUnsent.dx - x.toDouble(), _trackpadScrollUnsent.dy - y.toDouble()); - var sendMsg = x != 0 || y != 0; - if (_newScroll) { - sendMsg = true; - _newScroll = false; + 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; + } } - if (sendMsg) { - bind.sessionSendMouse( - id: id, msg: '{"type": "trackpad", "x": "$x", "y": "$y"}'); - } + bind.sessionSendMouse( + id: id, msg: '{"type": "trackpad", "x": "$x", "y": "$y"}'); } // Simple simulation for fling. @@ -372,20 +378,67 @@ class InputModel { }); } - void onPointerPanZoomEnd(PointerPanZoomEndEvent e) { - _newScroll = true; - _trackpadScrollUnsent = Offset.zero; - 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;