You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

X11合成:如何手动更新重定向窗口

如何在Composite MANUAL模式下更新处理后的窗口像素?

我想要对任意应用程序窗口进行后期处理(色彩调整、锐化、模糊等)。我使用Composite扩展将窗口内容获取为离屏像素图,再对其应用特效。为避免闪烁,我尝试使用MANUAL更新模式,以便在单帧中显示处理后的像素。根据Composite文档:

可以禁用这种自动更新机制,以便父窗口内容完全由外部应用程序决定。

但文档并未说明具体如何执行更新操作。我猜测不应直接将离屏像素图复制回窗口,因为源和目标本质上是同一个对象?

更新:我查阅了扩展源代码,找到了自动更新逻辑中执行复制操作的位置(compWindowUpdateAutomatic()),但使用xcb_render_composite()尝试后得到的结果依然无效。

以下是我当前的代码尝试,但显然复制回窗口的操作没有效果:

#include <cairo/cairo-xcb.h>
#include <stdio.h>
#include <stdlib.h>
#include <xcb/composite.h>
#include <xcb/damage.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h>

int main(int argc, char **argv)
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <window_id>\n", argv[0]);
        return -1;
    }
    xcb_window_t wid = (xcb_window_t)strtoul(argv[1], NULL, 0);

    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
    xcb_visualtype_t *visual = xcb_aux_find_visual_by_attrs(screen, XCB_VISUAL_CLASS_TRUE_COLOR, 24);
    xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, wid), NULL);

    xcb_damage_query_version(conn, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION);
    uint8_t DAMAGE_EVENT = xcb_get_extension_data(conn, &xcb_damage_id)->first_event;
    {
        //track damage in subwindows:
        xcb_query_tree_reply_t *r = xcb_query_tree_reply(conn, xcb_query_tree_unchecked(conn, wid), NULL);
        xcb_window_t *w = xcb_query_tree_children(r);
        for (int i = 0; i < r->children_len; ++i) {
            xcb_damage_damage_t damage = xcb_generate_id(conn);
            xcb_damage_create(conn, damage, w[i], XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
            xcb_flush(conn);
        }
        {
            xcb_damage_damage_t damage = xcb_generate_id(conn);
            xcb_damage_create(conn, damage, wid, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
            xcb_flush(conn);
        }
        free(r);
    }

    xcb_composite_redirect_window(conn, wid, XCB_COMPOSITE_REDIRECT_MANUAL);
    xcb_pixmap_t pixmap = xcb_generate_id(conn);
    xcb_composite_name_window_pixmap(conn, wid, pixmap);

    xcb_gcontext_t gc = xcb_generate_id(conn);
    xcb_create_gc(conn, gc, wid, 0, NULL);

    xcb_generic_event_t *event;
    while ((event = xcb_wait_for_event(conn))) {
        if (XCB_EVENT_RESPONSE_TYPE(event) == DAMAGE_EVENT + XCB_DAMAGE_NOTIFY) {
            xcb_damage_notify_event_t *de = (xcb_damage_notify_event_t *)event;
            {  // draw a translucent layer:
                cairo_surface_t *surface = cairo_xcb_surface_create(conn, pixmap, visual, geom->width, geom->height);
                cairo_t *cr = cairo_create(surface);

                cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.5);
                cairo_paint(cr);

                cairo_destroy(cr);
                cairo_surface_destroy(surface);
            }
            {  // copy back:
                xcb_copy_area(conn, pixmap, wid, gc, 0, 0, 0, 0, geom->width, geom->height);
            }
            xcb_damage_subtract(conn, de->damage, XCB_NONE, XCB_NONE);
            xcb_flush(conn);
        }

        free(event);
    }
    return -1;
}

编译命令:

cc main.c -o main -lxcb-composite -lxcb-damage -lcairo -lxcb-render -lxcb-util -lxcb

内容的提问来源于stack exchange,提问作者svlasov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 15:22:13