2025-11-18 18:47:11 -07:00
|
|
|
#define _MILSKO
|
|
|
|
|
#define USE_X11
|
|
|
|
|
#include "mdm.h"
|
|
|
|
|
|
2025-11-19 11:21:51 +09:00
|
|
|
#include <stb_ds.h>
|
2025-11-18 18:47:11 -07:00
|
|
|
|
|
|
|
|
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) {
|
2025-12-12 17:13:05 +09:00
|
|
|
while(1) {
|
|
|
|
|
pthread_mutex_lock(&xmutex);
|
|
|
|
|
if(root != NULL) {
|
|
|
|
|
pthread_mutex_unlock(&xmutex);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&xmutex);
|
|
|
|
|
}
|
2025-11-18 18:47:11 -07:00
|
|
|
loop_x();
|
|
|
|
|
XCloseDisplay(xdisplay);
|
2025-12-04 06:45:45 +09:00
|
|
|
return NULL;
|
2025-11-18 18:47:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2025-12-04 06:45:45 +09:00
|
|
|
XReparentWindow(xdisplay, frames[i].client, frames[i].frame->lowlevel->x11.window, MwDefaultBorderWidth(root), MwDefaultBorderWidth(root));
|
2025-12-07 01:47:17 +09:00
|
|
|
XMapWindow(xdisplay, frames[i].client);
|
2025-12-04 06:45:45 +09:00
|
|
|
XFlush(xdisplay);
|
2025-11-18 18:47:11 -07:00
|
|
|
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);
|
|
|
|
|
|
2025-11-22 13:02:24 +09:00
|
|
|
XGetWindowAttributes(xdisplay, w.client, &xwa);
|
|
|
|
|
XSelectInput(xdisplay, w.client, xwa.your_event_mask | StructureNotifyMask);
|
2025-11-18 18:47:11 -07:00
|
|
|
|
|
|
|
|
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);
|
2025-11-22 13:02:24 +09:00
|
|
|
if(i == 0) c = 1;
|
2025-11-18 18:47:11 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&xmutex);
|
|
|
|
|
|
|
|
|
|
if(c) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void kill_x(void) {
|
|
|
|
|
kill(xserver, SIGINT);
|
|
|
|
|
waitpid(xserver, NULL, 0);
|
|
|
|
|
}
|