Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 请求X11在C或C+中合成WM的图像+;_C++_C_X11_Xlib_Xcb - Fatal编程技术网

C++ 请求X11在C或C+中合成WM的图像+;

C++ 请求X11在C或C+中合成WM的图像+;,c++,c,x11,xlib,xcb,C++,C,X11,Xlib,Xcb,我需要从X服务器或WM请求并检索窗口的图像(我相信WM会进行实际的合成)。我需要能够获得窗口的图像,即使它被另一个窗口遮挡或位于另一个工作区(但仍然映射)。我需要使用C或C++,并希望使用XCB或XLIB。我想我也安装了Gtk+开发工具,但我已经有一段时间没有使用它们了 我尝试过使用xcb_composite_name_window_pixmap(),但没有成功(xcb错误) 我尝试使用render extension将窗口渲染为不产生错误的图片,但我仍然需要将图像加载到程序内存中 我尝试使用x

我需要从X服务器或WM请求并检索窗口的图像(我相信WM会进行实际的合成)。我需要能够获得窗口的图像,即使它被另一个窗口遮挡或位于另一个工作区(但仍然映射)。我需要使用C或C++,并希望使用XCB或XLIB。我想我也安装了Gtk+开发工具,但我已经有一段时间没有使用它们了

我尝试过使用xcb_composite_name_window_pixmap(),但没有成功(xcb错误)

我尝试使用render extension将窗口渲染为不产生错误的图片,但我仍然需要将图像加载到程序内存中

我尝试使用xcb_get_image来获取图片,但IIRC失败了(我认为是错误的资源)

我试着将图片复制到一个pixmap,并在上面使用xcb_get_image。我可以下载看起来像是图像的东西,但它看起来更像是屏幕上的随机区域,而不是实际的窗口

简言之,我只是在这一点上进行猜测

