feat(win32 gui): add direct copy to windows clipboard support

closes #100
This commit is contained in:
CJ van den Berg 2025-01-05 21:53:29 +01:00
parent ff04602d1c
commit 7cbd63accd
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
3 changed files with 40 additions and 11 deletions

View file

@ -350,18 +350,41 @@ 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(allocator: std.mem.Allocator) ![]u8 {
const win32 = struct {
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);
};
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 "user32" fn EmptyClipboard() windows.BOOL;
pub extern "kernel32" fn GlobalAlloc(flags: c_int, size: usize) ?windows.HANDLE;
pub extern "kernel32" fn GlobalFree(hMem: windows.HANDLE) windows.BOOL;
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);
const GMEM_MOVEABLE = @as(c_int, 2);
};
pub fn copy_to_windows_clipboard(text: []const u8) !void {
const mem = win32.GlobalAlloc(win32.GMEM_MOVEABLE, text.len + 1) orelse return error.GlobalAllocFalied;
const data: [*c]u8 = @ptrCast(win32.GlobalLock(mem) orelse return error.ClipboardDataLockFailed);
@memcpy(data[0..text.len], text);
data[text.len] = 0;
_ = win32.GlobalUnlock(mem);
if (win32.OpenClipboard(null) == 0) {
_ = win32.GlobalFree(mem);
return error.OpenClipBoardFailed;
}
defer _ = win32.CloseClipboard();
_ = win32.EmptyClipboard();
if (win32.SetClipboardData(win32.CF_TEXT, mem) == null) {
_ = win32.GlobalFree(mem);
}
}
pub fn request_windows_clipboard(allocator: std.mem.Allocator) ![]u8 {
if (win32.OpenClipboard(null) == 0)
return error.OpenClipBoardFailed;
defer _ = win32.CloseClipboard();

View file

@ -366,6 +366,7 @@ pub fn copy_to_system_clipboard(self: *Self, text: []const u8) void {
std.log.warn("TODO: copy_to_system_clipboard", .{});
}
pub const copy_to_windows_clipboard = @import("tuirenderer").copy_to_windows_clipboard;
pub const request_windows_clipboard = @import("tuirenderer").request_windows_clipboard;
pub fn request_mouse_cursor_text(self: *Self, push_or_pop: bool) void {

View file

@ -2163,7 +2163,12 @@ pub const Editor = struct {
if (self.clipboard) |old|
self.allocator.free(old);
self.clipboard = text;
tui.current().rdr.copy_to_system_clipboard(text);
if (builtin.os.tag == .windows) {
@import("renderer").copy_to_windows_clipboard(text) catch |e|
self.logger.print_err("clipboard", "failed to set clipboard: {any}", .{e});
} else {
tui.current().rdr.copy_to_system_clipboard(text);
}
}
fn copy_selection(root: Buffer.Root, sel: Selection, text_allocator: Allocator, metrics: Buffer.Metrics) ![]u8 {