瀏覽代碼

修复bug,让选择复制支持历史

阳聪 1 月之前
父節點
當前提交
2af200f885
共有 3 個文件被更改,包括 78 次插入17 次删除
  1. 15 0
      lib/src/ui/custom_text_edit.dart
  2. 46 9
      lib/src/ui/gesture/gesture_handler.dart
  3. 17 8
      lib/src/ui/render.dart

+ 15 - 0
lib/src/ui/custom_text_edit.dart

@@ -159,7 +159,22 @@ class CustomTextEditState extends State<CustomTextEdit> with TextInputClient {
     if (hasInputConnection) {
       _connection!.show();
     } else {
+      int? viewId = View.maybeOf(context)?.viewId;
+      
+      if (viewId == null && WidgetsBinding.instance.platformDispatcher.views.isNotEmpty) {
+        viewId = WidgetsBinding.instance.platformDispatcher.views.first.viewId;
+      }
+      
+      if (viewId == null) {
+        // Fallback or just return, but avoid crashing if possible, 
+        // though without a viewId we can't properly attach input on some versions.
+        // For robustness, we might try to proceed without it or log a warning, 
+        // but TextInputConfiguration now requires it on newer Flutter versions.
+        // If we can't find one, we can't open the keyboard safely.
+        return; 
+      }
       final config = TextInputConfiguration(
+        viewId: viewId,
         inputType: widget.inputType,
         inputAction: widget.inputAction,
         keyboardAppearance: widget.keyboardAppearance,

+ 46 - 9
lib/src/ui/gesture/gesture_handler.dart

@@ -1,5 +1,6 @@
 import 'package:flutter/gestures.dart';
 import 'package:flutter/widgets.dart';
+import 'package:xterm/src/core/buffer/cell_offset.dart';
 import 'package:xterm/src/core/mouse/button.dart';
 import 'package:xterm/src/core/mouse/button_state.dart';
 import 'package:xterm/src/terminal_view.dart';
@@ -59,6 +60,9 @@ class _TerminalGestureHandlerState extends State<TerminalGestureHandler> {
 
   LongPressStartDetails? _lastLongPressStartDetails;
 
+  CellOffset? _dragStartCellOffset;
+  CellOffset? _longPressStartCellOffset;
+
   @override
   Widget build(BuildContext context) {
     return TerminalGestureDetector(
@@ -162,13 +166,17 @@ class _TerminalGestureHandlerState extends State<TerminalGestureHandler> {
 
   void onLongPressStart(LongPressStartDetails details) {
     _lastLongPressStartDetails = details;
-    renderTerminal.selectWord(details.localPosition);
+    _longPressStartCellOffset = renderTerminal.getCellOffset(details.localPosition);
+    // Use selectWordByCell to start selection
+    renderTerminal.selectWordByCell(_longPressStartCellOffset!);
   }
 
   void onLongPressMoveUpdate(LongPressMoveUpdateDetails details) {
-    renderTerminal.selectWord(
-      _lastLongPressStartDetails!.localPosition,
-      details.localPosition,
+    if (_longPressStartCellOffset == null) return;
+    final currentCellOffset = renderTerminal.getCellOffset(details.localPosition);
+    renderTerminal.selectWordByCell(
+      _longPressStartCellOffset!,
+      currentCellOffset,
     );
   }
 
@@ -176,16 +184,45 @@ class _TerminalGestureHandlerState extends State<TerminalGestureHandler> {
 
   void onDragStart(DragStartDetails details) {
     _lastDragStartDetails = details;
+    _dragStartCellOffset = renderTerminal.getCellOffset(details.localPosition);
 
     details.kind == PointerDeviceKind.mouse
-        ? renderTerminal.selectCharacters(details.localPosition)
-        : renderTerminal.selectWord(details.localPosition);
+        ? renderTerminal.selectCharactersByCell(_dragStartCellOffset!)
+        : renderTerminal.selectWordByCell(_dragStartCellOffset!);
   }
 
   void onDragUpdate(DragUpdateDetails details) {
-    renderTerminal.selectCharacters(
-      _lastDragStartDetails!.localPosition,
-      details.localPosition,
+    if (_dragStartCellOffset == null) return;
+    
+    final currentCellOffset = renderTerminal.getCellOffset(details.localPosition);
+
+    // renderTerminal.selectCharacters(
+    //   _lastDragStartDetails!.localPosition,
+    //   details.localPosition,
+    // );
+    
+    // Instead of using screen coordinates, use logical cell coordinates.
+    // Assuming drag mode keeps the same selection granularity (char vs word).
+    // The original code used selectCharacters for update always? 
+    // Wait, original onDragStart did selectWord for touch, but onDragUpdate did selectCharacters.
+    // If I started with word selection (touch), should I continue with word selection?
+    // Usually yes.
+    
+    // But RenderTerminal.selectCharacters behaves differently than selectWord.
+    // Original code:
+    // onDragUpdate(DragUpdateDetails details) {
+    //   renderTerminal.selectCharacters(
+    //     _lastDragStartDetails!.localPosition,
+    //     details.localPosition,
+    //   );
+    // }
+    
+    // This looks like it switches to character selection during drag even if it started as word selection?
+    // Let's stick to what original code did: selectCharacters.
+    
+    renderTerminal.selectCharactersByCell(
+      _dragStartCellOffset!,
+      currentCellOffset,
     );
   }
 }

+ 17 - 8
lib/src/ui/render.dart

@@ -256,7 +256,12 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
   /// Selects entire words in the terminal that contains [from] and [to].
   void selectWord(Offset from, [Offset? to]) {
     final fromOffset = getCellOffset(from);
-    final fromBoundary = _terminal.buffer.getWordBoundary(fromOffset);
+    final toOffset = to != null ? getCellOffset(to) : null;
+    selectWordByCell(fromOffset, toOffset);
+  }
+
+  void selectWordByCell(CellOffset from, [CellOffset? to]) {
+    final fromBoundary = _terminal.buffer.getWordBoundary(from);
     if (fromBoundary == null) return;
     if (to == null) {
       _controller.setSelection(
@@ -265,8 +270,7 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
         mode: SelectionMode.line,
       );
     } else {
-      final toOffset = getCellOffset(to);
-      final toBoundary = _terminal.buffer.getWordBoundary(toOffset);
+      final toBoundary = _terminal.buffer.getWordBoundary(to);
       if (toBoundary == null) return;
       final range = fromBoundary.merge(toBoundary);
       _controller.setSelection(
@@ -281,18 +285,23 @@ class RenderTerminal extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
   /// least one cell is selected even if [from] and [to] are same.
   void selectCharacters(Offset from, [Offset? to]) {
     final fromPosition = getCellOffset(from);
+    final toPosition = to != null ? getCellOffset(to) : null;
+    selectCharactersByCell(fromPosition, toPosition);
+  }
+
+  void selectCharactersByCell(CellOffset from, [CellOffset? to]) {
     if (to == null) {
       _controller.setSelection(
-        _terminal.buffer.createAnchorFromOffset(fromPosition),
-        _terminal.buffer.createAnchorFromOffset(fromPosition),
+        _terminal.buffer.createAnchorFromOffset(from),
+        _terminal.buffer.createAnchorFromOffset(from),
       );
     } else {
-      var toPosition = getCellOffset(to);
-      if (toPosition.x >= fromPosition.x) {
+      var toPosition = to;
+      if (toPosition.x >= from.x) {
         toPosition = CellOffset(toPosition.x + 1, toPosition.y);
       }
       _controller.setSelection(
-        _terminal.buffer.createAnchorFromOffset(fromPosition),
+        _terminal.buffer.createAnchorFromOffset(from),
         _terminal.buffer.createAnchorFromOffset(toPosition),
       );
     }