I got this XWindows "hello, world" off the net. I have behavior I don't understand in a more complex program, but the simple program here also displays it:
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
Display *d;
Window w;
XEvent e;
const char *msg = "Hello, World!";
int s;
int x;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask | KeyPressMask);
XMapWindow(d, w);
XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg));
//XFlush(d);
while (1) {
XNextEvent(d, &e);
if (e.type == Expose) {
// XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg));
}
if (e.type == KeyPress) break;
}
XCloseDisplay(d);
return 0;
}
So the first XDrawString() call does not actually write to the window, but uncommenting the one in the expose event does. I find this behavior confusing. At the time of the first XDrawString(), the display, screen and window are all set up. Yet that does not draw and the one that appears in the event handler does. I also tried XFlush()'ing the queue, it makes no difference.
This effect had bearing on the (much) more complex code I am working on, which is placing characters on screen. I place them at the desired location in a pixmap that backs the screen, and then I do the same draw to the real screen to keep it in sync. The expose handler will copy the pixmap to the screen, which updates it, but that expose event won't happen until later, and besides, copying the entire pixmap back to the screen is more expensive than placing a single character.
I suspect I need to follow the draw to buffer with an operation flagging the rectangle under the character as invalid (this would be the MS windows way) and letting the event handler take care of it, but I would like to understand what goes on inside X11 to make this happen.