Redrawing a window using a callback procedure

In our tutorial so far, every time our window has been damaged we have had to manually redraw it. The application program is always responsible for redrawing its windows when they have been damaged. This can be accomplished by associating a callback with the window telling ProXL what to do when the window needs to be redrawn.

The steps required to automatically redraw our window are:

First, we must define the callback procedure to redraw our window:

     | ?- compile(user).
     | redraw(Window, Pixel3, Pixel4) :-
             Xdisplacement = 4,
             Ydisplacement = 5,
             A = 20,
             X0 is 2+Xdisplacement,
             Y0 is 2+A+Ydisplacement,
             X1 is 2,
             Y1 is 2+A,
             put_graphics_attributes(Window, [foreground(Pixel4)]),
             draw_string(Window, X0, Y0, 'Hello, world!!'),
             put_graphics_attributes(Window, [foreground(Pixel3)]),
             draw_string(Window, X1, Y1, 'Hello, world!!').
     | ^D
     % user compiled, 0.383 sec 380 bytes
     
     yes
     

Next we must register the callback for expose events sent to our window:

     | ?- win(Window),
          colors(_, _, Pixel3, Pixel4),
          put_window_attributes(Window,
                 [callback(expose,
                         [count(0)],
                         redraw(Window,Pixel3,Pixel4))]).
     
     Window = window(2376568),
     Pixel3 = 8,
     Pixel4 = 1
     

Here we have told ProXL that when the X server determines that it is necessary to redraw the window, by sending expose events, the procedure redraw/3 should be called. The X server may send several expose events, each specifying a different part of the window to be redrawn. Since this is a simple example, we don't bother to redraw the window part by part. We just redraw the entire window whenever any part of it needs to be redrawn. The second argument, count(0), accomplishes this by telling ProXL that it should call redraw/3 only if this is the last expose message in the group.2

Now if you do something to force X to redraw our window, like iconifying and then uniconifying it, or hiding it behind another window and then exposing it, you will find that the window is automatically refreshed. Try it.


Footnotes

  1. Since an expose event is sent to a window when it is first mapped (appears on the screen), it is not necessary to write separate code that initially draws the window and subsequently redraws the window.

  2. If we had wanted to do more precise redrawing, we would have put [position(X,Y),size(W,H)] as the second argument in our callback specification, in place of [count(0)], and passed X, Y, W, and H to the callback procedure. The callback procedure would then only redraw the area of the window thus specified.