summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2021-08-24 22:36:25 +0200
committerAki <please@ignore.pl>2021-08-24 22:36:25 +0200
commite8cca7931236dd19fa3b10fed777826534f78224 (patch)
tree9e5e4c5d07f295ce6da6ae56cf5630cf207d159e
parent0f960c843721066ce5d73eb9d8716d47c05f375c (diff)
downloadclipfs-e8cca7931236dd19fa3b10fed777826534f78224.zip
clipfs-e8cca7931236dd19fa3b10fed777826534f78224.tar.gz
clipfs-e8cca7931236dd19fa3b10fed777826534f78224.tar.bz2
Wrapped the selection getter in a FUSE stub
-rw-r--r--Makefile5
-rw-r--r--clipfs.c121
2 files changed, 112 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index cfffd49..b2650af 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
CFLAGS += -Wall -Wextra -Wpedantic
-CFLAGS += `pkg-config --cflags xcb xcb-util xcb-icccm`
-LDLIBS += `pkg-config --libs xcb xcb-util xcb-icccm`
+CFLAGS += -DFUSE_USE_VERSION=31
+CFLAGS += `pkg-config --cflags fuse3 xcb xcb-util xcb-icccm`
+LDLIBS += `pkg-config --libs fuse3 xcb xcb-util xcb-icccm`
all: clipfs
diff --git a/clipfs.c b/clipfs.c
index 20e806a..427a8bc 100644
--- a/clipfs.c
+++ b/clipfs.c
@@ -1,41 +1,68 @@
+#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fuse3/fuse.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;
+struct selection
+{
+ uint32_t len;
+ char * data;
+};
+
+void update_selection(void);
+xcb_atom_t get_atom(xcb_connection_t *, const char *);
+int clip_getattr(const char *, struct stat *, struct fuse_file_info *);
+int clip_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
+int clip_open(const char *, struct fuse_file_info *);
+int clip_read(const char *, char *, size_t, off_t, struct fuse_file_info *);
const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
const uint32_t values[] = {1, XCB_EVENT_MASK_PROPERTY_CHANGE};
+const struct fuse_operations clip_ops = {
+ .getattr = clip_getattr,
+ .readdir = clip_readdir,
+ .open = clip_open,
+ .read = clip_read,
+};
+
+static xcb_connection_t * c;
+static xcb_screen_t * s;
+static xcb_window_t w;
+static struct selection x = {.len = 0, .data = NULL};
-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);
+ xcb_flush(c);
+ fuse_main(argc, argv, &clip_ops, NULL);
+ xcb_disconnect(c);
+}
+
+
+void update_selection(void)
+{
+ 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.
// 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?
+ int done = 0; // TODO: Look into continuous notifications and keeping the data somewhere?
while (!done)
{
e = xcb_wait_for_event(c);
- if (NULL == e) break;
+ if (NULL == e) return;
if (XCB_SELECTION_NOTIFY != XCB_EVENT_RESPONSE_TYPE(e))
{
free(e);
@@ -48,7 +75,11 @@ int main(int argc, char ** argv)
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);
+ x.data = realloc(x.data, prop.name_len);
+ if (NULL == x.data)
+ x.len = 0;
+ x.len = prop.name_len;
+ memcpy(x.data, prop.name, prop.name_len);
xcb_icccm_get_text_property_reply_wipe(&prop);
xcb_delete_property(c, n->requestor, n->property);
done = 1;
@@ -56,9 +87,9 @@ int main(int argc, char ** argv)
}
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);
@@ -67,3 +98,69 @@ xcb_atom_t get_atom(xcb_connection_t * c, const char * name)
free(reply);
return atom;
}
+
+
+int clip_getattr(const char * path, struct stat * st, struct fuse_file_info * fi)
+{
+ (void) fi;
+ update_selection(); // TODO: The content is updated way too often.
+ memset(st, 0, sizeof(struct stat));
+ if (0 == strcmp(path, "/"))
+ {
+ st->st_mode = S_IFDIR | 0755;
+ st->st_nlink = 2;
+ }
+ else if (0 == strcmp(path + 1, "primary"))
+ {
+ st->st_mode = S_IFREG | 0444;
+ st->st_nlink = 1;
+ st->st_size = x.len;
+ }
+ else
+ return -ENOENT;
+ return 0;
+}
+
+
+int clip_readdir(
+ const char * path, void * buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info * fi,
+ enum fuse_readdir_flags flags)
+{
+ (void) offset;
+ (void) fi;
+ (void) flags;
+ if (0 != strcmp(path, "/"))
+ return -ENOENT;
+ filler(buf, ".", NULL, 0, 0);
+ filler(buf, "..", NULL, 0, 0);
+ filler(buf, "primary", NULL, 0, 0);
+ return 0;
+}
+
+
+int clip_open(const char * path, struct fuse_file_info * fi)
+{
+ if (0 != strcmp(path + 1, "primary"))
+ return -ENOENT;
+ if (O_RDONLY != (fi->flags & O_ACCMODE))
+ return -EACCES;
+ return 0; // TODO: Maybe queue selection content retrieval here?
+}
+
+
+int clip_read(const char * path, char * buf, size_t size, off_t offset, struct fuse_file_info * fi)
+{
+ (void) fi;
+ if (0 != strcmp(path + 1, "primary"))
+ return -ENOENT;
+ update_selection(); // TODO: The content is updated way too often.
+ if (offset < x.len)
+ {
+ if (offset + size > x.len)
+ size = x.len - offset;
+ memcpy(buf, x.data + offset, size);
+ }
+ else
+ size = 0;
+ return size;
+}