mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
Change copy-on-select behavior to be more idiomatic for Linux
Fixes #2345 The new docs for `copy-on-select`: Whether to automatically copy selected text to the clipboard. `true` will prefer to copy to the selection clipboard if supported by the OS, otherwise it will copy to the system clipboard. The value `clipboard` will always copy text to the system clipboard (for supported systems) as well as the system clipboard. This is sometimes a preferred behavior on Linux. Middle-click paste will always use the selection clipboard on Linux and the system clipboard on macOS. Middle-click paste is always enabled even if this is `false`. The default value is true on Linux and false on macOS. macOS copy on select behavior is not typical for applications so it is disabled by default. On Linux, this is a standard behavior so it is enabled by default.
This commit is contained in:
@ -1176,12 +1176,8 @@ fn setSelection(self: *Surface, sel_: ?terminal.Selection) !void {
|
||||
const prev_ = self.io.terminal.screen.selection;
|
||||
try self.io.terminal.screen.select(sel_);
|
||||
|
||||
// Determine the clipboard we want to copy selection to, if it is enabled.
|
||||
const clipboard: apprt.Clipboard = switch (self.config.copy_on_select) {
|
||||
.false => return,
|
||||
.true => .selection,
|
||||
.clipboard => .standard,
|
||||
};
|
||||
// If copy on select is false then exit early.
|
||||
if (self.config.copy_on_select == .false) return;
|
||||
|
||||
// Set our selection clipboard. If the selection is cleared we do not
|
||||
// clear the clipboard. If the selection is set, we only set the clipboard
|
||||
@ -1190,12 +1186,6 @@ fn setSelection(self: *Surface, sel_: ?terminal.Selection) !void {
|
||||
const sel = sel_ orelse return;
|
||||
if (prev_) |prev| if (sel.eql(prev)) return;
|
||||
|
||||
// Check if our runtime supports the selection clipboard at all.
|
||||
// We can save a lot of work if it doesn't.
|
||||
if (!self.rt_surface.supportsClipboard(clipboard)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const buf = self.io.terminal.screen.selectionString(self.alloc, .{
|
||||
.sel = sel,
|
||||
.trim = self.config.clipboard_trim_trailing_spaces,
|
||||
@ -1205,10 +1195,45 @@ fn setSelection(self: *Surface, sel_: ?terminal.Selection) !void {
|
||||
};
|
||||
defer self.alloc.free(buf);
|
||||
|
||||
self.rt_surface.setClipboardString(buf, clipboard, false) catch |err| {
|
||||
log.err("error setting clipboard string err={}", .{err});
|
||||
return;
|
||||
};
|
||||
// Set the clipboard. This is not super DRY but it is clear what
|
||||
// we're doing for each setting without being clever.
|
||||
switch (self.config.copy_on_select) {
|
||||
.false => unreachable, // handled above with an early exit
|
||||
|
||||
// Both standard and selection clipboards are set.
|
||||
.clipboard => {
|
||||
const clipboards: []const apprt.Clipboard = &.{ .standard, .selection };
|
||||
for (clipboards) |clipboard| self.rt_surface.setClipboardString(
|
||||
buf,
|
||||
clipboard,
|
||||
false,
|
||||
) catch |err| {
|
||||
log.err(
|
||||
"error setting clipboard string clipboard={} err={}",
|
||||
.{ clipboard, err },
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
// The selection clipboard is set if supported, otherwise the standard.
|
||||
.true => {
|
||||
const clipboard: apprt.Clipboard = if (self.rt_surface.supportsClipboard(.selection))
|
||||
.selection
|
||||
else
|
||||
.standard;
|
||||
|
||||
self.rt_surface.setClipboardString(
|
||||
buf,
|
||||
clipboard,
|
||||
false,
|
||||
) catch |err| {
|
||||
log.err(
|
||||
"error setting clipboard string clipboard={} err={}",
|
||||
.{ clipboard, err },
|
||||
);
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the cell size for the terminal grid. This can happen as
|
||||
@ -2680,19 +2705,11 @@ pub fn mouseButtonCallback(
|
||||
|
||||
// Middle-click pastes from our selection clipboard
|
||||
if (button == .middle and action == .press) {
|
||||
if (comptime builtin.target.isDarwin()) {
|
||||
// Fast-path for MacOS - always paste from clipboard on
|
||||
// middle-click.
|
||||
try self.startClipboardRequest(.standard, .{ .paste = {} });
|
||||
} else if (self.config.copy_on_select != .false) {
|
||||
const clipboard: apprt.Clipboard = switch (self.config.copy_on_select) {
|
||||
.true => .selection,
|
||||
.clipboard => .standard,
|
||||
.false => unreachable,
|
||||
};
|
||||
|
||||
try self.startClipboardRequest(clipboard, .{ .paste = {} });
|
||||
}
|
||||
const clipboard: apprt.Clipboard = if (self.rt_surface.supportsClipboard(.selection))
|
||||
.selection
|
||||
else
|
||||
.standard;
|
||||
try self.startClipboardRequest(clipboard, .{ .paste = {} });
|
||||
}
|
||||
|
||||
// Right-click down selects word for context menus. If the apprt
|
||||
|
@ -1114,15 +1114,27 @@ keybind: Keybinds = .{},
|
||||
/// limit per surface is double.
|
||||
@"image-storage-limit": u32 = 320 * 1000 * 1000,
|
||||
|
||||
/// Whether to automatically copy selected text to the clipboard. `true` will
|
||||
/// only copy on systems that support a selection clipboard.
|
||||
/// Whether to automatically copy selected text to the clipboard. `true`
|
||||
/// will prefer to copy to the selection clipboard if supported by the
|
||||
/// OS, otherwise it will copy to the system clipboard.
|
||||
///
|
||||
/// The value `clipboard` will copy to the system clipboard, making this work on
|
||||
/// macOS. Note that middle-click will also paste from the system clipboard in
|
||||
/// this case.
|
||||
/// The value `clipboard` will always copy text to the selection clipboard
|
||||
/// (for supported systems) as well as the system clipboard. This is sometimes
|
||||
/// a preferred behavior on Linux.
|
||||
///
|
||||
/// Note that if this is disabled, middle-click paste will also be disabled.
|
||||
@"copy-on-select": CopyOnSelect = .true,
|
||||
/// Middle-click paste will always use the selection clipboard on Linux
|
||||
/// and the system clipboard on macOS. Middle-click paste is always enabled
|
||||
/// even if this is `false`.
|
||||
///
|
||||
/// The default value is true on Linux and false on macOS. macOS copy on
|
||||
/// select behavior is not typical for applications so it is disabled by
|
||||
/// default. On Linux, this is a standard behavior so it is enabled by
|
||||
/// default.
|
||||
@"copy-on-select": CopyOnSelect = switch (builtin.os.tag) {
|
||||
.linux => .true,
|
||||
.macos => .false,
|
||||
else => .false,
|
||||
},
|
||||
|
||||
/// The time in milliseconds between clicks to consider a click a repeat
|
||||
/// (double, triple, etc.) or an entirely new single click. A value of zero will
|
||||
@ -4326,7 +4338,8 @@ pub const CopyOnSelect = enum {
|
||||
/// This is not supported on platforms such as macOS. This is the default.
|
||||
true,
|
||||
|
||||
/// Copy on select is enabled and goes to the system clipboard.
|
||||
/// Copy on select is enabled and goes to both the system clipboard
|
||||
/// and the selection clipboard (for Linux).
|
||||
clipboard,
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user