apprt: primary clipboard awareness (selection clipboard)

This commit is contained in:
Mitchell Hashimoto
2023-08-09 13:41:22 -07:00
parent 232bffe338
commit f3996ff0f8
4 changed files with 35 additions and 15 deletions

View File

@ -601,11 +601,11 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
.clipboard_read => |kind| try self.clipboardRead(kind), .clipboard_read => |kind| try self.clipboardRead(kind),
.clipboard_write => |req| switch (req) { .clipboard_write => |req| switch (req) {
.small => |v| try self.clipboardWrite(v.data[0..v.len]), .small => |v| try self.clipboardWrite(v.data[0..v.len], .standard),
.stable => |v| try self.clipboardWrite(v), .stable => |v| try self.clipboardWrite(v, .standard),
.alloc => |v| { .alloc => |v| {
defer v.alloc.free(v.data); defer v.alloc.free(v.data);
try self.clipboardWrite(v.data); try self.clipboardWrite(v.data, .standard);
}, },
}, },
@ -725,7 +725,7 @@ fn clipboardRead(self: *const Surface, kind: u8) !void {
return; return;
} }
const data = self.rt_surface.getClipboardString() catch |err| { const data = self.rt_surface.getClipboardString(.standard) catch |err| {
log.warn("error reading clipboard: {}", .{err}); log.warn("error reading clipboard: {}", .{err});
return; return;
}; };
@ -755,7 +755,7 @@ fn clipboardRead(self: *const Surface, kind: u8) !void {
self.io_thread.wakeup.notify() catch {}; self.io_thread.wakeup.notify() catch {};
} }
fn clipboardWrite(self: *const Surface, data: []const u8) !void { fn clipboardWrite(self: *const Surface, data: []const u8, loc: apprt.Clipboard) !void {
if (!self.config.clipboard_write) { if (!self.config.clipboard_write) {
log.info("application attempted to write clipboard, but 'clipboard-write' setting is off", .{}); log.info("application attempted to write clipboard, but 'clipboard-write' setting is off", .{});
return; return;
@ -773,7 +773,7 @@ fn clipboardWrite(self: *const Surface, data: []const u8) !void {
try dec.decode(buf, data); try dec.decode(buf, data);
assert(buf[buf.len] == 0); assert(buf[buf.len] == 0);
self.rt_surface.setClipboardString(buf) catch |err| { self.rt_surface.setClipboardString(buf, loc) catch |err| {
log.err("error setting clipboard string err={}", .{err}); log.err("error setting clipboard string err={}", .{err});
return; return;
}; };
@ -1972,7 +1972,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !void
}; };
defer self.alloc.free(buf); defer self.alloc.free(buf);
self.rt_surface.setClipboardString(buf) catch |err| { self.rt_surface.setClipboardString(buf, .standard) catch |err| {
log.err("error setting clipboard string err={}", .{err}); log.err("error setting clipboard string err={}", .{err});
return; return;
}; };
@ -1980,7 +1980,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !void
}, },
.paste_from_clipboard => { .paste_from_clipboard => {
const data = self.rt_surface.getClipboardString() catch |err| { const data = self.rt_surface.getClipboardString(.standard) catch |err| {
log.warn("error reading clipboard: {}", .{err}); log.warn("error reading clipboard: {}", .{err});
return; return;
}; };

View File

@ -913,9 +913,11 @@ pub const Surface = struct {
// )); // ));
} }
pub fn getClipboardString(self: *Surface) ![:0]const u8 { pub fn getClipboardString(
const clipboard = c.gtk_widget_get_clipboard(@ptrCast(self.gl_area)); self: *Surface,
clipboard_type: apprt.Clipboard,
) ![:0]const u8 {
const clipboard = getClipboard(@ptrCast(self.gl_area), clipboard_type);
const content = c.gdk_clipboard_get_content(clipboard) orelse { const content = c.gdk_clipboard_get_content(clipboard) orelse {
// On my machine, this NEVER works, so we fallback to glfw's // On my machine, this NEVER works, so we fallback to glfw's
// implementation... // implementation...
@ -933,12 +935,22 @@ pub const Surface = struct {
return std.mem.sliceTo(ptr, 0); return std.mem.sliceTo(ptr, 0);
} }
pub fn setClipboardString(self: *const Surface, val: [:0]const u8) !void { pub fn setClipboardString(
const clipboard = c.gtk_widget_get_clipboard(@ptrCast(self.gl_area)); self: *const Surface,
val: [:0]const u8,
clipboard_type: apprt.Clipboard,
) !void {
const clipboard = getClipboard(@ptrCast(self.gl_area), clipboard_type);
c.gdk_clipboard_set_text(clipboard, val.ptr); c.gdk_clipboard_set_text(clipboard, val.ptr);
} }
fn getClipboard(widget: *c.GtkWidget, clipboard: apprt.Clipboard) ?*c.GdkClipboard {
return switch (clipboard) {
.standard => c.gtk_widget_get_clipboard(widget),
.selection => c.gtk_widget_get_primary_clipboard(widget),
};
}
pub fn getCursorPos(self: *const Surface) !apprt.CursorPos { pub fn getCursorPos(self: *const Surface) !apprt.CursorPos {
return self.cursor_pos; return self.cursor_pos;
} }

View File

@ -23,3 +23,11 @@ pub const IMEPos = struct {
x: f64, x: f64,
y: f64, y: f64,
}; };
/// The clipboard type.
///
/// If this is changed, you must also update ghostty.h
pub const Clipboard = enum(u1) {
standard = 0, // ctrl+c/v
selection = 1, // also known as the "primary" clipboard
};

View File

@ -1417,7 +1417,7 @@ const StreamHandler = struct {
} }
pub fn clipboardContents(self: *StreamHandler, kind: u8, data: []const u8) !void { pub fn clipboardContents(self: *StreamHandler, kind: u8, data: []const u8) !void {
// Note: we ignore the "kind" field and always use the primary clipboard. // Note: we ignore the "kind" field and always use the standard clipboard.
// iTerm also appears to do this but other terminals seem to only allow // iTerm also appears to do this but other terminals seem to only allow
// certain. Let's investigate more. // certain. Let's investigate more.