2013-06-23 66 views
2

对于X上的揭发事件等待一段有限的时间,然后醒来并重新绘制,即使没有收到暴露事件,最好的方法是什么?目的是让opengl动画有时在其他地方运行,如果需要的话,我只是想重新绘制。这里是我的代码,因为我有现在,下面检查什么我正在寻找伪代码:X:以固定的时间间隔触发事件

do { 
     XNextEvent(dpy, &event); 
     switch(event.type) { 
      ... 
      case Expose: 
       need_redraw = True; 
       break; 
     } 
    } while(XPending(dpy)); /* loop to compress events */ 

    if (need_redraw) 
    { 
     // do redraw 
    } 

这是我想什么是伪例如:

bool animation_enabled = true; 
    XPostTimeoutEventEvery(0.3); // <-- X will send a "Timeout" 
            // event each 0.3 seconds. 

    do { 
     XNextEvent(dpy, &event); 
     switch(event.type) { 
      ... 
      case Expose: 
       // Redraw if it is required 
       need_redraw = True; 
       break; 
      // -- here -- 
      case Timeout: 
       // Otherwise, after 0.3 seconds, redraw anyway if 
       // the animation is running 
       if (animation_enabled) 
       { 
        need_redraw = True; 
       } 
       break; 


     } 
    } while(XPending(dpy)); /* loop to compress events */ 

    if (need_redraw) 
    { 
     // do redraw 

     // potentially change "animation_enabled" value 
    } 

回答

3

只需使用常规系统计时器;如果期望的事件没有及时到达,只要做你想做的事情。

X不是一个应用程序框架,它是一个显示协议。定时器在X11的范围之外。

检查here和该答案中提供的link

1

一个更简单的解决方案是使用与XNextEvent等效的非阻塞Xlib。这里是我用来检查X事件每次通过帧循环:

mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; 
while (XCheckWindowEvent(xDisplay, xWin, mask, &evt) || 
     XCheckTypedWindowEvent(xDisplay, xWin, ClientMessage, &evt)) { 
     /* Handle event */ 
} 

希望这会有所帮助。完整的代码是在我的演示的OpenGL/GLX程序

http://cs.anu.edu.au/~Hugh.Fisher/3dteach/glxcube.tar

1

XLIB不提供“超时” XNextEvent例行的版本。 但是,超时的版本可以很容易地实现。

您将需要一个功能 来检查,如果一个文件被给定的超时时间内更新 , 可以实现它使用select

#include <sys/select.h> 

static int wait_fd(int fd, double seconds) 
{ 
    struct timeval tv; 
    fd_set in_fds; 
    FD_ZERO(&in_fds); 
    FD_SET(fd, &in_fds); 
    tv.tv_sec = trunc(seconds); 
    tv.tv_usec = (seconds - trunc(seconds))*1000000; 
    return select(fd+1, &in_fds, 0, 0, &tv); 
} 

然后,您可以在文件描述符使用wait_fd 通过 ConnectionNumber(display) 返回给定的时限内等待事件 :

int XNextEventTimeout(Display *display, XEvent *event, double seconds) 
{ 
    if (XPending(display) || wait_fd(ConnectionNumber(display),seconds)) { 
     XNextEvent(display, event); 
     return 0; 
    } else { 
     return 1; 
    } 
} 

在您的主循环中, 可以使用XNextEventTimeout函数 等待给定超时内的事件。 如果超时,你可以模拟所需的事件, 在你情况下Expose事件:

for (;;) { 
    if (XNextEventTimeout(dpy, &event, 1.)) { 
     /* Handle timeout "event" 
     * one option is to simulate an Expose event */ 
     e.type = Expose; 
     e.xexpose.count = 0; 
    } 
    switch (event.type) { 
     case Expose: 
      /* Handle expose event */ 
      break; 

     /* ... */ 
     /* Handle other events */ 
    } 
}