我正在创建一个创建透明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_flush
和XFlush
在draw
似乎无法正常工作之后Expose
事件似乎也无济于事。如何确保我的循环从第一次迭代开始在窗口上绘画?
答案 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事件是正确的事情,但这不是问题所在。)