X11:如何延迟重绘直到处理完所有事件? [英] X11: How to delay repainting until all events are processed?

查看:58
本文介绍了X11:如何延迟重绘直到处理完所有事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个具有 X11/Xlib 接口的程序,我的事件处理循环如下所示:

while (XNextEvent(display, &ev) >= 0) {开关(ev.type){//处理事件}}

问题是当调整窗口大小时,我收到一堆 Expose 事件,告诉我要重绘窗口的哪些部分.如果我重绘它们以直接响应事件,重绘操作会非常滞后,因为它太慢了(调整大小后,我可以看到所有新失效的矩形都一一刷新.)

我想要做的是记录更新的窗口大小随着它的变化而变化,并且在没有更多事件需要处理时只对整个窗口(或至少两个矩形)运行一次重绘操作.

不幸的是,我看不到这样做的方法.我试过这个:

做{XPeekEvent(display, &ev);而 (XCheckMaskEvent(display, ExposureMask | StructureNotifyMask, &ev)) {开关(ev.type){//处理事件,记录但不处理重绘事件}}//没有更多的事件,在这里做组合重绘}

这确实有效,但效率有点低,如果我对 XCheckMaskEvent 调用不感兴趣的事件到达,不会将其从队列中删除,因此它会停留在那里停止 XPeekEvent 被阻塞,导致 100% CPU 使用.

我只是想知道是否有一种标准方法可以实现我所追求的延迟/组合重绘?许多 Xlib 事件处理函数似乎会阻塞,因此如果您想在它们阻塞之前进行一些处理,则它们不太适合使用,但前提是它们会阻塞!

<小时>

为了记录,这是我使用的解决方案.这是 n.m. 的简化版本:

while (XNextEvent(display, &ev) >= 0) {开关(ev.type){//处理事件,记住以后需要的任何重绘}如果(!XPending(显示)){//没有更多的事件,如果需要重绘}}

解决方案

尝试如下(未实际测试):

while (TRUE) {if (XPending(display) || !pendingRedraws) {//如果有事件未决,则获取并处理它//否则,我们既没有事件也没有挂起的重绘,所以我们可以//安全地阻塞事件队列XNextEvent (display, &ev);如果(isExposeEvent(&ev)){挂起重绘 = TRUE;}别的 {processEvent(&ev);}}别的 {//我们必须有一个挂起的重绘重绘();挂起重绘 = FALSE;}}

在重绘之前等待 10 毫秒左右可能是有益的.不幸的是,原始 Xlib 没有定时器接口.为此,您需要一个更高级别的工具包(包括 Xt 在内的所有工具包都有某种计时器接口),或者直接使用 X11 连接的底层套接字.

I'm writing a program that has an X11/Xlib interface, and my event processing loop looks like this:

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

The problem is when the window is resized, I get a bunch of Expose events telling me which parts of the window to redraw. If I redraw them in direct response to the events, the redraw operation lags terribly because it is so slow (after resizing I get to see all the newly invalidated rectangles refresh one by one.)

What I would like to do is to record the updated window size as it changes, and only run one redraw operation on the entire window (or at least only two rectangles) when there are no more events left to process.

Unfortunately I can't see a way to do this. I tried this:

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
}

Which does actually work, but it's a little inefficient, and if an event arrives that I am not interested in the XCheckMaskEvent call doesn't remove it from the queue, so it stays there stopping XPeekEvent from blocking, resulting in 100% CPU use.

I was just wondering whether there is a standard way to achieve the delayed/combined redraw that I am after? Many of the Xlib event processing functions seem to block, so they're not really suitable to use if you want to do some processing just before they block, but only if they would block!


EDIT: For the record, this is the solution I used. It's a simplified version of n.m.'s:

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

解决方案

Try something like the following (not actually tested):

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;
  }
}

It could be beneficial to wait for 10 ms or so before doing the redraw. Unfortunately the raw Xlib has no interface for timers. You need a higher-level toolkit for that (all toolkits including Xt have some kind of timer interface), or work directly with the underlying socket of the X11 connection.

这篇关于X11:如何延迟重绘直到处理完所有事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