| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | import 'package:flutter/gestures.dart'; | 
					
						
							|  |  |  | import 'package:flutter/services.dart'; | 
					
						
							|  |  |  | import 'package:flutter/widgets.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-11-01 17:01:43 +08:00
										 |  |  | import './state_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class InputModel { | 
					
						
							|  |  |  |   final WeakReference<FFI> parent; | 
					
						
							|  |  |  |   String keyboardMode = "legacy"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // keyboard
 | 
					
						
							|  |  |  |   var shift = false; | 
					
						
							|  |  |  |   var ctrl = false; | 
					
						
							|  |  |  |   var alt = false; | 
					
						
							|  |  |  |   var command = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  |   get id => parent.target?.id ?? ""; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06-06 07:39:44 +08:00
										 |  |  |   InputModel(this.parent) { | 
					
						
							|  |  |  |     sessionId = parent.target!.sessionId; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   KeyEventResult handleRawKeyEvent(FocusNode data, RawKeyEvent e) { | 
					
						
							| 
									
										
										
										
											2023-04-07 16:03:18 +08:00
										 |  |  |     if (isDesktop && !stateGlobal.grabKeyboard) { | 
					
						
							| 
									
										
										
										
											2023-02-21 18:43:43 +08:00
										 |  |  |       return KeyEventResult.handled; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 23:14:24 +09:00
										 |  |  |     // * Currently mobile does not enable map mode
 | 
					
						
							|  |  |  |     if (isDesktop) { | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |       bind.sessionGetKeyboardMode(sessionId: sessionId).then((result) { | 
					
						
							| 
									
										
										
										
											2023-02-09 23:14:24 +09:00
										 |  |  |         keyboardMode = result.toString(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     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-02-09 23:14:24 +09:00
										 |  |  |     // * Currently mobile does not enable map mode
 | 
					
						
							|  |  |  |     if (isDesktop && 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
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Map<String, dynamic> getEvent(PointerEvent evt, String type) { | 
					
						
							|  |  |  |     final Map<String, dynamic> out = {}; | 
					
						
							|  |  |  |     out['x'] = evt.position.dx; | 
					
						
							|  |  |  |     out['y'] = evt.position.dy; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     if (alt) out['alt'] = 'true'; | 
					
						
							|  |  |  |     if (shift) out['shift'] = 'true'; | 
					
						
							|  |  |  |     if (ctrl) out['ctrl'] = 'true'; | 
					
						
							|  |  |  |     if (command) out['command'] = 'true'; | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// 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.
 | 
					
						
							|  |  |  |   Map<String, String> modify(Map<String, String> evt) { | 
					
						
							|  |  |  |     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) { | 
					
						
							|  |  |  |     // Fix status
 | 
					
						
							|  |  |  |     if (!enter) { | 
					
						
							|  |  |  |       resetModifiers(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  |     _flingTimer?.cancel(); | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											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-01-04 20:06:48 +08:00
										 |  |  |       handleMouse(getEvent(e, _kMouseEventMove)); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |   void onPointerPanZoomStart(PointerPanZoomStartEvent e) { | 
					
						
							|  |  |  |     _stopFling = true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-11-20 22:46:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // https://docs.flutter.dev/release/breaking-changes/trackpad-gestures
 | 
					
						
							|  |  |  |   // TODO(support zoom in/out)
 | 
					
						
							|  |  |  |   void onPointerPanZoomUpdate(PointerPanZoomUpdateEvent e) { | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |     final delta = e.panDelta; | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _trackpadLastDelta = delta; | 
					
						
							| 
									
										
										
										
											2023-06-07 20:01:01 +08:00
										 |  |  |     var x = delta.dx.toInt(); | 
					
						
							|  |  |  |     var y = delta.dy.toInt(); | 
					
						
							|  |  |  |     if (x != 0 || y != 0) { | 
					
						
							|  |  |  |       bind.sessionSendMouse( | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |           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-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-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) { | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     debugPrint("onPointDownImage"); | 
					
						
							| 
									
										
										
										
											2023-03-20 18:42:03 +08:00
										 |  |  |     _stopFling = true; | 
					
						
							| 
									
										
										
										
											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-01-04 20:06:48 +08:00
										 |  |  |       handleMouse(getEvent(e, _kMouseEventDown)); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPointUpImage(PointerUpEvent e) { | 
					
						
							| 
									
										
										
										
											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-01-04 20:06:48 +08:00
										 |  |  |       handleMouse(getEvent(e, _kMouseEventUp)); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPointMoveImage(PointerMoveEvent e) { | 
					
						
							|  |  |  |     if (e.kind != ui.PointerDeviceKind.mouse) return; | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |     if (isPhysicalMouse.value) { | 
					
						
							| 
									
										
										
										
											2023-01-04 20:06:48 +08:00
										 |  |  |       handleMouse(getEvent(e, _kMouseEventMove)); | 
					
						
							| 
									
										
										
										
											2022-09-14 23:49:59 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPointerSignalImage(PointerSignalEvent e) { | 
					
						
							|  |  |  |     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({ | 
					
						
							|  |  |  |         'x': lastMousePos.dx, | 
					
						
							|  |  |  |         'y': lastMousePos.dy, | 
					
						
							|  |  |  |         'buttons': 0, | 
					
						
							|  |  |  |         'type': _kMouseEventMove, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 21:05:41 +08:00
										 |  |  |   void tryMoveEdgeOnExit(Offset pos) => handleMouse( | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |         { | 
					
						
							|  |  |  |           'x': pos.dx, | 
					
						
							|  |  |  |           'y': pos.dy, | 
					
						
							|  |  |  |           'buttons': 0, | 
					
						
							|  |  |  |           'type': _kMouseEventMove, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Offset setNearestEdge(double x, double y, Display d) { | 
					
						
							|  |  |  |     double left = x - d.x; | 
					
						
							|  |  |  |     double right = d.x + d.width - 1 - x; | 
					
						
							|  |  |  |     double top = y - d.y; | 
					
						
							|  |  |  |     double bottom = d.y + d.height - 1 - y; | 
					
						
							|  |  |  |     if (left < right && left < top && left < bottom) { | 
					
						
							|  |  |  |       x = d.x; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (right < left && right < top && right < bottom) { | 
					
						
							|  |  |  |       x = d.x + d.width - 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (top < left && top < right && top < bottom) { | 
					
						
							|  |  |  |       y = d.y; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (bottom < left && bottom < right && bottom < top) { | 
					
						
							|  |  |  |       y = d.y + d.height - 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return Offset(x, y); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void handleMouse( | 
					
						
							|  |  |  |     Map<String, dynamic> evt, { | 
					
						
							|  |  |  |     bool onExit = false, | 
					
						
							|  |  |  |   }) { | 
					
						
							| 
									
										
										
										
											2022-11-08 12:01:51 +08:00
										 |  |  |     double x = evt['x']; | 
					
						
							|  |  |  |     double y = max(0.0, evt['y']); | 
					
						
							|  |  |  |     final cursorModel = parent.target!.cursorModel; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |     if (cursorModel.isPeerControlProtected) { | 
					
						
							|  |  |  |       lastMousePos = ui.Offset(x, y); | 
					
						
							| 
									
										
										
										
											2022-11-08 13:37:08 +08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2022-11-08 12:01:51 +08:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 15:05:44 +08:00
										 |  |  |     lastMousePos = ui.Offset(x, y); | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         isMove = true; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     evt['type'] = type; | 
					
						
							| 
									
										
										
										
											2023-02-28 15:30:46 +08:00
										 |  |  |     y -= CanvasModel.topToEdge; | 
					
						
							|  |  |  |     x -= CanvasModel.leftToEdge; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     final canvasModel = parent.target!.canvasModel; | 
					
						
							| 
									
										
										
										
											2023-02-24 23:38:23 +08:00
										 |  |  |     final nearThr = 3; | 
					
						
							|  |  |  |     var nearRight = (canvasModel.size.width - x) < nearThr; | 
					
						
							|  |  |  |     var nearBottom = (canvasModel.size.height - y) < nearThr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     final ffiModel = parent.target!.ffiModel; | 
					
						
							|  |  |  |     if (isMove) { | 
					
						
							|  |  |  |       canvasModel.moveDesktopMouse(x, y); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     final d = ffiModel.display; | 
					
						
							| 
									
										
										
										
											2023-02-24 23:38:23 +08:00
										 |  |  |     final imageWidth = d.width * canvasModel.scale; | 
					
						
							|  |  |  |     final imageHeight = d.height * canvasModel.scale; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     if (canvasModel.scrollStyle == ScrollStyle.scrollbar) { | 
					
						
							|  |  |  |       x += imageWidth * canvasModel.scrollX; | 
					
						
							|  |  |  |       y += imageHeight * canvasModel.scrollY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // boxed size is a center widget
 | 
					
						
							|  |  |  |       if (canvasModel.size.width > imageWidth) { | 
					
						
							|  |  |  |         x -= ((canvasModel.size.width - imageWidth) / 2); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (canvasModel.size.height > imageHeight) { | 
					
						
							|  |  |  |         y -= ((canvasModel.size.height - imageHeight) / 2); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       x -= canvasModel.x; | 
					
						
							|  |  |  |       y -= canvasModel.y; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     x /= canvasModel.scale; | 
					
						
							|  |  |  |     y /= canvasModel.scale; | 
					
						
							| 
									
										
										
										
											2023-02-24 23:38:23 +08:00
										 |  |  |     if (canvasModel.scale > 0 && canvasModel.scale < 1) { | 
					
						
							|  |  |  |       final step = 1.0 / canvasModel.scale - 1; | 
					
						
							|  |  |  |       if (nearRight) { | 
					
						
							|  |  |  |         x += step; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (nearBottom) { | 
					
						
							|  |  |  |         y += step; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     x += d.x; | 
					
						
							|  |  |  |     y += d.y; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (onExit) { | 
					
						
							|  |  |  |       final pos = setNearestEdge(x, y, d); | 
					
						
							|  |  |  |       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) { | 
					
						
							|  |  |  |       debugPrintStack( | 
					
						
							|  |  |  |           label: 'canvasModel.scale value ${canvasModel.scale}, $e'); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-10 21:32:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     int minX = d.x.toInt(); | 
					
						
							|  |  |  |     int maxX = (d.x + d.width).toInt() - 1; | 
					
						
							|  |  |  |     int minY = d.y.toInt(); | 
					
						
							|  |  |  |     int maxY = (d.y + d.height).toInt() - 1; | 
					
						
							| 
									
										
										
										
											2023-03-13 21:18:10 +08:00
										 |  |  |     evtX = trySetNearestRange(evtX, minX, maxX, 5); | 
					
						
							|  |  |  |     evtY = trySetNearestRange(evtY, minY, maxY, 5); | 
					
						
							| 
									
										
										
										
											2023-03-13 21:03:43 +08:00
										 |  |  |     if (evtX < minX || evtY < minY || evtX > maxX || evtY > maxY) { | 
					
						
							| 
									
										
										
										
											2023-02-10 21:32:51 +08:00
										 |  |  |       // If left mouse up, no early return.
 | 
					
						
							|  |  |  |       if (evt['buttons'] != kPrimaryMouseButton || type != 'up') { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     if (type != '') { | 
					
						
							| 
									
										
										
										
											2023-02-26 23:29:36 +08:00
										 |  |  |       evtX = 0; | 
					
						
							|  |  |  |       evtY = 0; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-10 21:32:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-26 23:29:36 +08:00
										 |  |  |     evt['x'] = '$evtX'; | 
					
						
							|  |  |  |     evt['y'] = '$evtY'; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     var buttons = ''; | 
					
						
							|  |  |  |     switch (evt['buttons']) { | 
					
						
							| 
									
										
										
										
											2023-01-05 17:14:44 +08:00
										 |  |  |       case kPrimaryMouseButton: | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         buttons = 'left'; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2023-01-05 17:14:44 +08:00
										 |  |  |       case kSecondaryMouseButton: | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         buttons = 'right'; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2023-01-05 17:14:44 +08:00
										 |  |  |       case kMiddleMouseButton: | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |         buttons = 'wheel'; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2023-01-05 17:14:44 +08:00
										 |  |  |       case kBackMouseButton: | 
					
						
							|  |  |  |         buttons = 'back'; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case kForwardMouseButton: | 
					
						
							|  |  |  |         buttons = 'forward'; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2022-09-27 20:35:02 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     evt['buttons'] = buttons; | 
					
						
							| 
									
										
										
										
											2023-06-06 07:39:44 +08:00
										 |  |  |     bind.sessionSendMouse(sessionId: sessionId, msg: json.encode(evt)); | 
					
						
							| 
									
										
										
										
											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
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |