feat(terminal): add opt-in OSC 52 clipboard writes (#16072)

* feat(terminal): add opt-in OSC 52 clipboard writes

* Remove dup tr

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2026-09-05 13:21:49 +08:00
committed by GitHub
parent c1a587cfa4
commit 618bf37deb
68 changed files with 1279 additions and 119 deletions

View File

@@ -11,8 +11,38 @@ import 'input_modifier_utils.dart';
import 'model.dart';
import 'platform_model.dart';
import 'rustdesk_terminal.dart';
import 'terminal_copy_shortcut.dart';
import 'terminal_mouse_handler.dart';
bool canConfigureTerminalClipboardPermission({
required bool settingsDisabled,
required bool optionFixed,
}) =>
!settingsDisabled && !optionFixed;
bool canHandleTerminalClipboardWriteRequest({
required String localOption,
required bool canConfigurePermission,
}) =>
canConfigurePermission || localOption == kTerminalClipboardWriteAllowed;
TerminalClipboardWritePermission terminalClipboardWritePermission(
String localOption, {
required bool remoteClipboardEnabled,
bool canRequestConsent = true,
}) {
if (!remoteClipboardEnabled) {
return TerminalClipboardWritePermission.denied;
}
if (localOption == kTerminalClipboardWriteAllowed) {
return TerminalClipboardWritePermission.allowed;
}
if (localOption == kTerminalClipboardWriteUnconfigured && canRequestConsent) {
return TerminalClipboardWritePermission.unconfigured;
}
return TerminalClipboardWritePermission.denied;
}
class TerminalModel with ChangeNotifier {
final String id; // peer id
final FFI parent;
@@ -62,6 +92,9 @@ class TerminalModel with ChangeNotifier {
/// The listener (typically TerminalPage) can use this to auto-close the tab/page.
VoidCallback? onClosed;
ValueChanged<String>? onClipboardWriteBlocked;
ValueChanged<String>? onClipboardWriteSucceeded;
Future<void> _handleInput(String data) async {
// xterm can complete asynchronous input after the Flutter page has gone
// away. Stop before reading or clearing widget-owned modifier state.
@@ -130,7 +163,19 @@ class TerminalModel with ChangeNotifier {
}
TerminalModel(this.parent, [this.terminalId = 0]) : id = parent.id {
terminal = RustDeskTerminal(maxLines: 10000);
terminal = RustDeskTerminal(
maxLines: 10000,
onClipboardWrite: writeTerminalClipboard,
clipboardWritePermission: () => terminalClipboardWritePermission(
bind.mainGetLocalOption(key: kOptionAllowTerminalClipboardWrite),
remoteClipboardEnabled:
parent.ffiModel.permissions['clipboard'] != false,
canRequestConsent: onClipboardWriteBlocked != null,
),
onClipboardWriteBlocked: (text) => onClipboardWriteBlocked?.call(text),
onClipboardWriteSucceeded: (text) =>
onClipboardWriteSucceeded?.call(text),
);
terminal.mouseHandler = const WheelButtonFixMouseHandler();
terminalController = TerminalController();
@@ -593,6 +638,8 @@ class TerminalModel with ChangeNotifier {
clearAltLock = null;
onResizeExternal = null;
onClosed = null;
onClipboardWriteBlocked = null;
onClipboardWriteSucceeded = null;
// Clear buffers to free memory
_inputBuffer.clear();
_pendingOutputChunks.clear();