mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
OSC 52 clipboard write
This commit is contained in:
@ -594,6 +594,15 @@ pub fn handleMessage(self: *Window, msg: Message) !void {
|
||||
.cell_size => |size| try self.setCellSize(size),
|
||||
|
||||
.clipboard_read => |kind| try self.clipboardRead(kind),
|
||||
|
||||
.clipboard_write => |req| switch (req) {
|
||||
.small => |v| try self.clipboardWrite(v.data[0..v.len]),
|
||||
.stable => |v| try self.clipboardWrite(v),
|
||||
.alloc => |v| {
|
||||
defer v.alloc.free(v.data);
|
||||
try self.clipboardWrite(v.data);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,13 +617,14 @@ fn clipboardRead(self: *const Window, kind: u8) !void {
|
||||
// This must hold the base64 encoded data PLUS the OSC code surrounding it.
|
||||
const enc = std.base64.standard.Encoder;
|
||||
const size = enc.calcSize(data.len);
|
||||
var buf = try self.alloc.alloc(u8, size + 8); // 8 for OSC
|
||||
var buf = try self.alloc.alloc(u8, size + 9); // const for OSC
|
||||
defer self.alloc.free(buf);
|
||||
|
||||
// Wrap our data with the OSC code
|
||||
const prefix = try std.fmt.bufPrint(buf, "\x1b]52;{c};", .{kind});
|
||||
assert(prefix.len == 7);
|
||||
buf[buf.len - 1] = '\x1b';
|
||||
buf[buf.len - 2] = '\x1b';
|
||||
buf[buf.len - 1] = '\\';
|
||||
|
||||
// Do the base64 encoding
|
||||
const encoded = enc.encode(buf[prefix.len..], data);
|
||||
@ -627,6 +637,25 @@ fn clipboardRead(self: *const Window, kind: u8) !void {
|
||||
self.io_thread.wakeup.send() catch {};
|
||||
}
|
||||
|
||||
fn clipboardWrite(self: *const Window, data: []const u8) !void {
|
||||
const dec = std.base64.standard.Decoder;
|
||||
|
||||
// Build buffer
|
||||
const size = try dec.calcSizeForSlice(data);
|
||||
var buf = try self.alloc.allocSentinel(u8, size, 0);
|
||||
defer self.alloc.free(buf);
|
||||
buf[buf.len] = 0;
|
||||
|
||||
// Decode
|
||||
try dec.decode(buf, data);
|
||||
assert(buf[buf.len] == 0);
|
||||
|
||||
glfw.setClipboardString(buf) catch |err| {
|
||||
log.err("error setting clipboard string err={}", .{err});
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/// Change the cell size for the terminal grid. This can happen as
|
||||
/// a result of changing the font size at runtime.
|
||||
fn setCellSize(self: *Window, size: renderer.CellSize) !void {
|
||||
|
@ -829,6 +829,12 @@ const StreamHandler = struct {
|
||||
return;
|
||||
}
|
||||
|
||||
unreachable;
|
||||
// Write clipboard contents
|
||||
_ = self.window_mailbox.push(.{
|
||||
.clipboard_write = try Window.Message.WriteReq.init(
|
||||
self.alloc,
|
||||
data,
|
||||
),
|
||||
}, .{ .forever = {} });
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,14 @@
|
||||
const App = @import("../App.zig");
|
||||
const Window = @import("../Window.zig");
|
||||
const renderer = @import("../renderer.zig");
|
||||
const termio = @import("../termio.zig");
|
||||
|
||||
/// The message types that can be sent to a single window.
|
||||
pub const Message = union(enum) {
|
||||
/// Represents a write request. Magic number comes from the max size
|
||||
/// we want this union to be.
|
||||
pub const WriteReq = termio.MessageData(u8, 256);
|
||||
|
||||
/// Set the title of the window.
|
||||
/// TODO: we should change this to a "WriteReq" style structure in
|
||||
/// the termio message so that we can more efficiently send strings
|
||||
@ -15,6 +20,9 @@ pub const Message = union(enum) {
|
||||
|
||||
/// Read the clipboard and write to the pty.
|
||||
clipboard_read: u8,
|
||||
|
||||
/// Write the clipboard contents.
|
||||
clipboard_write: WriteReq,
|
||||
};
|
||||
|
||||
/// A window mailbox.
|
||||
|
Reference in New Issue
Block a user