xuty 5 лет назад
Родитель
Сommit
7cc0491cfd
2 измененных файлов с 125 добавлено и 85 удалено
  1. 61 23
      lib/frontend/input_listener.dart
  2. 64 62
      lib/frontend/terminal_view.dart

+ 61 - 23
lib/frontend/input_listener.dart

@@ -4,8 +4,13 @@ import 'package:meta/meta.dart';
 
 typedef KeyStrokeHandler = void Function(RawKeyEvent);
 typedef InputHandler = void Function(String);
+typedef ActionHandler = void Function(TextInputAction);
 typedef FocusHandler = void Function(bool);
 
+abstract class InputListenerController {
+  void requestKeyboard();
+}
+
 class InputListener extends StatefulWidget {
   InputListener({
     @required this.child,
@@ -25,25 +30,30 @@ class InputListener extends StatefulWidget {
 
   @override
   InputListenerState createState() => InputListenerState();
+
+  static InputListenerController of(BuildContext context) {
+    return context.findAncestorStateOfType<InputListenerState>();
+  }
 }
 
-class InputListenerState extends State<InputListener> {
+class InputListenerState extends State<InputListener>
+    implements InputListenerController {
   var focused = false;
   TextInputConnection conn;
 
   @override
   void initState() {
     focused = widget.focusNode.hasFocus;
-    widget.focusNode.addListener(onFocus);
+    widget.focusNode.addListener(onFocusChange);
     super.initState();
   }
 
   @override
   void didUpdateWidget(InputListener oldWidget) {
-    oldWidget.focusNode.removeListener(onFocus);
-    widget.focusNode.addListener(onFocus);
+    oldWidget.focusNode.removeListener(onFocusChange);
+    widget.focusNode.addListener(onFocusChange);
 
-    onFocus();
+    onFocusChange();
 
     super.didUpdateWidget(oldWidget);
   }
@@ -58,7 +68,15 @@ class InputListenerState extends State<InputListener> {
     );
   }
 
-  void onFocus() {
+  void requestKeyboard() {
+    if (widget.focusNode.hasFocus) {
+      openInputConnection();
+    } else {
+      widget.focusNode.requestFocus();
+    }
+  }
+
+  void onFocusChange() {
     if (focused == widget.focusNode.hasFocus) {
       return;
     }
@@ -69,38 +87,58 @@ class InputListenerState extends State<InputListener> {
       widget.onFocus(focused);
     }
 
-    if (focused) {
-      openTextInput();
-    }
+    openOrCloseInputConnectionIfNeeded();
   }
 
-  void openTextInput() {
-    final config = TextInputConfiguration();
-    conn = TextInput.attach(
-      TerminalTextInputClient(onInput),
-      config,
-    );
+  void openOrCloseInputConnectionIfNeeded() {
+    if (widget.focusNode.hasFocus && widget.focusNode.consumeKeyboardToken()) {
+      openInputConnection();
+    } else if (!widget.focusNode.hasFocus) {
+      closeInputConnectionIfNeeded();
+    }
+  }
 
-    final dx = 0.0;
-    final dy = 0.0;
-    conn.setEditableSizeAndTransform(
-      Size(10, 10),
-      Matrix4.translationValues(dx, dy, 0.0),
-    );
+  void openInputConnection() {
+    if (conn != null && conn.attached) {
+      conn.show();
+    } else {
+      final config = TextInputConfiguration();
+      final client = TerminalTextInputClient(onInput, onAction);
+      conn = TextInput.attach(client, config);
+
+      final dx = 0.0;
+      final dy = 0.0;
+      conn.setEditableSizeAndTransform(
+        Size(10, 10),
+        Matrix4.translationValues(dx, dy, 0.0),
+      );
+
+      conn.show();
+    }
+  }
 
-    conn.show();
+  void closeInputConnectionIfNeeded() {
+    if (conn != null && conn.attached) {
+      conn.close();
+      conn = null;
+    }
   }
 
   void onInput(String text) {
     widget.onInput(text);
     conn?.setEditingState(TextEditingValue.empty);
   }
+
+  void onAction(TextInputAction action) {
+    //
+  }
 }
 
 class TerminalTextInputClient extends TextInputClient {
-  TerminalTextInputClient(this.onInput);
+  TerminalTextInputClient(this.onInput, this.onAction);
 
   final InputHandler onInput;
+  final ActionHandler onAction;
 
   TextEditingValue _savedValue;
 

+ 64 - 62
lib/frontend/terminal_view.dart

@@ -12,7 +12,6 @@ import 'package:xterm/frontend/char_size.dart';
 import 'package:xterm/frontend/helpers.dart';
 import 'package:xterm/frontend/input_listener.dart';
 import 'package:xterm/frontend/input_map.dart';
-import 'package:xterm/frontend/mouse_listener.dart';
 import 'package:xterm/frontend/oscillator.dart';
 import 'package:xterm/frontend/cache.dart';
 import 'package:xterm/mouse/position.dart';
@@ -54,21 +53,25 @@ class TerminalView extends StatefulWidget {
     this.fontWidthScaleFactor = 1.0,
     this.fontHeightScaleFactor = 1.1,
     FocusNode focusNode,
+    ScrollController scrollController,
   })  : assert(terminal != null),
         focusNode = focusNode ?? FocusNode(),
+        scrollController = scrollController ?? ScrollController(),
         super(key: key ?? ValueKey(terminal));
 
   final Terminal terminal;
   final ResizeHandler onResize;
   final FocusNode focusNode;
+  final ScrollController scrollController;
 
   final double fontSize;
   final double fontWidthScaleFactor;
   final double fontHeightScaleFactor;
   final List<String> fontFamily;
 
-  CellSize getCharSize() {
+  CellSize measureCellSize() {
     final testString = 'xxxxxxxxxx' * 1000;
+
     final text = Text(
       testString,
       style: TextStyle(
@@ -76,23 +79,22 @@ class TerminalView extends StatefulWidget {
         fontSize: fontSize,
       ),
     );
-    final size = textSize(text);
 
-    final width = (size.width / testString.length);
-    final height = size.height;
+    final size = textSize(text);
 
-    final effectWidth = width * fontWidthScaleFactor;
-    final effectHeight = size.height * fontHeightScaleFactor;
+    final charWidth = (size.width / testString.length);
+    final charHeight = size.height;
 
-    // final ls
+    final cellWidth = charWidth * fontWidthScaleFactor;
+    final cellHeight = size.height * fontHeightScaleFactor;
 
     return CellSize(
-      charWidth: width,
-      charHeight: height,
-      cellWidth: effectWidth,
-      cellHeight: effectHeight,
-      letterSpacing: effectWidth - width,
-      lineSpacing: effectHeight - height,
+      charWidth: charWidth,
+      charHeight: charHeight,
+      cellWidth: cellWidth,
+      cellHeight: cellHeight,
+      letterSpacing: cellWidth - charWidth,
+      lineSpacing: cellHeight - charHeight,
     );
   }
 
@@ -109,7 +111,7 @@ class _TerminalViewState extends State<TerminalView> {
 
   int _lastTerminalWidth;
   int _lastTerminalHeight;
-  CellSize _charSize;
+  CellSize _cellSize;
   ViewportOffset _offset;
 
   var _minScrollExtent = 0.0;
@@ -129,7 +131,7 @@ class _TerminalViewState extends State<TerminalView> {
   void initState() {
     // oscillator.start();
     // oscillator.addListener(onTick);
-    _charSize = widget.getCharSize();
+    _cellSize = widget.measureCellSize();
     widget.terminal.addListener(onTerminalChange);
     super.initState();
   }
@@ -152,45 +154,6 @@ class _TerminalViewState extends State<TerminalView> {
 
   @override
   Widget build(BuildContext context) {
-    Widget result = Container(
-      constraints: BoxConstraints.expand(),
-      color: Color(widget.terminal.colorScheme.background.value),
-      child: CustomPaint(
-        painter: TerminalPainter(
-          terminal: widget.terminal,
-          view: widget,
-          oscillator: oscillator,
-          focused: focused,
-          charSize: _charSize,
-        ),
-      ),
-    );
-
-    result = GestureDetector(
-      child: result,
-      behavior: HitTestBehavior.deferToChild,
-      dragStartBehavior: DragStartBehavior.down,
-      onTapDown: (detail) {
-        widget.focusNode.requestFocus();
-        final pos = detail.localPosition;
-        final offset = getMouseOffset(pos.dx, pos.dy);
-        widget.terminal.mouseMode.onTap(widget.terminal, offset);
-        widget.terminal.refresh();
-      },
-      onPanStart: (detail) {
-        final pos = detail.localPosition;
-        final offset = getMouseOffset(pos.dx, pos.dy);
-        widget.terminal.mouseMode.onPanStart(widget.terminal, offset);
-        widget.terminal.refresh();
-      },
-      onPanUpdate: (detail) {
-        final pos = detail.localPosition;
-        final offset = getMouseOffset(pos.dx, pos.dy);
-        widget.terminal.mouseMode.onPanUpdate(widget.terminal, offset);
-        widget.terminal.refresh();
-      },
-    );
-
     return InputListener(
       onKeyStroke: onKeyStroke,
       onInput: onInput,
@@ -208,7 +171,7 @@ class _TerminalViewState extends State<TerminalView> {
               _minScrollExtent = 0.0;
               _maxScrollExtent = math.max(
                   0.0,
-                  _charSize.cellHeight * widget.terminal.buffer.height -
+                  _cellSize.cellHeight * widget.terminal.buffer.height -
                       constraints.maxHeight);
 
               offset.applyContentDimensions(_minScrollExtent, _maxScrollExtent);
@@ -216,7 +179,7 @@ class _TerminalViewState extends State<TerminalView> {
               _offset = offset;
               _offset.addListener(onScroll);
 
-              return result;
+              return buildTerminal(context);
             },
           );
         }),
@@ -224,9 +187,48 @@ class _TerminalViewState extends State<TerminalView> {
     );
   }
 
+  Widget buildTerminal(BuildContext context) {
+    return GestureDetector(
+      behavior: HitTestBehavior.deferToChild,
+      dragStartBehavior: DragStartBehavior.down,
+      onTapDown: (detail) {
+        InputListener.of(context).requestKeyboard();
+        final pos = detail.localPosition;
+        final offset = getMouseOffset(pos.dx, pos.dy);
+        widget.terminal.mouseMode.onTap(widget.terminal, offset);
+        widget.terminal.refresh();
+      },
+      onPanStart: (detail) {
+        final pos = detail.localPosition;
+        final offset = getMouseOffset(pos.dx, pos.dy);
+        widget.terminal.mouseMode.onPanStart(widget.terminal, offset);
+        widget.terminal.refresh();
+      },
+      onPanUpdate: (detail) {
+        final pos = detail.localPosition;
+        final offset = getMouseOffset(pos.dx, pos.dy);
+        widget.terminal.mouseMode.onPanUpdate(widget.terminal, offset);
+        widget.terminal.refresh();
+      },
+      child: Container(
+        constraints: BoxConstraints.expand(),
+        color: Color(widget.terminal.colorScheme.background.value),
+        child: CustomPaint(
+          painter: TerminalPainter(
+            terminal: widget.terminal,
+            view: widget,
+            oscillator: oscillator,
+            focused: focused,
+            charSize: _cellSize,
+          ),
+        ),
+      ),
+    );
+  }
+
   Position getMouseOffset(double px, double py) {
-    final col = (px / _charSize.cellWidth).floor();
-    final row = (py / _charSize.cellHeight).floor();
+    final col = (px / _cellSize.cellWidth).floor();
+    final row = (py / _cellSize.cellHeight).floor();
 
     final x = col;
     final y = widget.terminal.buffer.convertViewLineToRawLine(row) -
@@ -236,8 +238,8 @@ class _TerminalViewState extends State<TerminalView> {
   }
 
   void onResize(double width, double height) {
-    final termWidth = (width / _charSize.cellWidth).floor();
-    final termHeight = (height / _charSize.cellHeight).floor();
+    final termWidth = (width / _cellSize.cellWidth).floor();
+    final termHeight = (height / _cellSize.cellHeight).floor();
 
     if (_lastTerminalWidth != termWidth || _lastTerminalHeight != termHeight) {
       _lastTerminalWidth = termWidth;
@@ -289,7 +291,7 @@ class _TerminalViewState extends State<TerminalView> {
   }
 
   void onScroll() {
-    final charOffset = (_offset.pixels / _charSize.cellHeight).ceil();
+    final charOffset = (_offset.pixels / _cellSize.cellHeight).ceil();
     final offset = widget.terminal.invisibleHeight - charOffset;
     widget.terminal.buffer.setScrollOffset(offset);
   }