about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.build.yml11
-rw-r--r--.gitignore2
-rw-r--r--COPYING24
-rw-r--r--LICENSE5
-rw-r--r--Makefile17
-rw-r--r--README.md45
-rw-r--r--build.zig29
-rw-r--r--clipnotify.c28
-rw-r--r--src/main.zig13
-rw-r--r--src/x11.zig14
-rw-r--r--src/xfixes.zig18
11 files changed, 142 insertions, 64 deletions
diff --git a/.build.yml b/.build.yml
new file mode 100644
index 0000000..500a409
--- /dev/null
+++ b/.build.yml
@@ -0,0 +1,11 @@
+image: archlinux
+packages:
+  - libx11
+  - libxfixes
+  - zig
+sources:
+  - https://git.sr.ht/~cnx/clipbuzz
+tasks:
+  - build: |
+      cd clipbuzz
+      zig build
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e73c965
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+zig-cache/
+zig-out/
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..68a49da
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index ea9256a..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,5 +0,0 @@
-This is free and unencumbered software released into the public domain.
-
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
-software, either in source code form or as a compiled binary, for any purpose,
-commercial or non-commercial, and by any means.
diff --git a/Makefile b/Makefile
deleted file mode 100644
index ae81666..0000000
--- a/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-PREFIX ?= /usr/local
-
-x11_bsd_flags = -I/usr/X11R6/include -L/usr/X11R6/lib
-
-all:
-	${CC} ${CFLAGS} ${LDFLAGS} clipnotify.c -o clipnotify $(x11_bsd_flags) -lX11 -lXfixes
-
-install: all
-	mkdir -p ${DESTDIR}${PREFIX}/bin
-	cp -f clipnotify ${DESTDIR}${PREFIX}/bin
-	chmod 755 ${DESTDIR}${PREFIX}/bin/clipnotify
-
-uninstall:
-	rm -f ${DESTDIR}${PREFIX}/bin/clipnotify
-
-clean:
-	rm -f *.o *~ clipnotify
diff --git a/README.md b/README.md
index f86ef96..ef1e63d 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,35 @@
-clipnotify is a simple program that, using the
-[XFIXES](https://cgit.freedesktop.org/xorg/proto/fixesproto/plain/fixesproto.txt)
-extension to X11, waits until a new selection is available and then exits.
+# clipbuzz
+`clipbuzz` is a simple program that uses the [X Fixes Extension]
+to wait until a new clipboard or primary selection is available and exit.
+It was translated from [clipnotify] in C to Zig, and is intended for use
+within a clipboard manager like [threa] to avoid polling for selections.
 
-It was primarily designed for [clipmenu](https://github.com/cdown/clipmenu), to
-avoid polling for new selections.
+## Installation
+`clipbuzz` depends on [Xlib] and an [implementation of Xfixes]
+and uses [Zig] build tool:
 
-Here's how it's intended to be used:
+```sh
+zig build install --prefix $PREFIX
+```
 
-    while clipnotify; do
-        [an event happened, do something with the selection]
-    done
+where `$PREFIX` is usually `$HOME/.local`, `/usr/local` or `/usr`
+depending on your preference.  The dependencies can usually be
+found in your operating system's repository, and if you are lucky,
+`clipbuzz` itself as well!
 
-clipnotify doesn't try to print anything about the contents of the selection,
-it just exits when it changes. This is intentional -- X11's selection API is
-verging on the insane, and there are plenty of others who have already lost
-their sanity to bring us xclip/xsel/etc. Use one of those tools to complement
-clipnotify.
+## Usage
+```sh
+while clipbuzz
+do # something with xclip or xsel
+done
+```
+
+## Copying
+This is free and unencumbered software released into the public domain.
+
+[X Fixes Extension]: https://gitlab.freedesktop.org/xorg/proto/fixesproto
+[clipnotify]: https://github.com/cdown/clipnotify
+[threa]: https://sr.ht/~cnx/threa
+[Xlib]: https://gitlab.freedesktop.org/xorg/lib/libx11
+[implementation of Xfixes]: https://github.com/Airblader/unclutter-xfixes
+[Zig]: https://ziglang.org
diff --git a/build.zig b/build.zig
new file mode 100644
index 0000000..a0ba02c
--- /dev/null
+++ b/build.zig
@@ -0,0 +1,29 @@
+const std = @import("std");
+
+pub fn build(b: *std.build.Builder) void {
+    const exe = b.addExecutable("clipbuzz", "src/main.zig");
+    exe.linkLibC();
+    exe.linkSystemLibrary("X11");
+    exe.linkSystemLibrary("Xfixes");
+
+    // Standard target options allows the person running `zig build` to choose
+    // what target to build for. Here we do not override the defaults, which
+    // means any target is allowed, and the default is native. Other options
+    // for restricting supported target set are available.
+    exe.setTarget(b.standardTargetOptions(.{}));
+
+    // Standard release options allow the person running `zig build` to select
+    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
+    exe.setBuildMode(b.standardReleaseOptions());
+
+    exe.install();
+
+    const run_cmd = exe.run();
+    run_cmd.step.dependOn(b.getInstallStep());
+    if (b.args) |args| {
+        run_cmd.addArgs(args);
+    }
+
+    const run_step = b.step("run", "Run the app");
+    run_step.dependOn(&run_cmd.step);
+}
diff --git a/clipnotify.c b/clipnotify.c
deleted file mode 100644
index f09583e..0000000
--- a/clipnotify.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xfixes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(void) {
-    Display *disp;
-    Window root;
-    Atom clip;
-    XEvent evt;
-
-    disp = XOpenDisplay(NULL);
-    if (!disp) {
-        fprintf(stderr, "Can't open X display\n");
-        exit(1);
-    }
-
-    root = DefaultRootWindow(disp);
-
-    clip = XInternAtom(disp, "CLIPBOARD", False);
-
-    XFixesSelectSelectionInput(disp, root, XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask);
-    XFixesSelectSelectionInput(disp, root, clip, XFixesSetSelectionOwnerNotifyMask);
-
-    XNextEvent(disp, &evt);
-    XCloseDisplay(disp);
-}
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 0000000..c5a23cc
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,13 @@
+const x11 = @import("x11.zig");
+
+pub fn main() anyerror!void {
+    const display = x11.openDisplay(null) orelse return error.SystemResources;
+    defer _ = x11.closeDisplay(display);
+
+    const root = x11.getDefaultRootWindow(display);
+    x11.getSelection(display, root, "PRIMARY");
+    x11.getSelection(display, root, "CLIPBOARD");
+
+    var event: x11.Event = undefined;
+    _ = x11.nextEvent(display, &event);
+}
diff --git a/src/x11.zig b/src/x11.zig
new file mode 100644
index 0000000..faea858
--- /dev/null
+++ b/src/x11.zig
@@ -0,0 +1,14 @@
+const xlib = @cImport({ @cInclude("X11/Xlib.h"); });
+pub const Atom = xlib.Atom;
+pub const Display = xlib.Display;
+pub const Event = xlib.XEvent;
+pub const False = xlib.False;
+pub const Window = xlib.Window;
+pub const closeDisplay = xlib.XCloseDisplay;
+pub const getAtom = xlib.XInternAtom;
+pub const getDefaultRootWindow = xlib.XDefaultRootWindow;
+pub const nextEvent = xlib.XNextEvent;
+pub const openDisplay = xlib.XOpenDisplay;
+
+const xfixes = @import("xfixes.zig");
+pub const getSelection = xfixes.getSelection;
diff --git a/src/xfixes.zig b/src/xfixes.zig
new file mode 100644
index 0000000..9eb8afc
--- /dev/null
+++ b/src/xfixes.zig
@@ -0,0 +1,18 @@
+const x11 = @import("x11.zig");
+const Atom = x11.Atom;
+const Display = x11.Display;
+const False = x11.False;
+const Window = x11.Window;
+const getAtom = x11.getAtom;
+
+const xfixes = @cImport({ @cInclude("X11/extensions/Xfixes.h"); });
+const SET_SELECTION_OWNER = xfixes.XFixesSetSelectionOwnerNotifyMask;
+
+extern fn XFixesSelectSelectionInput(display: *Display, window: Window,
+                                     selection: Atom, event_mask: c_ulong) void;
+
+pub fn getSelection(display: *Display, window: Window,
+                    selection: [*c]const u8) void {
+    const atom = getAtom(display, selection, False);
+    XFixesSelectSelectionInput(display, window, atom, SET_SELECTION_OWNER);
+}