从在C或C X11合成WM请求图像++

问题描述 投票:1回答:1

我需要重新申请并取得从X服务器或WM窗口的图像(我相信WM执行实际的合成)。我需要能够得到窗口的图像,即使它被另一个窗口遮挡或位于另一个工作区(但仍映射)。我需要使用C或C ++,并想用XCB或Xlib的。我想我也有安装了GTK +的开发工具,但是,因为我用他们来说,这已经有一段时间。

我一直在使用xcb_composite_name_window_pixmap(),但没有成功(XCB错误)尝试。

我试着用渲染扩展来渲染窗口,其生产的没有错误的照片,但我仍然需要得到加载到我的程序内存中的图像。

我试图用xcb_get_image要获取的,IIRC,失败的图片(坏的资源,我相信)。

我试图将图片复制到一个像素映射,并在使用xcb_get_image。我能下载什么似乎是一个形象,但它看起来更像屏幕比实际窗口的任意区域。

总之,我只是在这一点上做的猜测。

我有困难的时候找到有组织和完整的文档。最近出版我可以找到关于X11,XCB,或Xlib的是自1994年(O'Reilly的书的Xlib和/或X11R6),我怀疑有多少,如果有的话,在这些扩展有效。大多数人的网页和在线文档有很多的“TODO:解释”和/或功能的描述,如“交付给X服务器的请求”。任何帮助,任何人都可以提供将使用的给我。

我目前正在运行WM我和翡翠用于窗口的装饰,没有其他标准的compiz在“桌面环境”的条款。我正在为一个自定义桌面一些实用的应用程序,我打算当他们准备释放。我想不管我做了一些窗口管理等工作,但是,如果它需要为每个特殊codepaths,我可以添加其他的路线。

编辑:我原本在这里添加非工作实例,然后剥离下来的工作示例,它已全部转移到一个答案,在意见建议。

c++ c x11 xlib xcb
1个回答
1
投票

我现在有一个工作的例子,我将张贴在这里:

#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;
}

这是矫枉过正的情况。我得到了我应该用XRENDER从某处的想法,并开始从扩展,我并不真的需要拉动数据吨。但真正的问题,我是给xcb_composite_name_window_pixmap像素图不应该先创建,而我只需要新的ID吧。事实证明,它是真正的,因为我希望它是简单的。所有你需要的是Window ID和大小,做一些检查,以确保复合材料是存在的,(在这种情况下> = 0.2)一个很好的版本,并调用xcb_composite_redirect_window,xcb_composite_name_window_pixmap(与所生成的像素图ID)和xcb_get_image(+回复,DATA_LEN,数据)的顺序,和你有图像。

© www.soinside.com 2019 - 2024. All rights reserved.