#include "wm.h" #include #include #include Monitor wm_monitor_open(Display *d, XineramaScreenInfo info) { Monitor m = { .display = d, .info = info }; return m; } void wm_monitors_open_all(Display *d) { int count; XineramaScreenInfo *xsi = XineramaQueryScreens(d, &count); if (!xsi) { printf("wm: Could not open display. Exiting.\n"); exit(1); } wm_monitors = malloc(count * sizeof(Monitor)); for (int i = 0; i < count; i++) { *(wm_monitors + i) = wm_monitor_open(d, *(xsi + i)); //cfg wm_monitors[i].wscount = 9; wm_monitors[i].wss = malloc(wm_smon->wscount*sizeof(int)); wm_monitors[i].selws = wm_monitors[i].wss[0]; for (int j = 0; j < wm_monitors[i].wscount; j++) wm_monitors[i].wss[i] = j; wm_monitors[i].clients = NULL; } wm_smon = &wm_monitors[0]; wm_smon->clients = &wm_root; } Display* wm_connect_display() { Display *d; if (!(d = XOpenDisplay(NULL))) { printf("wm: Could not open display. Exiting.\n"); exit(1); } return d; } static int wm_xerror_handler(Display *displau, XErrorEvent *e) { if (e->error_code == BadAccess) { wm_other_wm = true; } return 0; } static int wm_other_wm_handler(Display *displau, XErrorEvent *e) { printf("wm: Error occured. %d\n", e->error_code); return 0; } void wm_create_handler(XCreateWindowEvent e) { Client *nc = malloc(sizeof(Client)); Client *c; nc->wn = e.window; nc->m = wm_smon; nc->ws = nc->m->selws; nc->hidden = true; if (wm_smon->clients == NULL) { wm_smon->clients = nc; nc->prev = NULL; } else { LAST_WINDOW(c, wm_smon) c->next = nc; nc->prev = c; nc->next = NULL; } } // TODO void wm_destroy_handler(XDestroyWindowEvent e) { Client *c; // TODO: make function for linked list management for (c = wm_smon->clients; c; c = c->next) { if (e.window == c->wn) { if (c == wm_smon->clients) { if (c->next) wm_smon->clients = c->next; else wm_smon->clients = NULL; } else { if (!c->next) c->prev->next = NULL; else { c->prev->next = c->next; c->next->prev = c->prev; } } free(c); } } } void wm_reparent_handler(XReparentEvent e) { } // TODO void wm_configure_handler(XConfigureRequestEvent e) { Client *c; XWindowChanges ch; int cc_sws = 0; for (c = wm_smon->clients; c; c = c->next) { if (c->ws == wm_smon->selws) { cc_sws++; } } FIND_WINDOW(c, wm_smon, e.window) // dynamic if (cc_sws == 0) { c->x = 0; c->y = 0; c->w = wm_smon->info.width; c->h = wm_smon->info.height; } else { // TODO // c.x = m.h / cc_sws; } XConfigureWindow(wm_display, c->wn, e.value_mask, &ch); } void wm_map_handler(XMapRequestEvent e) { Client *c; XMapWindow(wm_display, e.window); FIND_WINDOW(c, wm_smon, e.window) c->hidden = false; } // TODO XWindowChanges wm_client_to_xwchanges(Client c) { XWindowChanges ch; ch.x = c.x; ch.y = c.y; ch.width = c.w; ch.height = c.h; ch.border_width = 0; ch.stack_mode = Above; return ch; } void wm_create_client(Window w) { } void wm_client_hide(Client *c) { if (c->hidden) return; c->hidden = true; XUnmapWindow(wm_display, c->wn); } void wm_client_show(Client *c) { if (!c->hidden) return; c->hidden = false; XMapWindow(wm_display, c->wn); } void wm_switch_ws(int ws) { if (ws > wm_smon->wscount) return; Client *c; for (c = wm_smon->clients; c; c = c->next) { if (c->ws == wm_smon->selws) { wm_client_hide(c); } } wm_smon->selws = ws; for (c = wm_smon->clients; c; c = c->next) { if (c->ws == wm_smon->selws) { wm_client_show(c); } } } void wm_mainloop() { while (1) { XEvent e; XNextEvent(wm_display, &e); switch (e.type) { case CreateNotify: wm_create_handler(e.xcreatewindow); break; case DestroyNotify: wm_destroy_handler(e.xdestroywindow); break; case ReparentNotify: wm_reparent_handler(e.xreparent); break; case ConfigureRequest: wm_configure_handler(e.xconfigurerequest); break; } } } void wm_init() { Display *d = wm_connect_display(); wm_display = d; wm_monitors_open_all(d); wm_root.wn = DefaultRootWindow(d); wm_last_client = &wm_root; XSetErrorHandler(&wm_other_wm_handler); XSelectInput(d, wm_root.wn, SubstructureRedirectMask | SubstructureNotifyMask); XSync(d, false); if (wm_other_wm) { printf("wm: Detected other window manager. Exiting.\n"); exit(1); } XSetErrorHandler(&wm_xerror_handler); wm_mainloop(); }