/* A hello-world program with XPutImage() and event handling. * * If you want to write a program that puts graphics on the screen, * regardless of how you do it, you need a certain amount of * system-dependent boilerplate just to open a window and slam a * framebuffer into it and get notified of mouse and keyboard events. * These two pages of total BULLSHIT are what you * need to do it with Xlib. * * This doesn’t cover the need to poll for events so you can do * background work when no events need processing; for that you can * use XPending(display) to see if events have been received and * select() on the ConnectionNumber(display) to see if any might be * waiting to be received. * * See xshmu.c and friends for a saner approach using XShmPutImage. */ #include #include #include #include #include #include #include void err(char *fmt, ...); void draw(uint32_t *buf, int width, int height, int cx, int cy); void redraw(Display *d, Window w, int screen, XImage *im, int ww, int hh); int main(int argc, char **argv) { int width = 640, height = 480; uint32_t *buf = malloc(width*height*sizeof(*buf)); if (!buf) { err("malloc"); } Display *d = XOpenDisplay(NULL); if (!d) { err("XOpenDisplay"); } int screen = DefaultScreen(d); Window w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, /* x, y */ width, height, 0, 0, /* borderwidth, border */ WhitePixel(d, screen)); XSelectInput(d, w, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | StructureNotifyMask); XMapWindow(d, w); draw(buf, width, height, width/2, height/2); XImage *im = XCreateImage(d, DefaultVisual(d, screen), 24, /* depth */ ZPixmap, /* format */ 0, /* offset (in X pixels) */ (char*)buf, /* data */ width, height, 32, /* bitmap_pad */ 0); /* let Xlib calculate bytes_per_line */ XEvent ev; for (;;) { XNextEvent(d, &ev); if (ev.type == Expose) { redraw(d, w, screen, im, width, height); } else if (ev.type == KeyPress) { break; } else if (ev.type == MotionNotify) { draw(buf, width, height, ev.xmotion.x, ev.xmotion.y); redraw(d, w, screen, im, width, height); } } XDestroyImage(im); XCloseDisplay(d); return 0; } void draw(uint32_t *buf, int width, int height, int cx, int cy) { for (int yy = 0; yy < height; yy++) { for (int xx = 0; xx < width; xx++) { buf[yy*width + xx] = (xx-cx)*(yy-cy); } } } void redraw(Display *d, Window w, int screen, XImage *im, int ww, int hh) { XPutImage(d, w, DefaultGC(d, screen), im, 0, 0, /* src_x, src_y */ 0, 0, /* dest_x, dest_y */ ww, hh); } void err(char *fmt, ...) { va_list args; va_start(args, fmt); perror(fmt); vfprintf(stderr, fmt, args); exit(-1); va_end(args); }