diff options
Diffstat (limited to 'dminiwm.c')
| -rw-r--r-- | dminiwm.c | 793 |
1 files changed, 0 insertions, 793 deletions
diff --git a/dminiwm.c b/dminiwm.c deleted file mode 100644 index a194d9a..0000000 --- a/dminiwm.c +++ /dev/null @@ -1,793 +0,0 @@ -/* Based on: - * - catwm at https://github.com/pyknite/catwm - * - 2wm at http://hg.suckless.org/2wm/ - * - dwm at http://dwm.suckless.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#include <sys/wait.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <X11/Xproto.h> -#include <X11/Xatom.h> - -#define LENGTH(x) (sizeof(x)/sizeof(*x)) - -enum { - WM_PROTOCOLS, - WM_DELETE_WINDOW, - _NET_WM_WINDOW_TYPE, - _NET_WM_WINDOW_TYPE_UTILITY, - _NET_WM_WINDOW_TYPE_DOCK, - _NET_WM_WINDOW_TYPE_SPLASH, - _NET_WM_WINDOW_TYPE_DIALOG, - _NET_WM_WINDOW_TYPE_NOTIFICATION, - ATOM_COUNT -}; - -/* layout modes */ -enum { - TILE, - MONOCLE, - BSTACK, - GRID, -}; - -/* structs */ -typedef union { - const char** com; - const int i; -} Arg; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*function)(const Arg arg); - const Arg arg; -} key; - -typedef struct client { - struct client *next; - struct client *prev; - Window win; -} client; - -typedef struct { - int master_size; - int mode; - int growth; - client *head; - client *current; - Bool showpanel; -} desktop; - -typedef struct { - const char *class; - const int desktop; - const Bool follow; -} AppRule; - -/* Functions */ -static void add_window(Window w); -static void buttonpressed(XEvent *e); -static void change_desktop(const Arg arg); -static void client_to_desktop(const Arg arg); -static void destroynotify(XEvent *e); -static void enternotify(XEvent *e); -static void die(const char* errstr, ...); -static int xerrorstart(); -static unsigned long getcolor(const char* color); -static void grabkeys(void); -static void keypress(XEvent *e); -static void killclient(); -static void maprequest(XEvent *e); -static void move_down(); -static void move_up(); -static void rotate_desktop(const Arg arg); -static void next_win(); -static void prev_win(); -static void cleanup(void); -static void quit(const Arg arg); -static void removeclient(client *c); -static void resize_master(const Arg arg); -static void resize_stack(const Arg arg); -static void save_desktop(int i); -static void select_desktop(int i); -static void togglepanel(); -static void deletewindow(Window w); -static void setup(void); -static void sigchld(); -static void spawn(const Arg arg); -static void run(void); -static void swap_master(); -static void last_desktop(); -static void switch_mode(const Arg arg); -static void tile(void); -static void update_current(void); - -#include "config.h" - -/* variables */ -static Bool running = True; -static Bool showpanel = SHOW_PANEL; -static int retval = 0; -static int current_desktop = 0; -static int previous_desktop = 0; -static int growth = 0; -static int mode = DEFAULT_MODE; -static int master_size; -static int sh; -static int sw; -static int screen; -static int xerror(Display *dis, XErrorEvent *ee); -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int win_focus; -static unsigned int win_unfocus; -static unsigned int numlockmask = 0; /* dynamic key lock mask */ -static Display *dis; -static Window root; -static client *head = NULL; -static client *current = NULL; -static Atom atoms[ATOM_COUNT]; -static desktop desktops[DESKTOPS]; - -/* events array */ -static void (*events[LASTEvent])(XEvent *e) = { - [KeyPress] = keypress, - [MapRequest] = maprequest, - [EnterNotify] = enternotify, - [ButtonPress] = buttonpressed, - [DestroyNotify] = destroynotify, -}; - -/* ~~~ Window Management ~~~ */ -void add_window(Window w) { - client *c, *t; - - if(!(c = (client *)calloc(1, sizeof(client)))) - die("error: could not calloc() %u bytes\n", sizeof(client)); - - if(!head) { - c->win = w; - head = c; - } else if(ATTACH_ASIDE) { - for(t=head; t->next; t=t->next); - c->prev = t; - c->win = w; - t->next = c; - } else { - t = head; - c->next = t; - t->prev = c; - c->win = w; - head = c; - } - - current = c; - save_desktop(current_desktop); - - if(FOLLOW_MOUSE) XSelectInput(dis, c->win, EnterWindowMask); -} - -void removeclient(client *c) { - if(!c->prev) { /* w is head */ - if(!c->next) { /* head is only window on screen */ - free(head); - head = NULL; - } else { /* more windows on screen */ - head->next->prev = NULL; - head = head->next; - } - current = head; - } else { /* w is on stack */ - if(!c->next) { /* w is last window on screen */ - c->prev->next = NULL; - } else { /* w is somewhere in the middle */ - c->next->prev = c->prev; - c->prev->next = c->next; - } - current = c->prev; - } - - save_desktop(current_desktop); - tile(); - if(mode == MONOCLE && current) - XMapWindow(dis, current->win); - update_current(); -} - -void killclient() { - if(!current) return; - deletewindow(current->win); - removeclient(current); -} - -void next_win() { - if(!current || (!current->next && !current->prev)) return; - if(mode == MONOCLE) XUnmapWindow(dis, current->win); - current = (current->next) ? current->next : head; - if(mode == MONOCLE) XMapWindow(dis, current->win); - update_current(); -} - -void prev_win() { - if(!current || (!current->next && !current->prev)) return; - if(mode == MONOCLE) XUnmapWindow(dis, current->win); - if(current->prev) current = current->prev; - else while(current->next) current=current->next; - if(mode == MONOCLE) XMapWindow(dis, current->win); - update_current(); -} - -void move_down() { - if(!current || current == head || !current->next) return; - Window tmpwin = current->win; - current->win = current->next->win; - current->next->win = tmpwin; - current = current->next; - save_desktop(current_desktop); - tile(); - update_current(); -} - -void move_up() { - if(!current || current == head || !current->prev) return; - Window tmpwin = current->win; - current->win = current->prev->win; - current->prev->win = tmpwin; - current = current->prev; - save_desktop(current_desktop); - tile(); - update_current(); -} - -void swap_master() { - if(!current || !head->next || mode == MONOCLE) return; - Window tmpwin = head->win; - current = (current == head) ? head->next : current; - head->win = current->win; - current->win = tmpwin; - current = head; - save_desktop(current_desktop); - tile(); - update_current(); -} - -/* ~~~ Desktop Management ~~~ */ -void change_desktop(const Arg arg) { - if(arg.i == current_desktop) return; - previous_desktop = current_desktop; - - /* save current desktop settings and unmap windows */ - save_desktop(current_desktop); - for(client *c=head; c; c=c->next) - XUnmapWindow(dis, c->win); - - /* read new desktop properties, tile and map new windows */ - select_desktop(arg.i); - tile(); - if(mode == MONOCLE && current) XMapWindow(dis, current->win); - else for(client *c=head; c; c=c->next) XMapWindow(dis, c->win); - - update_current(); -} - -void last_desktop() { - change_desktop((Arg){.i = previous_desktop}); -} - -void rotate_desktop(const Arg arg) { - change_desktop((Arg){.i = (current_desktop + DESKTOPS + arg.i) % DESKTOPS}); -} - -void client_to_desktop(const Arg arg) { - if(arg.i == current_desktop || !current) return; - - client *c = current; - int cd = current_desktop; - - select_desktop(arg.i); - add_window(c->win); - save_desktop(arg.i); - - select_desktop(cd); - XUnmapWindow(dis, c->win); - removeclient(c); - save_desktop(cd); - - tile(); - update_current(); - - if(FOLLOW_WINDOW) change_desktop(arg); -} - -void save_desktop(int i) { - desktops[i].master_size = master_size; - desktops[i].mode = mode; - desktops[i].growth = growth; - desktops[i].head = head; - desktops[i].current = current; - desktops[i].showpanel = showpanel; -} - -void select_desktop(int i) { - if(current_desktop == i) return; - master_size = desktops[i].master_size; - mode = desktops[i].mode; - growth = desktops[i].growth; - head = desktops[i].head; - current = desktops[i].current; - showpanel = desktops[i].showpanel; - current_desktop = i; -} - -void togglepanel() { - showpanel = !showpanel; - save_desktop(current_desktop); - tile(); -} - -void tile(void) { - if(!head) return; /* no need to arange anything */ - - client *c; - int n = 0; - int x = 0; - int panel_height = (showpanel) ? PANEL_HEIGHT : 0; - int y = (TOP_PANEL) ? panel_height : 0; - sh = XDisplayHeight(dis, screen) - panel_height - BORDER_WIDTH; - - if(!head->next) - XMoveResizeWindow(dis, head->win, 0, y, sw + 2*BORDER_WIDTH, sh + 2*BORDER_WIDTH); - else switch(mode) { - case TILE: - /* master window */ - XMoveResizeWindow(dis, head->win, 0, y, master_size - BORDER_WIDTH, sh - BORDER_WIDTH); - /* stack */ - for(n=0, c=head->next; c; c=c->next, ++n); /* count windows */ - growth = (n == 1) ? 0 : growth; /* if only one window don't care about growth */ - XMoveResizeWindow(dis, head->next->win, master_size + BORDER_WIDTH, y, sw - master_size - 2*BORDER_WIDTH, sh/n + growth - BORDER_WIDTH); - y += sh/n + growth; - for(c=head->next->next; c; c=c->next) { - XMoveResizeWindow(dis, c->win, master_size + BORDER_WIDTH, y, sw - master_size - 2*BORDER_WIDTH, sh/n - growth/(n-1) - BORDER_WIDTH); - y += sh/n - growth / (n-1); - } - break; - case MONOCLE: - for(c=head; c; c=c->next) - XMoveResizeWindow(dis, c->win, 0, y, sw + 2*BORDER_WIDTH, sh + 2*BORDER_WIDTH); - break; - case BSTACK: - /* master window */ - XMoveResizeWindow(dis, head->win, 0, y, sw - BORDER_WIDTH, master_size - BORDER_WIDTH); - /* stack */ - for(n=0, c=head->next; c; c=c->next, ++n); /* count windows */ - growth = (n == 1) ? 0 : growth; /* if only one window don't care about growth */ - XMoveResizeWindow(dis, head->next->win, 0, y + master_size + BORDER_WIDTH, sw/n + growth - BORDER_WIDTH, sh - master_size - 2*BORDER_WIDTH); - x = sw/n + growth; - for(c=head->next->next; c; c=c->next) { - XMoveResizeWindow(dis, c->win, x, y + master_size + BORDER_WIDTH, sw/n - growth/(n-1) - BORDER_WIDTH, sh-master_size - 2*BORDER_WIDTH); - x += sw/n - growth/(n-1); - } - break; - case GRID: - { - int xpos = 0; - int wdt = 0; - int ht = 0; - - for(c=head; c; c=c->next) ++x; - - for(c=head; c; c=c->next) { - ++n; - if(x >= 7) { - wdt = sw/3 - BORDER_WIDTH; - ht = sh/3 - BORDER_WIDTH; - if(n == 1 || n == 4 || n == 7) - xpos = 0; - if(n == 2 || n == 5 || n == 8) - xpos = sw/3 + BORDER_WIDTH; - if(n == 3 || n == 6 || n == 9) - xpos = 2*(sw/3) + BORDER_WIDTH; - if(n == 4 || n == 7) - y += sh/3 + BORDER_WIDTH; - if(n == x && n == 7) - wdt = sw - BORDER_WIDTH; - if(n == x && n == 8) - wdt = 2*(sw/3) - BORDER_WIDTH; - } else - if(x >= 5) { - wdt = sw/3 - BORDER_WIDTH; - ht = sh/2 - BORDER_WIDTH; - if(n == 1 || n == 4) - xpos = 0; - if(n == 2 || n == 5) - xpos = sw/3 + BORDER_WIDTH; - if(n == 3 || n == 6) - xpos = 2*(sw/3) + BORDER_WIDTH; - if(n == 4) - y += sh/2; // + BORDER_WIDTH; - if(n == x && n == 5) - wdt = 2*(sw/3) - BORDER_WIDTH; - } else { - if(x > 2) { - if(n == 1 || n == 2) - ht = sh/2 + growth - BORDER_WIDTH; - if(n >= 3) - ht = sh/2 - growth - 2*BORDER_WIDTH; - } - else - ht = sh - BORDER_WIDTH; - if(n == 1 || n == 3) { - xpos = 0; - wdt = master_size - BORDER_WIDTH; - } - if(n == 2 || n == 4) { - xpos = master_size+BORDER_WIDTH; - wdt = sw - master_size - 2*BORDER_WIDTH; - } - if(n == 3) - y += sh/2 + growth + BORDER_WIDTH; - if(n == x && n == 3) - wdt = sw - BORDER_WIDTH; - } - XMoveResizeWindow(dis, c->win, xpos, y, wdt, ht); - } - } - break; - } - free(c); -} - -void update_current(void) { - client *c; - - for(c=head; c; c=c->next) { - if(!head->next || mode == MONOCLE) - XSetWindowBorderWidth(dis, c->win, 0); - else - XSetWindowBorderWidth(dis, c->win, BORDER_WIDTH); - - if(current == c) { /* highlight current window */ - XSetWindowBorder(dis, c->win, win_focus); - XSetInputFocus(dis, c->win, RevertToParent, CurrentTime); - XRaiseWindow(dis, c->win); - if(CLICK_TO_FOCUS) XUngrabButton(dis, AnyButton, AnyModifier, c->win); - } else { - XSetWindowBorder(dis, c->win, win_unfocus); - if(CLICK_TO_FOCUS) XGrabButton(dis, AnyButton, AnyModifier, c->win, True, - ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None); - } - } - free(c); - XSync(dis, False); -} - -void switch_mode(const Arg arg) { - if(mode == arg.i) return; - if(mode == MONOCLE) for(client *c=head; c; c=c->next) XMapWindow(dis, c->win); - mode = arg.i; - if(mode == TILE || mode == GRID) master_size = sw * MASTER_SIZE; - else if(mode == BSTACK) master_size = sh * MASTER_SIZE; - tile(); - update_current(); -} - -void resize_master(const Arg arg) { - master_size += arg.i; - tile(); -} - -void resize_stack(const Arg arg) { - growth += arg.i; - tile(); -} - -/* ~~~ Keyboard Management ~~~ */ -void grabkeys(void) { - KeyCode code; - - XUngrabKey(dis, AnyKey, AnyModifier, root); - for(unsigned int i=0; i<LENGTH(keys); i++) { - code = XKeysymToKeycode(dis, keys[i].keysym); - XGrabKey(dis, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync); - XGrabKey(dis, code, keys[i].mod | LockMask, root, True, GrabModeAsync, GrabModeAsync); - XGrabKey(dis, code, keys[i].mod | numlockmask, root, True, GrabModeAsync, GrabModeAsync); - XGrabKey(dis, code, keys[i].mod | numlockmask | LockMask, root, True, GrabModeAsync, GrabModeAsync); - } -} - -void keypress(XEvent *e) { - static unsigned int len = sizeof keys / sizeof keys[0]; - unsigned int i; - KeySym keysym; - XKeyEvent *ev = &e->xkey; - - keysym = XKeycodeToKeysym(dis, (KeyCode)ev->keycode, 0); - for(i = 0; i < len; i++) - if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) && keys[i].function) - keys[i].function(keys[i].arg); -} - -/* ~~~ Signal Management ~~~ */ -void maprequest(XEvent *e) { - XMapRequestEvent *ev = &e->xmaprequest; - static XWindowAttributes wa; - - if(!XGetWindowAttributes(dis, ev->window, &wa)) return; - if(wa.override_redirect) return; - - /* window is transient */ - Window trans; - if(XGetTransientForHint(dis, ev->window, &trans) && trans) { - add_window(ev->window); - XMapWindow(dis, ev->window); - XSetInputFocus(dis, ev->window, RevertToParent, CurrentTime); - XRaiseWindow(dis, ev->window); - XFree(&trans); - return; - } - - /* window type is not normal (_NET_WM_WINDOW_TYPE_NORMAL) */ - Atom realType, *wintype; - int realFormat; - unsigned long count, extra; - unsigned char *data; - if(XGetWindowProperty(dis, ev->window, atoms[_NET_WM_WINDOW_TYPE], 0, 32, False, - XA_ATOM, &realType, &realFormat, &count, &extra, &data) == Success) - if(realType == XA_ATOM && count) { - wintype = (unsigned long *)data; - if(data) XFree(data); - for(unsigned int i=0; i<count; i++) - if(wintype[i] == atoms[_NET_WM_WINDOW_TYPE_UTILITY] || - wintype[i] == atoms[_NET_WM_WINDOW_TYPE_NOTIFICATION] || - wintype[i] == atoms[_NET_WM_WINDOW_TYPE_SPLASH] || - wintype[i] == atoms[_NET_WM_WINDOW_TYPE_DIALOG] || - wintype[i] == atoms[_NET_WM_WINDOW_TYPE_DOCK] ){ - add_window(ev->window); - XMapWindow(dis, ev->window); - XSetInputFocus(dis, ev->window, RevertToParent, CurrentTime); - XRaiseWindow(dis, ev->window); - return; - } - } - - /* window is normal and has a rule set */ - XClassHint ch = {0, 0}; - if(XGetClassHint(dis, ev->window, &ch)) - for(unsigned int i=0; i<LENGTH(rules); i++) - if(strcmp(ch.res_class, rules[i].class) == 0) { - int cd = current_desktop; - save_desktop(cd); - select_desktop(rules[i].desktop); - add_window(ev->window); - select_desktop(cd); - if(cd == rules[i].desktop) { - XMapWindow(dis, ev->window); - tile(); - update_current(); - } else if(rules[i].follow) - change_desktop((Arg){.i = rules[i].desktop}); - if(ch.res_class) XFree(ch.res_class); - if(ch.res_name) XFree(ch.res_name); - return; - } - - /* window is normal and has no rule set */ - add_window(ev->window); - XMapWindow(dis, ev->window); - tile(); - update_current(); -} - -void destroynotify(XEvent *e) { - client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - int cd = current_desktop; - Bool found = False; - - save_desktop(cd); - for(int d=0; d<DESKTOPS && !found; select_desktop(d++)) - for(c=head; c; c=c->next) - if((found = ev->window == c->win)) { - removeclient(c); - break; - } - select_desktop(cd); -} - -void enternotify(XEvent *e) { - client *c; - XCrossingEvent *ev = &e->xcrossing; - - if(FOLLOW_MOUSE) { - if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; - for(c=head; c; c=c->next) - if(ev->window == c->win) { - current = c; - update_current(); - return; - } - } -} - -void buttonpressed(XEvent *e) { - client *c; - XButtonPressedEvent *ev = &e->xbutton; - - if(CLICK_TO_FOCUS && ev->window != current->win && ev->button == Button1) - for(c=head; c; c=c->next) - if(ev->window == c->win) { - current = c; - update_current(); - return; - } -} - -void deletewindow(Window w) { - XEvent ev; - ev.type = ClientMessage; - ev.xclient.window = w; - ev.xclient.message_type = atoms[WM_PROTOCOLS]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = atoms[WM_DELETE_WINDOW]; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dis, w, False, NoEventMask, &ev); -} - -unsigned long getcolor(const char* color) { - Colormap map = DefaultColormap(dis, screen); - XColor c; - - if(!XAllocNamedColor(dis, map, color, &c, &c)) - die("error: cannot allocate color '%s'\n", c); - return c.pixel; -} - -void quit(const Arg arg) { - retval = arg.i; - running = False; -} - -void cleanup(void) { - Window root_return; - Window parent_return; - Window *children; - unsigned int nchildren; - - XUngrabKey(dis, AnyKey, AnyModifier, root); - - XQueryTree(dis, root, &root_return, &parent_return, &children, &nchildren); - for(unsigned int i = 0; i < nchildren; i++) - deletewindow(children[i]); - if(children) XFree(children); - - XSync(dis, False); - XSetInputFocus(dis, PointerRoot, RevertToPointerRoot, CurrentTime); -} - -void setup(void) { - sigchld(); - - screen = DefaultScreen(dis); - root = RootWindow(dis, screen); - - sw = XDisplayWidth(dis, screen) - BORDER_WIDTH; - sh = XDisplayHeight(dis, screen) - ((showpanel) ? PANEL_HEIGHT : 0) - BORDER_WIDTH; - master_size = ((mode == BSTACK) ? sh : sw) * MASTER_SIZE; - for(int i=0; i<DESKTOPS; i++) - save_desktop(i); - change_desktop((Arg){.i = DEFAULT_DESKTOP}); - - win_focus = getcolor(FOCUS); - win_unfocus = getcolor(UNFOCUS); - - XModifierKeymap *modmap = XGetModifierMapping(dis); - for (int k=0; k<8; k++) - for (int j=0; j<modmap->max_keypermod; j++) - if(modmap->modifiermap[modmap->max_keypermod*k + j] == XKeysymToKeycode(dis, XK_Num_Lock)) - numlockmask = (1 << k); - XFreeModifiermap(modmap); - - /* set up atoms for dialog/notification windows */ - atoms[WM_PROTOCOLS] = XInternAtom(dis, "WM_PROTOCOLS", False); - atoms[WM_DELETE_WINDOW] = XInternAtom(dis, "WM_DELETE_WINDOW", False); - atoms[_NET_WM_WINDOW_TYPE] = XInternAtom(dis, "_NET_WM_WINDOW_TYPE", False); - atoms[_NET_WM_WINDOW_TYPE_UTILITY] = XInternAtom(dis, "_NET_WM_WINDOW_TYPE_UTILITY", False); - atoms[_NET_WM_WINDOW_TYPE_DOCK] = XInternAtom(dis, "_NET_WM_WINDOW_TYPE_DOCK", False); - atoms[_NET_WM_WINDOW_TYPE_SPLASH] = XInternAtom(dis, "_NET_WM_WINDOW_TYPE_SPLASH", False); - atoms[_NET_WM_WINDOW_TYPE_DIALOG] = XInternAtom(dis, "_NET_WM_WINDOW_TYPE_DIALOG", False); - atoms[_NET_WM_WINDOW_TYPE_NOTIFICATION] = XInternAtom(dis, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); - - /* check if another window manager is running */ - xerrorxlib = XSetErrorHandler(xerrorstart); - XSelectInput(dis, DefaultRootWindow(dis), SubstructureNotifyMask|SubstructureRedirectMask); - XSync(dis, False); - XSetErrorHandler(xerror); - XSync(dis, False); - - grabkeys(); -} - -int xerrorstart() { - die("error: another window manager is already running\n"); - return -1; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int xerror(Display *dis, XErrorEvent *ee) { - if(ee->error_code == BadWindow - || (ee->error_code == BadMatch && (ee->request_code == X_SetInputFocus || ee->request_code == X_ConfigureWindow)) - || (ee->error_code == BadDrawable && (ee->request_code == X_PolyText8 || ee->request_code == X_PolyFillRectangle - || ee->request_code == X_PolySegment || ee->request_code == X_CopyArea)) - || (ee->error_code == BadAccess && ee->request_code == X_GrabKey)) - return 0; - fprintf(stderr, "error: xerror: request code: %d, error code: %d\n", ee->request_code, ee->error_code); - return xerrorxlib(dis, ee); /* may call exit */ -} - -void sigchld() { - if(signal(SIGCHLD, sigchld) == SIG_ERR) - die("error: can't install SIGCHLD handler\n"); - while(0 < waitpid(-1, NULL, WNOHANG)); -} - -void spawn(const Arg arg) { - if(fork() == 0) { - if(dis) close(ConnectionNumber(dis)); - setsid(); - execvp((char*)arg.com[0], (char**)arg.com); - fprintf(stderr, "error: execvp %s", (char *)arg.com[0]); - perror(" failed"); /* also prints the err msg */ - exit(EXIT_SUCCESS); - } -} - -void run(void) { - XEvent ev; - while(running && !XNextEvent(dis, &ev)) - if(events[ev.type]) - events[ev.type](&ev); -} - -void die(const char *errstr, ...) { - va_list ap; - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - if(argc == 2 && strcmp("-v", argv[1]) == 0) { - fprintf(stdout, "dminiwm-%s\n", VERSION); - return EXIT_SUCCESS; - } else if(argc != 1) - die("usage: dminiwm [-v]\n"); - if(!(dis = XOpenDisplay(NULL))) - die("error: cannot open display\n"); - setup(); - run(); - cleanup(); - XCloseDisplay(dis); - return retval; -} |
