summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2021-08-25 19:34:54 +0200
committerAki <please@ignore.pl>2021-08-25 19:34:54 +0200
commitb4ef9730e22e3232415c89ca288b6d3f1a7f5e4b (patch)
tree25c8abe369b482af450bf60480152303a305f440
parent28e585ad64855a098717ade41d26ac7c8c55246b (diff)
downloadclipfs-b4ef9730e22e3232415c89ca288b6d3f1a7f5e4b.zip
clipfs-b4ef9730e22e3232415c89ca288b6d3f1a7f5e4b.tar.gz
clipfs-b4ef9730e22e3232415c89ca288b6d3f1a7f5e4b.tar.bz2
Added naive support for remaining usual selections
-rw-r--r--clipfs.c68
1 files changed, 45 insertions, 23 deletions
diff --git a/clipfs.c b/clipfs.c
index 427a8bc..303defd 100644
--- a/clipfs.c
+++ b/clipfs.c
@@ -11,11 +11,14 @@
struct selection
{
+ const char * name;
uint32_t len;
char * data;
+ xcb_atom_t atom;
};
-void update_selection(void);
+int get_selection_index(const char *);
+void update_selection(int);
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);
@@ -34,7 +37,11 @@ const struct fuse_operations clip_ops = {
static xcb_connection_t * c;
static xcb_screen_t * s;
static xcb_window_t w;
-static struct selection x = {.len = 0, .data = NULL};
+static struct selection x[] = {
+ {.name = "primary", .len = 0, .data = NULL},
+ {.name = "secondary", .len = 0, .data = NULL},
+ {.name = "clipboard", .len = 0, .data = NULL},
+};
int main(int argc, char ** argv)
@@ -45,17 +52,29 @@ int main(int argc, char ** argv)
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);
+ x[0].atom = get_atom(c, "PRIMARY");
+ x[1].atom = get_atom(c, "PRIMARY"); // TODO: This is intentional until update can recognize missing selection.
+ x[2].atom = get_atom(c, "CLIPBOARD");
fuse_main(argc, argv, &clip_ops, NULL);
xcb_disconnect(c);
}
-void update_selection(void)
+int get_selection_index(const char * path)
+{
+ for (int i = 0; i < 3; ++i)
+ if (0 == strcmp(path + 1, x[i].name))
+ return i;
+ return -ENOENT;
+}
+
+
+void update_selection(const int i)
{
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_convert_selection(c, w, x[i].atom, UTF8_STRING, TARGET_PROPERTY, XCB_CURRENT_TIME);
xcb_flush(c);
xcb_generic_event_t * e;
int done = 0; // TODO: Look into continuous notifications and keeping the data somewhere?
@@ -69,17 +88,17 @@ void update_selection(void)
continue;
}
xcb_selection_notify_event_t * n = (xcb_selection_notify_event_t *) e;
- if (XCB_ATOM_PRIMARY == n->selection && XCB_NONE != n->property)
+ if (x[i].atom == 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))
{
- 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);
+ x[i].data = realloc(x[i].data, prop.name_len);
+ if (NULL == x[i].data)
+ x[i].len = 0;
+ x[i].len = prop.name_len;
+ memcpy(x[i].data, prop.name, prop.name_len);
xcb_icccm_get_text_property_reply_wipe(&prop);
xcb_delete_property(c, n->requestor, n->property);
done = 1;
@@ -103,21 +122,22 @@ xcb_atom_t get_atom(xcb_connection_t * c, const char * name)
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"))
+ else
{
+ const int i = get_selection_index(path);
+ if (-ENOENT == i)
+ return -ENOENT;
+ update_selection(i); // TODO: The content is updated way too often.
st->st_mode = S_IFREG | 0444;
st->st_nlink = 1;
- st->st_size = x.len;
+ st->st_size = x[i].len;
}
- else
- return -ENOENT;
return 0;
}
@@ -133,14 +153,15 @@ int clip_readdir(
return -ENOENT;
filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0, 0);
- filler(buf, "primary", NULL, 0, 0);
+ for (int i = 0; i < 3; ++i)
+ filler(buf, x[i].name, NULL, 0, 0);
return 0;
}
int clip_open(const char * path, struct fuse_file_info * fi)
{
- if (0 != strcmp(path + 1, "primary"))
+ if (-ENOENT == get_selection_index(path))
return -ENOENT;
if (O_RDONLY != (fi->flags & O_ACCMODE))
return -EACCES;
@@ -151,14 +172,15 @@ int clip_open(const char * path, struct fuse_file_info * fi)
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"))
+ const int i = get_selection_index(path);
+ if (-ENOENT == i)
return -ENOENT;
- update_selection(); // TODO: The content is updated way too often.
- if (offset < x.len)
+ update_selection(i); // TODO: The content is updated way too often.
+ if (offset < x[i].len)
{
- if (offset + size > x.len)
- size = x.len - offset;
- memcpy(buf, x.data + offset, size);
+ if (offset + size > x[i].len)
+ size = x[i].len - offset;
+ memcpy(buf, x[i].data + offset, size);
}
else
size = 0;