OSC 52 read

This commit is contained in:
Mitchell Hashimoto
2022-11-21 14:21:28 -08:00
parent 173aff1e80
commit f2a54bde42
4 changed files with 57 additions and 0 deletions

View File

@ -592,9 +592,41 @@ pub fn handleMessage(self: *Window, msg: Message) !void {
},
.cell_size => |size| try self.setCellSize(size),
.clipboard_read => |kind| try self.clipboardRead(kind),
}
}
fn clipboardRead(self: *const Window, kind: u8) !void {
const data = glfw.getClipboardString() catch |err| {
log.warn("error reading clipboard: {}", .{err});
return;
};
// Even if the clipboard data is empty we reply, since presumably
// the client app is expecting a reply. We first allocate our buffer.
// 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
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';
// Do the base64 encoding
const encoded = enc.encode(buf[prefix.len..], data);
assert(encoded.len == size);
_ = self.io_thread.mailbox.push(try termio.Message.writeReq(
self.alloc,
buf,
), .{ .forever = {} });
self.io_thread.wakeup.send() catch {};
}
/// 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 {

View File

@ -464,6 +464,12 @@ pub fn Stream(comptime Handler: type) type {
} else log.warn("unimplemented OSC callback: {}", .{cmd});
},
.clipboard_contents => |clip| {
if (@hasDecl(T, "clipboardContents")) {
try self.handler.clipboardContents(clip.kind, clip.data);
} else log.warn("unimplemented OSC callback: {}", .{cmd});
},
else => if (@hasDecl(T, "oscUnimplemented"))
try self.handler.oscUnimplemented(cmd)
else

View File

@ -815,4 +815,20 @@ const StreamHandler = struct {
.set_title = buf,
}, .{ .forever = {} });
}
pub fn clipboardContents(self: *StreamHandler, kind: u8, data: []const u8) !void {
// Note: we ignore the "kind" field and always use the primary clipboard.
// iTerm also appears to do this but other terminals seem to only allow
// certain. Let's investigate more.
// Get clipboard contents
if (data.len == 1 and data[0] == '?') {
_ = self.window_mailbox.push(.{
.clipboard_read = kind,
}, .{ .forever = {} });
return;
}
unreachable;
}
};

View File

@ -12,6 +12,9 @@ pub const Message = union(enum) {
/// Change the cell size.
cell_size: renderer.CellSize,
/// Read the clipboard and write to the pty.
clipboard_read: u8,
};
/// A window mailbox.