通过开罗表面绘制X窗口时,清除X窗口的正确方法是什么

时间:2018-05-16 21:20:06

标签: c cairo xlib

我正在尝试使用Cairo在透明的X窗口上绘图。根据官方开罗FAQ,清除透明表面的一种方法是将开罗算子设置为CLEAR。这在我的案例中似乎不起作用。我正在画一个不断增长和缩小的圆圈。最初,圆圈会增大,但当它缩小时,大圆圈会保留在窗口上。这让我觉得也许我应该在每次重绘时清除X窗口。

这是我提出的代码

XClearWindow(self->display, self->win_id);
cairo_push_group(self->context);

// Re-draw the whole canvas: Doesn't work as expected
// cairo_save(self->context);
// cairo_set_operator(self->context, CAIRO_OPERATOR_CLEAR);
// cairo_paint(self->context);
// cairo_restore(self->context);

// Invoke the draw callback <- Cairo drawing done here from Python
Canvas_on_draw(self, args_tuple, NULL);

cairo_pop_group_to_source(self->context);
cairo_paint(self->context);
cairo_surface_flush(self->surface);

XFlush(self->display);

正如您所看到的,我的解决方案是在使用Cairo绘制之前调用XClearWindow,然后使用XFlush刷新所有内容。但是,我不确定这是最干净的解决方案,它有点像黑客而不是正确的方法。例如,没有XFlush我会得到相当多的闪烁,但Xlib文档似乎暗示大多数应用程序不需要直接调用此函数。

编辑:在下面的答案之后,这就是我的代码:

    cairo_push_group(self->context);
    // Draw stuff
    cairo_pop_group_to_source(self->context);

    // The following cairo paradigm seems to have the same
    // effect as the following commented out lines:
    // XClearWindow(self->display, self->win_id);
    // cairo_paint(self->context);
    cairo_save(self->context);
    cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE);
    cairo_paint(self->context);
    cairo_restore(self->context);

这是预期的事情。

1 个答案:

答案 0 :(得分:1)

在最终cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE);之前添加cairo_paint()

您正在清除您创建的中间组。这意味着它在圆圈外是完全透明的。然后使用默认运算符OVER将此组绘制到目标窗口。绘制完全透明,只留下旧内容。使用SOURCE进行绘图实际上会将源复制到目标曲面。

附注:除非您根据需要致电XClearWindowcairo_surface_flush,否则无法保证cairo_surface_mark_dirty方法无效。