diff options
-rw-r--r-- | .build.yml | 11 | ||||
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | COPYING | 24 | ||||
-rw-r--r-- | LICENSE | 5 | ||||
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | README.md | 45 | ||||
-rw-r--r-- | build.zig | 29 | ||||
-rw-r--r-- | clipnotify.c | 28 | ||||
-rw-r--r-- | src/main.zig | 13 | ||||
-rw-r--r-- | src/x11.zig | 14 | ||||
-rw-r--r-- | src/xfixes.zig | 18 |
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); +} |