diff --git a/flutter/lib/common/widgets/gestures.dart b/flutter/lib/common/widgets/gestures.dart index 6c269656722f..b3cfeae6e632 100644 --- a/flutter/lib/common/widgets/gestures.dart +++ b/flutter/lib/common/widgets/gestures.dart @@ -86,7 +86,7 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer { // end switch (_currentState) { case GestureState.oneFingerPan: - debugPrint("TwoFingerState.pan onEnd"); + debugPrint("OneFingerState.pan onEnd"); if (onOneFingerPanEnd != null) { onOneFingerPanEnd!(_getDragEndDetails(d)); } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 352da9e6fa66..c313958bddfc 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -169,6 +169,13 @@ const int kWindowMainId = 0; const String kPointerEventKindTouch = "touch"; const String kPointerEventKindMouse = "mouse"; +const String kMouseEventTypeDefault = ""; +const String kMouseEventTypePanStart = "pan_start"; +const String kMouseEventTypePanUpdate = "pan_update"; +const String kMouseEventTypePanEnd = "pan_end"; +const String kMouseEventTypeDown = "down"; +const String kMouseEventTypeUp = "up"; + const String kKeyFlutterKey = "flutter_key"; const String kKeyShowDisplaysAsIndividualWindows = diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 3f413c499bf9..0cc0537d67bb 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -856,7 +856,7 @@ class InputModel { _stopFling = true; if (isViewOnly) return; if (peerPlatform == kPeerPlatformAndroid) { - handlePointerEvent('touch', 'pan_start', e.position); + handlePointerEvent('touch', kMouseEventTypePanStart, e.position); } } @@ -899,8 +899,8 @@ class InputModel { } if (x != 0 || y != 0) { if (peerPlatform == kPeerPlatformAndroid) { - handlePointerEvent( - 'touch', 'pan_update', Offset(x.toDouble(), y.toDouble())); + handlePointerEvent('touch', kMouseEventTypePanUpdate, + Offset(x.toDouble(), y.toDouble())); } else { bind.sessionSendMouse( sessionId: sessionId, @@ -962,7 +962,7 @@ class InputModel { void onPointerPanZoomEnd(PointerPanZoomEndEvent e) { if (peerPlatform == kPeerPlatformAndroid) { - handlePointerEvent('touch', 'pan_end', e.position); + handlePointerEvent('touch', kMouseEventTypePanEnd, e.position); return; } @@ -1080,7 +1080,7 @@ class InputModel { onExit: true, ); - int trySetNearestRange(int v, int min, int max, int n) { + static int tryGetNearestRange(int v, int min, int max, int n) { if (v < min && v >= min - n) { v = min; } @@ -1120,13 +1120,13 @@ class InputModel { // to-do: handle mouse events late final dynamic evtValue; - if (type == 'pan_update') { + if (type == kMouseEventTypePanUpdate) { evtValue = { 'x': x.toInt(), 'y': y.toInt(), }; } else { - final isMoveTypes = ['pan_start', 'pan_end']; + final isMoveTypes = [kMouseEventTypePanStart, kMouseEventTypePanEnd]; final pos = handlePointerDevicePos( kPointerEventKindTouch, x, @@ -1181,14 +1181,14 @@ class InputModel { return; } - var type = ''; + var type = kMouseEventTypeDefault; var isMove = false; switch (evt['type']) { case _kMouseEventDown: - type = 'down'; + type = kMouseEventTypeDown; break; case _kMouseEventUp: - type = 'up'; + type = kMouseEventTypeUp; break; case _kMouseEventMove: _pointerMovedAfterEnter = true; @@ -1199,7 +1199,7 @@ class InputModel { } evt['type'] = type; - if (type == 'down' && !_pointerMovedAfterEnter) { + if (type == kMouseEventTypeDown && !_pointerMovedAfterEnter) { // Move mouse to the position of the down event first. lastMousePos = ui.Offset(x, y); refreshMousePos(); @@ -1372,6 +1372,14 @@ class InputModel { return null; } + return InputModel.getPointInRemoteRect( + true, peerPlatform, kind, evtType, evtX, evtY, rect, + buttons: buttons); + } + + static Point? getPointInRemoteRect(bool isLocalDesktop, String? peerPlatform, + String kind, String evtType, int evtX, int evtY, Rect rect, + {int buttons = kPrimaryMouseButton}) { int minX = rect.left.toInt(); // https://github.com/rustdesk/rustdesk/issues/6678 // For Windows, [0,maxX], [0,maxY] should be set to enable window snapping. @@ -1380,15 +1388,34 @@ class InputModel { int minY = rect.top.toInt(); int maxY = (rect.top + rect.height).toInt() - (peerPlatform == kPeerPlatformWindows ? 0 : 1); - evtX = trySetNearestRange(evtX, minX, maxX, 5); - evtY = trySetNearestRange(evtY, minY, maxY, 5); - if (kind == kPointerEventKindMouse) { - if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { - // If left mouse up, no early return. - if (!(buttons == kPrimaryMouseButton && evtType == 'up')) { - return null; + evtX = InputModel.tryGetNearestRange(evtX, minX, maxX, 5); + evtY = InputModel.tryGetNearestRange(evtY, minY, maxY, 5); + if (isLocalDesktop) { + if (kind == kPointerEventKindMouse) { + if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { + // If left mouse up, no early return. + if (!(buttons == kPrimaryMouseButton && + evtType == kMouseEventTypeUp)) { + return null; + } } } + } else { + bool evtXInRange = evtX >= minX && evtX <= maxX; + bool evtYInRange = evtY >= minY && evtY <= maxY; + if (!(evtXInRange || evtYInRange)) { + return null; + } + if (evtX < minX) { + evtX = minX; + } else if (evtX > maxX) { + evtX = maxX; + } + if (evtY < minY) { + evtY = minY; + } else if (evtY > maxY) { + evtY = maxY; + } } return Point(evtX, evtY); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 80a6809d5181..7765ebc40867 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -6,6 +6,7 @@ import 'dart:ui' as ui; import 'package:bot_toast/bot_toast.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hbb/common/widgets/peers_view.dart'; @@ -1516,10 +1517,13 @@ class CanvasModel with ChangeNotifier { _x = (size.width - displayWidth * _scale) / 2; _y = (size.height - displayHeight * _scale) / 2; _imageOverflow.value = _x < 0 || y < 0; + if (isMobile && style == kRemoteViewStyleOriginal) { + _moveToCenterCursor(); + } if (notify) { notifyListeners(); } - if (refreshMousePos) { + if (!isMobile && refreshMousePos) { parent.target?.inputModel.refreshMousePos(); } tryUpdateScrollStyle(Duration.zero, style); @@ -1709,8 +1713,6 @@ class CanvasModel with ChangeNotifier { _timerMobileFocusCanvasCursor = Timer(Duration(milliseconds: 100), () async { await updateViewStyle(refreshMousePos: false, notify: false); - _moveToCenterCursor(); - parent.target?.cursorModel.ensureCursorInVisibleRect(); notifyListeners(); }); } @@ -2015,17 +2017,6 @@ class CursorModel with ChangeNotifier { return Offset(xoffset, yoffset); } - void ensureCursorInVisibleRect() { - final ensureVisibleValue = 50.0; - final r = getVisibleRect(); - final minX = r.left; - final maxX = max(r.right - ensureVisibleValue, r.left); - final minY = r.top; - final maxY = max(r.bottom - ensureVisibleValue, minY); - _x = min(max(_x, minX), maxX); - _y = min(max(_y, minY), maxY); - } - get scale => parent.target?.canvasModel.scale ?? 1.0; // mobile Soft keyboard, block touch event from the KeyHelpTools @@ -2042,6 +2033,7 @@ class CursorModel with ChangeNotifier { return false; } + // For touch mode move(double x, double y) { if (shouldBlock(x, y)) { _lastIsBlocked = true; @@ -2129,13 +2121,34 @@ class CursorModel with ChangeNotifier { } if (dx == 0 && dy == 0) return; - _x += dx; - _y += dy; + + Point? newPos; + final rect = parent.target?.ffiModel.rect; + if (rect == null) { + // unreachable + return; + } + newPos = InputModel.getPointInRemoteRect( + false, + parent.target?.ffiModel.pi.platform, + kPointerEventKindMouse, + kMouseEventTypeDefault, + (_x + dx).toInt(), + (_y + dy).toInt(), + rect, + buttons: kPrimaryButton); + if (newPos == null) { + return; + } + dx = newPos.x - _x; + dy = newPos.y - _y; + _x = newPos.x.toDouble(); + _y = newPos.y.toDouble(); if (tryMoveCanvasX && dx != 0) { - parent.target?.canvasModel.panX(-dx); + parent.target?.canvasModel.panX(-dx * scale); } if (tryMoveCanvasY && dy != 0) { - parent.target?.canvasModel.panY(-dy); + parent.target?.canvasModel.panY(-dy * scale); } parent.target?.inputModel.moveMouse(_x, _y);