summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2021-08-24 20:02:06 +0200
committerAki <please@ignore.pl>2021-08-24 20:02:06 +0200
commit0f960c843721066ce5d73eb9d8716d47c05f375c (patch)
tree282ef0ce82ae5406390916dafb9bf56053ac6316
downloadclipfs-0f960c843721066ce5d73eb9d8716d47c05f375c.zip
clipfs-0f960c843721066ce5d73eb9d8716d47c05f375c.tar.gz
clipfs-0f960c843721066ce5d73eb9d8716d47c05f375c.tar.bz2
Implemented program that reads X PRIMARY selection
Hopefully, this can act as a base for the FUSE.
-rw-r--r--.gitignore2
-rw-r--r--Makefile12
-rw-r--r--clipfs.c69
3 files changed, 83 insertions, 0 deletions
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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_util.h>
+
+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;
+}