diff options
-rw-r--r-- | clipfs.c | 68 |
1 files changed, 53 insertions, 15 deletions
@@ -16,6 +16,13 @@ struct selection xcb_atom_t atom; }; +enum Status +{ + STATUS_TARGETS, + STATUS_SELECTION, + STATUS_DONE, +}; + int get_selection_index(const char *); xcb_window_t find_owner(int); void update_selection(int); @@ -83,15 +90,20 @@ xcb_window_t find_owner(const int i) 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: Look into ways to support various TARGETS. + const xcb_atom_t PROPERTY = get_atom(c, "_RECEIVED_SELECTION"); // TODO: Get intern atoms beforehand. + const xcb_atom_t PNG = get_atom(c, "image/png"); + const xcb_atom_t JPG = get_atom(c, "image/jpg"); + const xcb_atom_t PIXMAP = get_atom(c, "PIXMAP"); // TODO: Format of this one depends on the application. + const xcb_atom_t UTF8_STRING = get_atom(c, "UTF8_STRING"); + const xcb_atom_t TARGETS = get_atom(c, "TARGETS"); // TODO-multiple: MULTIPLE? if (XCB_WINDOW_NONE == find_owner(i)) return; - xcb_convert_selection(c, w, x[i].atom, UTF8_STRING, TARGET_PROPERTY, XCB_CURRENT_TIME); + xcb_convert_selection(c, w, x[i].atom, TARGETS, PROPERTY, XCB_CURRENT_TIME); xcb_flush(c); + xcb_atom_t target = UTF8_STRING; xcb_generic_event_t * e; - int done = 0; // TODO: Look into continuous notifications. - while (!done) + int status = STATUS_TARGETS; // TODO: Look into continuous notifications. + while (STATUS_DONE != status) { e = xcb_wait_for_event(c); if (NULL == e) return; @@ -104,17 +116,42 @@ void update_selection(const int i) if (x[i].atom == n->selection && XCB_NONE != n->property) { xcb_get_property_cookie_t cookie = xcb_get_property( - c, 1, w, TARGET_PROPERTY, XCB_ATOM_ANY, 0, UINT32_MAX); + c, 1, w, PROPERTY, XCB_ATOM_ANY, 0, UINT32_MAX); xcb_get_property_reply_t * reply = xcb_get_property_reply(c, cookie, NULL); if (reply) { - const int len = xcb_get_property_value_length(reply); - x[i].data = realloc(x[i].data, len); - if (NULL == x[i].data) - x[i].len = 0; - x[i].len = len; - memcpy(x[i].data, xcb_get_property_value(reply), len); - done = 1; + const unsigned len = xcb_get_property_value_length(reply); + xcb_atom_t * atoms; + switch (status) + { + case STATUS_TARGETS: + atoms = (xcb_atom_t *) xcb_get_property_value(reply); + for (unsigned j = 0; j < len / sizeof(xcb_atom_t); ++j) + { // TODO: Find a way to get original format? + if (JPG != target && PNG == atoms[j]) + target = PNG; + if (JPG == atoms[j]) + target = JPG; + if (PNG != target && JPG != target && PIXMAP == atoms[j]) + target = PIXMAP; + } + xcb_convert_selection(c, w, x[i].atom, target, PROPERTY, XCB_CURRENT_TIME); + xcb_flush(c); + status = STATUS_SELECTION; + break; + case STATUS_SELECTION: + if (NULL == x[i].data && len != x[i].len) + x[i].data = realloc(x[i].data, len); + if (NULL == x[i].data) + x[i].len = 0; + x[i].len = len; + memcpy(x[i].data, xcb_get_property_value(reply), len); + status = STATUS_DONE; + break; + case STATUS_DONE: + default: + break; // Unreachable + } free(reply); } } @@ -175,10 +212,12 @@ int clip_readdir( int clip_open(const char * path, struct fuse_file_info * fi) { - if (-ENOENT == get_selection_index(path)) + const int i = get_selection_index(path); + if (-ENOENT == i) return -ENOENT; if (O_RDONLY != (fi->flags & O_ACCMODE)) return -EACCES; + update_selection(i); // TODO: The content is updated way too often. return 0; // TODO: Maybe queue selection content retrieval here? } @@ -189,7 +228,6 @@ int clip_read(const char * path, char * buf, size_t size, off_t offset, struct f const int i = get_selection_index(path); if (-ENOENT == i) return -ENOENT; - update_selection(i); // TODO: The content is updated way too often. if (offset < x[i].len) { if (offset + size > x[i].len) |