#include "xsimple.h" #include #include #include XVARS xv; static Atom wm_protocols, wm_delete_window; static void cleanup(void) { XCloseDisplay(xv.d); } static void sighandler(int sig) { xv.sig++; } void xinit(char *appname, char *classname, char *winname, int x, int y, int width, int height, int resizable, char *bgcolor, char *fgcolor, long evtmask) { unsigned long bgc, fgc; XClassHint *ch; XSizeHints *sh; if (! (xv.d = XOpenDisplay(NULL))) { fprintf(stderr, "xinit(): Error opening display\n"); exit(1); } atexit(cleanup); xv.s = DefaultScreen(xv.d); xv.v = DefaultVisual(xv.d, xv.s); xv.depth = DefaultDepth(xv.d, xv.s); xv.cmap = DefaultColormap(xv.d, xv.s); xv.x = x; xv.y = y; xv.dwidth = DisplayWidth(xv.d, xv.s); xv.dheight = DisplayHeight(xv.d, xv.s); xv.width = (width == 0 ? xv.dwidth : width); xv.height = (height == 0 ? xv.dheight : height); xv.bwidth = xv.twidth = 0; if ((xv.v->class != TrueColor) || (xv.depth != 16 && xv.depth != 24)) { fprintf(stderr, "xinit(): Unsupported visual\n"); exit(1); } xv.sig = 0; signal(SIGHUP, sighandler); signal(SIGINT, sighandler); signal(SIGTERM, sighandler); initcolors(); bgc = getnamedcolor(bgcolor, NULL); fgc = getnamedcolor(fgcolor, NULL); xv.w = XCreateSimpleWindow(xv.d, DefaultRootWindow(xv.d), xv.x, xv.y, xv.width, xv.height, 0, fgc, bgc); XSelectInput(xv.d, xv.w, StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask | evtmask); xv.pmap = mkpixmap(resizable ? xv.dwidth : xv.width, resizable ? xv.dheight : xv.height, xv.depth); xv.gc = XCreateGC(xv.d, xv.pmap, 0, NULL); ch = XAllocClassHint(); ch->res_name = appname; ch->res_class = classname; XSetClassHint(xv.d, xv.w, ch); settitle(winname); sh = XAllocSizeHints(); sh->flags = USPosition | USSize | PMaxSize | (resizable ? 0 : PMinSize); sh->x = xv.x; sh->y = xv.y; sh->width = xv.width; sh->height = xv.height; if (resizable) { sh->max_width = xv.dwidth; sh->max_height = xv.dheight; } else { sh->min_width = sh->max_width = xv.width; sh->min_height = sh->max_height = xv.height; } XSetWMNormalHints(xv.d, xv.w, sh); wm_protocols = XInternAtom(xv.d, "WM_PROTOCOLS", False); wm_delete_window = XInternAtom(xv.d, "WM_DELETE_WINDOW", False); XSetWMProtocols(xv.d, xv.w, &wm_delete_window, 1); XMapWindow(xv.d, xv.w); } int getevent(XEvent *event) { XEvent e; if (xv.sig) exit(0); if (! XPending(xv.d)) return 0; XNextEvent(xv.d, &e); switch (e.type) { case ReparentNotify: { Window rootw, parentw = xv.w, currentw, child, *children; int nchildren; int x1, y1, x2, y2; XTranslateCoordinates(xv.d, xv.w, DefaultRootWindow(xv.d), 0, 0, &x1, &y1, &child); do { currentw = parentw; XQueryTree(xv.d, currentw, &rootw, &parentw, &children, &nchildren); XFree(children); } while (parentw != rootw); XTranslateCoordinates(xv.d, currentw, DefaultRootWindow(xv.d), 0, 0, &x2, &y2, &child); xv.bwidth = x1 - x2; xv.twidth = y1 - y2; } break; case ConfigureNotify: { XConfigureEvent *ce = (XConfigureEvent *)&e; Window child; XTranslateCoordinates(xv.d, xv.w, DefaultRootWindow(xv.d), 0, 0, &xv.x, &xv.y, &child); xv.width = ce->width; xv.height = ce->height; } break; case ClientMessage: if (e.xclient.message_type == wm_protocols && e.xclient.data.l[0] == wm_delete_window) exit(0); break; } *event = e; return 1; } void doexpose(XEvent *event) { for (;;) { XExposeEvent *ee = (XExposeEvent *)event; update(ee->x, ee->y, ee->width, ee->height); if (! ee->count) break; XNextEvent(xv.d, event); } } void update(int x, int y, int width, int height) { if (x == 0 && y == 0 && width == 0 && height == 0) { width = xv.width; height = xv.height; } XSync(xv.d, False); XCopyArea(xv.d, xv.pmap, xv.w, xv.gc, x, y, width, height, x, y); XSync(xv.d, False); } .