X11:直到所有事件被处理如何延迟重绘?(X11: How to delay repainting

2019-08-01 10:34发布

我正在写有X11 / Xlib的接口,和我的事件处理循环看起来像这样的程序:

while (XNextEvent(display, &ev) >= 0) {
    switch (ev.type) {
        // Process events
    }
}

问题是,当窗口大小,我得到了一堆Expose事件告诉我的窗口部件重绘其。 如果我到事件的直接反应重绘他们,重绘操作非常滞后,因为它是如此之慢(调整我能看到所有新失效的矩形刷新逐一后)。

我想这样做是为了记录更新的窗口大小,它的变化,只有整个窗口上运行一个重绘操作(或至少只有两个矩形)时,有没有更多的事件留下来处理。

不幸的是,我不能明白的方式来做到这一点。 我尝试这样做:

do {
    XPeekEvent(display, &ev);
    while (XCheckMaskEvent(display, ExposureMask | StructureNotifyMask, &ev)) {
        switch (ev.type) {
            // Process events, record but don't process redraw events
        }
    }
    // No more events, do combined redraw here
}

这实际上做的工作,但它是一个小效率低,而且如果一个事件到达时,我不感兴趣的XCheckMaskEvent调用不会从队列中删除它,所以它在那里停留停止XPeekEvent阻塞,导致100%的CPU使用。

我只是想知道是否有实现的延迟/组合重绘我是后一种标准的方式? 许多Xlib的事件处理功能似乎阻塞,因此,他们没有真正合适的,如果你想要做他们阻止之前一些处理使用,但只有当他们将阻止!


编辑:为了记录在案,这是我使用的解决方案。 这是纳米的一个简化版本:

while (XNextEvent(display, &ev) >= 0) {
    switch (ev.type) {
        // Process events, remember any redraws needed later
    }
    if (!XPending(display)) {
        // No more events, redraw if needed
    }
}

Answer 1:

尝试类似如下(没有实际测试过):

while (TRUE) {
  if (XPending(display) || !pendingRedraws) {
    // if an event is pending, fetch it and process it
    // otherwise, we have neither events nor pending redraws, so we can
    // safely block on the event queue
    XNextEvent (display, &ev);
    if (isExposeEvent(&ev)) {
      pendingRedraws = TRUE;
    }
    else {
      processEvent(&ev);
    }
  }
  else {
    // we must have a pending redraw
    redraw();
    pendingRedraws = FALSE;
  }
}

这可能是有益的,等待10毫秒左右做重绘之前。 不幸的是,原始的Xlib有计时器没有接口。 您需要一个更高级别的工具包(所有的工具包,包括XT有某种计时器接口),或直接与X11连接的基础套接字工作。



Answer 2:

FWIW一个UI工具包,例如GTK +的确是这样:

  • 对于每个窗口,保持(所有公开事件的联合)一个“损坏区域”
  • 当损伤区域变为非空,增加了一个“空闲处理器”,这是一种功能,当它没有别的做事件循环运行
  • 当事件队列为空,X插槽无关阅读空闲处理器将运行(根据poll()ConnectionNumber(dpy)
  • 当然空闲处理器重绘损坏区域

在GTK +,他们正在改变这种过度到一个更现代的3D引擎为导向的方式(清理垂直同步损坏区域)在未来的版本,但它在相当简单的方式上面工作了很多年。

当转换为原始Xlib中,这看起来像左右波长的答案:当你有损坏区域,并重绘!XPending() 因此,随时接受这个答案我只是想我会添加一些额外的信息。

如果你想要的东西像计时器和空闲,你可以考虑的东西艾克libev http://software.schmorp.de/pkg/libev.html它的设计只是拖放在您的应用程序一对夫妇的源文件(这是不成立是一个外部依赖性)。 你会显示的文件描述符添加到事件循环。

对于跟踪损坏的地区,人们经常剪切和粘贴,它是由X服务器的“机器无关的”代码的文件“miregion.c”。 只是谷歌的miregion.c或下载X服务器源和寻找它。 A“区域”这里简直是矩形列表支持,例如联合运营和相交。 为了与旧区域添加伤害,工会吧,修复损伤,减去它,等等。



文章来源: X11: How to delay repainting until all events are processed?
标签: x11 repaint xlib