Quellcode durchsuchen

TerminalBackend interface

Out, ExitCode, write and resize are now routed via the Terminal
Terminal triggers initialization of the backend (so that the initialization can happen in the Terminal Isolate)
devmil vor 4 Jahren
Ursprung
Commit
df9c4cb671

+ 0 - 5
lib/frontend/terminal_view.dart

@@ -21,13 +21,10 @@ import 'package:xterm/theme/terminal_style.dart';
 import 'package:xterm/util/bit_flags.dart';
 import 'package:xterm/util/bit_flags.dart';
 import 'package:xterm/util/hash_values.dart';
 import 'package:xterm/util/hash_values.dart';
 
 
-typedef TerminalResizeHandler = void Function(int width, int height);
-
 class TerminalView extends StatefulWidget {
 class TerminalView extends StatefulWidget {
   TerminalView({
   TerminalView({
     Key? key,
     Key? key,
     required this.terminal,
     required this.terminal,
-    this.onResize,
     this.style = const TerminalStyle(),
     this.style = const TerminalStyle(),
     this.opacity = 1.0,
     this.opacity = 1.0,
     FocusNode? focusNode,
     FocusNode? focusNode,
@@ -40,7 +37,6 @@ class TerminalView extends StatefulWidget {
         super(key: key ?? ValueKey(terminal));
         super(key: key ?? ValueKey(terminal));
 
 
   final TerminalUiInteraction terminal;
   final TerminalUiInteraction terminal;
-  final TerminalResizeHandler? onResize;
   final FocusNode focusNode;
   final FocusNode focusNode;
   final bool autofocus;
   final bool autofocus;
   final ScrollController scrollController;
   final ScrollController scrollController;
@@ -288,7 +284,6 @@ class _TerminalViewState extends State<TerminalView> {
     _lastTerminalWidth = termWidth;
     _lastTerminalWidth = termWidth;
     _lastTerminalHeight = termHeight;
     _lastTerminalHeight = termHeight;
 
 
-    widget.onResize?.call(termWidth, termHeight);
     widget.terminal.resize(termWidth, termHeight);
     widget.terminal.resize(termWidth, termHeight);
   }
   }
 
 

+ 1 - 1
lib/mouse/mouse_mode.dart

@@ -49,6 +49,6 @@ class MouseModeX10 extends MouseMode {
     buffer.writeCharCode(btn + 32);
     buffer.writeCharCode(btn + 32);
     buffer.writeCharCode(px + 32);
     buffer.writeCharCode(px + 32);
     buffer.writeCharCode(py + 32);
     buffer.writeCharCode(py + 32);
-    terminal.onInput(buffer.toString());
+    terminal.backend?.write(buffer.toString());
   }
   }
 }
 }

+ 4 - 3
lib/terminal/csi.dart

@@ -306,10 +306,11 @@ void csiDeviceStatusReportHandler(CSI csi, Terminal terminal) {
 
 
   switch (csi.params[0]) {
   switch (csi.params[0]) {
     case 5:
     case 5:
-      terminal.onInput("\x1b[0n");
+      terminal.backend?.write("\x1b[0n");
       break;
       break;
     case 6: // report cursor position
     case 6: // report cursor position
-      terminal.onInput("\x1b[${terminal.cursorX + 1};${terminal.cursorY + 1}R");
+      terminal.backend
+          ?.write("\x1b[${terminal.cursorX + 1};${terminal.cursorY + 1}R");
       break;
       break;
     default:
     default:
       terminal.debug
       terminal.debug
@@ -325,7 +326,7 @@ void csiSendDeviceAttributesHandler(CSI csi, Terminal terminal) {
     response = '>0;0;0';
     response = '>0;0;0';
   }
   }
 
 
-  terminal.onInput('\x1b[${response}c');
+  terminal.backend?.write('\x1b[${response}c');
 }
 }
 
 
 void csiCursorUpHandler(CSI csi, Terminal terminal) {
 void csiCursorUpHandler(CSI csi, Terminal terminal) {

+ 10 - 6
lib/terminal/terminal.dart

@@ -14,6 +14,7 @@ import 'package:xterm/terminal/cursor.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/sbc.dart';
 import 'package:xterm/terminal/sbc.dart';
 import 'package:xterm/terminal/tabs.dart';
 import 'package:xterm/terminal/tabs.dart';
+import 'package:xterm/terminal/terminal_backend.dart';
 import 'package:xterm/theme/terminal_color.dart';
 import 'package:xterm/theme/terminal_color.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_themes.dart';
 import 'package:xterm/theme/terminal_themes.dart';
@@ -32,7 +33,7 @@ void _defaultIconHandler(String _) {}
 
 
 class Terminal with Observable {
 class Terminal with Observable {
   Terminal({
   Terminal({
-    this.onInput = _defaultInputHandler,
+    this.backend,
     this.onBell = _defaultBellHandler,
     this.onBell = _defaultBellHandler,
     this.onTitleChange = _defaultTitleHandler,
     this.onTitleChange = _defaultTitleHandler,
     this.onIconChange = _defaultIconHandler,
     this.onIconChange = _defaultIconHandler,
@@ -40,6 +41,8 @@ class Terminal with Observable {
     this.theme = TerminalThemes.defaultTheme,
     this.theme = TerminalThemes.defaultTheme,
     required int maxLines,
     required int maxLines,
   }) : _maxLines = maxLines {
   }) : _maxLines = maxLines {
+    backend?.init();
+    backend?.out.listen(write);
     _mainBuffer = Buffer(this);
     _mainBuffer = Buffer(this);
     _altBuffer = Buffer(this);
     _altBuffer = Buffer(this);
     _buffer = _mainBuffer;
     _buffer = _mainBuffer;
@@ -182,7 +185,7 @@ class Terminal with Observable {
   final tabs = Tabs();
   final tabs = Tabs();
   final debug = DebugHandler();
   final debug = DebugHandler();
 
 
-  final TerminalInputHandler onInput;
+  final TerminalBackend? backend;
   final BellHandler onBell;
   final BellHandler onBell;
   final TitleChangeHandler onTitleChange;
   final TitleChangeHandler onTitleChange;
   final IconChangeHandler onIconChange;
   final IconChangeHandler onIconChange;
@@ -349,6 +352,7 @@ class Terminal with Observable {
   /// than 0. Text reflow is currently not implemented and will be avaliable in
   /// than 0. Text reflow is currently not implemented and will be avaliable in
   /// the future.
   /// the future.
   void resize(int newWidth, int newHeight) {
   void resize(int newWidth, int newHeight) {
+    backend?.resize(newWidth, newHeight);
     newWidth = max(newWidth, 1);
     newWidth = max(newWidth, 1);
     newHeight = max(newHeight, 1);
     newHeight = max(newHeight, 1);
 
 
@@ -429,7 +433,7 @@ class Terminal with Observable {
       if (record.action.type == KeytabActionType.input) {
       if (record.action.type == KeytabActionType.input) {
         debug.onMsg('input: ${record.action.value}');
         debug.onMsg('input: ${record.action.value}');
         final input = keytabUnescape(record.action.value);
         final input = keytabUnescape(record.action.value);
-        onInput(input);
+        backend?.write(input);
         return;
         return;
       }
       }
     }
     }
@@ -438,7 +442,7 @@ class Terminal with Observable {
       if (key.index >= TerminalKey.keyA.index &&
       if (key.index >= TerminalKey.keyA.index &&
           key.index <= TerminalKey.keyZ.index) {
           key.index <= TerminalKey.keyZ.index) {
         final input = key.index - TerminalKey.keyA.index + 1;
         final input = key.index - TerminalKey.keyA.index + 1;
-        onInput(String.fromCharCode(input));
+        backend?.write(String.fromCharCode(input));
         return;
         return;
       }
       }
     }
     }
@@ -447,7 +451,7 @@ class Terminal with Observable {
       if (key.index >= TerminalKey.keyA.index &&
       if (key.index >= TerminalKey.keyA.index &&
           key.index <= TerminalKey.keyZ.index) {
           key.index <= TerminalKey.keyZ.index) {
         final input = [0x1b, key.index - TerminalKey.keyA.index + 65];
         final input = [0x1b, key.index - TerminalKey.keyA.index + 65];
-        onInput(String.fromCharCodes(input));
+        backend?.write(String.fromCharCodes(input));
         return;
         return;
       }
       }
     }
     }
@@ -508,7 +512,7 @@ class Terminal with Observable {
       data = '\x1b[200~$data\x1b[201~';
       data = '\x1b[200~$data\x1b[201~';
     }
     }
 
 
-    onInput(data);
+    backend?.write(data);
   }
   }
 
 
   void selectWord(int x, int y) {}
   void selectWord(int x, int y) {}

+ 9 - 0
lib/terminal/terminal_backend.dart

@@ -0,0 +1,9 @@
+abstract class TerminalBackend {
+  void init();
+
+  Stream<String> get out;
+  Future<int> get exitCode;
+
+  void write(String input);
+  void resize(int width, int height);
+}

+ 28 - 46
lib/terminal/terminal_isolate.dart

@@ -7,6 +7,7 @@ import 'package:xterm/mouse/position.dart';
 import 'package:xterm/mouse/selection.dart';
 import 'package:xterm/mouse/selection.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/terminal.dart';
 import 'package:xterm/terminal/terminal.dart';
+import 'package:xterm/terminal/terminal_backend.dart';
 import 'package:xterm/terminal/terminal_ui_interaction.dart';
 import 'package:xterm/terminal/terminal_ui_interaction.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_themes.dart';
 import 'package:xterm/theme/terminal_themes.dart';
@@ -27,9 +28,7 @@ void terminalMain(SendPort port) async {
       case 'init':
       case 'init':
         final TerminalInitData initData = msg[1];
         final TerminalInitData initData = msg[1];
         _terminal = Terminal(
         _terminal = Terminal(
-            onInput: (String input) {
-              port.send(['onInput', input]);
-            },
+            backend: initData.backend,
             onTitleChange: (String title) {
             onTitleChange: (String title) {
               port.send(['onTitleChange', title]);
               port.send(['onTitleChange', title]);
             },
             },
@@ -45,56 +44,35 @@ void terminalMain(SendPort port) async {
         _terminal.addListener(() {
         _terminal.addListener(() {
           port.send(['notify']);
           port.send(['notify']);
         });
         });
+        initData.backend?.exitCode.then((value) => port.send(['exit', value]));
         port.send(['notify']);
         port.send(['notify']);
         break;
         break;
       case 'write':
       case 'write':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.write(msg[1]);
+        _terminal?.write(msg[1]);
         break;
         break;
       case 'refresh':
       case 'refresh':
-        if (_terminal == null) {
-          break;
-        }
-
-        _terminal.refresh();
+        _terminal?.refresh();
         break;
         break;
       case 'selection.clear':
       case 'selection.clear':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.selection.clear();
+        _terminal?.selection.clear();
         break;
         break;
       case 'mouseMode.onTap':
       case 'mouseMode.onTap':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.mouseMode.onTap(_terminal, msg[1]);
+        _terminal?.mouseMode.onTap(_terminal, msg[1]);
         break;
         break;
       case 'mouseMode.onPanStart':
       case 'mouseMode.onPanStart':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.mouseMode.onPanStart(_terminal, msg[1]);
+        _terminal?.mouseMode.onPanStart(_terminal, msg[1]);
         break;
         break;
       case 'mouseMode.onPanUpdate':
       case 'mouseMode.onPanUpdate':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.mouseMode.onPanUpdate(_terminal, msg[1]);
+        _terminal?.mouseMode.onPanUpdate(_terminal, msg[1]);
         break;
         break;
       case 'setScrollOffsetFromBottom':
       case 'setScrollOffsetFromBottom':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.setScrollOffsetFromBottom(msg[1]);
+        _terminal?.setScrollOffsetFromBottom(msg[1]);
         break;
         break;
       case 'resize':
       case 'resize':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.resize(msg[1], msg[2]);
+        _terminal?.resize(msg[1], msg[2]);
+        break;
+      case 'onInput':
+        _terminal?.backend?.write(msg[1]);
         break;
         break;
       case 'keyInput':
       case 'keyInput':
         if (_terminal == null) {
         if (_terminal == null) {
@@ -141,8 +119,8 @@ class TerminalInitData {
   PlatformBehavior platform;
   PlatformBehavior platform;
   TerminalTheme theme;
   TerminalTheme theme;
   int maxLines;
   int maxLines;
-
-  TerminalInitData(this.platform, this.theme, this.maxLines);
+  TerminalBackend? backend;
+  TerminalInitData(this.backend, this.platform, this.theme, this.maxLines);
 }
 }
 
 
 class TerminalState {
 class TerminalState {
@@ -199,7 +177,7 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   SendPort? _sendPort;
   SendPort? _sendPort;
   late Isolate _isolate;
   late Isolate _isolate;
 
 
-  final TerminalInputHandler onInput;
+  final TerminalBackend? backend;
   final BellHandler onBell;
   final BellHandler onBell;
   final TitleChangeHandler onTitleChange;
   final TitleChangeHandler onTitleChange;
   final IconChangeHandler onIconChange;
   final IconChangeHandler onIconChange;
@@ -209,13 +187,15 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   final int maxLines;
   final int maxLines;
 
 
   TerminalState? _lastState;
   TerminalState? _lastState;
+  final _backendExited = Completer<int>();
+  Future<int> get backendExited => _backendExited.future;
 
 
   TerminalState? get lastState {
   TerminalState? get lastState {
     return _lastState;
     return _lastState;
   }
   }
 
 
   TerminalIsolate(
   TerminalIsolate(
-      {this.onInput = _defaultInputHandler,
+      {this.backend,
       this.onBell = _defaultBellHandler,
       this.onBell = _defaultBellHandler,
       this.onTitleChange = _defaultTitleHandler,
       this.onTitleChange = _defaultTitleHandler,
       this.onIconChange = _defaultIconHandler,
       this.onIconChange = _defaultIconHandler,
@@ -312,9 +292,6 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
     _receivePort.listen((message) {
     _receivePort.listen((message) {
       String action = message[0];
       String action = message[0];
       switch (action) {
       switch (action) {
-        case 'onInput':
-          this.onInput(message[1]);
-          break;
         case 'onBell':
         case 'onBell':
           this.onBell();
           this.onBell();
           break;
           break;
@@ -334,10 +311,15 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
           }
           }
           this.notifyListeners();
           this.notifyListeners();
           break;
           break;
+        case 'exit':
+          _backendExited.complete(message[1]);
+          break;
       }
       }
     });
     });
-    _sendPort!.send(
-        ['init', TerminalInitData(this.platform, this.theme, this.maxLines)]);
+    _sendPort!.send([
+      'init',
+      TerminalInitData(this.backend, this.platform, this.theme, this.maxLines)
+    ]);
     await initialRefreshCompleted.future;
     await initialRefreshCompleted.future;
   }
   }
 
 
@@ -427,7 +409,7 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   }
   }
 
 
   void raiseOnInput(String text) {
   void raiseOnInput(String text) {
-    onInput(text);
+    _sendPort!.send(['onInput', text]);
   }
   }
 
 
   void keyInput(
   void keyInput(

+ 1 - 0
lib/xterm.dart

@@ -1,5 +1,6 @@
 library xterm;
 library xterm;
 
 
 export 'terminal/terminal_isolate.dart';
 export 'terminal/terminal_isolate.dart';
+export 'terminal/terminal_backend.dart';
 export 'terminal/terminal_ui_interaction.dart';
 export 'terminal/terminal_ui_interaction.dart';
 export 'terminal/platform.dart';
 export 'terminal/platform.dart';