Note: This is a continuation of the answer to What process created this X11 window? from unix.stackexchange. That answer mentions XResQueryClientIds
from X-Resource v1.2 extension. I'd like to know how to use it.
How can I use python's xcffib module to find all X11 window IDs associated with a provided PID (assuming no race conditions; windows or processes aren't being created or destroyed).
I don't know much about X11, the XCB API documentation seems incomplete, and the auto-generated xcffib python bindings are undocumented. From what I gather, I need:
xcb_connect
xcb_get_extension_data
mentions "?QueryExtension requests"xcb_get_extension_data
assuming no race conditions; windows or processes aren't being created or destroyed
Assuming is bad if you know that the assumption doesn't hold. Luckily, you don't need this assumption. Just use xcb_grab_server
and xcb_ungrab_server
around your operations and this won't be an issue.
Now, as for XResQueryClientIds
, you can actually just type in man xcb_res_query_client_ids
. XCB just provides this, no need to actually query the extension. Here's a sample program. Compile it with gcc -lxcb -lxcb-res main.c
and then execute it by passing a window ID as the only argument (e.g., ./a.out 0x2c00004
).
#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/res.h>
int main(int argc, char *argv[]) {
int screen;
xcb_connection_t *conn = xcb_connect(NULL, &screen);
xcb_res_client_id_spec_t spec = {0};
spec.client = strtol(argv[1], NULL, 0);
spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
xcb_generic_error_t *err = NULL;
xcb_res_query_client_ids_cookie_t cookie = xcb_res_query_client_ids(conn, 1, &spec);
xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply(conn, cookie, &err);
if (reply == NULL) {
fprintf(stderr, "Uh-Oh! :(\n");
return -1;
}
uint32_t *pid = NULL;
xcb_res_client_id_value_iterator_t it = xcb_res_query_client_ids_ids_iterator(reply);
for (; it.rem; xcb_res_client_id_value_next(&it)) {
spec = it.data->spec;
if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
pid = xcb_res_client_id_value_value(it.data);
break;
}
}
free(reply);
xcb_disconnect(conn);
fprintf(stderr, "PID: %d\n", *pid);
}
To give proper attribution, I didn't know any of this myself either, I just googled for the XCB function name and came across this. To understand the individual parts I suggest reading the Xlib documentation of it. XCB is often rather… "under-documented", as you've noticed, but it's really just the same as Xlib with other slightly different names for the most part.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With