为什么没有cairo在循环的第一次迭代中绘制?

时间:2018-06-03 00:08:18

标签: c x11 cairo

我正在创建一个创建透明X窗口并使用cairo绘制它们的库。在主线程中实现了一个事件循环,而绘制操作则在循环内的一个单独的线程中进行。后者看起来像这样

  while (self->_running) {
    PyGILState_Release(gstate);
    usleep(1000); // Sleep 1 ms
    gstate = PyGILState_Ensure();

    if (self->_expiry <= gettime()) {
      draw(self, args_tuple); // All the cairo code is in here
      self->_expiry += interval;
      interval = self->interval;
    }
  }

事件循环定期调用XNextEvent以仅捕获按键/按钮。在从主线程启动新UI线程之前映射窗口。

当UI线程上的迭代之间的间隔(上面的self->inteval值)很大(秒的数量级)时,窗口在循环的第一次迭代时保持透明,并且它仅从第二次迭代。在draw循环之前调用while并没有帮助,除非在调用draw之间有几毫秒的暂停。例如,如果我在interval = 25循环之前放置while,那么第二次调用draw会在应用程序执行的大多数窗口上绘制实现此代码。

我尝试过的事情:

  • cairo_surface_flushXFlushdraw似乎无法正常工作之后
  • 发送Expose事件似乎也无济于事。

如何确保我的循环从第一次迭代开始在窗口上绘画?

2 个答案:

答案 0 :(得分:1)

我错过的是ExposureMask调用中的XSelectInput标记。设置此标志后,必须使用以下模式在事件循环中查找Expose个事件:

  switch (e.type) {
  case Expose:
    if (e.xexpose.count == 0) {
      BaseCanvas__redraw(canvas);
    }
    return;
  }

重绘操作不需要是完整的绘制操作集。修改了cairo上下文后,只需要在目的地上重新绘制它就足够了

void
BaseCanvas__redraw(BaseCanvas * self) {
  cairo_save(self->context);
  cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE);
  cairo_paint(self->context);
  cairo_restore(self->context);
}

答案 1 :(得分:-1)

对我来说,看起来你正在映射窗口,然后立即启动一个尝试绘制到窗口的线程。因此,如果您尝试在窗口管理器实际使窗口可见之前绘制,则您的绘图无处可去。如果窗口管理器赢得比赛并且窗口实际上在绘制之前可见,则绘图实际上有效。

你自己的答案不是你问题的答案。问题是&#34;为什么它在第一次迭代中保持透明?&#34;你的答案是(基本上)&#34;不要使用线程,只需在主循环中进行所有绘制&#34;。 (当然,处理Expose事件是正确的事情,但这不是问题所在。)