From 0f960c843721066ce5d73eb9d8716d47c05f375c Mon Sep 17 00:00:00 2001 From: Aki Date: Tue, 24 Aug 2021 20:02:06 +0200 Subject: Implemented program that reads X PRIMARY selection Hopefully, this can act as a base for the FUSE. --- .gitignore | 2 ++ Makefile | 12 +++++++++++ clipfs.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 clipfs.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c79fc1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +clipfs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cfffd49 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -Wall -Wextra -Wpedantic +CFLAGS += `pkg-config --cflags xcb xcb-util xcb-icccm` +LDLIBS += `pkg-config --libs xcb xcb-util xcb-icccm` + +all: clipfs + +clipfs: + +clean: + rm -f *.o clipfs + +.PHONY: all clean diff --git a/clipfs.c b/clipfs.c new file mode 100644 index 0000000..20e806a --- /dev/null +++ b/clipfs.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#include +#include +#include + +xcb_connection_t * c; +xcb_screen_t * s; +xcb_window_t w; + +const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; +const uint32_t values[] = {1, XCB_EVENT_MASK_PROPERTY_CHANGE}; + +xcb_atom_t get_atom(xcb_connection_t *, const char *); + +int main(int argc, char ** argv) +{ + (void) argc; + (void) argv; + c = xcb_connect(NULL, NULL); + s = xcb_setup_roots_iterator(xcb_get_setup(c)).data; + w = xcb_generate_id(c); + xcb_atom_t TARGET_PROPERTY = get_atom(c, "_TARGET_SELECTION"); + xcb_atom_t UTF8_STRING = get_atom(c, "UTF8_STRING"); // TODO: Actually, focus on "rawest" format at first. + xcb_create_window( + c, XCB_COPY_FROM_PARENT, w, s->root, 0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT, s->root_visual, mask, values); + // TODO-maybe: Look for the selection owner first? + xcb_convert_selection(c, w, XCB_ATOM_PRIMARY, UTF8_STRING, TARGET_PROPERTY, XCB_CURRENT_TIME); + xcb_flush(c); + xcb_generic_event_t * e; + int done = 0; // TODO: Look into continuous notifications? + while (!done) + { + e = xcb_wait_for_event(c); + if (NULL == e) break; + if (XCB_SELECTION_NOTIFY != XCB_EVENT_RESPONSE_TYPE(e)) + { + free(e); + continue; + } + xcb_selection_notify_event_t * n = (xcb_selection_notify_event_t *) e; + if (XCB_ATOM_PRIMARY == n->selection && XCB_NONE != n->property) + { + xcb_icccm_get_text_property_reply_t prop; + xcb_get_property_cookie_t cookie = xcb_icccm_get_text_property(c, n->requestor, n->property); + if (xcb_icccm_get_text_property_reply(c, cookie, &prop, NULL)) + { + printf("%.*s\n", prop.name_len, prop.name); + xcb_icccm_get_text_property_reply_wipe(&prop); + xcb_delete_property(c, n->requestor, n->property); + done = 1; + } + } + free(e); + } + xcb_disconnect(c); +} + +xcb_atom_t get_atom(xcb_connection_t * c, const char * name) +{ + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, 0, strlen(name), name); + xcb_intern_atom_reply_t * reply = xcb_intern_atom_reply(c, cookie, NULL); + xcb_atom_t atom = reply->atom; + free(reply); + return atom; +} -- cgit v1.1