I am trying to be notified about any pointer motion. Since I don't want to run as the window manager, I need to set XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION
on all windows which I do both on startup and when I get a create notify event.
This seems to work fine in general and I receive motion notify events on all windows. However, somehow, this isn't true for Google Chrome windows. I checked the event mask by explicitly querying it afterwards and it is correctly set. I also don't see anything unusual in the propagation mask.
What could cause Google Chrome to not report motion notify events? AFAIK, the X protocol doesn't allow that except for active pointer grabs which Chrome surely doesn't have.
Here is how I register myself on all existing windows. I call register_events
on the root window and whenever I receive a create notify event as well:
static void register_events(xcb_window_t window) {
xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(connection,
window, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_LEAVE_WINDOW });
xcb_generic_error_t *error = xcb_request_check(connection, cookie);
if (error != NULL) {
xcb_disconnect(connection);
errx(EXIT_FAILURE, "could not subscribe to events on a window, bailing out");
}
}
static void register_existing_windows(void) {
xcb_query_tree_reply_t *reply;
if ((reply = xcb_query_tree_reply(connection, xcb_query_tree(connection, root), 0)) == NULL) {
return;
}
int len = xcb_query_tree_children_length(reply);
xcb_window_t *children = xcb_query_tree_children(reply);
for (int i = 0; i < len; i++) {
register_events(children[i]);
}
xcb_flush(connection);
free(reply);
}