Question

What's the best way of waiting a finite a mount of time for an expose event on X, then waking up and doing a redraw, even if not expose event has been received? The purpose is to have an opengl animation running at sometimes where at others I simply want to redraw if needed. Here is my code as I have it now, check below for pseudo-code of what I'm looking for:

    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
    } 

And this is a pseudo-example of what I would like:

    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 
    } 
Was it helpful?

Solution

Just use a regular system timer; if a desired event doesn't arrive in time, just do whatever you want to do.

X is not an application framework, it's a display protocol. Timers are outside (of that) scope of X11.

Check here and the link provided in that answer.

OTHER TIPS

A simpler solution is to use the non-blocking Xlib equivalents to XNextEvent. Here's what I use to check for X events each time through the frame loop:

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

Hope this helps. The full code is in my demo OpenGL/GLX program

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

XLib does not offer a "timed out" version of XNextEvent. But, a timed out version can be easily implemented.

You will need a function that checks if a file has been updated within a given timeout, you can implement it using 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);
}

Then, you can use wait_fd in the file descriptor returned by ConnectionNumber(display) to wait for an event within a given time limit:

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

In your main loop, you can use the XNextEventTimeout function to wait for events within a given timeout. If the timeout expires, you can simulate the desired event, in you case an Expose event:

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 */
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top