浏览代码

feat!: add TerminalBackend.resizeFull() for receiving terminal size in pixels

In addition to terminal width and height in the unit of
columns and rows provided by TerminalBackend.resize(),
now there is a TerminalBackend.resizeFull() method that
can be implemented to receive terminal width and height
in pixels in additional to in columns and rows. This is
to fulfill the winsize struct in different Unix platforms.

In order to ensure minimum API changes,
TerminalBackend.resizeFull() is implemented in a way
that existing TerminalBackend implementations does not
need to resizeFull() if they do not need the additional
information. Instead they can just implement resize()
to fulfill the TerminalBackend interface.

BREAKING CHANGE: Implementations of TerminalBackend should
    now extends TerminalBackend instead of implements
    TerminalBackend. Simply changing implements to extends
    will be enough to resolve the breaking API changes.
michaellee8 4 年之前
父节点
当前提交
b5021203f8

+ 2 - 2
example/lib/isolate.dart

@@ -2,8 +2,8 @@ import 'dart:async';
 
 import 'package:flutter/material.dart';
 import 'package:xterm/flutter.dart';
-import 'package:xterm/xterm.dart';
 import 'package:xterm/isolate.dart';
+import 'package:xterm/xterm.dart';
 
 void main() {
   runApp(MyApp());
@@ -30,7 +30,7 @@ class MyHomePage extends StatefulWidget {
   _MyHomePageState createState() => _MyHomePageState();
 }
 
-class FakeTerminalBackend implements TerminalBackend {
+class FakeTerminalBackend extends TerminalBackend {
   Completer<int> _exitCodeCompleter;
   // ignore: close_sinks
   StreamController<String> _outStream;

+ 1 - 1
example/lib/main.dart

@@ -29,7 +29,7 @@ class MyHomePage extends StatefulWidget {
   _MyHomePageState createState() => _MyHomePageState();
 }
 
-class FakeTerminalBackend implements TerminalBackend {
+class FakeTerminalBackend extends TerminalBackend {
   Completer<int> _exitCodeCompleter;
   // ignore: close_sinks
   StreamController<String> _outStream;

+ 1 - 1
example/lib/ssh.dart

@@ -35,7 +35,7 @@ class MyHomePage extends StatefulWidget {
   _MyHomePageState createState() => _MyHomePageState();
 }
 
-class SSHTerminalBackend implements TerminalBackend {
+class SSHTerminalBackend extends TerminalBackend {
   SSHClient client;
 
   String _host;

+ 4 - 4
lib/frontend/terminal_view.dart

@@ -1,4 +1,3 @@
-import 'dart:io';
 import 'dart:math' as math;
 import 'dart:ui';
 
@@ -7,15 +6,15 @@ import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
-import 'package:xterm/buffer/line/line.dart';
 import 'package:xterm/buffer/cell_flags.dart';
+import 'package:xterm/buffer/line/line.dart';
+import 'package:xterm/frontend/cache.dart';
 import 'package:xterm/frontend/char_size.dart';
 import 'package:xterm/frontend/helpers.dart';
 import 'package:xterm/frontend/input_behavior.dart';
 import 'package:xterm/frontend/input_behaviors.dart';
 import 'package:xterm/frontend/input_listener.dart';
 import 'package:xterm/frontend/oscillator.dart';
-import 'package:xterm/frontend/cache.dart';
 import 'package:xterm/mouse/position.dart';
 import 'package:xterm/terminal/terminal_ui_interaction.dart';
 import 'package:xterm/theme/terminal_style.dart';
@@ -311,7 +310,8 @@ class _TerminalViewState extends State<TerminalView> {
     _lastTerminalWidth = termWidth;
     _lastTerminalHeight = termHeight;
 
-    widget.terminal.resize(termWidth, termHeight);
+    widget.terminal
+        .resize(termWidth, termHeight, _width!.floor(), _height!.floor());
   }
 
   TextEditingValue? onInput(TextEditingValue value) {

+ 5 - 4
lib/terminal/terminal.dart

@@ -4,13 +4,13 @@ import 'dart:math' show max, min;
 
 import 'package:xterm/buffer/buffer.dart';
 import 'package:xterm/buffer/line/line.dart';
-import 'package:xterm/mouse/position.dart';
-import 'package:xterm/mouse/selection.dart';
 import 'package:xterm/input/keys.dart';
 import 'package:xterm/input/keytab/keytab.dart';
 import 'package:xterm/input/keytab/keytab_escape.dart';
 import 'package:xterm/input/keytab/keytab_record.dart';
 import 'package:xterm/mouse/mouse_mode.dart';
+import 'package:xterm/mouse/position.dart';
+import 'package:xterm/mouse/selection.dart';
 import 'package:xterm/terminal/ansi.dart';
 import 'package:xterm/terminal/cursor.dart';
 import 'package:xterm/terminal/platform.dart';
@@ -357,8 +357,9 @@ class Terminal with Observable implements TerminalUiInteraction {
   /// Resize the terminal screen. [newWidth] and [newHeight] should be greater
   /// than 0. Text reflow is currently not implemented and will be avaliable in
   /// the future.
-  void resize(int newWidth, int newHeight) {
-    backend?.resize(newWidth, newHeight);
+  void resize(
+      int newWidth, int newHeight, int newPixelWidth, int newPixelHeight) {
+    backend?.resizeFull(newWidth, newHeight, newPixelWidth, newPixelHeight);
     newWidth = max(newWidth, 1);
     newHeight = max(newHeight, 1);
 

+ 10 - 0
lib/terminal/terminal_backend.dart

@@ -19,8 +19,18 @@ abstract class TerminalBackend {
   void write(String input);
 
   /// notifies the backend about a view port resize that happened
+  /// If resizeFull() is overrode, resize() will not be called, but still
+  /// requires an empty method as a stub for API compatibility reasons.
   void resize(int width, int height);
 
+  /// notifies the backend about a view port resize that happened, with information
+  /// including both row/column and pixel width/height.
+  /// Not required to be overrode if the [TerminalBackend] does not require
+  /// pixel size information, just override resize() instead.
+  void resizeFull(int columns, int rows, int pixelWidth, int pixelHeight) {
+    resize(columns, rows);
+  }
+
   /// terminates this backend
   void terminate();
 

+ 14 - 3
lib/terminal/terminal_isolate.dart

@@ -104,7 +104,7 @@ void terminalMain(SendPort port) async {
         _terminal?.setScrollOffsetFromBottom(msg[1]);
         break;
       case _IsolateCommand.resize:
-        _terminal?.resize(msg[1], msg[2]);
+        _terminal?.resize(msg[1], msg[2], msg[3], msg[4]);
         break;
       case _IsolateCommand.onInput:
         _terminal?.backend?.write(msg[1]);
@@ -155,6 +155,7 @@ class TerminalInitData {
   TerminalTheme theme;
   int maxLines;
   TerminalBackend? backend;
+
   TerminalInitData(this.backend, this.platform, this.theme, this.maxLines);
 }
 
@@ -204,7 +205,9 @@ class TerminalState {
 }
 
 void _defaultBellHandler() {}
+
 void _defaultTitleHandler(String _) {}
+
 void _defaultIconHandler(String _) {}
 
 /// The TerminalIsolate class hosts an Isolate that runs a Terminal.
@@ -434,8 +437,15 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
     _sendPort?.send([_IsolateCommand.paste, data]);
   }
 
-  void resize(int newWidth, int newHeight) {
-    _sendPort?.send([_IsolateCommand.resize, newWidth, newHeight]);
+  void resize(
+      int newWidth, int newHeight, int newPixelWidth, int newPixelHeight) {
+    _sendPort?.send([
+      _IsolateCommand.resize,
+      newWidth,
+      newHeight,
+      newPixelWidth,
+      newPixelHeight
+    ]);
   }
 
   void raiseOnInput(String text) {
@@ -456,6 +466,7 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   var _isTerminated = false;
 
   final _backendExited = Completer<int>();
+
   @override
   Future<int> get backendExited => _backendExited.future;
 

+ 2 - 1
lib/terminal/terminal_ui_interaction.dart

@@ -95,7 +95,8 @@ abstract class TerminalUiInteraction with Observable {
 
   /// notifies the Terminal about a resize that happened. The Terminal will
   /// do any resize / reflow logic and notify the backend about the resize
-  void resize(int newWidth, int newHeight);
+  void resize(
+      int newWidth, int newHeight, int newPixelWidth, int newPixelHeight);
 
   /// notifies the Terminal about key input
   void keyInput(