From 233e881f95de8f6449e6d22904c55ec8e2192c24 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Tue, 24 Dec 2024 14:44:12 +0100 Subject: [PATCH] feat: add support for pasting from the native windows clipboard This give us OSC52 equivalent support on windows. closes #95 --- src/renderer/vaxis/renderer.zig | 24 ++++++++++++++++++++++++ src/tui/mainview.zig | 7 +++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/renderer/vaxis/renderer.zig b/src/renderer/vaxis/renderer.zig index 6e866ee..80bccb3 100644 --- a/src/renderer/vaxis/renderer.zig +++ b/src/renderer/vaxis/renderer.zig @@ -349,6 +349,30 @@ pub fn request_system_clipboard(self: *Self) void { self.vx.requestSystemClipboard(self.tty.anyWriter()) catch |e| log.logger(log_name).err("request_system_clipboard", e); } +pub fn request_windows_clipboard(self: *Self) ![]u8 { + const windows = std.os.windows; + const win32 = struct { + pub extern "user32" fn OpenClipboard(hWndNewOwner: ?windows.HWND) callconv(windows.WINAPI) windows.BOOL; + pub extern "user32" fn CloseClipboard() callconv(windows.WINAPI) windows.BOOL; + pub extern "user32" fn SetClipboardData(uFormat: windows.UINT, hMem: windows.HANDLE) callconv(windows.WINAPI) ?windows.HANDLE; + pub extern "user32" fn GetClipboardData(uFormat: windows.UINT) callconv(windows.WINAPI) ?windows.HANDLE; + pub extern "kernel32" fn GlobalLock(hMem: windows.HANDLE) ?windows.LPVOID; + pub extern "kernel32" fn GlobalUnlock(hMem: windows.HANDLE) windows.BOOL; + const CF_TEXT = @as(c_int, 1); + }; + + if (win32.OpenClipboard(null) == 0) + return error.OpenClipBoardFailed; + defer _ = win32.CloseClipboard(); + + const mem = win32.GetClipboardData(win32.CF_TEXT) orelse return error.ClipboardDataRetrievalFailed; + const data: [*c]u8 = @ptrCast(win32.GlobalLock(mem) orelse return error.ClipboardDataLockFailed); + const text = std.mem.span(data); + defer _ = win32.GlobalUnlock(mem); + + return self.allocator.dupe(u8, text); +} + pub fn request_mouse_cursor_text(self: *Self, push_or_pop: bool) void { if (push_or_pop) self.vx.setMouseShape(.text) else self.vx.setMouseShape(.default); } diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index b675ac8..e5d00e1 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -571,8 +571,11 @@ const cmds = struct { pub const open_previous_file_meta = .{ .description = "Open the previous file" }; pub fn system_paste(_: *Self, _: Ctx) Result { - if (builtin.os.tag == .windows) - return command.executeName("paste", .{}) catch {}; + if (builtin.os.tag == .windows) { + const text = try tui.current().rdr.request_windows_clipboard(); + defer tui.current().rdr.allocator.free(text); + return command.executeName("paste", command.fmt(.{text})) catch {}; + } tui.current().rdr.request_system_clipboard(); } pub const system_paste_meta = .{ .description = "Paste from system clipboard" };