mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-14 08:21:02 +03:00
fix(terminal): send SGR mouse wheel reports with the button codes app… (#15817)
* fix(terminal): send SGR mouse wheel reports with the button codes apps expect xterm.dart 4.0.0 encodes the wheel buttons as 64+4..64+7 rather than 64+0..64+3, so the low bits land on the modifier field and every wheel report the terminal emits reads as wheel-with-Shift. Strict full-screen applications reject the modified event, which is why neither the mouse wheel nor the trackpad scrolls anything once the peer application takes over the alternate screen. Install a mouse handler that keeps every upstream reporting decision and only re-encodes the wheel buttons as 64..67. Non-wheel reports pass through untouched, and the emitted bytes stay identical once upstream ships the same fix, so this can be dropped without a behavior change. Upstream: TerminalStudio/xterm.dart#238 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(terminal): correct the wheel report row, drop the wasted report build Address review feedback on the wheel button fix: - The X10/utf row was encoded as `32 + y + 1` while y is already 1-based, so every normal-mode report pointed one row too low and the `y > limit` guard disagreed with what it emitted. - Gate the wheel path on `mouseMode.reportScroll` and the button state instead of building and discarding a full report string from `defaultMouseHandler` on every scroll tick. This also makes the hardcoded SGR 'M' provably right, since a wheel release now returns before the report is built. - Derive the wire code as `id - 4` and drop `_wheelButtonId`, whose `default` branch was unreachable and defeated enum exhaustiveness. - Assign `mouseHandler` after construction so the `Terminal(...)` line stays untouched. Cover the utf, urxvt, null-byte overflow and click-only branches, and assert that TerminalModel actually installs the handler. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:xterm/xterm.dart';
|
||||
import 'input_modifier_utils.dart';
|
||||
import 'model.dart';
|
||||
import 'platform_model.dart';
|
||||
import 'terminal_mouse_handler.dart';
|
||||
|
||||
class TerminalModel with ChangeNotifier {
|
||||
final String id; // peer id
|
||||
@@ -129,6 +130,7 @@ class TerminalModel with ChangeNotifier {
|
||||
|
||||
TerminalModel(this.parent, [this.terminalId = 0]) : id = parent.id {
|
||||
terminal = Terminal(maxLines: 10000);
|
||||
terminal.mouseHandler = const WheelButtonFixMouseHandler();
|
||||
terminalController = TerminalController();
|
||||
|
||||
// Setup terminal callbacks
|
||||
|
||||
42
flutter/lib/models/terminal_mouse_handler.dart
Normal file
42
flutter/lib/models/terminal_mouse_handler.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:xterm/xterm.dart';
|
||||
|
||||
/// xterm 4.0.0 encodes wheel buttons as 68..71; the extra bit reads as a Shift
|
||||
/// modifier, so strict full-screen apps ignore the report and never scroll.
|
||||
/// Upstream fix: TerminalStudio/xterm.dart#238.
|
||||
class WheelButtonFixMouseHandler implements TerminalMouseHandler {
|
||||
const WheelButtonFixMouseHandler();
|
||||
|
||||
@override
|
||||
String? call(TerminalMouseEvent event) {
|
||||
if (!event.button.isWheel) {
|
||||
return defaultMouseHandler(event);
|
||||
}
|
||||
// Same gate as UpDownMouseHandler: only the scroll modes report a wheel,
|
||||
// and a wheel release is never reported, so the report is always a press.
|
||||
if (!event.state.mouseMode.reportScroll ||
|
||||
event.buttonState == TerminalMouseButtonState.up) {
|
||||
return null;
|
||||
}
|
||||
return _reportWheel(event);
|
||||
}
|
||||
|
||||
String _reportWheel(TerminalMouseEvent event) {
|
||||
// Wheel buttons 4..7 go on the wire as 64..67, but `id` is 64 + 4..7.
|
||||
final button = event.button.id - 4;
|
||||
final x = event.position.x + 1;
|
||||
final y = event.position.y + 1;
|
||||
switch (event.state.mouseReportMode) {
|
||||
case MouseReportMode.normal:
|
||||
case MouseReportMode.utf:
|
||||
final limit =
|
||||
event.state.mouseReportMode == MouseReportMode.normal ? 223 : 2015;
|
||||
final col = x > limit ? '\x00' : String.fromCharCode(32 + x);
|
||||
final row = y > limit ? '\x00' : String.fromCharCode(32 + y);
|
||||
return '\x1b[M${String.fromCharCode(32 + button)}$col$row';
|
||||
case MouseReportMode.sgr:
|
||||
return '\x1b[<$button;$x;${y}M';
|
||||
case MouseReportMode.urxvt:
|
||||
return '\x1b[${32 + button};$x;${y}M';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user