python:使用XresQueryClientId将PID设置为X11窗口ID

python:使用XresQueryClientId将PID设置为X11窗口ID,python,x11,xcb,Python,X11,Xcb,注意:这是对来自unix.stackexchange的答案的继续。这个答案提到了来自的XResQueryClientIds。我想知道如何使用它 如何使用查找与提供的PID关联的所有X11窗口ID(假设没有竞争条件;未创建或销毁窗口或进程) 我对X11了解不多,它似乎不完整,而且没有文档记录。根据我收集的信息,我需要: 创建连接:xcb\u connect 获取扩展名:?未记录 查询扩展名:?xcb\u get\u extension\u data提及“?查询扩展请求” 获取查询响应:xcb\u

注意:这是对来自unix.stackexchange的答案的继续。这个答案提到了来自的
XResQueryClientIds
。我想知道如何使用它

如何使用查找与提供的PID关联的所有X11窗口ID(假设没有竞争条件;未创建或销毁窗口或进程)

我对X11了解不多,它似乎不完整,而且没有文档记录。根据我收集的信息,我需要:

  • 创建连接:
    xcb\u connect
  • 获取扩展名:?未记录
  • 查询扩展名:?
    xcb\u get\u extension\u data
    提及“?查询扩展请求”
  • 获取查询响应:
    xcb\u Get\u extension\u data
  • 使用和解压缩响应
  • 假设没有种族条件;未创建或销毁窗口或进程

    假设是坏的,如果你知道假设不成立。幸运的是,你不需要这个假设。只需在您的操作中使用
    xcb_grab_服务器
    xcb_ungrab_服务器
    ,这不会成为问题

    现在,对于
    XResQueryClientIds
    ,您实际上只需输入
    man xcb\u res\u query\u client\u id
    。XCB只提供了这个功能,不需要实际查询扩展。这是一个示例程序。使用
    gcc-lxcb-lxcb res main.c
    编译它,然后通过传递窗口ID作为唯一参数来执行它(例如,
    /a.out 0x2c00004

    #包括
    #包括
    #包括
    #包括
    int main(int argc,char*argv[]){
    int屏幕;
    xcb_connection\u t*conn=xcb_connect(空,屏幕和);
    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_id_cookie_t cookie=xcb_res_query_client_id(conn、1和spec);
    xcb\u res\u query\u client\u ids\u reply\u t*reply=xcb\u res\u query\u client\u ids\u reply(连接、cookie和错误);
    if(reply==NULL){
    fprintf(stderr,“嗯,哦!:(\n”);
    返回-1;
    }
    uint32_t*pid=NULL;
    xcb_res_client_id_value_iterator_t it=xcb_res_query_client_id_ids_iterator(回复);
    对于(;it.rem;xcb_res_client_id_value_next(&it)){
    spec=it.data->spec;
    if(规范掩码和XCB\u RES\u客户端\u ID\u掩码\u本地\u客户端\u PID){
    pid=xcb_res_client_id_value_value(it.data);
    打破
    }
    }
    免费(回复);
    xcb_断开(连接);
    fprintf(标准,“PID:%d\n”,*PID);
    }
    

    为了给出正确的归属,我自己也不知道这些,我只是在谷歌上搜索了XCB函数名,发现了它。为了理解各个部分,我建议阅读它的Xlib文档。XCB通常是“文档不足”的,正如您所注意到的,但它实际上与Xlib相同,但大多数名称略有不同。

    如果我的答案有帮助,请将其标记为已接受。我注意到您一直在这样做,但尚未对我的答案给出任何反馈。这并不是我所要求的,但很有帮助。XCFIB:1]0.1(fedora 23)存在很多问题即使使用手动xauth 2]尝试手动打包结构,连接也会中断,这是一种错误的方式3]许多方法做同样的事情,其中大多数都是错误的方式4]没有文档5]0.4.2(当前)有更改,破坏了与xlib的兼容性(应在下一版本中修复)。实际上,我尝试过的任何一行都有一些问题,可能是我(文档),来自旧版本,来自坏补丁,或者来自坏协议。不管怎么说,由于所有这些问题,我本来打算切换到libxcb(c),但是由于,
    xcb\u res\u query\u client\u id\u reply\t
    充满了垃圾(读取超出范围).补丁修复了所有绑定的问题,所以现在xcffib工作得很好,现在我知道我在做什么了。我看到你在调试上花了不少功夫。太棒了!这太棒了。我自己弄清楚这些东西可能很容易就花了我几天的时间。
    #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);
    }