如何获取XCB提供的所有剪贴板事件?

问题描述 投票:0回答:0

我目前正在开发一个跨主机剪贴板共享工具,可以共享文本、富文本或文件。 根据我目前所学,我已经知道需要处理哪些 X11 事件,但我无法听取它们。 我当前的代码我只能捕获选择文本的事件。

我想知道如何获得 ctrl+c 事件?

#include <QCoreApplication>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <xcb/xcb.h>

#include <xcb/xfixes.h>

/**
 *  Enumeration of standard X11 atom identifiers
 */
typedef enum std_x_atoms {
    /** The TARGETS atom identifier **/
    X_ATOM_TARGETS = 0,
    /** The MULTIPLE atom identifier **/
    X_ATOM_MULTIPLE,
    /** The TIMESTAMP atom identifier **/
    X_ATOM_TIMESTAMP,
    /** The INCR atom identifier **/
    X_ATOM_INCR,
    /** The CLIPBOARD atom identifier **/
    X_ATOM_CLIPBOARD,
    /** The UTF8_STRING atom identifier **/
    X_ATOM_UTF8_STRING,
    X_ATOM_XCLIPD,
    /** End marker sentinel **/
    X_ATOM_END
} std_x_atoms;

/**
 *  Union to simplify getting interned atoms from XCB
 */
typedef union atom_c {
    /** The atom **/
    xcb_atom_t atom;
    /** The cookie returned by xcb_intern_atom **/
    xcb_intern_atom_cookie_t cookie;
} atom_c;

/**
 *  The standard atom names. These values should match the
 *  std_x_atoms enumeration.
 */
const char * const g_std_atom_names[X_ATOM_END] = {
    "TARGETS", "MULTIPLE", "TIMESTAMP", "INCR",
    "CLIPBOARD", "UTF8_STRING", "XCLIPD"
};

atom_c std_atoms[X_ATOM_END];

/**
 *  \brief Interns the list of atoms
 *
 *  \param [in] xc The XCB connection.
 *  \param [out] atoms The location to store interned atoms.
 *  \param [in] atom_names The names of the atoms to intern.
 *  \param [in] number The number of atoms to intern.
 *  \return true iff all atoms were interned.
 */
static bool x11_intern_atoms(xcb_connection_t *xc, atom_c *atoms, const char * const *atom_names, int number) {
    for (int i = 0; i < number; i++) {
        atoms[i].cookie = xcb_intern_atom(xc, 0,
                                          strlen(atom_names[i]), atom_names[i]);
    }

    for (int i  = 0; i < number; i++) {
        xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xc,
                                         atoms[i].cookie, NULL);
        if (reply == NULL) {
            return false;
        }

        atoms[i].atom = reply->atom;
        free(reply); /* XCB: Do not use custom allocators */
    }

    return true;
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    xcb_connection_t    *c;
    xcb_screen_t        *screen;
    xcb_window_t         win;
    xcb_generic_event_t *e;
    uint32_t             mask = 0;
    uint32_t             values[2];

    /* Create the window */
    c = xcb_connect (NULL, NULL);
    screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
    if (!x11_intern_atoms(c, std_atoms, g_std_atom_names, X_ATOM_END))
        return 1;
//    xcb_flush (c);

    win = xcb_generate_id (c);
    mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    values[0] = screen->white_pixel;
    values[1] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;;
    xcb_create_window (c,                             /* Connection          */
                       XCB_COPY_FROM_PARENT,          /* depth               */
                       win,                           /* window Id           */
                       screen->root,                  /* parent window       */
                       0, 0,                          /* x, y                */
                       150, 150,                      /* width, height       */
                       10,                            /* border_width        */
                       XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                       screen->root_visual,           /* visual              */
                       mask, values);                 /* masks */

    xcb_map_window (c, win);
    xcb_flush (c);

    // init xfixes
    xcb_generic_error_t *error = 0;
    const xcb_query_extension_reply_t *reply = xcb_get_extension_data(c, &xcb_xfixes_id);
    if (!reply || !reply->present) {
        return -1;
    }
    xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(c,
                                                                                     XCB_XFIXES_MAJOR_VERSION,
                                                                                     XCB_XFIXES_MINOR_VERSION);
    xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (c,
                                                                                     xfixes_query_cookie, &error);
    if (!xfixes_query || error || xfixes_query->major_version < 2) {
        free(error);
    }
    free(xfixes_query);

    // delivers request
    mask =  XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE
            | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY
            | XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER;
    xcb_xfixes_select_selection_input_checked(c, win, XCB_ATOM_NONE, mask);

    xcb_flush(c);
    // recevie events
    uint response_type;
    while (e = xcb_wait_for_event(c)) {
        xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(e);
        printf("response_type = %d\n", response_type);
        response_type = notify_event->response_type & ~0x80;
        printf("response_type = %d\n", response_type);
        if (response_type == reply->first_event + XCB_XFIXES_SELECTION_NOTIFY) {
            printf("notify\n");
        } else {
            printf("code:%d\n", response_type);
        }
    }
    return a.exec();
}
c++ qt clipboard x11 xcb
© www.soinside.com 2019 - 2024. All rights reserved.