| 
									
										
										
										
											2023-07-19 01:26:43 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							|  |  |  | import 'package:flutter/services.dart'; | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  | import 'package:flutter/gestures.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  | import 'package:flutter_hbb/models/platform_model.dart'; | 
					
						
							|  |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  | import 'package:flutter_hbb/consts.dart'; | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  | import 'package:flutter_hbb/models/model.dart'; | 
					
						
							|  |  |  | import 'package:flutter_hbb/models/input_model.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import './gestures.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class RawKeyFocusScope extends StatelessWidget { | 
					
						
							|  |  |  |   final FocusNode? focusNode; | 
					
						
							|  |  |  |   final ValueChanged<bool>? onFocusChange; | 
					
						
							|  |  |  |   final InputModel inputModel; | 
					
						
							|  |  |  |   final Widget child; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 22:39:30 +08:00
										 |  |  |   RawKeyFocusScope({ | 
					
						
							|  |  |  |     this.focusNode, | 
					
						
							|  |  |  |     this.onFocusChange, | 
					
						
							|  |  |  |     required this.inputModel, | 
					
						
							|  |  |  |     required this.child, | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return FocusScope( | 
					
						
							|  |  |  |         autofocus: true, | 
					
						
							|  |  |  |         child: Focus( | 
					
						
							|  |  |  |             autofocus: true, | 
					
						
							|  |  |  |             canRequestFocus: true, | 
					
						
							|  |  |  |             focusNode: focusNode, | 
					
						
							|  |  |  |             onFocusChange: onFocusChange, | 
					
						
							| 
									
										
										
										
											2023-02-21 18:43:43 +08:00
										 |  |  |             onKey: inputModel.handleRawKeyEvent, | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |             child: child)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  | class RawTouchGestureDetectorRegion extends StatefulWidget { | 
					
						
							|  |  |  |   final Widget child; | 
					
						
							|  |  |  |   final FFI ffi; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   late final InputModel inputModel = ffi.inputModel; | 
					
						
							|  |  |  |   late final FfiModel ffiModel = ffi.ffiModel; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RawTouchGestureDetectorRegion({ | 
					
						
							|  |  |  |     required this.child, | 
					
						
							|  |  |  |     required this.ffi, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   State<RawTouchGestureDetectorRegion> createState() => | 
					
						
							|  |  |  |       _RawTouchGestureDetectorRegionState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:48:58 +08:00
										 |  |  | /// touchMode only:
 | 
					
						
							|  |  |  | ///   LongPress -> right click
 | 
					
						
							|  |  |  | ///   OneFingerPan -> start/end -> left down start/end
 | 
					
						
							|  |  |  | ///   onDoubleTapDown -> move to
 | 
					
						
							|  |  |  | ///   onLongPressDown => move to
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// mouseMode only:
 | 
					
						
							|  |  |  | ///   DoubleFiner -> right click
 | 
					
						
							|  |  |  | ///   HoldDrag -> left drag
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  | class _RawTouchGestureDetectorRegionState | 
					
						
							|  |  |  |     extends State<RawTouchGestureDetectorRegion> { | 
					
						
							|  |  |  |   Offset _cacheLongPressPosition = Offset(0, 0); | 
					
						
							|  |  |  |   double _mouseScrollIntegral = 0; // mouse scroll speed controller
 | 
					
						
							|  |  |  |   double _scale = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PointerDeviceKind? lastDeviceKind; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   FFI get ffi => widget.ffi; | 
					
						
							|  |  |  |   FfiModel get ffiModel => widget.ffiModel; | 
					
						
							|  |  |  |   InputModel get inputModel => widget.inputModel; | 
					
						
							|  |  |  |   bool get handleTouch => isDesktop || ffiModel.touchMode; | 
					
						
							|  |  |  |   SessionID get sessionId => ffi.sessionId; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return RawGestureDetector( | 
					
						
							|  |  |  |       child: widget.child, | 
					
						
							|  |  |  |       gestures: makeGestures(context), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onTapDown(TapDownDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							| 
									
										
										
										
											2023-10-02 12:17:11 +08:00
										 |  |  |       // Desktop or mobile "Touch mode"
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |       ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy); | 
					
						
							| 
									
										
										
										
											2023-07-25 15:32:42 +08:00
										 |  |  |       inputModel.tapDown(MouseButtons.left); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onTapUp(TapUpDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							|  |  |  |       ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy); | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |       inputModel.tapUp(MouseButtons.left); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:32:42 +08:00
										 |  |  |   onTap() { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-02 10:15:20 +08:00
										 |  |  |     if (!handleTouch) { | 
					
						
							| 
									
										
										
										
											2023-10-02 12:17:11 +08:00
										 |  |  |       // Mobile, "Mouse mode"
 | 
					
						
							| 
									
										
										
										
											2023-10-02 10:15:20 +08:00
										 |  |  |       inputModel.tap(MouseButtons.left); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-25 15:32:42 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   onDoubleTapDown(TapDownDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							|  |  |  |       ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onDoubleTap() { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     inputModel.tap(MouseButtons.left); | 
					
						
							|  |  |  |     inputModel.tap(MouseButtons.left); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onLongPressDown(LongPressDownDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							|  |  |  |       ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy); | 
					
						
							|  |  |  |       _cacheLongPressPosition = d.localPosition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |   onLongPressUp() { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							|  |  |  |       inputModel.tapUp(MouseButtons.left); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   // for mobiles
 | 
					
						
							|  |  |  |   onLongPress() { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							|  |  |  |       ffi.cursorModel | 
					
						
							|  |  |  |           .move(_cacheLongPressPosition.dx, _cacheLongPressPosition.dy); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     inputModel.tap(MouseButtons.right); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |   onDoubleFinerTapDown(TapDownDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // ignore for desktop and mobile
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   onDoubleFinerTap(TapDownDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-25 15:32:42 +08:00
										 |  |  |     if (isDesktop || !ffiModel.touchMode) { | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |       inputModel.tap(MouseButtons.right); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onHoldDragStart(DragStartDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!handleTouch) { | 
					
						
							|  |  |  |       inputModel.sendMouse('down', MouseButtons.left); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onHoldDragUpdate(DragUpdateDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!handleTouch) { | 
					
						
							|  |  |  |       ffi.cursorModel.updatePan(d.delta.dx, d.delta.dy, handleTouch); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onHoldDragEnd(DragEndDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!handleTouch) { | 
					
						
							|  |  |  |       inputModel.sendMouse('up', MouseButtons.left); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onOneFingerPanStart(BuildContext context, DragStartDetails d) { | 
					
						
							|  |  |  |     lastDeviceKind = d.kind ?? lastDeviceKind; | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (handleTouch) { | 
					
						
							|  |  |  |       inputModel.sendMouse('down', MouseButtons.left); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:48:58 +08:00
										 |  |  |       ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       final offset = ffi.cursorModel.offset; | 
					
						
							|  |  |  |       final cursorX = offset.dx; | 
					
						
							|  |  |  |       final cursorY = offset.dy; | 
					
						
							|  |  |  |       final visible = | 
					
						
							|  |  |  |           ffi.cursorModel.getVisibleRect().inflate(1); // extend edges
 | 
					
						
							|  |  |  |       final size = MediaQueryData.fromView(View.of(context)).size; | 
					
						
							|  |  |  |       if (!visible.contains(Offset(cursorX, cursorY))) { | 
					
						
							|  |  |  |         ffi.cursorModel.move(size.width / 2, size.height / 2); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onOneFingerPanUpdate(DragUpdateDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ffi.cursorModel.updatePan(d.delta.dx, d.delta.dy, handleTouch); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onOneFingerPanEnd(DragEndDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |     inputModel.sendMouse('up', MouseButtons.left); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // scale + pan event
 | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |   onTwoFingerScaleStart(ScaleStartDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   onTwoFingerScaleUpdate(ScaleUpdateDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (isDesktop) { | 
					
						
							| 
									
										
										
										
											2023-07-19 01:26:43 +08:00
										 |  |  |       final scale = ((d.scale - _scale) * 1000).toInt(); | 
					
						
							|  |  |  |       _scale = d.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-07-19 01:26:43 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       // mobile
 | 
					
						
							|  |  |  |       ffi.canvasModel.updateScale(d.scale / _scale); | 
					
						
							|  |  |  |       _scale = d.scale; | 
					
						
							|  |  |  |       ffi.canvasModel.panX(d.focalPointDelta.dx); | 
					
						
							|  |  |  |       ffi.canvasModel.panY(d.focalPointDelta.dy); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onTwoFingerScaleEnd(ScaleEndDetails d) { | 
					
						
							|  |  |  |     if (lastDeviceKind != PointerDeviceKind.touch) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (isDesktop) { | 
					
						
							| 
									
										
										
										
											2023-07-19 01:26:43 +08:00
										 |  |  |       bind.sessionSendPointer( | 
					
						
							|  |  |  |           sessionId: sessionId, | 
					
						
							| 
									
										
										
										
											2023-08-09 23:42:53 +08:00
										 |  |  |           msg: json.encode( | 
					
						
							|  |  |  |               PointerEventToRust(kPointerEventKindTouch, 'scale', 0).toJson())); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       // mobile
 | 
					
						
							|  |  |  |       _scale = 1; | 
					
						
							|  |  |  |       bind.sessionSetViewStyle(sessionId: sessionId, value: ""); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-19 01:26:43 +08:00
										 |  |  |     inputModel.sendMouse('up', MouseButtons.left); | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   get onHoldDragCancel => null; | 
					
						
							|  |  |  |   get onThreeFingerVerticalDragUpdate => ffi.ffiModel.isPeerAndroid | 
					
						
							|  |  |  |       ? null | 
					
						
							|  |  |  |       : (d) { | 
					
						
							|  |  |  |           _mouseScrollIntegral += d.delta.dy / 4; | 
					
						
							|  |  |  |           if (_mouseScrollIntegral > 1) { | 
					
						
							|  |  |  |             inputModel.scroll(1); | 
					
						
							|  |  |  |             _mouseScrollIntegral = 0; | 
					
						
							|  |  |  |           } else if (_mouseScrollIntegral < -1) { | 
					
						
							|  |  |  |             inputModel.scroll(-1); | 
					
						
							|  |  |  |             _mouseScrollIntegral = 0; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   makeGestures(BuildContext context) { | 
					
						
							|  |  |  |     return <Type, GestureRecognizerFactory>{ | 
					
						
							|  |  |  |       // Official
 | 
					
						
							|  |  |  |       TapGestureRecognizer: | 
					
						
							|  |  |  |           GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>( | 
					
						
							|  |  |  |               () => TapGestureRecognizer(), (instance) { | 
					
						
							|  |  |  |         instance | 
					
						
							|  |  |  |           ..onTapDown = onTapDown | 
					
						
							| 
									
										
										
										
											2023-07-25 15:32:42 +08:00
										 |  |  |           ..onTapUp = onTapUp | 
					
						
							|  |  |  |           ..onTap = onTap; | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |       }), | 
					
						
							|  |  |  |       DoubleTapGestureRecognizer: | 
					
						
							|  |  |  |           GestureRecognizerFactoryWithHandlers<DoubleTapGestureRecognizer>( | 
					
						
							|  |  |  |               () => DoubleTapGestureRecognizer(), (instance) { | 
					
						
							|  |  |  |         instance | 
					
						
							|  |  |  |           ..onDoubleTapDown = onDoubleTapDown | 
					
						
							|  |  |  |           ..onDoubleTap = onDoubleTap; | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |       LongPressGestureRecognizer: | 
					
						
							|  |  |  |           GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>( | 
					
						
							|  |  |  |               () => LongPressGestureRecognizer(), (instance) { | 
					
						
							|  |  |  |         instance | 
					
						
							|  |  |  |           ..onLongPressDown = onLongPressDown | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |           ..onLongPressUp = onLongPressUp | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |           ..onLongPress = onLongPress; | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |       // Customized
 | 
					
						
							|  |  |  |       HoldTapMoveGestureRecognizer: | 
					
						
							|  |  |  |           GestureRecognizerFactoryWithHandlers<HoldTapMoveGestureRecognizer>( | 
					
						
							|  |  |  |               () => HoldTapMoveGestureRecognizer(), | 
					
						
							|  |  |  |               (instance) => instance | 
					
						
							|  |  |  |                 ..onHoldDragStart = onHoldDragStart | 
					
						
							|  |  |  |                 ..onHoldDragUpdate = onHoldDragUpdate | 
					
						
							|  |  |  |                 ..onHoldDragCancel = onHoldDragCancel | 
					
						
							|  |  |  |                 ..onHoldDragEnd = onHoldDragEnd), | 
					
						
							|  |  |  |       DoubleFinerTapGestureRecognizer: | 
					
						
							|  |  |  |           GestureRecognizerFactoryWithHandlers<DoubleFinerTapGestureRecognizer>( | 
					
						
							|  |  |  |               () => DoubleFinerTapGestureRecognizer(), (instance) { | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |         instance | 
					
						
							|  |  |  |           ..onDoubleFinerTap = onDoubleFinerTap | 
					
						
							|  |  |  |           ..onDoubleFinerTapDown = onDoubleFinerTapDown; | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |       }), | 
					
						
							|  |  |  |       CustomTouchGestureRecognizer: | 
					
						
							|  |  |  |           GestureRecognizerFactoryWithHandlers<CustomTouchGestureRecognizer>( | 
					
						
							|  |  |  |               () => CustomTouchGestureRecognizer(), (instance) { | 
					
						
							|  |  |  |         instance.onOneFingerPanStart = | 
					
						
							|  |  |  |             (DragStartDetails d) => onOneFingerPanStart(context, d); | 
					
						
							|  |  |  |         instance | 
					
						
							|  |  |  |           ..onOneFingerPanUpdate = onOneFingerPanUpdate | 
					
						
							|  |  |  |           ..onOneFingerPanEnd = onOneFingerPanEnd | 
					
						
							| 
									
										
										
										
											2023-07-25 22:09:42 +08:00
										 |  |  |           ..onTwoFingerScaleStart = onTwoFingerScaleStart | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |           ..onTwoFingerScaleUpdate = onTwoFingerScaleUpdate | 
					
						
							|  |  |  |           ..onTwoFingerScaleEnd = onTwoFingerScaleEnd | 
					
						
							|  |  |  |           ..onThreeFingerVerticalDragUpdate = onThreeFingerVerticalDragUpdate; | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | class RawPointerMouseRegion extends StatelessWidget { | 
					
						
							|  |  |  |   final InputModel inputModel; | 
					
						
							|  |  |  |   final Widget child; | 
					
						
							|  |  |  |   final MouseCursor? cursor; | 
					
						
							|  |  |  |   final PointerEnterEventListener? onEnter; | 
					
						
							|  |  |  |   final PointerExitEventListener? onExit; | 
					
						
							| 
									
										
										
										
											2022-12-21 22:39:30 +08:00
										 |  |  |   final PointerDownEventListener? onPointerDown; | 
					
						
							|  |  |  |   final PointerUpEventListener? onPointerUp; | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |   RawPointerMouseRegion({ | 
					
						
							|  |  |  |     this.onEnter, | 
					
						
							|  |  |  |     this.onExit, | 
					
						
							|  |  |  |     this.cursor, | 
					
						
							|  |  |  |     this.onPointerDown, | 
					
						
							|  |  |  |     this.onPointerUp, | 
					
						
							|  |  |  |     required this.inputModel, | 
					
						
							|  |  |  |     required this.child, | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Listener( | 
					
						
							| 
									
										
										
										
											2023-07-17 20:07:55 +08:00
										 |  |  |       onPointerHover: inputModel.onPointHoverImage, | 
					
						
							|  |  |  |       onPointerDown: (evt) { | 
					
						
							|  |  |  |         onPointerDown?.call(evt); | 
					
						
							|  |  |  |         inputModel.onPointDownImage(evt); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       onPointerUp: (evt) { | 
					
						
							|  |  |  |         onPointerUp?.call(evt); | 
					
						
							|  |  |  |         inputModel.onPointUpImage(evt); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       onPointerMove: inputModel.onPointMoveImage, | 
					
						
							|  |  |  |       onPointerSignal: inputModel.onPointerSignalImage, | 
					
						
							|  |  |  |       onPointerPanZoomStart: inputModel.onPointerPanZoomStart, | 
					
						
							|  |  |  |       onPointerPanZoomUpdate: inputModel.onPointerPanZoomUpdate, | 
					
						
							|  |  |  |       onPointerPanZoomEnd: inputModel.onPointerPanZoomEnd, | 
					
						
							|  |  |  |       child: MouseRegion( | 
					
						
							|  |  |  |         cursor: cursor ?? MouseCursor.defer, | 
					
						
							|  |  |  |         onEnter: onEnter, | 
					
						
							|  |  |  |         onExit: onExit, | 
					
						
							|  |  |  |         child: child, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2022-09-27 22:16:27 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } |