#include #include #include #include #include #include #include #include #define N_WINDOWS 2 struct window { Window w; int width, height; }; struct data { Display *dpy; struct window windows[N_WINDOWS]; GLXContext ctx; XVisualInfo *visinfo; }; static void redraw(struct data *data, int window_num) { struct window *window = data->windows + window_num; glXMakeCurrent(data->dpy, window->w, data->ctx); glClearColor((window_num % 3) == 0, (window_num % 3) == 1, (window_num % 3) == 2, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glXSwapBuffers(data->dpy, window->w); } static Window make_window(struct data *data, unsigned int width, unsigned int height) { XSetWindowAttributes attr; unsigned long mask; Window root; Window win; root = RootWindow(data->dpy, 0); /* window attributes */ attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(data->dpy, root, data->visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | PointerMotionMask | KeyPressMask; mask = CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(data->dpy, root, 0, 0, width, height, 0, data->visinfo->depth, InputOutput, data->visinfo->visual, mask, &attr); if (!win) { printf("Error: XCreateWindow failed\n"); exit(1); } return win; } static bool handle_event(struct data *data, int window_num, const XEvent *event) { struct window *window = data->windows + window_num; KeySym sym; switch (event->type) { case KeyPress: sym = XKeycodeToKeysym(data->dpy, event->xkey.keycode, 0); if (sym == XK_Escape || sym == XK_q || sym == XK_Q) return false; break; case ConfigureNotify: window->width = event->xconfigure.width; window->height = event->xconfigure.height; break; case Expose: redraw(data, window_num); break; } return true; } static void event_loop(struct data *data) { int window_num; while (1) { XEvent event; XNextEvent(data->dpy, &event); for (window_num = 0; window_num < N_WINDOWS; window_num++) { if (data->windows[window_num].w == event.xany.window) { if (!handle_event(data, window_num, &event)) return; break; } } } } int main(int argc, char *argv[]) { int attrib[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; struct data data; int i; data.dpy = XOpenDisplay(NULL); if (!data.dpy) { printf("Error: XOpenDisplay failed\n"); return 1; } if (!(data.visinfo = glXChooseVisual(data.dpy, 0, attrib))) { printf("Error: couldn't get an RGB, Double-buffered visual\n"); return 1; } if (!(data.ctx = glXCreateContext(data.dpy, data.visinfo, NULL, True))) { printf("Error: glXCreateContext failed\n"); return 1; } for (i = 0; i < N_WINDOWS; i++) { data.windows[i].w = make_window(&data, 800, 600); XMapWindow(data.dpy, data.windows[i].w); } event_loop(&data); glXMakeCurrent(data.dpy, None, NULL); glXDestroyContext(data.dpy, data.ctx); for (i = 0; i < N_WINDOWS; i++) XDestroyWindow(data.dpy, data.windows[i].w); XCloseDisplay(data.dpy); return 0; }