#define _MILSKO #define USE_X11 #include "mdm.h" #include static pid_t xserver; static int got_usr1; Display* xdisplay; pthread_t xthread; pthread_mutex_t xmutex; static void catch_usr1(int sig) { (void)sig; got_usr1 = 1; } int launch_x(void) { got_usr1 = 0; signal(SIGUSR1, catch_usr1); if((xserver = fork()) == 0) { signal(SIGUSR1, SIG_IGN); execlp("X", "X", ":0", NULL); _exit(-1); } else { while(!got_usr1) { if(waitpid(xserver, NULL, WNOHANG) != 0) { fprintf(stderr, "server died. what happened?\n"); return 1; } usleep(1000); } } setenv("DISPLAY", ":0", 1); return 0; } static int wm_detected = 0; static int wm_detect(Display* disp, XErrorEvent* ev) { (void)disp; (void)ev; wm_detected = 1; } static void* x11_thread_routine(void* arg) { while(1) { pthread_mutex_lock(&xmutex); if(root != NULL) { pthread_mutex_unlock(&xmutex); break; } pthread_mutex_unlock(&xmutex); } loop_x(); XCloseDisplay(xdisplay); return NULL; } int init_x(void) { XColor bg; void* old; xdisplay = XOpenDisplay(NULL); bg.red = 0x1c * 256; bg.green = 0x45 * 256; bg.blue = 0x73 * 256; XAllocColor(xdisplay, DefaultColormap(xdisplay, DefaultScreen(xdisplay)), &bg); XSetWindowBackground(xdisplay, DefaultRootWindow(xdisplay), bg.pixel); XClearWindow(xdisplay, DefaultRootWindow(xdisplay)); XFlush(xdisplay); old = XSetErrorHandler(wm_detect); XSelectInput(xdisplay, DefaultRootWindow(xdisplay), SubstructureRedirectMask); XSync(xdisplay, False); XSetErrorHandler(old); if(wm_detected) { fprintf(stderr, "WM or something seem to be running\n"); return 1; } pthread_mutex_init(&xmutex, NULL); pthread_create(&xthread, NULL, x11_thread_routine, NULL); return 0; } int x_width(void) { return DisplayWidth(xdisplay, DefaultScreen(xdisplay)); } int x_height(void) { return DisplayHeight(xdisplay, DefaultScreen(xdisplay)); } typedef struct window { MwWidget frame; Window client; } window_t; void loop_x(void) { XEvent ev; window_t* frames = NULL; while(1) { XNextEvent(xdisplay, &ev); if(ev.type == MapRequest) { XWindowAttributes xwa; window_t w; int i; pthread_mutex_lock(&xmutex); for(i = 0; i < arrlen(frames); i++) { if(frames[i].frame->lowlevel->x11.window == ev.xmaprequest.window) { XMapWindow(xdisplay, ev.xmaprequest.window); XReparentWindow(xdisplay, frames[i].client, frames[i].frame->lowlevel->x11.window, MwDefaultBorderWidth(root), MwDefaultBorderWidth(root)); XMapWindow(xdisplay, frames[i].client); XFlush(xdisplay); break; } } if(i != arrlen(frames)) { pthread_mutex_unlock(&xmutex); continue; } XGetWindowAttributes(xdisplay, ev.xmaprequest.window, &xwa); w.client = ev.xmaprequest.window; w.frame = MwVaCreateWidget(MwWindowClass, "frame", root, xwa.x - MwDefaultBorderWidth(root), xwa.y - MwDefaultBorderWidth(root), xwa.width + MwDefaultBorderWidth(root) * 2, xwa.height + MwDefaultBorderWidth(root) * 2, MwNhasBorder, 1, MwNinverted, 0, NULL); XGetWindowAttributes(xdisplay, w.client, &xwa); XSelectInput(xdisplay, w.client, xwa.your_event_mask | StructureNotifyMask); arrput(frames, w); pthread_mutex_unlock(&xmutex); } else if(ev.type == UnmapNotify) { int i; int c = 0; pthread_mutex_lock(&xmutex); for(i = 0; i < arrlen(frames); i++) { if(frames[i].client == ev.xunmap.window) { MwDestroyWidget(frames[i].frame); arrdel(frames, i); if(i == 0) c = 1; break; } } pthread_mutex_unlock(&xmutex); if(c) break; } } } void kill_x(void) { kill(xserver, SIGINT); waitpid(xserver, NULL, 0); }