[
  {
    "path": "LICENSE",
    "content": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or distribute this\nsoftware, either in source code form or as a compiled binary, for any purpose,\ncommercial or non-commercial, and by any means.\n"
  },
  {
    "path": "Makefile",
    "content": "PREFIX ?= /usr/local\n\nx11_bsd_flags = -I/usr/X11R6/include -L/usr/X11R6/lib\n\nall:\n\t${CC} ${CFLAGS} ${LDFLAGS} clipnotify.c -o clipnotify $(x11_bsd_flags) -lX11 -lXfixes\n\ninstall: all\n\tmkdir -p ${DESTDIR}${PREFIX}/bin\n\tcp -f clipnotify ${DESTDIR}${PREFIX}/bin\n\tchmod 755 ${DESTDIR}${PREFIX}/bin/clipnotify\n\nuninstall:\n\trm -f ${DESTDIR}${PREFIX}/bin/clipnotify\n\nclean:\n\trm -f *.o *~ clipnotify\n"
  },
  {
    "path": "README.md",
    "content": "clipnotify is a simple program that, using the\n[XFIXES](https://cgit.freedesktop.org/xorg/proto/fixesproto/plain/fixesproto.txt)\nextension to X11, waits until a new selection is available and then exits.\n\nIt was primarily designed for [clipmenu](https://github.com/cdown/clipmenu), to\navoid polling for new selections.\n\nHere's how it's intended to be used:\n\n    while read; do\n        [an event happened, do something with the selection]\n    done < <(clipnotify -l)\n\nOr:\n\n    while clipnotify; do\n        [an event happened, do something with the selection]\n    done\n\nclipnotify doesn't try to print anything about the contents of the selection,\nit just exits when it changes. This is intentional -- X11's selection API is\nverging on the insane, and there are plenty of others who have already lost\ntheir sanity to bring us xclip/xsel/etc. Use one of those tools to complement\nclipnotify.\n\nYou can choose a particular selection with `-s`, and loop instead of exiting\nwith `-l`. See `clipmenu -h` for more information.\n"
  },
  {
    "path": "clipnotify.c",
    "content": "#include <X11/Xatom.h>\n#include <X11/Xlib.h>\n#include <X11/extensions/Xfixes.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\nstatic enum selections {\n    NONE = 0,\n    SELECTION_CLIPBOARD = (1 << 0),\n    SELECTION_PRIMARY = (1 << 1),\n    SELECTION_SECONDARY = (1 << 2)\n} selections = NONE;\n\nstatic int loop;\n\nint main(int argc, char *argv[]) {\n    static const char *usage =\n        \"%s: Notify by exiting on clipboard events.\\n\\n\"\n        \"  -l    Instead of exiting, print a newline when a new selection is available.\\n\"\n        \"  -s    The selection to use. Available selections:\\n\"\n        \"        clipboard, primary, secondary\\n\"\n        \"        The default is to monitor clipboard and primary.\\n\";\n    Display *disp;\n    Window root;\n    Atom clip;\n    XEvent evt;\n    int opt;\n\n    while ((opt = getopt(argc, argv, \"hs:l\")) != -1) {\n        switch (opt) {\n            case 'h':\n                printf(usage, argv[0]);\n                return EXIT_SUCCESS;\n            case 'l':\n                loop = 1;\n                break;\n            case 's': {\n                char *token = strtok(optarg, \",\");\n                while (token != NULL) {\n                    if (strcmp(token, \"clipboard\") == 0) {\n                        selections |= SELECTION_CLIPBOARD;\n                    } else if (strcmp(token, \"primary\") == 0) {\n                        selections |= SELECTION_PRIMARY;\n                    } else if (strcmp(token, \"secondary\") == 0) {\n                        selections |= SELECTION_SECONDARY;\n                    } else {\n                        fprintf(stderr, \"Unknown selection '%s'\\n\", token);\n                        return EXIT_FAILURE;\n                    }\n                    token = strtok(NULL, \",\");\n                }\n                break;\n            }\n            default:\n                fprintf(stderr, usage, argv[0]);\n                return EXIT_FAILURE;\n        }\n    }\n\n    disp = XOpenDisplay(NULL);\n    if (!disp) {\n        fprintf(stderr, \"Can't open X display\\n\");\n        return EXIT_FAILURE;\n    }\n\n    root = DefaultRootWindow(disp);\n\n    clip = XInternAtom(disp, \"CLIPBOARD\", False);\n\n    /* <= 1.0.2 backwards compatibility */\n    if (!selections)\n        selections = SELECTION_CLIPBOARD | SELECTION_PRIMARY;\n\n    if (selections & SELECTION_CLIPBOARD)\n        XFixesSelectSelectionInput(disp, root, clip,\n                                   XFixesSetSelectionOwnerNotifyMask);\n    if (selections & SELECTION_PRIMARY)\n        XFixesSelectSelectionInput(disp, root, XA_PRIMARY,\n                                   XFixesSetSelectionOwnerNotifyMask);\n    if (selections & SELECTION_SECONDARY)\n        XFixesSelectSelectionInput(disp, root, XA_SECONDARY,\n                                   XFixesSetSelectionOwnerNotifyMask);\n\n    if (loop) {\n        (void)setvbuf(stdout, NULL, _IONBF, 0);\n        do {\n            XNextEvent(disp, &evt);\n            printf(\"\\n\");\n        } while (1);\n    } else {\n        XNextEvent(disp, &evt);\n    }\n    XCloseDisplay(disp);\n}\n"
  }
]