gesture_handler.dart 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import 'package:flutter/gestures.dart';
  2. import 'package:flutter/widgets.dart';
  3. import 'package:xterm/src/core/mouse/button.dart';
  4. import 'package:xterm/src/core/mouse/button_state.dart';
  5. import 'package:xterm/src/terminal_view.dart';
  6. import 'package:xterm/src/ui/controller.dart';
  7. import 'package:xterm/src/ui/gesture/gesture_detector.dart';
  8. import 'package:xterm/src/ui/pointer_input.dart';
  9. import 'package:xterm/src/ui/render.dart';
  10. class TerminalGestureHandler extends StatefulWidget {
  11. const TerminalGestureHandler({
  12. super.key,
  13. required this.terminalView,
  14. required this.terminalController,
  15. this.child,
  16. this.onTapUp,
  17. this.onSingleTapUp,
  18. this.onTapDown,
  19. this.onSecondaryTapDown,
  20. this.onSecondaryTapUp,
  21. this.onTertiaryTapDown,
  22. this.onTertiaryTapUp,
  23. this.readOnly = false,
  24. });
  25. final TerminalViewState terminalView;
  26. final TerminalController terminalController;
  27. final Widget? child;
  28. final GestureTapUpCallback? onTapUp;
  29. final GestureTapUpCallback? onSingleTapUp;
  30. final GestureTapDownCallback? onTapDown;
  31. final GestureTapDownCallback? onSecondaryTapDown;
  32. final GestureTapUpCallback? onSecondaryTapUp;
  33. final GestureTapDownCallback? onTertiaryTapDown;
  34. final GestureTapUpCallback? onTertiaryTapUp;
  35. final bool readOnly;
  36. @override
  37. State<TerminalGestureHandler> createState() => _TerminalGestureHandlerState();
  38. }
  39. class _TerminalGestureHandlerState extends State<TerminalGestureHandler> {
  40. TerminalViewState get terminalView => widget.terminalView;
  41. RenderTerminal get renderTerminal => terminalView.renderTerminal;
  42. DragStartDetails? _lastDragStartDetails;
  43. LongPressStartDetails? _lastLongPressStartDetails;
  44. @override
  45. Widget build(BuildContext context) {
  46. return TerminalGestureDetector(
  47. child: widget.child,
  48. onTapUp: widget.onTapUp,
  49. onSingleTapUp: onSingleTapUp,
  50. onTapDown: onTapDown,
  51. onSecondaryTapDown: onSecondaryTapDown,
  52. onSecondaryTapUp: onSecondaryTapUp,
  53. onTertiaryTapDown: onSecondaryTapDown,
  54. onTertiaryTapUp: onSecondaryTapUp,
  55. onLongPressStart: onLongPressStart,
  56. onLongPressMoveUpdate: onLongPressMoveUpdate,
  57. // onLongPressUp: onLongPressUp,
  58. onDragStart: onDragStart,
  59. onDragUpdate: onDragUpdate,
  60. onDoubleTapDown: onDoubleTapDown,
  61. );
  62. }
  63. bool get _shouldSendTapEvent =>
  64. !widget.readOnly &&
  65. widget.terminalController.shouldSendPointerInput(PointerInput.tap);
  66. void _tapDown(
  67. GestureTapDownCallback? callback,
  68. TapDownDetails details,
  69. TerminalMouseButton button, {
  70. bool forceCallback = false,
  71. }) {
  72. // Check if the terminal should and can handle the tap down event.
  73. var handled = false;
  74. if (_shouldSendTapEvent) {
  75. handled = renderTerminal.mouseEvent(
  76. button,
  77. TerminalMouseButtonState.down,
  78. details.localPosition,
  79. );
  80. }
  81. // If the event was not handled by the terminal, use the supplied callback.
  82. if (!handled || forceCallback) {
  83. callback?.call(details);
  84. }
  85. }
  86. void _tapUp(
  87. GestureTapUpCallback? callback,
  88. TapUpDetails details,
  89. TerminalMouseButton button, {
  90. bool forceCallback = false,
  91. }) {
  92. // Check if the terminal should and can handle the tap up event.
  93. var handled = false;
  94. if (_shouldSendTapEvent) {
  95. handled = renderTerminal.mouseEvent(
  96. button,
  97. TerminalMouseButtonState.up,
  98. details.localPosition,
  99. );
  100. }
  101. // If the event was not handled by the terminal, use the supplied callback.
  102. if (!handled && forceCallback) {
  103. callback?.call(details);
  104. }
  105. }
  106. void onTapDown(TapDownDetails details) {
  107. // onTapDown is special, as it will always call the supplied callback.
  108. // The TerminalView depends on it to bring the terminal into focus.
  109. _tapDown(
  110. widget.onTapDown,
  111. details,
  112. TerminalMouseButton.left,
  113. forceCallback: true,
  114. );
  115. }
  116. void onSingleTapUp(TapUpDetails details) {
  117. _tapUp(widget.onSingleTapUp, details, TerminalMouseButton.left);
  118. }
  119. void onSecondaryTapDown(TapDownDetails details) {
  120. _tapDown(widget.onSecondaryTapDown, details, TerminalMouseButton.right);
  121. }
  122. void onSecondaryTapUp(TapUpDetails details) {
  123. _tapUp(widget.onSecondaryTapUp, details, TerminalMouseButton.right);
  124. }
  125. void onTertiaryTapDown(TapDownDetails details) {
  126. _tapDown(widget.onTertiaryTapDown, details, TerminalMouseButton.middle);
  127. }
  128. void onTertiaryTapUp(TapUpDetails details) {
  129. _tapUp(widget.onTertiaryTapUp, details, TerminalMouseButton.right);
  130. }
  131. void onDoubleTapDown(TapDownDetails details) {
  132. renderTerminal.selectWord(details.localPosition);
  133. }
  134. void onLongPressStart(LongPressStartDetails details) {
  135. _lastLongPressStartDetails = details;
  136. renderTerminal.selectWord(details.localPosition);
  137. }
  138. void onLongPressMoveUpdate(LongPressMoveUpdateDetails details) {
  139. renderTerminal.selectWord(
  140. _lastLongPressStartDetails!.localPosition,
  141. details.localPosition,
  142. );
  143. }
  144. // void onLongPressUp() {}
  145. void onDragStart(DragStartDetails details) {
  146. _lastDragStartDetails = details;
  147. details.kind == PointerDeviceKind.mouse
  148. ? renderTerminal.selectCharacters(details.localPosition)
  149. : renderTerminal.selectWord(details.localPosition);
  150. }
  151. void onDragUpdate(DragUpdateDetails details) {
  152. renderTerminal.selectCharacters(
  153. _lastDragStartDetails!.localPosition,
  154. details.localPosition,
  155. );
  156. }
  157. }