#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; }