Next | Prev | Up | Top | Contents | Index

Xlib Event Handling

This section discusses different kinds of user input and explains how you can use Xlib to perform them. OpenGL programs running under the X Window System are responsible for responding to events sent by the X server. Examples of X events are Expose, ButtonPress, ConfigureNotify, and so on.

Note: In addition to mouse devices, Silicon Graphics systems support various other input devices (for example, spaceballs). You can integrate them with your OpenGL program using the X input extension. For more information, see the X Input Extension Library Specification available online through IRIS Insight.


Handling Mouse Events

To handle mouse events, your program first has to request them, then use them in the main (event handling) loop. Here's an example code fragment from Xlib/mouse.c, an Xlib program that uses mouse motion events. Example 3-3 shows how the mouse processing, along with the other event processing, is defined.

Example 3-3 : Event Handling With Xlib

static int
process_input(Display *dpy) {
    XEvent event;
    Bool redraw = 0;
    static int mstate, omx, omy, mx, my;

    do {
        char buf[31];
        KeySym keysym;

        XNextEvent(dpy, &event);
        switch(event.type) {
        case Expose:
            redraw = 1;
            break;
        case ConfigureNotify:
            glViewport(0, 0, event.xconfigure.width,
                       event.xconfigure.height);
            redraw = 1;
            break;
        case KeyPress:
            (void) XLookupString(&event.xkey, buf, sizeof(buf),
                   &keysym, NULL);
            switch (keysym) {
            case XK_Escape:
                exit(EXIT_SUCCESS);
            default:
                break;
            }
        case ButtonPress:
            if (event.xbutton.button == Button2) {
                mstate |= 2;
                mx = event.xbutton.x;
                my = event.xbutton.y;
            } else if (event.xbutton.button == Button1) {
                mstate |= 1;
                mx = event.xbutton.x;
                my = event.xbutton.y;
            }
            break;
        case ButtonRelease:
            if (event.xbutton.button == Button2)
                mstate &= ~2;
            else if (event.xbutton.button == Button1)
                mstate &= ~1;
            break;
        case MotionNotify:
            if (mstate) {
                omx = mx;
                omy = my;
                mx = event.xbutton.x;
                my = event.xbutton.y;
                update_view(mstate, omx,mx,omy,my);
                redraw = 1;
            }
            break;
        default:
            break;
        }
    } while (XPending(dpy));
    return redraw;
}
The process_input() function is then used by the main loop:

 while (1) {
        if (process_input(dpy)) {
            draw_scene();
            ...
           }
}

Exposing a Window

When a user selects a window that has been completely or partly covered, the X server generates one or more Expose events. It is difficult to determine exactly what was drawn in the now-exposed region and redraw only that portion of the window. Instead, OpenGL programs usually just redraw the entire window. (Note that backing store is not supported on Silicon Graphics systems.)

If redrawing is not an acceptable solution, the OpenGL program can do all your rendering into a GLXPixmap instead of directly to the window; then, any time the program needs to redraw the window, you can simply copy the GLXPixmap's contents into the window using XCopyArea(). For more information, see "Using Pixmaps".

Caution: Rendering to a GLXPixmap is much slower than rendering to a window. For example, on a RealityEngine, rendering to a pixmap is perhaps 5% the speed of rendering to a window. When handling X events for OpenGL programs, remember that Expose events come in batches. When you expose a window that is partly covered by two or more other windows, two or more Expose events are generated, one for each exposed region. Each one indicates a simple rectangle in the window to be redrawn. If you are going to redraw the entire window, read the entire batch of Expose events. It is wasteful and inefficient to redraw the window for each Expose event.


Next | Prev | Up | Top | Contents | Index