#include #include #include #include int WINDOW_WIDTH = 600; int WINDOW_HEIGHT = 300; void quit(Display *display, Window win, GC gc) { // Clean up and close the window XFreeGC(display, gc); XUnmapWindow(display, win); XDestroyWindow(display, win); XCloseDisplay(display); exit(0); } void redraw(Display *display, Window win, GC gc) { XSetForeground(display, gc, 0xFFFFFF); XFillRectangle(display, win, gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); XFlush(display); } int main() { Display *display; Window win; GC gc; XEvent event; int key, button; Window window_returned; int x, y, screenX, screenY, width, height, borderWidth, depth; unsigned int mask_return; XConfigureEvent cEvent; // Opens connection to X server display = XOpenDisplay(NULL); // Create a simple window, set the title and get the graphics context then // make is visible and get ready to draw win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0x000000, 0xFFFFFF); // Indicate which events we want to handle XSelectInput(display, win, KeyPressMask | // When key is pressed on keyboard KeyReleaseMask | // When key is released on keyboard ButtonPressMask | // When Mouse Button is Pressed ButtonReleaseMask | // When Mouse Button is Released EnterWindowMask | // When Mouse Enters Window LeaveWindowMask | // When mouse Leaves Window PointerMotionMask | // When mouse is moved within window ExposureMask | // When the window is exposed StructureNotifyMask // When there is a change in window structure ); // Create the window and display it XStoreName(display, win, "Event Handler"); gc = XCreateGC(display, win, 0, NULL); XMapWindow(display, win); XFlush(display); usleep(20000); // sleep for 20 milliseconds. // Indicate that we'd like to be able to gracefully handle window closing Atom WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", False); XSetWMProtocols(display, win, &WM_DELETE_WINDOW, 1); // Go into infinite loop handling X11 events while(1) { XNextEvent(display, &event); switch(event.type) { case EnterNotify: printf("Mouse entered window\n"); break; case LeaveNotify: printf("Mouse left window\n"); break; case Expose: printf("Window has been exposed\n"); redraw(display, win, gc); break; case KeyPress: key = event.xkey.keycode; printf("Key has been pressed with keycode: %d\n", key); if (key == 0x09) // Check for ESC key, then quit quit(display, win, gc); break; case KeyRelease: key = event.xkey.keycode; printf("Key has been released with keycode: %d\n", key); break; case ButtonPress: button = event.xbutton.button; XQueryPointer(display, win, &window_returned, &window_returned, &screenX, &screenY, &x, &y, &mask_return); printf("Button %d has been pressed at location (%d, %d)\n", button, x, y); break; case ButtonRelease: button = event.xbutton.button; printf("Button %d has been released\n", button); break; case MotionNotify: XQueryPointer(display, win, &window_returned, &window_returned, &screenX, &screenY, &x, &y, &mask_return); printf("Mouse moved to window position (%d, %d) and screen position (%d, %d)\n", x, y, screenX, screenY); break; case ConfigureNotify: cEvent = event.xconfigure; // Need to check for window resizing, since this type of event can be generated for other reasons too if ((cEvent.width != WINDOW_WIDTH) || (cEvent.height != WINDOW_HEIGHT)) { WINDOW_WIDTH = cEvent.width; WINDOW_HEIGHT = cEvent.height; printf("Window resized to be %d X %d\n", WINDOW_WIDTH, WINDOW_HEIGHT); redraw(display, win, gc); } break; case ClientMessage: printf("Window closed\n"); // We really should check here for other client message types, // but since the only protocol registered above is WM_DELETE_WINDOW, // it is safe to assume that we want the window closing event. quit(display, win, gc); default: printf("Unknown Event\n"); } } }