Parcourir la source

🖱️ enhanced scroll support

xuty il y a 5 ans
Parent
commit
0896bc6ea4
4 fichiers modifiés avec 77 ajouts et 59 suppressions
  1. 21 21
      example/pubspec.lock
  2. 32 17
      lib/frontend/terminal_view.dart
  3. 4 1
      lib/terminal/terminal.dart
  4. 20 20
      pubspec.lock

+ 21 - 21
example/pubspec.lock

@@ -5,63 +5,63 @@ packages:
     dependency: transitive
     description:
       name: async
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.5.0-nullsafety"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.0-nullsafety"
   characters:
     dependency: transitive
     description:
       name: characters
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety.2"
   charcode:
     dependency: transitive
     description:
       name: charcode
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.2.0-nullsafety"
   clock:
     dependency: transitive
     description:
       name: clock
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety"
   collection:
     dependency: transitive
     description:
       name: collection
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.15.0-nullsafety.2"
   convert:
     dependency: transitive
     description:
       name: convert
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.1"
   cupertino_icons:
     dependency: "direct main"
     description:
       name: cupertino_icons
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "0.1.3"
   fake_async:
     dependency: transitive
     description:
       name: fake_async
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety"
   flutter:
@@ -78,28 +78,28 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "0.12.10-nullsafety"
   meta:
     dependency: transitive
     description:
       name: meta
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.3.0-nullsafety.2"
   path:
     dependency: transitive
     description:
       name: path
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.8.0-nullsafety"
   quiver:
     dependency: transitive
     description:
       name: quiver
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.3"
   sky_engine:
@@ -111,56 +111,56 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.8.0-nullsafety"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.10.0-nullsafety"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.0-nullsafety"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.2.0-nullsafety"
   test_api:
     dependency: transitive
     description:
       name: test_api
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "0.2.19-nullsafety"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.3.0-nullsafety.2"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.0-nullsafety.2"
   xterm:

+ 32 - 17
lib/frontend/terminal_view.dart

@@ -110,6 +110,10 @@ class _TerminalViewState extends State<TerminalView> {
   int _lastTerminalWidth;
   int _lastTerminalHeight;
   CharSize _charSize;
+  ViewportOffset _offset;
+
+  var _minScrollExtent = 0.0;
+  var _maxScrollExtent = 0.0;
 
   void onTerminalChange() {
     if (mounted) {
@@ -195,13 +199,27 @@ class _TerminalViewState extends State<TerminalView> {
       autofocus: true,
       child: MouseRegion(
         cursor: SystemMouseCursors.text,
-        child: MouseListener(
-          onScroll: onScroll,
-          child: LayoutBuilder(builder: (context, constraints) {
-            onResize(constraints.maxWidth, constraints.maxHeight);
-            return result;
-          }),
-        ),
+        child: LayoutBuilder(builder: (context, constraints) {
+          onResize(constraints.maxWidth, constraints.maxHeight);
+          return Scrollable(
+            viewportBuilder: (context, offset) {
+              offset.applyViewportDimension(constraints.maxHeight);
+
+              _minScrollExtent = 0.0;
+              _maxScrollExtent = math.max(
+                  0.0,
+                  _charSize.effectHeight * widget.terminal.buffer.height -
+                      constraints.maxHeight);
+
+              offset.applyContentDimensions(_minScrollExtent, _maxScrollExtent);
+
+              _offset = offset;
+              _offset.addListener(onScroll);
+
+              return result;
+            },
+          );
+        }),
       ),
     );
   }
@@ -261,7 +279,7 @@ class _TerminalViewState extends State<TerminalView> {
       );
     }
 
-    widget.terminal.buffer.setScrollOffset(0);
+    _offset.moveTo(_maxScrollExtent);
   }
 
   void onFocus(bool focused) {
@@ -270,14 +288,10 @@ class _TerminalViewState extends State<TerminalView> {
     });
   }
 
-  void onScroll(Offset offset) {
-    final delta = math.max(1, offset.dy.abs() ~/ 10);
-
-    if (offset.dy > 0) {
-      widget.terminal.buffer.screenScrollDown(delta);
-    } else if (offset.dy < 0) {
-      widget.terminal.buffer.screenScrollUp(delta);
-    }
+  void onScroll() {
+    final charOffset = (_offset.pixels / _charSize.effectHeight).ceil();
+    final offset = widget.terminal.invisibleHeight - charOffset;
+    widget.terminal.buffer.setScrollOffset(offset);
   }
 }
 
@@ -485,7 +499,8 @@ class TerminalPainter extends CustomPainter {
     );
 
     // final tp = textLayoutCache.getOrPerformLayout(span);
-    final tp = textLayoutCacheV2.getOrPerformLayout(span, hashValues(cell.codePoint, cell.attr));
+    final tp = textLayoutCacheV2.getOrPerformLayout(
+        span, hashValues(cell.codePoint, cell.attr));
 
     tp.paint(canvas, Offset(offsetX, offsetY));
   }

+ 4 - 1
lib/terminal/terminal.dart

@@ -1,5 +1,5 @@
 import 'dart:async';
-import 'dart:math' show max;
+import 'dart:math' show max, min;
 
 import 'package:async/async.dart';
 import 'package:xterm/buffer/buffer.dart';
@@ -70,6 +70,9 @@ class Terminal with Observable {
   int get viewWidth => _viewWidth;
   int get viewHeight => _viewHeight;
 
+  int get visibleHeight => min(_viewHeight, buffer.height);
+  int get invisibleHeight => buffer.height - visibleHeight;
+
   bool _originMode = false;
   bool _replaceMode = false;
   bool _lineFeed = true;

+ 20 - 20
pubspec.lock

@@ -5,56 +5,56 @@ packages:
     dependency: "direct main"
     description:
       name: async
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.5.0-nullsafety"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.0-nullsafety"
   characters:
     dependency: transitive
     description:
       name: characters
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety.2"
   charcode:
     dependency: transitive
     description:
       name: charcode
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.2.0-nullsafety"
   clock:
     dependency: transitive
     description:
       name: clock
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety"
   collection:
     dependency: transitive
     description:
       name: collection
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.15.0-nullsafety.2"
   convert:
     dependency: "direct main"
     description:
       name: convert
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.1"
   fake_async:
     dependency: transitive
     description:
       name: fake_async
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety"
   flutter:
@@ -71,28 +71,28 @@ packages:
     dependency: transitive
     description:
       name: matcher
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "0.12.10-nullsafety"
   meta:
     dependency: "direct main"
     description:
       name: meta
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.3.0-nullsafety.2"
   path:
     dependency: transitive
     description:
       name: path
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.8.0-nullsafety"
   quiver:
     dependency: "direct main"
     description:
       name: quiver
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.3"
   sky_engine:
@@ -104,56 +104,56 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.8.0-nullsafety"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.10.0-nullsafety"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.0-nullsafety"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.1.0-nullsafety"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.2.0-nullsafety"
   test_api:
     dependency: transitive
     description:
       name: test_api
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "0.2.19-nullsafety"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "1.3.0-nullsafety.2"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
-      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
+      url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
     source: hosted
     version: "2.1.0-nullsafety.2"
 sdks: