|
|
@@ -103,21 +103,13 @@ class _TerminalViewState extends State<TerminalView> {
|
|
|
/// been updated and needs to be syncronized to flutter side.
|
|
|
double? _terminalScrollExtent;
|
|
|
|
|
|
- /// Keep track of view port building to avoid calling `setState()` during
|
|
|
- /// layout. During layout `ScrollNotification`s are sometimes dispatched, may
|
|
|
- /// lead to unexpected calling of `setState()`. This is a temporary patch and
|
|
|
- /// should be replaced when better approachs are discovered.
|
|
|
- var _isDuringViewportBuilding = false;
|
|
|
-
|
|
|
void onTerminalChange() {
|
|
|
- if (!mounted) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
_terminalScrollExtent =
|
|
|
_cellSize.cellHeight * widget.terminal.buffer.scrollOffsetFromTop;
|
|
|
|
|
|
- setState(() {});
|
|
|
+ if (mounted) {
|
|
|
+ setState(() {});
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// listen to oscillator to update mouse blink etc.
|
|
|
@@ -179,7 +171,11 @@ class _TerminalViewState extends State<TerminalView> {
|
|
|
child: Scrollable(
|
|
|
controller: widget.scrollController,
|
|
|
viewportBuilder: (context, offset) {
|
|
|
- _isDuringViewportBuilding = true;
|
|
|
+ /// use [_EmptyScrollActivity] to suppress unexpected behaviors
|
|
|
+ /// that come from [applyViewportDimension].
|
|
|
+ widget.scrollController.position.beginActivity(
|
|
|
+ _EmptyScrollActivity(),
|
|
|
+ );
|
|
|
|
|
|
// set viewport height.
|
|
|
offset.applyViewportDimension(constraints.maxHeight);
|
|
|
@@ -202,8 +198,6 @@ class _TerminalViewState extends State<TerminalView> {
|
|
|
_terminalScrollExtent = null;
|
|
|
}
|
|
|
|
|
|
- _isDuringViewportBuilding = false;
|
|
|
-
|
|
|
return buildTerminal(context);
|
|
|
},
|
|
|
),
|
|
|
@@ -279,23 +273,15 @@ class _TerminalViewState extends State<TerminalView> {
|
|
|
final termWidth = (width / _cellSize.cellWidth).floor();
|
|
|
final termHeight = (height / _cellSize.cellHeight).floor();
|
|
|
|
|
|
- if (_lastTerminalWidth != termWidth || _lastTerminalHeight != termHeight) {
|
|
|
- _lastTerminalWidth = termWidth;
|
|
|
- _lastTerminalHeight = termHeight;
|
|
|
-
|
|
|
- // print('($termWidth, $termHeight)');
|
|
|
-
|
|
|
- widget.onResize?.call(termWidth, termHeight);
|
|
|
+ if (_lastTerminalWidth == termWidth && _lastTerminalHeight == termHeight) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- SchedulerBinding.instance!.addPostFrameCallback((_) {
|
|
|
- widget.terminal.resize(termWidth, termHeight);
|
|
|
- widget.terminal.refresh();
|
|
|
- });
|
|
|
+ _lastTerminalWidth = termWidth;
|
|
|
+ _lastTerminalHeight = termHeight;
|
|
|
|
|
|
- // Future.delayed(Duration.zero).then((_) {
|
|
|
- // widget.terminal.resize(termWidth, termHeight);
|
|
|
- // });
|
|
|
- }
|
|
|
+ widget.onResize?.call(termWidth, termHeight);
|
|
|
+ widget.terminal.resize(termWidth, termHeight);
|
|
|
}
|
|
|
|
|
|
TextEditingValue? onInput(TextEditingValue value) {
|
|
|
@@ -303,6 +289,7 @@ class _TerminalViewState extends State<TerminalView> {
|
|
|
}
|
|
|
|
|
|
void onKeyStroke(RawKeyEvent event) {
|
|
|
+ // TODO: find a way to stop scrolling immediately after key stroke.
|
|
|
widget.inputBehavior.onKeyStroke(event, widget.terminal);
|
|
|
widget.terminal.buffer.setScrollOffsetFromBottom(0);
|
|
|
}
|
|
|
@@ -322,10 +309,6 @@ class _TerminalViewState extends State<TerminalView> {
|
|
|
final topOffset = (offset / _cellSize.cellHeight).ceil();
|
|
|
final bottomOffset = widget.terminal.invisibleHeight - topOffset;
|
|
|
|
|
|
- if (_isDuringViewportBuilding) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
setState(() {
|
|
|
widget.terminal.buffer.setScrollOffsetFromBottom(bottomOffset);
|
|
|
});
|
|
|
@@ -567,3 +550,28 @@ class TerminalPainter extends CustomPainter {
|
|
|
return terminal.dirty;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/// A scroll activity delegate that does nothing. Used to construct
|
|
|
+/// [_EmptyScrollActivity].
|
|
|
+class _EmptyScrollActivityDelegate implements ScrollActivityDelegate {
|
|
|
+ const _EmptyScrollActivityDelegate();
|
|
|
+
|
|
|
+ final axisDirection = AxisDirection.down;
|
|
|
+
|
|
|
+ double setPixels(double pixels) => 0;
|
|
|
+
|
|
|
+ void applyUserOffset(double delta) {}
|
|
|
+
|
|
|
+ void goIdle() {}
|
|
|
+
|
|
|
+ void goBallistic(double velocity) {}
|
|
|
+}
|
|
|
+
|
|
|
+/// A scroll activity that does nothing. Used to suppress unexpected behaviors
|
|
|
+/// from [Scrollable].
|
|
|
+class _EmptyScrollActivity extends IdleScrollActivity {
|
|
|
+ _EmptyScrollActivity() : super(_EmptyScrollActivityDelegate());
|
|
|
+
|
|
|
+ @override
|
|
|
+ void applyNewDimensions() {}
|
|
|
+}
|