zig 0.9.0 and allocator passdown/separate clipboard common logic
This commit is contained in:
parent
69d7d0611e
commit
eb8058c930
28
src/clipboard.zig
Normal file
28
src/clipboard.zig
Normal file
|
@ -0,0 +1,28 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn clipboardChanged(allocator: std.mem.Allocator, contents: []const u8) !void {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena_allocator.deinit();
|
||||
const aa = arena_allocator.allocator();
|
||||
const clip_contents = try aa.dupe(u8, contents);
|
||||
defer aa.free(clip_contents);
|
||||
|
||||
// Dear lord, change this
|
||||
const key = [_]u8{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
};
|
||||
const in = [_]u8{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
var out: [16]u8 = undefined;
|
||||
var ctx = std.crypto.core.aes.Aes256.initEnc(key);
|
||||
ctx.encrypt(out[0..], in[0..]);
|
||||
// Do the work. We are assumed here to
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
const writer = stdout;
|
||||
try writer.print("{s}", .{clip_contents});
|
||||
}
|
||||
|
||||
test "full integration" {
|
||||
var allocator = std.testing.allocator;
|
||||
try clipboardChanged(allocator, "hello world");
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
const std = @import("std");
|
||||
const clip = @import("clipboard.zig");
|
||||
|
||||
const c = @cImport({
|
||||
@cInclude("limits.h");
|
||||
@cInclude("X11/Xlib.h");
|
||||
|
@ -9,7 +11,7 @@ pub fn main() !u8 {
|
|||
var watch = false;
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = &gpa.allocator;
|
||||
const allocator = gpa.allocator();
|
||||
var args = std.process.args();
|
||||
defer args.deinit();
|
||||
while (args.next(allocator)) |arg_or_err| {
|
||||
|
@ -20,12 +22,11 @@ pub fn main() !u8 {
|
|||
break;
|
||||
}
|
||||
}
|
||||
clipboardAction(watch) catch return 1;
|
||||
clipboardAction(allocator, watch) catch return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub fn clipboardAction(watch: bool) !void {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
pub fn clipboardAction(allocator: std.mem.Allocator, watch: bool) !void {
|
||||
var display: *c.Display = c.XOpenDisplay(null).?;
|
||||
defer _ = c.XCloseDisplay(display);
|
||||
const default_screen = c.XDefaultScreen(display);
|
||||
|
@ -33,13 +34,13 @@ pub fn clipboardAction(watch: bool) !void {
|
|||
var window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color);
|
||||
defer _ = c.XDestroyWindow(display, window);
|
||||
// Watch will not return
|
||||
if (watch) try watchClip(display, window, "CLIPBOARD", stdout);
|
||||
var result = (try printSelection(display, window, "CLIPBOARD", "UTF8_STRING", stdout)) or
|
||||
(try printSelection(display, window, "CLIPBOARD", "STRING", stdout));
|
||||
if (watch) try watchClip(allocator, display, window, "CLIPBOARD");
|
||||
var result = (try printSelection(allocator, display, window, "CLIPBOARD", "UTF8_STRING")) or
|
||||
(try printSelection(allocator, display, window, "CLIPBOARD", "STRING"));
|
||||
if (!result) return error.ClipboardActionFailed;
|
||||
}
|
||||
|
||||
fn watchClip(display: *c.Display, window: c.Window, bufname: [*c]const u8, writer: anytype) !void {
|
||||
fn watchClip(allocator: std.mem.Allocator, display: *c.Display, window: c.Window, bufname: [*c]const u8) !void {
|
||||
var event_base: c_int = undefined;
|
||||
var error_base: c_int = undefined;
|
||||
var event: c.XEvent = undefined;
|
||||
|
@ -54,14 +55,13 @@ fn watchClip(display: *c.Display, window: c.Window, bufname: [*c]const u8, write
|
|||
if (event.type == event_base + c.XFixesSelectionNotify and
|
||||
event.xselection.property == bufid)
|
||||
{
|
||||
_ = try writer.print("y", .{});
|
||||
if (!try printSelection(display, window, bufname, "UTF8_STRING", writer))
|
||||
_ = try printSelection(display, window, bufname, "STRING", writer);
|
||||
if (!try printSelection(allocator, display, window, bufname, "UTF8_STRING"))
|
||||
_ = try printSelection(allocator, display, window, bufname, "STRING");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn printSelection(display: *c.Display, window: c.Window, bufname: [*c]const u8, fmtname: [*c]const u8, writer: anytype) !bool {
|
||||
fn printSelection(allocator: std.mem.Allocator, display: *c.Display, window: c.Window, bufname: [*c]const u8, fmtname: [*c]const u8) !bool {
|
||||
var ressize: c_ulong = undefined;
|
||||
var restail: c_ulong = undefined;
|
||||
var resbits: c_int = undefined;
|
||||
|
@ -82,17 +82,15 @@ fn printSelection(display: *c.Display, window: c.Window, bufname: [*c]const u8,
|
|||
_ = c.XGetWindowProperty(display, window, propid, 0, c.LONG_MAX / 4, c.True, c.AnyPropertyType, &fmtid, &resbits, &ressize, &restail, &result);
|
||||
defer _ = c.XFree(result);
|
||||
if (fmtid != incrid)
|
||||
try writer.print("{s}", .{result});
|
||||
_ = async clip.clipboardChanged(allocator, std.mem.span(result)); // TODO: Ensure we don't start queueing these things up
|
||||
|
||||
if (fmtid == incrid) {
|
||||
ressize = 1;
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(&gpa.allocator);
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena_allocator.deinit();
|
||||
var buffer = std.ArrayList(u8).init(&arena_allocator.allocator);
|
||||
var local_allocator = arena_allocator.allocator();
|
||||
var buffer = std.ArrayList(u8).init(local_allocator);
|
||||
defer buffer.deinit();
|
||||
// try writer.print("BIG:", .{});
|
||||
while (ressize > 0) {
|
||||
_ = c.XNextEvent(display, &event);
|
||||
while (event.type != c.PropertyNotify or event.xproperty.atom != propid or event.xproperty.state != c.PropertyNewValue) {
|
||||
|
@ -101,9 +99,9 @@ fn printSelection(display: *c.Display, window: c.Window, bufname: [*c]const u8,
|
|||
|
||||
_ = c.XGetWindowProperty(display, window, propid, 0, c.LONG_MAX / 4, c.True, c.AnyPropertyType, &fmtid, &resbits, &ressize, &restail, &result);
|
||||
//defer _ = c.XFree(result); // Creates double free error, but not sure why
|
||||
try buffer.appendSlice(try std.fmt.allocPrint(&arena_allocator.allocator, "{s}", .{result}));
|
||||
try buffer.appendSlice(try std.fmt.allocPrint(local_allocator, "{s}", .{result}));
|
||||
}
|
||||
try writer.print("{s}", .{buffer.items});
|
||||
_ = async clip.clipboardChanged(allocator, buffer.items);
|
||||
}
|
||||
return true;
|
||||
} else // request failed, e.g. owner can't convert to the target format
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const clip = @import("clipboard.zig");
|
||||
const w = std.os.windows;
|
||||
|
||||
extern "user32" fn MessageBoxA(hWnd: ?w.HANDLE, lpText: ?w.LPCSTR, lpCaption: ?w.LPCSTR, uType: w.UINT) callconv(w.WINAPI) c_int;
|
||||
|
@ -76,7 +77,7 @@ extern "USER32" fn CreateWindowExA(
|
|||
hWndParent: ?w.HWND,
|
||||
hMenu: ?w.HMENU,
|
||||
hInstance: ?w.HINSTANCE,
|
||||
lpParam: ?*c_void,
|
||||
lpParam: ?*anyopaque,
|
||||
) callconv(w.WINAPI) ?w.HWND;
|
||||
|
||||
const WNDPROC = fn (
|
||||
|
@ -643,7 +644,7 @@ extern "KERNEL32" fn GlobalUnlock(
|
|||
|
||||
extern "KERNEL32" fn GlobalLock(
|
||||
hMem: isize,
|
||||
) callconv(w.WINAPI) ?*c_void;
|
||||
) callconv(w.WINAPI) ?*anyopaque;
|
||||
|
||||
const GLOBAL_ALLOC_FLAGS = enum(u32) {
|
||||
HND = 66,
|
||||
|
@ -951,6 +952,7 @@ pub export fn wWinMain(hInstance: w.HINSTANCE, hPrevInstance: ?w.HINSTANCE, lpCm
|
|||
if (hwnd == null)
|
||||
return 0;
|
||||
|
||||
UpdateContents(hwnd.?);
|
||||
// Run the message loop.
|
||||
|
||||
var msg: MSG = .{
|
||||
|
@ -974,7 +976,7 @@ pub export fn wWinMain(hInstance: w.HINSTANCE, hPrevInstance: ?w.HINSTANCE, lpCm
|
|||
}
|
||||
|
||||
fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) callconv(w.WINAPI) w.LRESULT { //APIENTRY {
|
||||
const allocator = &gpa.allocator;
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
switch (uMsg) {
|
||||
WM_PAINT => {
|
||||
|
@ -1035,7 +1037,6 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
},
|
||||
@enumToInt(CF_TEXT) => {
|
||||
_ = GetClientRect(hwnd, &rc);
|
||||
// TODO: copy our lpstr and ship it to our common handler
|
||||
_ = DrawTextA(hdc, contents, -1, &rc, DT_LEFT);
|
||||
},
|
||||
|
||||
|
@ -1089,25 +1090,7 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
}
|
||||
},
|
||||
WM_CLIPBOARDUPDATE => { // Message arrives only after AddClipboardFormatListener
|
||||
|
||||
// Get a lock on the clipboard
|
||||
if (OpenClipboard(hwnd) > 0) {
|
||||
defer _ = CloseClipboard();
|
||||
var hglb = GetClipboardData(uFormat).?;
|
||||
const hnd = @intCast(isize, @ptrToInt(hglb));
|
||||
var lpstr = GlobalLock(hnd).?;
|
||||
defer _ = GlobalUnlock(hnd);
|
||||
|
||||
if (free_contents) {
|
||||
allocator.free(contents);
|
||||
}
|
||||
free_contents = true;
|
||||
contents = std.fmt.allocPrintZ(allocator, "{s}", .{@ptrCast([*:0]const u8, lpstr)}) catch blk: {
|
||||
_ = MessageBoxA(hwnd, "Allocation failed copying clipboard contents", "Error", 0);
|
||||
free_contents = false;
|
||||
break :blk "";
|
||||
};
|
||||
}
|
||||
UpdateContents(hwnd);
|
||||
if (RedrawWindow(hwnd, null, null, RDW_INVALIDATE) != w.TRUE) {
|
||||
_ = MessageBoxA(hwnd, "Redraw failed", "Error", 0);
|
||||
}
|
||||
|
@ -1168,6 +1151,10 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
}
|
||||
},
|
||||
WM_DESTROY => {
|
||||
// remove last item before we go down
|
||||
if (free_contents) {
|
||||
allocator.free(contents);
|
||||
}
|
||||
_ = RemoveClipboardFormatListener(hwnd);
|
||||
_ = Shell_NotifyIconA(NIM_DELETE, &icon_data);
|
||||
PostQuitMessage(0);
|
||||
|
@ -1187,3 +1174,26 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn UpdateContents(hwnd: w.HWND) void {
|
||||
const allocator = gpa.allocator();
|
||||
// Get a lock on the clipboard
|
||||
if (OpenClipboard(hwnd) > 0) {
|
||||
defer _ = CloseClipboard();
|
||||
var hglb = GetClipboardData(uFormat).?;
|
||||
const hnd = @intCast(isize, @ptrToInt(hglb));
|
||||
var lpstr = GlobalLock(hnd).?;
|
||||
defer _ = GlobalUnlock(hnd);
|
||||
|
||||
if (free_contents) {
|
||||
allocator.free(contents);
|
||||
}
|
||||
free_contents = true;
|
||||
contents = std.fmt.allocPrintZ(allocator, "{s}", .{@ptrCast([*:0]const u8, lpstr)}) catch blk: {
|
||||
_ = MessageBoxA(hwnd, "Allocation failed copying clipboard contents", "Error", 0);
|
||||
free_contents = false;
|
||||
break :blk "";
|
||||
};
|
||||
}
|
||||
_ = async clip.clipboardChanged(allocator, contents); // Notify common handler
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user