简体   繁体   中英

XCB get all root events

I'm writing an xcb app that tooks all root events. I wrote this code:

#include <stdio.h>
#include <stdlib.h>

#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>

int main(void) {
    xcb_connection_t *connection = xcb_connect(NULL, NULL);
    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
    xcb_generic_event_t *event;

    const uint32_t values[] = {
        XCB_EVENT_MASK_BUTTON_PRESS
    };

    xcb_change_window_attributes(connection, screen->root, XCB_CW_EVENT_MASK, values);
    xcb_aux_sync(connection);
    xcb_flush(connection);

    while ((event = xcb_wait_for_event(connection))) {
        switch (event->response_type & ~0x80) {
            case XCB_EXPOSE: {
                puts("expose");
                break;
            }
            case XCB_BUTTON_PRESS: {
                puts("mouse clicked");
                break;
            }
        }
        free(event);
    }

    xcb_disconnect(connection);

    return 0;
}

But this doesn't work if I need to get events on DISPLAY:0, how can I do this? If I try to check what xcb_poll_for_event returns, it returns NULL because another window manager is running, so I need to get access to the running wm.

xcb_poll_for_event is the non-blocking alternative to xcb_wait_for_event . The difference is that it returns NULL if there are no queued events, while xcb_wait_for_event blocks until an event is received. If you are calling xcb_poll_for_event , a return value of NULL is not (at least directly) because another window manager is running. If your code does not need to run code outside of the event loop once the event loop has started, you might be looking for xcb_wait_for_event . Otherwise, continuing with xcb_poll_for_event , you will want to continue to poll for events until you receive the events you are interested in (ignoring NULL return values).

From my understanding of the XCB and Xlib documentation, it is possible that the window manager could be preventing your client from receiving button press events by setting the XCB_CW_DONT_PROPAGATE mask. This might cause your client to not be able to receive button press events on the root window. The window manager registering to receive button press events on the root window shouldn't stop your client from receiving these same button press events unless XCB_CW_DONT_PROPAGATE is indeed set.

While in your code example you are only registering for the XCB_BUTTON_PRESS event mask, your question says you want to receive all events on the root window. This is not fully possible when another window manager is running: an X window manager is, by definition, the one client that can register for substructure redirection on the root window (this is not unique to the root window; only one client can register for substructure redirection on any window). Substructure redirection is required for your client to receive the following events on the root window:

  • XCB_CIRCULATE_REQUEST
  • XCB_CONFIGURE_REQUEST
  • XCB_MAP_REQUEST

However, to my knowledge, your client should be able to receive all other events that the window manager has not restricted the generation or propagation of. If you wish for your client to all events by becoming a window manager, then you can register for the XCB_SUBSTRUCTURE_REDIRECT and XCB_SUBSTRUCTURE_NOTIFY event masks on the root window yourself.

Do note, however, that if your client is not the first to attempt to register for substructure redirection on the root window it will not be granted substructure redirection. A typical window manager will crash in response to not being granted substructure redirection on the root window, printing a message explaining that another window manager is running.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM