Преглед на файлове

Fixes scrolling and initial size propagation

devmil преди 4 години
родител
ревизия
5da873ab86
променени са 4 файла, в които са добавени 53 реда и са изтрити 33 реда
  1. 24 18
      lib/frontend/terminal_view.dart
  2. 9 0
      lib/terminal/terminal.dart
  3. 18 15
      lib/terminal/terminal_isolate.dart
  4. 2 0
      lib/terminal/terminal_ui_interaction.dart

+ 24 - 18
lib/frontend/terminal_view.dart

@@ -184,20 +184,23 @@ class _TerminalViewState extends State<TerminalView> {
                 // set viewport height.
                 offset.applyViewportDimension(constraints.maxHeight);
 
-                final minScrollExtent = 0.0;
-
-                final maxScrollExtent = math.max(
-                    0.0,
-                    _cellSize.cellHeight * widget.terminal.terminalHeight -
-                        constraints.maxHeight);
-
-                // set how much the terminal can scroll
-                offset.applyContentDimensions(minScrollExtent, maxScrollExtent);
-
-                // syncronize pending terminal scroll extent to ScrollController
-                if (_terminalScrollExtent != null) {
-                  position.correctPixels(_terminalScrollExtent!);
-                  _terminalScrollExtent = null;
+                if (widget.terminal.isReady) {
+                  final minScrollExtent = 0.0;
+
+                  final maxScrollExtent = math.max(
+                      0.0,
+                      _cellSize.cellHeight * widget.terminal.bufferHeight -
+                          constraints.maxHeight);
+
+                  // set how much the terminal can scroll
+                  offset.applyContentDimensions(
+                      minScrollExtent, maxScrollExtent);
+
+                  // syncronize pending terminal scroll extent to ScrollController
+                  if (_terminalScrollExtent != null) {
+                    position.correctPixels(_terminalScrollExtent!);
+                    _terminalScrollExtent = null;
+                  }
                 }
 
                 return buildTerminal(context);
@@ -272,6 +275,9 @@ class _TerminalViewState extends State<TerminalView> {
   int? _lastTerminalHeight;
 
   void onSize(double width, double height) {
+    if (!widget.terminal.isReady) {
+      return;
+    }
     final termWidth = (width / _cellSize.cellWidth).floor();
     final termHeight = (height / _cellSize.cellHeight).floor();
 
@@ -310,10 +316,7 @@ class _TerminalViewState extends State<TerminalView> {
   void onScroll(double offset) {
     final topOffset = (offset / _cellSize.cellHeight).ceil();
     final bottomOffset = widget.terminal.invisibleHeight - topOffset;
-
-    setState(() {
-      widget.terminal.setScrollOffsetFromBottom(bottomOffset);
-    });
+    widget.terminal.setScrollOffsetFromBottom(bottomOffset);
   }
 }
 
@@ -334,6 +337,9 @@ class TerminalPainter extends CustomPainter {
 
   @override
   void paint(Canvas canvas, Size size) {
+    if (!terminal.isReady) {
+      return;
+    }
     _paintBackground(canvas);
 
     // if (oscillator.value) {

+ 9 - 0
lib/terminal/terminal.dart

@@ -196,6 +196,15 @@ class Terminal with Observable {
   int get cursorY => buffer.cursorY;
   int get scrollOffset => buffer.scrollOffsetFromBottom;
 
+  void setScrollOffsetFromBottom(int scrollOffset) {
+    final oldOffset = _buffer.scrollOffsetFromBottom;
+    _buffer.setScrollOffsetFromBottom(scrollOffset);
+    if (oldOffset != scrollOffset) {
+      _dirty = true;
+      refresh();
+    }
+  }
+
   /// Writes data to the terminal. Terminal sequences and special characters are
   /// interpreted.
   ///

+ 18 - 15
lib/terminal/terminal_isolate.dart

@@ -1,3 +1,4 @@
+import 'dart:async';
 import 'dart:isolate';
 
 import 'package:xterm/buffer/buffer_line.dart';
@@ -7,7 +8,6 @@ import 'package:xterm/mouse/selection.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/terminal.dart';
 import 'package:xterm/terminal/terminal_ui_interaction.dart';
-import 'package:xterm/theme/terminal_color.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_themes.dart';
 import 'package:xterm/util/observable.dart';
@@ -45,6 +45,7 @@ void terminalMain(SendPort port) async {
         _terminal.addListener(() {
           port.send(['notify']);
         });
+        port.send(['notify']);
         break;
       case 'write':
         if (_terminal == null) {
@@ -87,7 +88,7 @@ void terminalMain(SendPort port) async {
         if (_terminal == null) {
           break;
         }
-        _terminal.buffer.setScrollOffsetFromBottom(msg[1]);
+        _terminal.setScrollOffsetFromBottom(msg[1]);
         break;
       case 'resize':
         if (_terminal == null) {
@@ -95,12 +96,6 @@ void terminalMain(SendPort port) async {
         }
         _terminal.resize(msg[1], msg[2]);
         break;
-      case 'setScrollOffsetFromBottom':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.buffer.setScrollOffsetFromBottom(msg[1]);
-        break;
       case 'keyInput':
         if (_terminal == null) {
           break;
@@ -230,25 +225,25 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
       : _platform = platform;
 
   @override
-  int get scrollOffsetFromBottom => _lastState?.scrollOffsetFromBottom ?? 0;
+  int get scrollOffsetFromBottom => _lastState!.scrollOffsetFromBottom;
 
   @override
-  int get scrollOffsetFromTop => _lastState?.scrollOffsetFromTop ?? 0;
+  int get scrollOffsetFromTop => _lastState!.scrollOffsetFromTop;
 
   @override
-  int get scrollOffset => _lastState?.scrollOffset ?? 0;
+  int get scrollOffset => _lastState!.scrollOffset;
 
   @override
-  int get bufferHeight => _lastState?.bufferHeight ?? 0;
+  int get bufferHeight => _lastState!.bufferHeight;
 
   @override
-  int get terminalHeight => _lastState?.viewHeight ?? 0;
+  int get terminalHeight => _lastState!.viewHeight;
 
   @override
-  int get terminalWidth => _lastState?.viewWidth ?? 0;
+  int get terminalWidth => _lastState!.viewWidth;
 
   @override
-  int get invisibleHeight => _lastState?.invisibleHeight ?? 0;
+  int get invisibleHeight => _lastState!.invisibleHeight;
 
   @override
   Selection? get selection => _lastState?.selection;
@@ -305,7 +300,11 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   @override
   PlatformBehavior get platform => _platform;
 
+  @override
+  bool get isReady => _lastState != null;
+
   void start() async {
+    final initialRefreshCompleted = Completer<bool>();
     var firstReceivePort = ReceivePort();
     _isolate = await Isolate.spawn(terminalMain, firstReceivePort.sendPort);
     _sendPort = await firstReceivePort.first;
@@ -330,12 +329,16 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
           break;
         case 'newState':
           _lastState = message[1];
+          if (!initialRefreshCompleted.isCompleted) {
+            initialRefreshCompleted.complete(true);
+          }
           this.notifyListeners();
           break;
       }
     });
     _sendPort!.send(
         ['init', TerminalInitData(this.platform, this.theme, this.maxLines)]);
+    await initialRefreshCompleted.future;
   }
 
   void stop() {

+ 2 - 0
lib/terminal/terminal_ui_interaction.dart

@@ -24,6 +24,8 @@ abstract class TerminalUiInteraction with Observable {
   bool get dirty;
   PlatformBehavior get platform;
 
+  bool get isReady;
+
   void refresh();
   void clearSelection();
   void onMouseTap(Position position);