【问题标题】:X: trigger events at fixed intervalsX:以固定间隔触发事件
【发布时间】:2013-06-23 15:17:06
【问题描述】:

在 X 上等待有限时间的公开事件,然后醒来并进行重绘,即使未收到公开事件,最好的方法是什么?目的是让 opengl 动画在有时我只想在需要时重绘的地方运行。这是我现在拥有的代码,请在下面查看我正在寻找的伪代码:

    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 
    } 

【问题讨论】:

    标签: c opengl x11 glx


    【解决方案1】:

    只需使用常规系统计时器即可;如果想要的活动没有及时到达,那就做你想做的事。

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

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

    【讨论】:

      【解决方案2】:

      一个更简单的解决方案是使用 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

      【讨论】:

        【解决方案3】:

        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 */
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-05
          • 2018-10-22
          • 1970-01-01
          • 1970-01-01
          • 2017-09-04
          • 1970-01-01
          • 2011-10-17
          • 1970-01-01
          相关资源
          最近更新 更多