| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  | import 'dart:async'; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  | import 'dart:io'; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | import 'dart:math'; | 
					
						
							| 
									
										
										
										
											2022-11-02 22:23:23 +08:00
										 |  |  | import 'dart:ui' as ui; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  | import 'package:desktop_multi_window/desktop_multi_window.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | import 'package:flutter/gestures.dart'; | 
					
						
							|  |  |  | import 'package:flutter/services.dart'; | 
					
						
							|  |  |  | import 'package:flutter/widgets.dart'; | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  | import 'package:flutter_hbb/main.dart'; | 
					
						
							|  |  |  | import 'package:flutter_hbb/utils/multi_window_manager.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | import '../../models/model.dart'; | 
					
						
							|  |  |  | import '../../models/platform_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | import '../common.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | import '../consts.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | /// Mouse button enum.
 | 
					
						
							|  |  |  | enum MouseButtons { left, right, wheel } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  | const _kMouseEventDown = 'mousedown'; | 
					
						
							|  |  |  | const _kMouseEventUp = 'mouseup'; | 
					
						
							|  |  |  | const _kMouseEventMove = 'mousemove'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  | class CanvasCoords { | 
					
						
							|  |  |  |   double x = 0; | 
					
						
							|  |  |  |   double y = 0; | 
					
						
							|  |  |  |   double scale = 1.0; | 
					
						
							|  |  |  |   double scrollX = 0; | 
					
						
							|  |  |  |   double scrollY = 0; | 
					
						
							|  |  |  |   ScrollStyle scrollStyle = ScrollStyle.scrollauto; | 
					
						
							|  |  |  |   Size size = Size.zero; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CanvasCoords(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Map<String, dynamic> toJson() { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       'x': x, | 
					
						
							|  |  |  |       'y': y, | 
					
						
							|  |  |  |       'scale': scale, | 
					
						
							|  |  |  |       'scrollX': scrollX, | 
					
						
							|  |  |  |       'scrollY': scrollY, | 
					
						
							|  |  |  |       'scrollStyle': | 
					
						
							|  |  |  |           scrollStyle == ScrollStyle.scrollauto ? 'scrollauto' : 'scrollbar', | 
					
						
							|  |  |  |       'size': { | 
					
						
							|  |  |  |         'w': size.width, | 
					
						
							|  |  |  |         'h': size.height, | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static CanvasCoords fromJson(Map<String, dynamic> json) { | 
					
						
							|  |  |  |     final model = CanvasCoords(); | 
					
						
							|  |  |  |     model.x = json['x']; | 
					
						
							|  |  |  |     model.y = json['y']; | 
					
						
							|  |  |  |     model.scale = json['scale']; | 
					
						
							|  |  |  |     model.scrollX = json['scrollX']; | 
					
						
							|  |  |  |     model.scrollY = json['scrollY']; | 
					
						
							|  |  |  |     model.scrollStyle = json['scrollStyle'] == 'scrollauto' | 
					
						
							|  |  |  |         ? ScrollStyle.scrollauto | 
					
						
							|  |  |  |         : ScrollStyle.scrollbar; | 
					
						
							|  |  |  |     model.size = Size(json['size']['w'], json['size']['h']); | 
					
						
							|  |  |  |     return model; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static CanvasCoords fromCanvasModel(CanvasModel model) { | 
					
						
							|  |  |  |     final coords = CanvasCoords(); | 
					
						
							|  |  |  |     coords.x = model.x; | 
					
						
							|  |  |  |     coords.y = model.y; | 
					
						
							|  |  |  |     coords.scale = model.scale; | 
					
						
							|  |  |  |     coords.scrollX = model.scrollX; | 
					
						
							|  |  |  |     coords.scrollY = model.scrollY; | 
					
						
							|  |  |  |     coords.scrollStyle = model.scrollStyle; | 
					
						
							|  |  |  |     coords.size = model.size; | 
					
						
							|  |  |  |     return coords; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CursorCoords { | 
					
						
							|  |  |  |   Offset offset = Offset.zero; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CursorCoords(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Map<String, dynamic> toJson() { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       'offset_x': offset.dx, | 
					
						
							|  |  |  |       'offset_y': offset.dy, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static CursorCoords fromJson(Map<String, dynamic> json) { | 
					
						
							|  |  |  |     final model = CursorCoords(); | 
					
						
							|  |  |  |     model.offset = Offset(json['offset_x'], json['offset_y']); | 
					
						
							|  |  |  |     return model; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static CursorCoords fromCursorModel(CursorModel model) { | 
					
						
							|  |  |  |     final coords = CursorCoords(); | 
					
						
							|  |  |  |     coords.offset = model.offset; | 
					
						
							|  |  |  |     return coords; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RemoteWindowCoords { | 
					
						
							|  |  |  |   RemoteWindowCoords( | 
					
						
							|  |  |  |       this.windowRect, this.canvas, this.cursor, this.remoteRect); | 
					
						
							|  |  |  |   Rect windowRect; | 
					
						
							|  |  |  |   CanvasCoords canvas; | 
					
						
							|  |  |  |   CursorCoords cursor; | 
					
						
							|  |  |  |   Rect remoteRect; | 
					
						
							|  |  |  |   Offset relativeOffset = Offset.zero; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Map<String, dynamic> toJson() { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       'canvas': canvas.toJson(), | 
					
						
							|  |  |  |       'cursor': cursor.toJson(), | 
					
						
							|  |  |  |       'windowRect': rectToJson(windowRect), | 
					
						
							|  |  |  |       'remoteRect': rectToJson(remoteRect), | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static Map<String, dynamic> rectToJson(Rect r) { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       'l': r.left, | 
					
						
							|  |  |  |       't': r.top, | 
					
						
							|  |  |  |       'w': r.width, | 
					
						
							|  |  |  |       'h': r.height, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static Rect rectFromJson(Map<String, dynamic> json) { | 
					
						
							|  |  |  |     return Rect.fromLTWH( | 
					
						
							|  |  |  |       json['l'], | 
					
						
							|  |  |  |       json['t'], | 
					
						
							|  |  |  |       json['w'], | 
					
						
							|  |  |  |       json['h'], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RemoteWindowCoords.fromJson(Map<String, dynamic> json) | 
					
						
							|  |  |  |       : windowRect = rectFromJson(json['windowRect']), | 
					
						
							|  |  |  |         canvas = CanvasCoords.fromJson(json['canvas']), | 
					
						
							|  |  |  |         cursor = CursorCoords.fromJson(json['cursor']), | 
					
						
							|  |  |  |         remoteRect = rectFromJson(json['remoteRect']); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | extension ToString on MouseButtons { | 
					
						
							|  |  |  |   String get value { | 
					
						
							|  |  |  |     switch (this) { | 
					
						
							|  |  |  |       case MouseButtons.left: | 
					
						
							|  |  |  |         return 'left'; | 
					
						
							|  |  |  |       case MouseButtons.right: | 
					
						
							|  |  |  |         return 'right'; | 
					
						
							|  |  |  |       case MouseButtons.wheel: | 
					
						
							|  |  |  |         return 'wheel'; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  | class PointerEventToRust { | 
					
						
							|  |  |  |   final String kind; | 
					
						
							|  |  |  |   final String type; | 
					
						
							|  |  |  |   final dynamic value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PointerEventToRust(this.kind, this.type, this.value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Map<String, dynamic> toJson() { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       'k': kind, | 
					
						
							|  |  |  |       'v': { | 
					
						
							|  |  |  |         't': type, | 
					
						
							|  |  |  |         'v': value, | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  | class ToReleaseKeys { | 
					
						
							|  |  |  |   RawKeyEvent? lastLShiftKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastRShiftKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastLCtrlKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastRCtrlKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastLAltKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastRAltKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastLCommandKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastRCommandKeyEvent; | 
					
						
							|  |  |  |   RawKeyEvent? lastSuperKeyEvent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   reset() { | 
					
						
							|  |  |  |     lastLShiftKeyEvent = null; | 
					
						
							|  |  |  |     lastRShiftKeyEvent = null; | 
					
						
							|  |  |  |     lastLCtrlKeyEvent = null; | 
					
						
							|  |  |  |     lastRCtrlKeyEvent = null; | 
					
						
							|  |  |  |     lastLAltKeyEvent = null; | 
					
						
							|  |  |  |     lastRAltKeyEvent = null; | 
					
						
							|  |  |  |     lastLCommandKeyEvent = null; | 
					
						
							|  |  |  |     lastRCommandKeyEvent = null; | 
					
						
							|  |  |  |     lastSuperKeyEvent = null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateKeyDown(LogicalKeyboardKey logicKey, RawKeyDownEvent e) { | 
					
						
							|  |  |  |     if (e.isAltPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.altLeft) { | 
					
						
							|  |  |  |         lastLAltKeyEvent = e; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.altRight) { | 
					
						
							|  |  |  |         lastRAltKeyEvent = e; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else if (e.isControlPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.controlLeft) { | 
					
						
							|  |  |  |         lastLCtrlKeyEvent = e; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.controlRight) { | 
					
						
							|  |  |  |         lastRCtrlKeyEvent = e; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else if (e.isShiftPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.shiftLeft) { | 
					
						
							|  |  |  |         lastLShiftKeyEvent = e; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.shiftRight) { | 
					
						
							|  |  |  |         lastRShiftKeyEvent = e; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else if (e.isMetaPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.metaLeft) { | 
					
						
							|  |  |  |         lastLCommandKeyEvent = e; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.metaRight) { | 
					
						
							|  |  |  |         lastRCommandKeyEvent = e; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.superKey) { | 
					
						
							|  |  |  |         lastSuperKeyEvent = e; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateKeyUp(LogicalKeyboardKey logicKey, RawKeyUpEvent e) { | 
					
						
							|  |  |  |     if (e.isAltPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.altLeft) { | 
					
						
							|  |  |  |         lastLAltKeyEvent = null; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.altRight) { | 
					
						
							|  |  |  |         lastRAltKeyEvent = null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else if (e.isControlPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.controlLeft) { | 
					
						
							|  |  |  |         lastLCtrlKeyEvent = null; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.controlRight) { | 
					
						
							|  |  |  |         lastRCtrlKeyEvent = null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else if (e.isShiftPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.shiftLeft) { | 
					
						
							|  |  |  |         lastLShiftKeyEvent = null; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.shiftRight) { | 
					
						
							|  |  |  |         lastRShiftKeyEvent = null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else if (e.isMetaPressed) { | 
					
						
							|  |  |  |       if (logicKey == LogicalKeyboardKey.metaLeft) { | 
					
						
							|  |  |  |         lastLCommandKeyEvent = null; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.metaRight) { | 
					
						
							|  |  |  |         lastRCommandKeyEvent = null; | 
					
						
							|  |  |  |       } else if (logicKey == LogicalKeyboardKey.superKey) { | 
					
						
							|  |  |  |         lastSuperKeyEvent = null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   release(KeyEventResult Function(RawKeyEvent e) handleRawKeyEvent) { | 
					
						
							|  |  |  |     for (final key in [ | 
					
						
							|  |  |  |       lastLShiftKeyEvent, | 
					
						
							|  |  |  |       lastRShiftKeyEvent, | 
					
						
							|  |  |  |       lastLCtrlKeyEvent, | 
					
						
							|  |  |  |       lastRCtrlKeyEvent, | 
					
						
							|  |  |  |       lastLAltKeyEvent, | 
					
						
							|  |  |  |       lastRAltKeyEvent, | 
					
						
							|  |  |  |       lastLCommandKeyEvent, | 
					
						
							|  |  |  |       lastRCommandKeyEvent, | 
					
						
							|  |  |  |       lastSuperKeyEvent, | 
					
						
							|  |  |  |     ]) { | 
					
						
							|  |  |  |       if (key != null) { | 
					
						
							|  |  |  |         handleRawKeyEvent(RawKeyUpEvent( | 
					
						
							|  |  |  |           data: key.data, | 
					
						
							|  |  |  |           character: key.character, | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | class InputModel { | 
					
						
							|  |  |  |   final WeakReference<FFI> parent; | 
					
						
							| 
									
										
										
										
											2023-11-29 21:31:27 +08:00
										 |  |  |   String keyboardMode = ''; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // keyboard
 | 
					
						
							|  |  |  |   var shift = false; | 
					
						
							|  |  |  |   var ctrl = false; | 
					
						
							|  |  |  |   var alt = false; | 
					
						
							|  |  |  |   var command = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  |   final ToReleaseKeys toReleaseKeys = ToReleaseKeys(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |   // trackpad
 | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |   var _trackpadLastDelta = Offset.zero; | 
					
						
							|  |  |  |   var _stopFling = true; | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |   var _fling = false; | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |   Timer? _flingTimer; | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |   final _flingBaseDelay = 30; | 
					
						
							| 
									
										
										
										
											2023-06-28 23:00:29 +08:00
										 |  |  |   // trackpad, peer linux
 | 
					
						
							|  |  |  |   final _trackpadSpeed = 0.06; | 
					
						
							|  |  |  |   var _trackpadScrollUnsent = Offset.zero; | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:04:12 +08:00
										 |  |  |   var _lastScale = 1.0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 12:43:47 +08:00
										 |  |  |   bool _pointerMovedAfterEnter = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   // mouse
 | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |   final isPhysicalMouse = false.obs; | 
					
						
							| 
									
										
										
										
											2023-01-05 14:58:38 +08:00
										 |  |  |   int _lastButtons = 0; | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |   Offset lastMousePos = Offset.zero; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |   bool _queryOtherWindowCoords = false; | 
					
						
							|  |  |  |   Rect? _windowRect; | 
					
						
							|  |  |  |   List<RemoteWindowCoords> _remoteWindowCoords = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |   late final SessionID sessionId; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  |   bool get keyboardPerm => parent.target!.ffiModel.keyboard; | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |   String get id => parent.target?.id ?? ''; | 
					
						
							|  |  |  |   String? get peerPlatform => parent.target?.ffiModel.pi.platform; | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |   bool get isViewOnly => parent.target!.ffiModel.viewOnly; | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |   double get devicePixelRatio => parent.target!.canvasModel.devicePixelRatio; | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |   InputModel(this.parent) { | 
					
						
							|  |  |  |     sessionId = parent.target!.sessionId; | 
					
						
							| 
									
										
										
										
											2023-11-29 21:31:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // It is ok to call updateKeyboardMode() directly.
 | 
					
						
							|  |  |  |     // Because `bind` is initialized in `PlatformFFI.init()` which is called very early.
 | 
					
						
							|  |  |  |     // But we still wrap it in a Future.delayed() to make it more clear.
 | 
					
						
							|  |  |  |     Future.delayed(Duration(milliseconds: 100), () { | 
					
						
							|  |  |  |       updateKeyboardMode(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateKeyboardMode() async { | 
					
						
							|  |  |  |     // * Currently mobile does not enable map mode
 | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isDesktop || isWebDesktop) { | 
					
						
							| 
									
										
										
										
											2023-11-29 21:31:27 +08:00
										 |  |  |       if (keyboardMode.isEmpty) { | 
					
						
							|  |  |  |         keyboardMode = | 
					
						
							|  |  |  |             await bind.sessionGetKeyboardMode(sessionId: sessionId) ?? | 
					
						
							|  |  |  |                 kKeyLegacyMode; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  |   KeyEventResult handleRawKeyEvent(RawKeyEvent e) { | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return KeyEventResult.handled; | 
					
						
							|  |  |  |     if ((isDesktop || isWebDesktop) && !isInputSourceFlutter) { | 
					
						
							| 
									
										
										
										
											2023-02-21 18:43:43 +08:00
										 |  |  |       return KeyEventResult.handled; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |     final key = e.logicalKey; | 
					
						
							|  |  |  |     if (e is RawKeyDownEvent) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |       if (!e.repeat) { | 
					
						
							|  |  |  |         if (e.isAltPressed && !alt) { | 
					
						
							|  |  |  |           alt = true; | 
					
						
							|  |  |  |         } else if (e.isControlPressed && !ctrl) { | 
					
						
							|  |  |  |           ctrl = true; | 
					
						
							|  |  |  |         } else if (e.isShiftPressed && !shift) { | 
					
						
							|  |  |  |           shift = true; | 
					
						
							|  |  |  |         } else if (e.isMetaPressed && !command) { | 
					
						
							|  |  |  |           command = true; | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  |       toReleaseKeys.updateKeyDown(key, e); | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (e is RawKeyUpEvent) { | 
					
						
							|  |  |  |       if (key == LogicalKeyboardKey.altLeft || | 
					
						
							|  |  |  |           key == LogicalKeyboardKey.altRight) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         alt = false; | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |       } else if (key == LogicalKeyboardKey.controlLeft || | 
					
						
							|  |  |  |           key == LogicalKeyboardKey.controlRight) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         ctrl = false; | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |       } else if (key == LogicalKeyboardKey.shiftRight || | 
					
						
							|  |  |  |           key == LogicalKeyboardKey.shiftLeft) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         shift = false; | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |       } else if (key == LogicalKeyboardKey.metaLeft || | 
					
						
							|  |  |  |           key == LogicalKeyboardKey.metaRight || | 
					
						
							|  |  |  |           key == LogicalKeyboardKey.superKey) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         command = false; | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       toReleaseKeys.updateKeyUp(key, e); | 
					
						
							| 
									
										
										
										
											2022-09-26 20:01:01 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 23:14:24 +09:00
										 |  |  |     // * Currently mobile does not enable map mode
 | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if ((isDesktop || isWebDesktop) && keyboardMode == 'map') { | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |       mapKeyboardMode(e); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       legacyKeyboardMode(e); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return KeyEventResult.handled; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void mapKeyboardMode(RawKeyEvent e) { | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |     int positionCode = -1; | 
					
						
							|  |  |  |     int platformCode = -1; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     bool down; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (e.data is RawKeyEventDataMacOs) { | 
					
						
							|  |  |  |       RawKeyEventDataMacOs newData = e.data as RawKeyEventDataMacOs; | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |       positionCode = newData.keyCode; | 
					
						
							|  |  |  |       platformCode = newData.keyCode; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } else if (e.data is RawKeyEventDataWindows) { | 
					
						
							|  |  |  |       RawKeyEventDataWindows newData = e.data as RawKeyEventDataWindows; | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |       positionCode = newData.scanCode; | 
					
						
							|  |  |  |       platformCode = newData.keyCode; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } else if (e.data is RawKeyEventDataLinux) { | 
					
						
							|  |  |  |       RawKeyEventDataLinux newData = e.data as RawKeyEventDataLinux; | 
					
						
							| 
									
										
										
										
											2023-01-10 14:11:49 +08:00
										 |  |  |       // scanCode and keyCode of RawKeyEventDataLinux are incorrect.
 | 
					
						
							|  |  |  |       // 1. scanCode means keycode
 | 
					
						
							|  |  |  |       // 2. keyCode means keysym
 | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |       positionCode = newData.scanCode; | 
					
						
							|  |  |  |       platformCode = newData.keyCode; | 
					
						
							| 
									
										
										
										
											2022-09-29 18:56:47 +08:00
										 |  |  |     } else if (e.data is RawKeyEventDataAndroid) { | 
					
						
							| 
									
										
										
										
											2022-09-28 00:12:08 -07:00
										 |  |  |       RawKeyEventDataAndroid newData = e.data as RawKeyEventDataAndroid; | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |       positionCode = newData.scanCode + 8; | 
					
						
							|  |  |  |       platformCode = newData.keyCode; | 
					
						
							|  |  |  |     } else {} | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (e is RawKeyDownEvent) { | 
					
						
							|  |  |  |       down = true; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       down = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |     inputRawKey(e.character ?? '', platformCode, positionCode, down); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   /// Send raw Key Event
 | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |   void inputRawKey(String name, int platformCode, int positionCode, bool down) { | 
					
						
							| 
									
										
										
										
											2023-01-10 14:11:49 +08:00
										 |  |  |     const capslock = 1; | 
					
						
							|  |  |  |     const numlock = 2; | 
					
						
							|  |  |  |     const scrolllock = 3; | 
					
						
							|  |  |  |     int lockModes = 0; | 
					
						
							|  |  |  |     if (HardwareKeyboard.instance.lockModesEnabled | 
					
						
							|  |  |  |         .contains(KeyboardLockMode.capsLock)) { | 
					
						
							|  |  |  |       lockModes |= (1 << capslock); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (HardwareKeyboard.instance.lockModesEnabled | 
					
						
							|  |  |  |         .contains(KeyboardLockMode.numLock)) { | 
					
						
							|  |  |  |       lockModes |= (1 << numlock); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (HardwareKeyboard.instance.lockModesEnabled | 
					
						
							|  |  |  |         .contains(KeyboardLockMode.scrollLock)) { | 
					
						
							|  |  |  |       lockModes |= (1 << scrolllock); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     bind.sessionHandleFlutterKeyEvent( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |         sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         name: name, | 
					
						
							| 
									
										
										
										
											2023-04-04 18:35:01 +08:00
										 |  |  |         platformCode: platformCode, | 
					
						
							|  |  |  |         positionCode: positionCode, | 
					
						
							| 
									
										
										
										
											2023-01-10 14:11:49 +08:00
										 |  |  |         lockModes: lockModes, | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         downOrUp: down); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void legacyKeyboardMode(RawKeyEvent e) { | 
					
						
							|  |  |  |     if (e is RawKeyDownEvent) { | 
					
						
							|  |  |  |       if (e.repeat) { | 
					
						
							|  |  |  |         sendRawKey(e, press: true); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         sendRawKey(e, down: true); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (e is RawKeyUpEvent) { | 
					
						
							|  |  |  |       sendRawKey(e); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void sendRawKey(RawKeyEvent e, {bool? down, bool? press}) { | 
					
						
							|  |  |  |     // for maximum compatibility
 | 
					
						
							| 
									
										
										
										
											2022-09-26 00:50:12 -07:00
										 |  |  |     final label = physicalKeyMap[e.physicalKey.usbHidUsage] ?? | 
					
						
							|  |  |  |         logicalKeyMap[e.logicalKey.keyId] ?? | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |         e.logicalKey.keyLabel; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     inputKey(label, down: down, press: press ?? false); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   /// Send key stroke event.
 | 
					
						
							|  |  |  |   /// [down] indicates the key's state(down or up).
 | 
					
						
							|  |  |  |   /// [press] indicates a click event(down and up).
 | 
					
						
							|  |  |  |   void inputKey(String name, {bool? down, bool? press}) { | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  |     if (!keyboardPerm) return; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     bind.sessionInputKey( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |         sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         name: name, | 
					
						
							|  |  |  |         down: down ?? false, | 
					
						
							|  |  |  |         press: press ?? true, | 
					
						
							|  |  |  |         alt: alt, | 
					
						
							|  |  |  |         ctrl: ctrl, | 
					
						
							|  |  |  |         shift: shift, | 
					
						
							|  |  |  |         command: command); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |   Map<String, dynamic> _getMouseEvent(PointerEvent evt, String type) { | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     final Map<String, dynamic> out = {}; | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Check update event type and set buttons to be sent.
 | 
					
						
							| 
									
										
										
										
											2023-01-05 14:58:38 +08:00
										 |  |  |     int buttons = _lastButtons; | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |     if (type == _kMouseEventMove) { | 
					
						
							| 
									
										
										
										
											2023-01-09 02:30:18 -05:00
										 |  |  |       // flutter may emit move event if one button is pressed and another button
 | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |       // is pressing or releasing.
 | 
					
						
							| 
									
										
										
										
											2023-01-05 14:58:38 +08:00
										 |  |  |       if (evt.buttons != _lastButtons) { | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |         // For simplicity
 | 
					
						
							|  |  |  |         // Just consider 3 - 1 ((Left + Right buttons) - Left button)
 | 
					
						
							|  |  |  |         // Do not consider 2 - 1 (Right button - Left button)
 | 
					
						
							|  |  |  |         // or 6 - 5 ((Right + Mid buttons) - (Left + Mid buttons))
 | 
					
						
							|  |  |  |         // and so on
 | 
					
						
							| 
									
										
										
										
											2023-01-05 14:58:38 +08:00
										 |  |  |         buttons = evt.buttons - _lastButtons; | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |         if (buttons > 0) { | 
					
						
							|  |  |  |           type = _kMouseEventDown; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           type = _kMouseEventUp; | 
					
						
							|  |  |  |           buttons = -buttons; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |       if (evt.buttons != 0) { | 
					
						
							|  |  |  |         buttons = evt.buttons; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-05 14:58:38 +08:00
										 |  |  |     _lastButtons = evt.buttons; | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     out['buttons'] = buttons; | 
					
						
							|  |  |  |     out['type'] = type; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     return out; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   /// Send a mouse tap event(down and up).
 | 
					
						
							|  |  |  |   void tap(MouseButtons button) { | 
					
						
							|  |  |  |     sendMouse('down', button); | 
					
						
							|  |  |  |     sendMouse('up', button); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   void tapDown(MouseButtons button) { | 
					
						
							|  |  |  |     sendMouse('down', button); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 21:04:12 +08:00
										 |  |  |   void tapUp(MouseButtons button) { | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     sendMouse('up', button); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   /// Send scroll event with scroll distance [y].
 | 
					
						
							|  |  |  |   void scroll(int y) { | 
					
						
							|  |  |  |     bind.sessionSendMouse( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |         sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         msg: json | 
					
						
							|  |  |  |             .encode(modify({'id': id, 'type': 'wheel', 'y': y.toString()}))); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Reset key modifiers to false, including [shift], [ctrl], [alt] and [command].
 | 
					
						
							|  |  |  |   void resetModifiers() { | 
					
						
							|  |  |  |     shift = ctrl = alt = command = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Modify the given modifier map [evt] based on current modifier key status.
 | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |   Map<String, dynamic> modify(Map<String, dynamic> evt) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     if (ctrl) evt['ctrl'] = 'true'; | 
					
						
							|  |  |  |     if (shift) evt['shift'] = 'true'; | 
					
						
							|  |  |  |     if (alt) evt['alt'] = 'true'; | 
					
						
							|  |  |  |     if (command) evt['command'] = 'true'; | 
					
						
							|  |  |  |     return evt; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Send mouse press event.
 | 
					
						
							|  |  |  |   void sendMouse(String type, MouseButtons button) { | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  |     if (!keyboardPerm) return; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     bind.sessionSendMouse( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |         sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         msg: json.encode(modify({'type': type, 'buttons': button.value}))); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void enterOrLeave(bool enter) { | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  |     toReleaseKeys.release(handleRawKeyEvent); | 
					
						
							| 
									
										
										
										
											2023-12-17 12:43:47 +08:00
										 |  |  |     _pointerMovedAfterEnter = false; | 
					
						
							| 
									
										
										
										
											2023-11-29 20:57:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     // Fix status
 | 
					
						
							|  |  |  |     if (!enter) { | 
					
						
							|  |  |  |       resetModifiers(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |     _flingTimer?.cancel(); | 
					
						
							| 
									
										
										
										
											2023-11-28 23:57:48 +08:00
										 |  |  |     if (!isInputSourceFlutter) { | 
					
						
							|  |  |  |       bind.sessionEnterOrLeave(sessionId: sessionId, enter: enter); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Send mouse movement event with distance in [x] and [y].
 | 
					
						
							|  |  |  |   void moveMouse(double x, double y) { | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  |     if (!keyboardPerm) return; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     var x2 = x.toInt(); | 
					
						
							|  |  |  |     var y2 = y.toInt(); | 
					
						
							|  |  |  |     bind.sessionSendMouse( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |         sessionId: sessionId, | 
					
						
							|  |  |  |         msg: json.encode(modify({'x': '$x2', 'y': '$y2'}))); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   void onPointHoverImage(PointerHoverEvent e) { | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _stopFling = true; | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2023-05-04 20:31:03 +08:00
										 |  |  |     if (e.kind != ui.PointerDeviceKind.mouse) return; | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |     if (!isPhysicalMouse.value) { | 
					
						
							|  |  |  |       isPhysicalMouse.value = true; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |     if (isPhysicalMouse.value) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       handleMouse(_getMouseEvent(e, _kMouseEventMove), e.position); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |   void onPointerPanZoomStart(PointerPanZoomStartEvent e) { | 
					
						
							| 
									
										
										
										
											2023-07-18 21:04:12 +08:00
										 |  |  |     _lastScale = 1.0; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _stopFling = true; | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     if (peerPlatform == kPeerPlatformAndroid) { | 
					
						
							|  |  |  |       handlePointerEvent('touch', 'pan_start', e.position); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // https://docs.flutter.dev/release/breaking-changes/trackpad-gestures
 | 
					
						
							|  |  |  |   void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent e) { | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     if (peerPlatform != kPeerPlatformAndroid) { | 
					
						
							|  |  |  |       final scale = ((e.scale - _lastScale) * 1000).toInt(); | 
					
						
							|  |  |  |       _lastScale = e.scale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (scale != 0) { | 
					
						
							|  |  |  |         bind.sessionSendPointer( | 
					
						
							|  |  |  |             sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |             msg: json.encode( | 
					
						
							|  |  |  |                 PointerEventToRust(kPointerEventKindTouch, 'scale', scale) | 
					
						
							|  |  |  |                     .toJson())); | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-07-19 01:18:10 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-28 23:06:01 +08:00
										 |  |  |     final delta = e.panDelta; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _trackpadLastDelta = delta; | 
					
						
							| 
									
										
										
										
											2023-06-28 23:00:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |     var x = delta.dx.toInt(); | 
					
						
							|  |  |  |     var y = delta.dy.toInt(); | 
					
						
							| 
									
										
										
										
											2023-08-10 08:37:18 +08:00
										 |  |  |     if (peerPlatform == kPeerPlatformLinux) { | 
					
						
							| 
									
										
										
										
											2023-06-28 23:00:29 +08:00
										 |  |  |       _trackpadScrollUnsent += (delta * _trackpadSpeed); | 
					
						
							|  |  |  |       x = _trackpadScrollUnsent.dx.truncate(); | 
					
						
							|  |  |  |       y = _trackpadScrollUnsent.dy.truncate(); | 
					
						
							|  |  |  |       _trackpadScrollUnsent -= Offset(x.toDouble(), y.toDouble()); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (x == 0 && y == 0) { | 
					
						
							|  |  |  |         final thr = 0.1; | 
					
						
							|  |  |  |         if (delta.dx.abs() > delta.dy.abs()) { | 
					
						
							|  |  |  |           x = delta.dx > thr ? 1 : (delta.dx < -thr ? -1 : 0); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           y = delta.dy > thr ? 1 : (delta.dy < -thr ? -1 : 0); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-06-28 22:35:21 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |     if (x != 0 || y != 0) { | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |       if (peerPlatform == kPeerPlatformAndroid) { | 
					
						
							| 
									
										
										
										
											2023-11-28 23:57:48 +08:00
										 |  |  |         handlePointerEvent( | 
					
						
							|  |  |  |             'touch', 'pan_update', Offset(x.toDouble(), y.toDouble())); | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |       } else { | 
					
						
							|  |  |  |         bind.sessionSendMouse( | 
					
						
							|  |  |  |             sessionId: sessionId, | 
					
						
							|  |  |  |             msg: '{"type": "trackpad", "x": "$x", "y": "$y"}'); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-21 08:24:44 -07:00
										 |  |  |   void _scheduleFling(double x, double y, int delay) { | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  |     if ((x == 0 && y == 0) || _stopFling) { | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |       _fling = false; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _flingTimer = Timer(Duration(milliseconds: delay), () { | 
					
						
							|  |  |  |       if (_stopFling) { | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |         _fling = false; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |       final d = 0.97; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |       x *= d; | 
					
						
							|  |  |  |       y *= d; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 10:52:43 +08:00
										 |  |  |       // Try set delta (x,y) and delay.
 | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |       var dx = x.toInt(); | 
					
						
							|  |  |  |       var dy = y.toInt(); | 
					
						
							| 
									
										
										
										
											2023-06-28 23:00:29 +08:00
										 |  |  |       if (parent.target?.ffiModel.pi.platform == kPeerPlatformLinux) { | 
					
						
							|  |  |  |         dx = (x * _trackpadSpeed).toInt(); | 
					
						
							|  |  |  |         dy = (y * _trackpadSpeed).toInt(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |       var delay = _flingBaseDelay; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (dx == 0 && dy == 0) { | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |         _fling = false; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       bind.sessionSendMouse( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |           sessionId: sessionId, | 
					
						
							|  |  |  |           msg: '{"type": "trackpad", "x": "$dx", "y": "$dy"}'); | 
					
						
							| 
									
										
										
										
											2023-05-21 08:24:44 -07:00
										 |  |  |       _scheduleFling(x, y, delay); | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |   void waitLastFlingDone() { | 
					
						
							|  |  |  |     if (_fling) { | 
					
						
							|  |  |  |       _stopFling = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (var i = 0; i < 5; i++) { | 
					
						
							|  |  |  |       if (!_fling) { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       sleep(Duration(milliseconds: 10)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     _flingTimer?.cancel(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |   void onPointerPanZoomEnd(PointerPanZoomEndEvent e) { | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     if (peerPlatform == kPeerPlatformAndroid) { | 
					
						
							|  |  |  |       handlePointerEvent('touch', 'pan_end', e.position); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-19 01:18:10 +08:00
										 |  |  |     bind.sessionSendPointer( | 
					
						
							|  |  |  |         sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |         msg: json.encode( | 
					
						
							|  |  |  |             PointerEventToRust(kPointerEventKindTouch, 'scale', 0).toJson())); | 
					
						
							| 
									
										
										
										
											2023-07-19 01:18:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |     waitLastFlingDone(); | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _stopFling = false; | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-21 08:24:44 -07:00
										 |  |  |     // 2.0 is an experience value
 | 
					
						
							|  |  |  |     double minFlingValue = 2.0; | 
					
						
							|  |  |  |     if (_trackpadLastDelta.dx.abs() > minFlingValue || | 
					
						
							|  |  |  |         _trackpadLastDelta.dy.abs() > minFlingValue) { | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |       _fling = true; | 
					
						
							| 
									
										
										
										
											2023-05-21 08:24:44 -07:00
										 |  |  |       _scheduleFling( | 
					
						
							|  |  |  |           _trackpadLastDelta.dx, _trackpadLastDelta.dy, _flingBaseDelay); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _trackpadLastDelta = Offset.zero; | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-02-01 16:29:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   void onPointDownImage(PointerDownEvent e) { | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     debugPrint("onPointDownImage ${e.kind}"); | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _stopFling = true; | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |     if (isDesktop) _queryOtherWindowCoords = true; | 
					
						
							|  |  |  |     _remoteWindowCoords = []; | 
					
						
							|  |  |  |     _windowRect = null; | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2023-05-04 20:31:03 +08:00
										 |  |  |     if (e.kind != ui.PointerDeviceKind.mouse) { | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |       if (isPhysicalMouse.value) { | 
					
						
							|  |  |  |         isPhysicalMouse.value = false; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |     if (isPhysicalMouse.value) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       handleMouse(_getMouseEvent(e, _kMouseEventDown), e.position); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPointUpImage(PointerUpEvent e) { | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |     if (isDesktop) _queryOtherWindowCoords = false; | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2023-05-04 20:31:03 +08:00
										 |  |  |     if (e.kind != ui.PointerDeviceKind.mouse) return; | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |     if (isPhysicalMouse.value) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       handleMouse(_getMouseEvent(e, _kMouseEventUp), e.position); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPointMoveImage(PointerMoveEvent e) { | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     if (e.kind != ui.PointerDeviceKind.mouse) return; | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |     if (_queryOtherWindowCoords) { | 
					
						
							|  |  |  |       Future.delayed(Duration.zero, () async { | 
					
						
							|  |  |  |         _windowRect = await fillRemoteCoordsAndGetCurFrame(_remoteWindowCoords); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       _queryOtherWindowCoords = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |     if (isPhysicalMouse.value) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       handleMouse(_getMouseEvent(e, _kMouseEventMove), e.position); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |   static Future<Rect?> fillRemoteCoordsAndGetCurFrame( | 
					
						
							|  |  |  |       List<RemoteWindowCoords> remoteWindowCoords) async { | 
					
						
							|  |  |  |     final coords = | 
					
						
							|  |  |  |         await rustDeskWinManager.getOtherRemoteWindowCoordsFromMain(); | 
					
						
							|  |  |  |     final wc = WindowController.fromWindowId(kWindowId!); | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       final frame = await wc.getFrame(); | 
					
						
							|  |  |  |       for (final c in coords) { | 
					
						
							|  |  |  |         c.relativeOffset = Offset( | 
					
						
							|  |  |  |             c.windowRect.left - frame.left, c.windowRect.top - frame.top); | 
					
						
							|  |  |  |         remoteWindowCoords.add(c); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return frame; | 
					
						
							|  |  |  |     } catch (e) { | 
					
						
							|  |  |  |       // Unreachable code
 | 
					
						
							|  |  |  |       debugPrint("Failed to get frame of window $kWindowId, it may be hidden"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |   void onPointerSignalImage(PointerSignalEvent e) { | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     if (isViewOnly) return; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     if (e is PointerScrollEvent) { | 
					
						
							|  |  |  |       var dx = e.scrollDelta.dx.toInt(); | 
					
						
							|  |  |  |       var dy = e.scrollDelta.dy.toInt(); | 
					
						
							|  |  |  |       if (dx > 0) { | 
					
						
							|  |  |  |         dx = -1; | 
					
						
							|  |  |  |       } else if (dx < 0) { | 
					
						
							|  |  |  |         dx = 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (dy > 0) { | 
					
						
							|  |  |  |         dy = -1; | 
					
						
							|  |  |  |       } else if (dy < 0) { | 
					
						
							|  |  |  |         dy = 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       bind.sessionSendMouse( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |           sessionId: sessionId, | 
					
						
							|  |  |  |           msg: '{"type": "wheel", "x": "$dx", "y": "$dy"}'); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 22:12:36 +08:00
										 |  |  |   void refreshMousePos() => handleMouse({ | 
					
						
							|  |  |  |         'buttons': 0, | 
					
						
							|  |  |  |         'type': _kMouseEventMove, | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       }, lastMousePos); | 
					
						
							| 
									
										
										
										
											2023-01-30 22:12:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 21:05:41 +08:00
										 |  |  |   void tryMoveEdgeOnExit(Offset pos) => handleMouse( | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |         { | 
					
						
							|  |  |  |           'buttons': 0, | 
					
						
							|  |  |  |           'type': _kMouseEventMove, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |         pos, | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |         onExit: true, | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int trySetNearestRange(int v, int min, int max, int n) { | 
					
						
							|  |  |  |     if (v < min && v >= min - n) { | 
					
						
							|  |  |  |       v = min; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (v > max && v <= max + n) { | 
					
						
							|  |  |  |       v = max; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |   Offset setNearestEdge(double x, double y, Rect rect) { | 
					
						
							|  |  |  |     double left = x - rect.left; | 
					
						
							|  |  |  |     double right = rect.right - 1 - x; | 
					
						
							|  |  |  |     double top = y - rect.top; | 
					
						
							|  |  |  |     double bottom = rect.bottom - 1 - y; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     if (left < right && left < top && left < bottom) { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |       x = rect.left; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (right < left && right < top && right < bottom) { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |       x = rect.right - 1; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (top < left && top < right && top < bottom) { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |       y = rect.top; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (bottom < left && bottom < right && bottom < top) { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |       y = rect.bottom - 1; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return Offset(x, y); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |   void handlePointerEvent(String kind, String type, Offset offset) { | 
					
						
							|  |  |  |     double x = offset.dx; | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     double y = offset.dy; | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     if (_checkPeerControlProtected(x, y)) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Only touch events are handled for now. So we can just ignore buttons.
 | 
					
						
							|  |  |  |     // to-do: handle mouse events
 | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     late final dynamic evtValue; | 
					
						
							|  |  |  |     if (type == 'pan_update') { | 
					
						
							|  |  |  |       evtValue = { | 
					
						
							| 
									
										
										
										
											2023-08-10 01:02:27 +08:00
										 |  |  |         'x': x.toInt(), | 
					
						
							|  |  |  |         'y': y.toInt(), | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |       }; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       final isMoveTypes = ['pan_start', 'pan_end']; | 
					
						
							|  |  |  |       final pos = handlePointerDevicePos( | 
					
						
							|  |  |  |         kPointerEventKindTouch, | 
					
						
							|  |  |  |         x, | 
					
						
							|  |  |  |         y, | 
					
						
							|  |  |  |         isMoveTypes.contains(type), | 
					
						
							|  |  |  |         type, | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |       if (pos == null) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       evtValue = { | 
					
						
							| 
									
										
										
										
											2023-08-10 01:02:27 +08:00
										 |  |  |         'x': pos.x, | 
					
						
							|  |  |  |         'y': pos.y, | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |       }; | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     final evt = PointerEventToRust(kind, type, evtValue).toJson(); | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     bind.sessionSendPointer( | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |         sessionId: sessionId, msg: json.encode(modify(evt))); | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-11-08 12:01:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |   bool _checkPeerControlProtected(double x, double y) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |     final cursorModel = parent.target!.cursorModel; | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |     if (cursorModel.isPeerControlProtected) { | 
					
						
							|  |  |  |       lastMousePos = ui.Offset(x, y); | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2022-11-08 13:37:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |     if (!cursorModel.gotMouseControl) { | 
					
						
							|  |  |  |       bool selfGetControl = | 
					
						
							|  |  |  |           (x - lastMousePos.dx).abs() > kMouseControlDistance || | 
					
						
							|  |  |  |               (y - lastMousePos.dy).abs() > kMouseControlDistance; | 
					
						
							|  |  |  |       if (selfGetControl) { | 
					
						
							|  |  |  |         cursorModel.gotMouseControl = true; | 
					
						
							| 
									
										
										
										
											2022-11-08 12:01:51 +08:00
										 |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |         lastMousePos = ui.Offset(x, y); | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2022-11-08 12:01:51 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |     lastMousePos = ui.Offset(x, y); | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void handleMouse( | 
					
						
							|  |  |  |     Map<String, dynamic> evt, | 
					
						
							|  |  |  |     Offset offset, { | 
					
						
							|  |  |  |     bool onExit = false, | 
					
						
							|  |  |  |   }) { | 
					
						
							|  |  |  |     double x = offset.dx; | 
					
						
							|  |  |  |     double y = max(0.0, offset.dy); | 
					
						
							| 
									
										
										
										
											2023-08-09 07:39:16 +08:00
										 |  |  |     if (_checkPeerControlProtected(x, y)) { | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-08 12:01:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     var type = ''; | 
					
						
							|  |  |  |     var isMove = false; | 
					
						
							|  |  |  |     switch (evt['type']) { | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |       case _kMouseEventDown: | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         type = 'down'; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |       case _kMouseEventUp: | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         type = 'up'; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |       case _kMouseEventMove: | 
					
						
							| 
									
										
										
										
											2023-12-17 12:43:47 +08:00
										 |  |  |         _pointerMovedAfterEnter = true; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         isMove = true; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     evt['type'] = type; | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-17 12:43:47 +08:00
										 |  |  |     if (type == 'down' && !_pointerMovedAfterEnter) { | 
					
						
							|  |  |  |       // Move mouse to the position of the down event first.
 | 
					
						
							|  |  |  |       lastMousePos = ui.Offset(x, y); | 
					
						
							|  |  |  |       refreshMousePos(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  |     final pos = handlePointerDevicePos( | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |       kPointerEventKindMouse, | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  |       x, | 
					
						
							|  |  |  |       y, | 
					
						
							|  |  |  |       isMove, | 
					
						
							|  |  |  |       type, | 
					
						
							|  |  |  |       onExit: onExit, | 
					
						
							|  |  |  |       buttons: evt['buttons'], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     if (pos == null) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     if (type != '') { | 
					
						
							| 
									
										
										
										
											2023-08-10 03:55:03 +08:00
										 |  |  |       evt['x'] = '0'; | 
					
						
							|  |  |  |       evt['y'] = '0'; | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       evt['x'] = '${pos.x}'; | 
					
						
							|  |  |  |       evt['y'] = '${pos.y}'; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Map<int, String> mapButtons = { | 
					
						
							|  |  |  |       kPrimaryMouseButton: 'left', | 
					
						
							|  |  |  |       kSecondaryMouseButton: 'right', | 
					
						
							|  |  |  |       kMiddleMouseButton: 'wheel', | 
					
						
							|  |  |  |       kBackMouseButton: 'back', | 
					
						
							|  |  |  |       kForwardMouseButton: 'forward' | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     evt['buttons'] = mapButtons[evt['buttons']] ?? ''; | 
					
						
							| 
									
										
										
										
											2023-08-08 23:53:53 +08:00
										 |  |  |     bind.sessionSendMouse(sessionId: sessionId, msg: json.encode(modify(evt))); | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Point? handlePointerDevicePos( | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     String kind, | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  |     double x, | 
					
						
							|  |  |  |     double y, | 
					
						
							|  |  |  |     bool isMove, | 
					
						
							|  |  |  |     String evtType, { | 
					
						
							|  |  |  |     bool onExit = false, | 
					
						
							|  |  |  |     int buttons = kPrimaryMouseButton, | 
					
						
							|  |  |  |   }) { | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |     final ffiModel = parent.target!.ffiModel; | 
					
						
							|  |  |  |     CanvasCoords canvas = | 
					
						
							|  |  |  |         CanvasCoords.fromCanvasModel(parent.target!.canvasModel); | 
					
						
							|  |  |  |     Rect? rect = ffiModel.rect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isMove) { | 
					
						
							|  |  |  |       if (_remoteWindowCoords.isNotEmpty && | 
					
						
							|  |  |  |           _windowRect != null && | 
					
						
							|  |  |  |           !_isInCurrentWindow(x, y)) { | 
					
						
							|  |  |  |         final coords = | 
					
						
							|  |  |  |             findRemoteCoords(x, y, _remoteWindowCoords, devicePixelRatio); | 
					
						
							|  |  |  |         if (coords != null) { | 
					
						
							|  |  |  |           isMove = false; | 
					
						
							|  |  |  |           canvas = coords.canvas; | 
					
						
							|  |  |  |           rect = coords.remoteRect; | 
					
						
							|  |  |  |           x -= coords.relativeOffset.dx / devicePixelRatio; | 
					
						
							|  |  |  |           y -= coords.relativeOffset.dy / devicePixelRatio; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-28 15:30:46 +08:00
										 |  |  |     y -= CanvasModel.topToEdge; | 
					
						
							|  |  |  |     x -= CanvasModel.leftToEdge; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     if (isMove) { | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |       parent.target!.canvasModel.moveDesktopMouse(x, y); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |     return _handlePointerDevicePos( | 
					
						
							|  |  |  |       kind, | 
					
						
							|  |  |  |       x, | 
					
						
							|  |  |  |       y, | 
					
						
							|  |  |  |       isMove, | 
					
						
							|  |  |  |       canvas, | 
					
						
							|  |  |  |       rect, | 
					
						
							|  |  |  |       evtType, | 
					
						
							|  |  |  |       onExit: onExit, | 
					
						
							|  |  |  |       buttons: buttons, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool _isInCurrentWindow(double x, double y) { | 
					
						
							|  |  |  |     final w = _windowRect!.width / devicePixelRatio; | 
					
						
							|  |  |  |     final h = _windowRect!.width / devicePixelRatio; | 
					
						
							|  |  |  |     return x >= 0 && y >= 0 && x <= w && y <= h; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static RemoteWindowCoords? findRemoteCoords(double x, double y, | 
					
						
							|  |  |  |       List<RemoteWindowCoords> remoteWindowCoords, double devicePixelRatio) { | 
					
						
							|  |  |  |     x *= devicePixelRatio; | 
					
						
							|  |  |  |     y *= devicePixelRatio; | 
					
						
							|  |  |  |     for (final c in remoteWindowCoords) { | 
					
						
							|  |  |  |       if (x >= c.relativeOffset.dx && | 
					
						
							|  |  |  |           y >= c.relativeOffset.dy && | 
					
						
							|  |  |  |           x <= c.relativeOffset.dx + c.windowRect.width && | 
					
						
							|  |  |  |           y <= c.relativeOffset.dy + c.windowRect.height) { | 
					
						
							|  |  |  |         return c; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Point? _handlePointerDevicePos( | 
					
						
							|  |  |  |     String kind, | 
					
						
							|  |  |  |     double x, | 
					
						
							|  |  |  |     double y, | 
					
						
							|  |  |  |     bool moveInCanvas, | 
					
						
							|  |  |  |     CanvasCoords canvas, | 
					
						
							|  |  |  |     Rect? rect, | 
					
						
							|  |  |  |     String evtType, { | 
					
						
							|  |  |  |     bool onExit = false, | 
					
						
							|  |  |  |     int buttons = kPrimaryMouseButton, | 
					
						
							|  |  |  |   }) { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     if (rect == null) { | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     final nearThr = 3; | 
					
						
							|  |  |  |     var nearRight = (canvas.size.width - x) < nearThr; | 
					
						
							|  |  |  |     var nearBottom = (canvas.size.height - y) < nearThr; | 
					
						
							|  |  |  |     final imageWidth = rect.width * canvas.scale; | 
					
						
							|  |  |  |     final imageHeight = rect.height * canvas.scale; | 
					
						
							|  |  |  |     if (canvas.scrollStyle == ScrollStyle.scrollbar) { | 
					
						
							|  |  |  |       x += imageWidth * canvas.scrollX; | 
					
						
							|  |  |  |       y += imageHeight * canvas.scrollY; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // boxed size is a center widget
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |       if (canvas.size.width > imageWidth) { | 
					
						
							|  |  |  |         x -= ((canvas.size.width - imageWidth) / 2); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |       if (canvas.size.height > imageHeight) { | 
					
						
							|  |  |  |         y -= ((canvas.size.height - imageHeight) / 2); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |       x -= canvas.x; | 
					
						
							|  |  |  |       y -= canvas.y; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |     x /= canvas.scale; | 
					
						
							|  |  |  |     y /= canvas.scale; | 
					
						
							|  |  |  |     if (canvas.scale > 0 && canvas.scale < 1) { | 
					
						
							|  |  |  |       final step = 1.0 / canvas.scale - 1; | 
					
						
							| 
									
										
										
										
											2023-02-24 23:38:23 +08:00
										 |  |  |       if (nearRight) { | 
					
						
							|  |  |  |         x += step; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (nearBottom) { | 
					
						
							|  |  |  |         y += step; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     x += rect.left; | 
					
						
							|  |  |  |     y += rect.top; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (onExit) { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |       final pos = setNearestEdge(x, y, rect); | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |       x = pos.dx; | 
					
						
							|  |  |  |       y = pos.dy; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-26 23:29:36 +08:00
										 |  |  |     var evtX = 0; | 
					
						
							|  |  |  |     var evtY = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							| 
									
										
										
										
											2023-02-26 23:31:11 +08:00
										 |  |  |       evtX = x.round(); | 
					
						
							|  |  |  |       evtY = y.round(); | 
					
						
							| 
									
										
										
										
											2023-02-26 23:29:36 +08:00
										 |  |  |     } catch (e) { | 
					
						
							| 
									
										
										
										
											2024-04-27 13:45:44 +08:00
										 |  |  |       debugPrintStack(label: 'canvas.scale value ${canvas.scale}, $e'); | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  |       return null; | 
					
						
							| 
									
										
										
										
											2023-02-26 23:29:36 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-10 21:32:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     int minX = rect.left.toInt(); | 
					
						
							| 
									
										
										
										
											2023-12-16 21:41:55 +08:00
										 |  |  |     // https://github.com/rustdesk/rustdesk/issues/6678
 | 
					
						
							|  |  |  |     // For Windows, [0,maxX], [0,maxY] should be set to enable window snapping.
 | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     int maxX = (rect.left + rect.width).toInt() - | 
					
						
							|  |  |  |         (peerPlatform == kPeerPlatformWindows ? 0 : 1); | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     int minY = rect.top.toInt(); | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     int maxY = (rect.top + rect.height).toInt() - | 
					
						
							|  |  |  |         (peerPlatform == kPeerPlatformWindows ? 0 : 1); | 
					
						
							| 
									
										
										
										
											2023-03-13 21:18:10 +08:00
										 |  |  |     evtX = trySetNearestRange(evtX, minX, maxX, 5); | 
					
						
							|  |  |  |     evtY = trySetNearestRange(evtY, minY, maxY, 5); | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |     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; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-02-10 21:32:51 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 14:00:48 +08:00
										 |  |  |     return Point(evtX, evtY); | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Web only
 | 
					
						
							|  |  |  |   void listenToMouse(bool yesOrNo) { | 
					
						
							|  |  |  |     if (yesOrNo) { | 
					
						
							|  |  |  |       platformFFI.startDesktopWebListener(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       platformFFI.stopDesktopWebListener(); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |