From e0e2374c513c7d0519f2f8f1c41dcd66b182ef13 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Tue, 9 Nov 2021 10:44:33 -0800 Subject: [PATCH] isolate OS-specifics to separate files --- src/linux.zig | 97 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 100 +++--------------------------------------------- src/windows.zig | 6 +++ 3 files changed, 109 insertions(+), 94 deletions(-) create mode 100644 src/linux.zig create mode 100644 src/windows.zig diff --git a/src/linux.zig b/src/linux.zig new file mode 100644 index 0000000..6315172 --- /dev/null +++ b/src/linux.zig @@ -0,0 +1,97 @@ +const std = @import("std"); +const c = @cImport({ + @cInclude("limits.h"); + @cInclude("X11/Xlib.h"); + @cInclude("X11/extensions/Xfixes.h"); +}); + +fn printSelection(display: *c.Display, window: c.Window, bufname: [*c]const u8, fmtname: [*c]const u8, writer: anytype) !bool { + var ressize: c_ulong = undefined; + var restail: c_ulong = undefined; + var resbits: c_int = undefined; + var bufid = c.XInternAtom(display, bufname, c.False); + var fmtid = c.XInternAtom(display, fmtname, c.False); + var propid = c.XInternAtom(display, "XSEL_DATA", c.False); + var incrid = c.XInternAtom(display, "INCR", c.False); + var event: c.XEvent = undefined; + + _ = c.XSelectInput(display, window, c.PropertyChangeMask); + _ = c.XConvertSelection(display, bufid, fmtid, propid, window, c.CurrentTime); + _ = c.XNextEvent(display, &event); + while (event.type != c.SelectionNotify or event.xselection.selection != bufid) + _ = c.XNextEvent(display, &event); + + if (event.xselection.property > 0) { + var result: [*c]u8 = undefined; + _ = 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}); + + if (fmtid == incrid) { + ressize = 1; + while (ressize > 0) { + _ = c.XNextEvent(display, &event); + while (event.type != c.PropertyNotify or event.xproperty.atom != propid or event.xproperty.state != c.PropertyNewValue) { + _ = c.XNextEvent(display, &event); + } + + _ = c.XGetWindowProperty(display, window, propid, 0, c.LONG_MAX / 4, c.True, c.AnyPropertyType, &fmtid, &resbits, &ressize, &restail, &result); + defer _ = c.XFree(result); + try writer.print("{s}", .{result}); + } + } + return true; + } else // request failed, e.g. owner can't convert to the target format + return false; +} + +fn watch(display: *c.Display, window: c.Window, bufname: [*c]const u8, writer: anytype) !void { + var event_base: c_int = undefined; + var error_base: c_int = undefined; + var event: c.XEvent = undefined; + var bufid = c.XInternAtom(display, bufname, c.False); + + _ = c.XFixesQueryExtension(display, &event_base, &error_base); + _ = c.XFixesSelectSelectionInput(display, c.XDefaultRootWindow(display), bufid, c.XFixesSetSelectionOwnerNotifyMask); + + while (true) { + _ = c.XNextEvent(display, &event); + + // _ = try writer.print("{d} == {d} + {d}. {d} == {d}", .{ event.type, event_base, c.XFixesSelectionNotify, event.xselection.selection, bufid }); + // _ = std.debug.print("{}", .{event.xselection}); + + 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); + } + } +} + +pub fn clipboardAction() !void { + const stdout = std.io.getStdOut().writer(); + var display: *c.Display = c.XOpenDisplay(null).?; + defer _ = c.XCloseDisplay(display); + const default_screen = c.XDefaultScreen(display); + var color = c.XBlackPixel(display, default_screen); + var window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color); + defer _ = c.XDestroyWindow(display, window); + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = &gpa.allocator; + var args = std.process.args(); + defer args.deinit(); + while (args.next(allocator)) |arg_or_err| { + const arg = try arg_or_err; + defer allocator.free(arg); + if (std.mem.eql(u8, arg, "-w")) { + try watch(display, window, "CLIPBOARD", stdout); + } + } + var result = (try printSelection(display, window, "CLIPBOARD", "UTF8_STRING", stdout)) or + (try printSelection(display, window, "CLIPBOARD", "STRING", stdout)); + if (!result) return error.ClipboardActionFailed; +} diff --git a/src/main.zig b/src/main.zig index 8d96eb3..05282c6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,99 +1,11 @@ const std = @import("std"); -const c = @cImport({ - @cInclude("limits.h"); - @cInclude("X11/Xlib.h"); - @cInclude("X11/extensions/Xfixes.h"); -}); - -fn printSelection(display: *c.Display, window: c.Window, bufname: [*c]const u8, fmtname: [*c]const u8, writer: anytype) !bool { - var ressize: c_ulong = undefined; - var restail: c_ulong = undefined; - var resbits: c_int = undefined; - var bufid = c.XInternAtom(display, bufname, c.False); - var fmtid = c.XInternAtom(display, fmtname, c.False); - var propid = c.XInternAtom(display, "XSEL_DATA", c.False); - var incrid = c.XInternAtom(display, "INCR", c.False); - var event: c.XEvent = undefined; - - _ = c.XSelectInput(display, window, c.PropertyChangeMask); - _ = c.XConvertSelection(display, bufid, fmtid, propid, window, c.CurrentTime); - _ = c.XNextEvent(display, &event); - while (event.type != c.SelectionNotify or event.xselection.selection != bufid) - _ = c.XNextEvent(display, &event); - - if (event.xselection.property > 0) { - var result: [*c]u8 = undefined; - _ = 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}); - - if (fmtid == incrid) { - ressize = 1; - while (ressize > 0) { - _ = c.XNextEvent(display, &event); - while (event.type != c.PropertyNotify or event.xproperty.atom != propid or event.xproperty.state != c.PropertyNewValue) { - _ = c.XNextEvent(display, &event); - } - - _ = c.XGetWindowProperty(display, window, propid, 0, c.LONG_MAX / 4, c.True, c.AnyPropertyType, &fmtid, &resbits, &ressize, &restail, &result); - defer _ = c.XFree(result); - try writer.print("{s}", .{result}); - } - } - return true; - } else // request failed, e.g. owner can't convert to the target format - return false; -} - -fn watch(display: *c.Display, window: c.Window, bufname: [*c]const u8, writer: anytype) !void { - var event_base: c_int = undefined; - var error_base: c_int = undefined; - var event: c.XEvent = undefined; - var bufid = c.XInternAtom(display, bufname, c.False); - - _ = c.XFixesQueryExtension(display, &event_base, &error_base); - _ = c.XFixesSelectSelectionInput(display, c.XDefaultRootWindow(display), bufid, c.XFixesSetSelectionOwnerNotifyMask); - - while (true) { - _ = c.XNextEvent(display, &event); - - // _ = try writer.print("{d} == {d} + {d}. {d} == {d}", .{ event.type, event_base, c.XFixesSelectionNotify, event.xselection.selection, bufid }); - // _ = std.debug.print("{}", .{event.xselection}); - - 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); - } - } -} pub fn main() !u8 { - const stdout = std.io.getStdOut().writer(); - var display: *c.Display = c.XOpenDisplay(null).?; - defer _ = c.XCloseDisplay(display); - const default_screen = c.XDefaultScreen(display); - var color = c.XBlackPixel(display, default_screen); - var window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color); - defer _ = c.XDestroyWindow(display, window); - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - const allocator = &gpa.allocator; - var args = std.process.args(); - defer args.deinit(); - while (args.next(allocator)) |arg_or_err| { - const arg = try arg_or_err; - defer allocator.free(arg); - if (std.mem.eql(u8, arg, "-w")) { - try watch(display, window, "CLIPBOARD", stdout); - } + if (std.builtin.os.tag == .linux) { + @import("linux.zig").clipboardAction() catch return 1; } - var result = (try printSelection(display, window, "CLIPBOARD", "UTF8_STRING", stdout)) or - (try printSelection(display, window, "CLIPBOARD", "STRING", stdout)); - if (result) - return 0; - return 1; + if (std.builtin.os.tag == .windows) { + @import("windows.zig").clipboardAction() catch return 1; + } + return 0; } diff --git a/src/windows.zig b/src/windows.zig new file mode 100644 index 0000000..4694d06 --- /dev/null +++ b/src/windows.zig @@ -0,0 +1,6 @@ +const std = @import("std"); + +pub fn clipboardAction() !void { + const stdout = std.io.getStdOut().writer(); + try stdout.print("All your codebase are belong to us", .{}); +}