Redrawing using the double buffer: recopy.c

The program redraw.c solves the problem of ``window erasure'', but suffers from two drawbacks. First, everything is drawn has to be remembered (at least until some other drawings covers it, which may be hard to check). Second, there may be some flickering, as the program has to draw everything each time the window is exposed. The flickering is due to screen refresh taking place while the redrawing is not finished yet.

The solution of these problem is again to use the double buffer. The double buffering tecnique used for animation was to always draw in the double buffer, and then copy in the window. If we just want to save the contents of the window, we can also use another tecnique: everything is drawn to the window, we draw to the double buffer.

Either way, the double buffer will always contains a copy of the window. As a result, each time the window is erased, we can restore its contents by copying the double buffer to it.

The program coloredsquares.c can be modified as follows. First, we need a pixmap to be the double buffer, and an event to receive events.

  Pixmap double_buffer;

  XEvent e;

Before entering the main cycle, we have to allocate the pixmap, fill it with black, and tell the X server that we are interested in receiving Expose events.

  /* create the double buffer */
  double_buffer = XCreatePixmap(dpy, root,
                  wa.width, wa.height, wa.depth);
  XSetForeground(dpy, g, BlackPixelOfScreen(DefaultScreenOfDisplay(dpy)));
  XFillRectangle(dpy, double_buffer, g, 0, 0, wa.width, wa.height);
  XCopyArea(dpy, double_buffer, root, g, 0, 0, wa.width, wa.height, 0, 0);


  /* we want expose events */
  XSelectInput(dpy, root, ExposureMask);

In order to be able to draw in the window and the double buffer using the same colors and positions, we need three variables for x, y and the color.

      /* set color and position */
      x=random()%(wa.width-50);
      y=random()%(wa.height-40);
      c=xcolors[random()%NCOLORS].pixel;
      

      /* draw in the window and in the double buffer */
      XSetForeground(dpy, g, xcolors[random()%NCOLORS].pixel);
      XFillRectangle (dpy, root, g, x, y, 50, 40);
      XFillRectangle (dpy, double_buffer, g, x, y, 50, 40);

After that, we have to check for events. For simplicity, we do not check whether the received event is really an Expose: if there is any event in the queue, we remove all of them by calling XCheckWindowEvent until it returns False, and then copy the double buffer to the window. This guarantees that, each time the window is made visible, it contents is restored by copying the double buffer to it.

This completes the module recopy.c. The XFlush instruction is not needed, as XCheckWindowEvent flushes the output. This module uses the tecnique of writing to the window and to the double buffer the same things at each step, but writing to the double buffer and then copying to the window at each step (using clipping if necessary), as it is made for animation, is a feasible alternative.