Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does it matter when you draw in XWindows?

Tags:

c

linux

x11

xlib

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.

like image 703
Scott Franco Avatar asked Dec 17 '22 17:12

Scott Franco


1 Answers

X servers are not required to provide backing store by themselves, so Expose events are sent when the window needs to be drawn. This is the same functionality that happens in other environments also. In the beginning you can draw, but the X server may not have set up the window properly yet and will later report to you when it’s ready to have contents drawn on to screen. The drawing is kind of directly on screen, not to a backing buffer, so it has to be done every time the window is brought in front.

As for requesting a redraw yourself you can use XSendEvent to send an Expose event yourself and then X will relay it to your event loop. So it’s practically exactly the same as Windows does.

like image 145
Sami Kuhmonen Avatar answered Dec 20 '22 07:12

Sami Kuhmonen