我很难找到有组织、完整的文档。我能找到的关于X11、XCB或Xlib的最新出版物是1994年出版的(关于Xlib和/或X11R6的O'Reilly书),我怀疑这些扩展是否有很多有效之处。大多数手册页和在线文档都有很多“待办事项:解释这一点”和/或功能描述,如“向X服务器发送请求”。任何人能提供的任何帮助对我都是有用的

我目前正在为我的WM运行compiz,为窗户装饰运行emerald,而在“桌面环境”方面没有其他标准。我正在为定制桌面开发一些实用程序,我计划在它们准备好后发布。我希望我所做的一切都能与其他一些WM一起工作,但是,如果每个WM都需要特殊的代码路径,我可以添加其他WM


编辑:我最初在这里添加了一个非工作示例,然后是一个精简的工作示例,这些示例都被移动到了评论中建议的答案中。

我现在有一个工作示例,我将在这里发布:

#include <xcb/xcb.h>
#include <xcb/xproto.h>
#include <xcb/composite.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "usage: %s windowId\n", argv[0]);
        return EXIT_FAILURE;
    }
    xcb_window_t req_win_id = strtoul(argv[1], NULL, 0);
    xcb_connection_t *connection = xcb_connect(NULL, NULL);
    xcb_generic_error_t *err = NULL, *err2 = NULL;

    xcb_composite_query_version_cookie_t comp_ver_cookie = xcb_composite_query_version(connection, 0, 2);
    xcb_composite_query_version_reply_t *comp_ver_reply = xcb_composite_query_version_reply(connection, comp_ver_cookie, &err);
    if (comp_ver_reply)
    {
        if (comp_ver_reply->minor_version < 2) {
            fprintf(stderr, "query composite failure: server returned v%d.%d\n", comp_ver_reply->major_version, comp_ver_reply->minor_version);
            free(comp_ver_reply);
            return EXIT_FAILURE;
        }
        free(comp_ver_reply);
    }
    else if (err)
    {
        fprintf(stderr, "xcb error: %d\n", err->error_code);
        free(err);
        return EXIT_FAILURE;
    }

    const xcb_setup_t *setup = xcb_get_setup(connection);
    xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(setup);
    xcb_screen_t *screen = screen_iter.data;
    // request redirection of window
    xcb_composite_redirect_window(connection, req_win_id, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
    int win_h, win_w, win_d;

    xcb_get_geometry_cookie_t gg_cookie = xcb_get_geometry(connection, req_win_id);
    xcb_get_geometry_reply_t *gg_reply = xcb_get_geometry_reply(connection, gg_cookie, &err);
    if (gg_reply) {
        win_w = gg_reply->width;
        win_h = gg_reply->height;
        win_d = gg_reply->depth;
        free(gg_reply);
    } else {
        if (err) {
            fprintf(stderr, "get geometry: XCB error %d\n", err->error_code);
            free(err);
        }
        return EXIT_FAILURE;
    }

    // create a pixmap
    xcb_pixmap_t win_pixmap = xcb_generate_id(connection);
    xcb_composite_name_window_pixmap(connection, req_win_id, win_pixmap);

    // get the image
    xcb_get_image_cookie_t gi_cookie = xcb_get_image(connection, XCB_IMAGE_FORMAT_Z_PIXMAP, win_pixmap, 0, 0, win_w, win_h, (uint32_t)(~0UL));
    xcb_get_image_reply_t *gi_reply = xcb_get_image_reply(connection, gi_cookie, &err);
    if (gi_reply) {
        int data_len = xcb_get_image_data_length(gi_reply);
        fprintf(stderr, "data_len = %d\n", data_len);
        fprintf(stderr, "visual = %u\n", gi_reply->visual);
        fprintf(stderr, "depth = %u\n", gi_reply->depth);
        fprintf(stderr, "size = %dx%d\n", win_w, win_h);
        uint8_t *data = xcb_get_image_data(gi_reply);
        fwrite(data, data_len, 1, stdout);
        free(gi_reply);
    }
    return EXIT_SUCCESS;
}
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
如果(argc<2){
fprintf(stderr,“用法:%s windowId\n”,argv[0]);
返回退出失败;
}
xcb_window_t req_win_id=strtoul(argv[1],NULL,0);
xcb_connection\u t*connection=xcb_connect(NULL,NULL);
xcb_generic_error_t*err=NULL,*err2=NULL;
xcb\u复合查询版本cookie\t复合版本cookie=xcb\u复合查询版本(连接,0,2);
xcb_复合查询版本回复*comp_ver_reply=xcb_复合查询版本回复(连接、comp_ver_cookie和错误);
如果(公司回复)
{
如果(复合版本回复->次要版本<2){
fprintf(stderr,“查询复合故障:服务器返回v%d.%d\n”,复合版本应答->主要版本,复合版本应答->次要版本);
免费(补偿回复);
返回退出失败;
}
免费(补偿回复);
}
否则如果(错误)
{
fprintf(标准,“xcb错误:%d\n”,错误->错误代码);
自由(错误);
返回退出失败;
}
const xcb_setup\u t*setup=xcb_get_setup(连接);
xcb\U屏幕迭代器\U t屏幕迭代器=xcb\U设置\U根迭代器(设置);
xcb_screen_t*screen=screen_iter.data;
//请求窗口重定向
xcb_复合重定向窗口(连接、请求赢id、xcb_复合重定向自动);
赢,赢,赢;
xcb_get_geometry_cookie_t gg_cookie=xcb_get_geometry(连接,请求赢号);
xcb_get_geometry_reply_t*gg_reply=xcb_get_geometry_reply(连接、gg_cookie和错误);
如果(GGU回复){
win_w=gg_回复->宽度;
win_h=gg_回复->高度;
win\U d=gg\U回复->深度;
免费(GGU回复);
}否则{
如果(错误){
fprintf(stderr,“获取几何体:XCB错误%d\n”,错误->错误代码);
自由(错误);
}
返回退出失败;
}
//创建一个pixmap
xcb_pixmap_t win_pixmap=xcb_generate_id(连接);
xcb_复合_名称_窗口_pixmap(连接、请求_赢_id、赢_pixmap);
//获取图像
xcb_get_image_cookie_t gi_cookie=xcb_get_image(连接,xcb_image_格式_Z_PIXMAP,win_PIXMAP,0,0,win_w,win_h,(uint32_t)(~0UL));
xcb_get_image_reply_t*gi_reply=xcb_get_image_reply(连接、gi_cookie和错误);
如果(GIU回复){
int data_len=xcb_get_image_data_length(gi_回复);
fprintf(标准,“数据长度=%d\n”,数据长度);
fprintf(标准,“视觉=%u\n”,gi\u回复->视觉);
fprintf(标准,“深度=%u\n”,gi\u回复->深度);
fprintf(标准,“大小=%dx%d\n”,赢w,赢h);
uint8_t*data=xcb_获取图像_数据(gi_回复);
fwrite(数据,数据长度,1,标准输出);
免费(GIU回复);
}
返回退出成功;
}

这是一个过度的例子。我的想法是,我应该从某个地方使用Xrender,并开始从该扩展中提取大量我并不真正需要的数据。但我遇到的真正问题是,不应该首先创建给xcb_composite_name_window_pixmap的pixmap,而只是需要它的新id。事实证明,它真的和我想象的一样简单。您所需要的只是窗口ID和大小,执行一些检查以确保composite存在并且是一个好的版本(本例中为>=0.2),然后依次调用xcb_composite_redirect_Window、xcb_composite_name_Window_pixmap(使用生成的pixmap ID)和xcb_get_image(+reply,data_len,data),您就拥有了该图像。

我无法为您编写代码。我可能会解释你的代码出了什么问题,并提出修复建议,但我需要先看看。请发一封信,很公平。我会抓起一些我写的东西,并将其添加到问题中。@n.m.好了。这有点难让我