aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/dwm/dwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/dwm/dwm.c')
-rw-r--r--sys/cmd/dwm/dwm.c1185
1 files changed, 0 insertions, 1185 deletions
diff --git a/sys/cmd/dwm/dwm.c b/sys/cmd/dwm/dwm.c
deleted file mode 100644
index 0567650..0000000
--- a/sys/cmd/dwm/dwm.c
+++ /dev/null
@@ -1,1185 +0,0 @@
-#include "dwm.h"
-
-/* global variables */
-char broken[] = "<broken>";
-char stext[256];
-int scanner;
-int screen;
-int sw, sh; /* X display screen geometry width, height */
-int bh, blw = 0; /* bar geometry */
-int lrpad; /* sum of left and right padding for text */
-int (*xerrorxlib)(Display *, XErrorEvent *);
-uint numlockmask = 0;
-void (*handler[LASTEvent]) (XEvent *) = {
- [ButtonPress] = buttonpress,
- [ClientMessage] = clientmessage,
- [ConfigureRequest] = configurerequest,
- [ConfigureNotify] = configurenotify,
- [DestroyNotify] = destroynotify,
- [EnterNotify] = enternotify,
- [Expose] = expose,
- [FocusIn] = focusin,
- [KeyPress] = keypress,
- [MappingNotify] = mappingnotify,
- [MapRequest] = maprequest,
- [MotionNotify] = motionnotify,
- [PropertyNotify] = propertynotify,
- [UnmapNotify] = unmapnotify
-};
-
-xcb_connection_t *xcon;
-
-Atom wmatom[WMLast] = {0}, netatom[NetLast] = {0};
-int running = 1;
-Cur *cursor[MouseLast] = {0};
-Clr **scheme = nil;
-Display *dpy = nil;
-Drw *drw = nil;
-Monitor *mons = nil, *selmon = nil;
-Window root = {0}, wmcheckwin = {0};
-
-/* compile-time check if all tags fit into an uint bit array. */
-struct NumTags { char limitexceeded[arrlen(tags) > 31 ? -1 : 1]; };
-
-/* function implementations */
-void
-arrange(Monitor *m)
-{
- if (m)
- showhide(m->stack);
- else for (m = mons; m; m = m->next)
- showhide(m->stack);
- if (m) {
- arrangemon(m);
- restack(m);
- } else for (m = mons; m; m = m->next)
- arrangemon(m);
-}
-
-void
-arrangemon(Monitor *m)
-{
- strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
- if (m->lt[m->sellt]->arrange)
- m->lt[m->sellt]->arrange(m);
-}
-
-void
-buttonpress(XEvent *e)
-{
- uint i, x, click;
- Arg arg = {0};
- Client *c;
- Monitor *m;
- XButtonPressedEvent *ev = &e->xbutton;
-
- click = ClkRootWin;
- /* focus monitor if necessary */
- if ((m = wintomon(ev->window)) && m != selmon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- focus(nil);
- }
- if (ev->window == selmon->barwin) {
- i = x = 0;
- do
- x += TEXTW(tags[i]);
- while (ev->x >= x && ++i < arrlen(tags));
- if (i < arrlen(tags)) {
- click = ClkTagBar;
- arg.ui = 1 << i;
- } else if (ev->x < x + blw)
- click = ClkLtSymbol;
- else if (ev->x > selmon->ww - TEXTW(stext))
- click = ClkStatusText;
- else
- click = ClkWinTitle;
- } else if ((c = wintoclient(ev->window))) {
- focus(c);
- restack(selmon);
- XAllowEvents(dpy, ReplayPointer, CurrentTime);
- click = ClkClientWin;
- }
- for (i = 0; i < arrlen(buttons); i++)
- if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
-}
-
-void
-checkotherwm(void)
-{
- xerrorxlib = XSetErrorHandler(xerrorstart);
- /* this causes an error if some other window manager is running */
- XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XSync(dpy, False);
-}
-
-void
-cleanup(void)
-{
- Arg a = {.ui = ~0};
- Layout foo = { "", nil };
- Monitor *m;
- size_t i;
-
- view(&a);
- selmon->lt[selmon->sellt] = &foo;
- for (m = mons; m; m = m->next)
- while (m->stack)
- unmanage(m->stack, 0);
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- while (mons)
- cleanupmon(mons);
- for (i = 0; i < MouseLast; i++)
- drw_cur_free(drw, cursor[i]);
- for (i = 0; i < arrlen(colors); i++)
- free(scheme[i]);
- XDestroyWindow(dpy, wmcheckwin);
- drw_free(drw);
- XSync(dpy, False);
- XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
-}
-
-void
-cleanupmon(Monitor *mon)
-{
- Monitor *m;
-
- if (mon == mons)
- mons = mons->next;
- else {
- for (m = mons; m && m->next != mon; m = m->next);
- m->next = mon->next;
- }
- XUnmapWindow(dpy, mon->barwin);
- XDestroyWindow(dpy, mon->barwin);
- free(mon);
-}
-
-void
-clientmessage(XEvent *e)
-{
- XClientMessageEvent *cme = &e->xclient;
- Client *c = wintoclient(cme->window);
-
- if (!c)
- return;
- if (cme->message_type == netatom[NetWMState]) {
- if (cme->data.l[1] == netatom[NetWMFullscreen]
- || cme->data.l[2] == netatom[NetWMFullscreen])
- setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
- || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
- } else if (cme->message_type == netatom[NetActiveWindow]) {
- if (c != selmon->sel && !c->isurgent)
- seturgent(c, 1);
- }
-}
-
-void
-configurenotify(XEvent *e)
-{
- Monitor *m;
- Client *c;
- XConfigureEvent *ev = &e->xconfigure;
- int dirty;
-
- /* TODO: updategeom handling sucks, needs to be simplified */
- if (ev->window == root) {
- dirty = (sw != ev->width || sh != ev->height);
- sw = ev->width;
- sh = ev->height;
- if (updategeom() || dirty) {
- drw_resize(drw, sw, bh);
- updatebars();
- for (m = mons; m; m = m->next) {
- for (c = m->clients; c; c = c->next)
- if (c->isfullscreen)
- resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
- }
- focus(nil);
- arrange(nil);
- }
- }
-}
-
-void
-configurerequest(XEvent *e)
-{
- Client *c;
- Monitor *m;
- XConfigureRequestEvent *ev = &e->xconfigurerequest;
- XWindowChanges wc;
-
- if ((c = wintoclient(ev->window))) {
- if (ev->value_mask & CWBorderWidth)
- c->bw = ev->border_width;
- else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
- m = c->mon;
- if (ev->value_mask & CWX) {
- c->oldx = c->x;
- c->x = m->mx + ev->x;
- }
- if (ev->value_mask & CWY) {
- c->oldy = c->y;
- c->y = m->my + ev->y;
- }
- if (ev->value_mask & CWWidth) {
- c->oldw = c->w;
- c->w = ev->width;
- }
- if (ev->value_mask & CWHeight) {
- c->oldh = c->h;
- c->h = ev->height;
- }
- if ((c->x + c->w) > m->mx + m->mw && c->isfloating)
- c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */
- if ((c->y + c->h) > m->my + m->mh && c->isfloating)
- c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
- if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
- configure(c);
- if (ISVISIBLE(c))
- XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
- } else
- configure(c);
- } else {
- wc.x = ev->x;
- wc.y = ev->y;
- wc.width = ev->width;
- wc.height = ev->height;
- wc.border_width = ev->border_width;
- wc.sibling = ev->above;
- wc.stack_mode = ev->detail;
- XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
- }
- XSync(dpy, False);
-}
-
-Monitor *
-createmon(void)
-{
- Monitor *m;
-
- m = ecalloc(1, sizeof(Monitor));
- m->tagset[0] = m->tagset[1] = 1;
- m->mfact = mfact;
- m->nmaster = nmaster;
- m->showbar = showbar;
- m->topbar = topbar;
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % arrlen(layouts)];
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
- return m;
-}
-
-void
-destroynotify(XEvent *e)
-{
- Client *c;
- XDestroyWindowEvent *ev = &e->xdestroywindow;
-
- if ((c = wintoclient(ev->window)))
- unmanage(c, 1);
- else if ((c = swallowing(ev->window)))
- unmanage(c->swallowing, 1);
-}
-
-Monitor *
-dirtomon(int dir)
-{
- Monitor *m = nil;
-
- if (dir > 0) {
- if (!(m = selmon->next))
- m = mons;
- } else if (selmon == mons)
- for (m = mons; m->next; m = m->next);
- else
- for (m = mons; m->next != selmon; m = m->next);
- return m;
-}
-
-void
-drawbar(Monitor *m)
-{
- int x, w, tw = 0;
- int boxs = drw->fonts->h / 9;
- int boxw = drw->fonts->h / 6 + 2;
- uint i, occ = 0, urg = 0;
- Client *c;
-
- /* draw status first so it can be overdrawn by tags later */
- if(m == selmon) { /* status is only drawn on selected monitor */
- drw_setscheme(drw, scheme[SchemeNorm]);
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
- }
-
- for(c = m->clients; c; c = c->next) {
- occ |= c->tags;
- if (c->isurgent)
- urg |= c->tags;
- }
- x = 0;
- for(i = 0; i < arrlen(tags); i++) {
- w = TEXTW(tags[i]);
- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
- if (occ & 1 << i)
- drw_rect(drw, x + boxs, boxs, boxw, boxw,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- urg & 1 << i);
- x += w;
- }
- w = blw = TEXTW(m->ltsymbol);
- drw_setscheme(drw, scheme[SchemeNorm]);
- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
-
- if((w = m->ww - tw - x) > bh) {
- if (m->sel) {
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
- if (m->sel->isfloating)
- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
- } else {
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, x, 0, w, bh, 1, 1);
- }
- }
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
-}
-
-void
-drawbars(void)
-{
- Monitor *m;
-
- for (m = mons; m; m = m->next)
- drawbar(m);
-}
-
-void
-enternotify(XEvent *e)
-{
- Client *c;
- Monitor *m;
- XCrossingEvent *ev = &e->xcrossing;
-
- if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
- return;
- c = wintoclient(ev->window);
- m = c ? c->mon : wintomon(ev->window);
- if (m != selmon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- } else if (!c || c == selmon->sel)
- return;
- focus(c);
-}
-
-void
-expose(XEvent *e)
-{
- Monitor *m;
- XExposeEvent *ev = &e->xexpose;
-
- if (ev->count == 0 && (m = wintomon(ev->window)))
- drawbar(m);
-}
-
-/* there are some broken focus acquiring clients needing extra handling */
-void
-focusin(XEvent *e)
-{
- XFocusChangeEvent *ev = &e->xfocus;
-
- if (selmon->sel && ev->window != selmon->sel->win)
- setfocus(selmon->sel);
-}
-
-int
-getrootptr(int *x, int *y)
-{
- int di;
- uint dui;
- Window dummy;
-
- return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
-}
-
-long
-getstate(Window w)
-{
- int format;
- long result = -1;
- unsigned char *p = nil;
- unsigned long n, extra;
- Atom real;
-
- if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
- &real, &format, &n, &extra, (unsigned char **)&p) != Success)
- return -1;
- if (n != 0)
- result = *p;
- XFree(p);
- return result;
-}
-
-int
-gettextprop(Window w, Atom atom, char *text, uint size)
-{
- char **list = nil;
- int n;
- XTextProperty name;
-
- if (!text || size == 0)
- return 0;
- text[0] = '\0';
- if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
- return 0;
- if (name.encoding == XA_STRING)
- strncpy(text, (char *)name.value, size - 1);
- else {
- if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
- strncpy(text, *list, size - 1);
- XFreeStringList(list);
- }
- }
- text[size - 1] = '\0';
- XFree(name.value);
- return 1;
-}
-
-void
-grabkeys(void)
-{
- updatenumlockmask();
- {
- uint i, j;
- uint modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
- KeyCode code;
-
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for (i = 0; i < arrlen(keys); i++)
- if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
- for (j = 0; j < arrlen(modifiers); j++)
- XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
- True, GrabModeAsync, GrabModeAsync);
- }
-}
-
-static
-int
-isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
-{
- while (n--)
- if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
- && unique[n].width == info->width && unique[n].height == info->height)
- return 0;
- return 1;
-}
-
-void
-keypress(XEvent *e)
-{
- uint i;
- KeySym keysym;
- XKeyEvent *ev;
-
- ev = &e->xkey;
- keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0);
- for (i = 0; i < arrlen(keys); i++)
- if (keysym == keys[i].keysym
- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
- keys[i].func(&(keys[i].arg));
-}
-
-void
-manage(Window w, XWindowAttributes *wa)
-{
- Client *c, *t = nil, *term = nil;
- Window trans = None;
- XWindowChanges wc;
-
- c = ecalloc(1, sizeof(Client));
- c->win = w;
- c->pid = winpid(w);
- /* geometry */
- c->x = c->oldx = wa->x;
- c->y = c->oldy = wa->y;
- c->w = c->oldw = wa->width;
- c->h = c->oldh = wa->height;
- c->oldbw = wa->border_width;
-
- updatetitle(c);
- if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
- c->mon = t->mon;
- c->tags = t->tags;
- } else {
- c->mon = selmon;
- applyrules(c);
- term = termof(c);
- }
-
- if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
- c->x = c->mon->mx + c->mon->mw - WIDTH(c);
- if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh)
- c->y = c->mon->my + c->mon->mh - HEIGHT(c);
- c->x = MAX(c->x, c->mon->mx);
- /* only fix client y-offset, if the client center might cover the bar */
- c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
- && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
- c->bw = borderpx;
-
- selmon->tagset[selmon->seltags] &= ~scratchtag;
- if(!strcmp(c->name, scratchname)) {
- c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag;
- c->isfloating = 1;
- c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
- c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
- }
-
- wc.border_width = c->bw;
- XConfigureWindow(dpy, w, CWBorderWidth, &wc);
- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
- configure(c); /* propagates border_width, if size doesn't change */
- updatewindowtype(c);
- updatesizehints(c);
- updatewmhints(c);
- XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
- grabbuttons(c, 0);
-
- if (!c->isfloating)
- c->isfloating = c->oldstate = trans != None || c->isfixed;
- if (c->isfloating)
- XRaiseWindow(dpy, c->win);
-
- /* attach(c); */
- attachbottom(c);
- attachstack(c);
-
- XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
- XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
- setclientstate(c, NormalState);
- if (c->mon == selmon)
- unfocus(selmon->sel, 0);
- c->mon->sel = c;
- arrange(c->mon);
- XMapWindow(dpy, c->win);
- if (term)
- swallow(term, c);
- focus(nil);
-}
-
-void
-mappingnotify(XEvent *e)
-{
- XMappingEvent *ev = &e->xmapping;
-
- XRefreshKeyboardMapping(ev);
- if (ev->request == MappingKeyboard)
- grabkeys();
-}
-
-void
-maprequest(XEvent *e)
-{
- static XWindowAttributes wa;
- XMapRequestEvent *ev = &e->xmaprequest;
-
- if (!XGetWindowAttributes(dpy, ev->window, &wa))
- return;
- if (wa.override_redirect)
- return;
- if (!wintoclient(ev->window))
- manage(ev->window, &wa);
-}
-
-void
-monocle(Monitor *m)
-{
- uint n = 0;
- Client *c;
-
- for (c = m->clients; c; c = c->next)
- if (ISVISIBLE(c))
- n++;
- if (n > 0) /* override layout symbol */
- snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
- for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
-}
-
-void
-motionnotify(XEvent *e)
-{
- static Monitor *mon = nil;
- Monitor *m;
- XMotionEvent *ev = &e->xmotion;
-
- if (ev->window != root)
- return;
- if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
- unfocus(selmon->sel, 1);
- selmon = m;
- focus(nil);
- }
- mon = m;
-}
-
-void
-propertynotify(XEvent *e)
-{
- Client *c;
- Window trans;
- XPropertyEvent *ev = &e->xproperty;
-
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
- updatestatus();
- else if (ev->state == PropertyDelete)
- return; /* ignore */
- else if ((c = wintoclient(ev->window))) {
- switch(ev->atom) {
- default: break;
- case XA_WM_TRANSIENT_FOR:
- if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
- (c->isfloating = (wintoclient(trans)) != nil))
- arrange(c->mon);
- break;
- case XA_WM_NORMAL_HINTS:
- updatesizehints(c);
- break;
- case XA_WM_HINTS:
- updatewmhints(c);
- drawbars();
- break;
- }
- if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
- updatetitle(c);
- if (c == c->mon->sel)
- drawbar(c->mon);
- }
- if (ev->atom == netatom[NetWMWindowType])
- updatewindowtype(c);
- }
-}
-
-Monitor *
-recttomon(int x, int y, int w, int h)
-{
- Monitor *m, *r = selmon;
- int a, area = 0;
-
- for (m = mons; m; m = m->next)
- if ((a = INTERSECT(x, y, w, h, m)) > area) {
- area = a;
- r = m;
- }
- return r;
-}
-
-void
-restack(Monitor *m)
-{
- Client *c;
- XEvent ev;
- XWindowChanges wc;
-
- drawbar(m);
- if (!m->sel)
- return;
- if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
- XRaiseWindow(dpy, m->sel->win);
- if (m->lt[m->sellt]->arrange) {
- wc.stack_mode = Below;
- wc.sibling = m->barwin;
- for (c = m->stack; c; c = c->snext)
- if (!c->isfloating && ISVISIBLE(c)) {
- XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
- wc.sibling = c->win;
- }
- }
- XSync(dpy, False);
- while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
-}
-
-void
-run(void)
-{
- XEvent ev;
- /* main event loop */
- XSync(dpy, False);
- while (running && !XNextEvent(dpy, &ev))
- if (handler[ev.type])
- handler[ev.type](&ev); /* call handler */
-}
-
-void
-scan(void)
-{
- uint i, num;
- Window d1, d2, *wins = nil;
- XWindowAttributes wa;
- char swin[256];
-
- scanner = 1;
-
- if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
- for (i = 0; i < num; i++) {
- if (!XGetWindowAttributes(dpy, wins[i], &wa)
- || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
- continue;
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
- manage(wins[i], &wa);
- else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin))
- manage(wins[i], &wa);
- }
- for (i = 0; i < num; i++) { /* now the transients */
- if (!XGetWindowAttributes(dpy, wins[i], &wa))
- continue;
- if (XGetTransientForHint(dpy, wins[i], &d1)
- && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
- manage(wins[i], &wa);
- }
- if (wins)
- XFree(wins);
- }
-
- scanner = 0;
-}
-
-void
-setup(void)
-{
- int i;
- XSetWindowAttributes wa;
- Atom utf8string;
-
- /* clean up any zombies immediately */
- sigchld(0);
-
- /* init screen */
- screen = DefaultScreen(dpy);
- sw = DisplayWidth(dpy, screen);
- sh = DisplayHeight(dpy, screen);
- root = RootWindow(dpy, screen);
- drw = drw_create(dpy, screen, root, sw, sh);
- if (!drw_fontset_create(drw, fonts, arrlen(fonts)))
- fatal("no fonts could be loaded.");
-
- lrpad = drw->fonts->h;
- bh = drw->fonts->h + 2;
- updategeom();
-
- /* init atoms */
- utf8string = XInternAtom(dpy, "UTF8_STRING", False);
- wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
- wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
- wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
- wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
-
- netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
- netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
- netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
- netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
- netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- netatom[NetWMWindowOpacity] = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False);
- netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
-
- /* init cursors */
- cursor[MouseNormal] = drw_cur_create(drw, XC_left_ptr);
- cursor[MouseResize] = drw_cur_create(drw, XC_sizing);
- cursor[MouseMove] = drw_cur_create(drw, XC_fleur);
-
- /* init appearance */
- scheme = ecalloc(arrlen(colors), sizeof(Clr *));
- for (i = 0; i < arrlen(colors); i++)
- scheme[i] = drw_scm_create(drw, colors[i], 3);
-
- /* init bars */
- updatebars();
- updatestatus();
-
- /* supporting window for NetWMCheck */
- wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
- XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
- PropModeReplace, (uchar *) &wmcheckwin, 1);
- XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
- PropModeReplace, (uchar *) "dwm", 3);
- XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
- PropModeReplace, (uchar *) &wmcheckwin, 1);
- /* EWMH support per view */
- XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
- PropModeReplace, (uchar *) netatom, NetLast);
- XDeleteProperty(dpy, root, netatom[NetClientList]);
- /* select events */
- wa.cursor = cursor[MouseNormal]->cursor;
- wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
- |ButtonPressMask|PointerMotionMask|EnterWindowMask
- |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
- XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
- XSelectInput(dpy, root, wa.event_mask);
- grabkeys();
- focus(nil);
-}
-
-
-void
-sigchld(int unused)
-{
- if (signal(SIGCHLD, sigchld) == SIG_ERR)
- fatal("can't install SIGCHLD handler:");
- while (0 < waitpid(-1, nil, WNOHANG));
-}
-
-Client *
-swallowing(Window w)
-{
- Client *c;
- Monitor *m;
-
- for (m = mons; m; m = m->next) {
- for (c = m->clients; c; c = c->next) {
- if (c->swallowing && c->swallowing->win == w)
- return c;
- }
- }
-
- return nil;
-}
-
-void
-tile(Monitor *m)
-{
- uint i, n, h, r, mw, my, ty;
- Client *c;
-
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
- ;
-
- if (n == 0)
- return;
-
- if (n > m->nmaster)
- mw = m->nmaster ? (m->ww+gapx) * m->mfact : 0;
- else
- mw = m->ww - gapx;
-
- for (i = 0, my = ty = gapx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
- r = MIN(n, m->nmaster) - i;
- h = (m->wh - my)/r - gapx;
- resize(c, m->wx + gapx, m->wy + my, mw - (2*c->bw) - gapx, h - (2*c->bw), 0);
- if (my + HEIGHT(c) + gapx < m->wh)
- my += HEIGHT(c) + gapx;
- } else {
- r = (n-i);
- h = (m->wh - ty)/r - gapx;
- resize(c, m->wx + mw + gapx, m->wy + ty, m->ww - mw - (2*c->bw) - (2*gapx), h - (2*c->bw), 0);
- if (ty + HEIGHT(c) + gapx < m->wh)
- ty += HEIGHT(c) + gapx;
- }
-}
-
-void
-unmapnotify(XEvent *e)
-{
- Client *c;
- XUnmapEvent *ev = &e->xunmap;
-
- if ((c = wintoclient(ev->window))) {
- if (ev->send_event)
- setclientstate(c, WithdrawnState);
- else
- unmanage(c, 0);
- }
-}
-
-void
-updatebars(void)
-{
- Monitor *m;
- XSetWindowAttributes wa = {
- .override_redirect = True,
- .background_pixmap = ParentRelative,
- .event_mask = ButtonPressMask|ExposureMask
- };
- XClassHint ch = {"dwm", "dwm"};
- for (m = mons; m; m = m->next) {
- if (m->barwin)
- continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
- XDefineCursor(dpy, m->barwin, cursor[MouseNormal]->cursor);
- XMapRaised(dpy, m->barwin);
- XSetClassHint(dpy, m->barwin, &ch);
- }
-}
-
-void
-updatebarpos(Monitor *m)
-{
- m->wy = m->my;
- m->wh = m->mh;
- if (m->showbar) {
- m->wh -= bh;
- m->by = m->topbar ? m->wy : m->wy + m->wh;
- m->wy = m->topbar ? m->wy + bh : m->wy;
- } else
- m->by = -bh;
-}
-
-void
-updateclientlist()
-{
- Client *c;
- Monitor *m;
-
- XDeleteProperty(dpy, root, netatom[NetClientList]);
- for (m = mons; m; m = m->next)
- for (c = m->clients; c; c = c->next)
- XChangeProperty(dpy, root, netatom[NetClientList],
- XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
-}
-
-int
-updategeom(void)
-{
- int dirty = 0;
-
- if (XineramaIsActive(dpy)) {
- int i, j, n, nn;
- Client *c;
- Monitor *m;
- XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
- XineramaScreenInfo *unique = nil;
-
- for (n = 0, m = mons; m; m = m->next, n++);
- /* only consider unique geometries as separate screens */
- unique = ecalloc(nn, sizeof(XineramaScreenInfo));
- for (i = 0, j = 0; i < nn; i++)
- if (isuniquegeom(unique, j, &info[i]))
- memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
- XFree(info);
- nn = j;
- if (n <= nn) { /* new monitors available */
- for (i = 0; i < (nn - n); i++) {
- for (m = mons; m && m->next; m = m->next);
- if (m)
- m->next = createmon();
- else
- mons = createmon();
- }
- for (i = 0, m = mons; i < nn && m; m = m->next, i++)
- if (i >= n
- || unique[i].x_org != m->mx || unique[i].y_org != m->my
- || unique[i].width != m->mw || unique[i].height != m->mh)
- {
- dirty = 1;
- m->num = i;
- m->mx = m->wx = unique[i].x_org;
- m->my = m->wy = unique[i].y_org;
- m->mw = m->ww = unique[i].width;
- m->mh = m->wh = unique[i].height;
- updatebarpos(m);
- }
- } else { /* less monitors available nn < n */
- for (i = nn; i < n; i++) {
- for (m = mons; m && m->next; m = m->next);
- while ((c = m->clients)) {
- dirty = 1;
- m->clients = c->next;
- detachstack(c);
- c->mon = mons;
- /* attach(c); */
- attachbottom(c);
- attachstack(c);
- }
- if (m == selmon)
- selmon = mons;
- cleanupmon(m);
- }
- }
- free(unique);
- } else
- { /* default monitor setup */
- if (!mons)
- mons = createmon();
- if (mons->mw != sw || mons->mh != sh) {
- dirty = 1;
- mons->mw = mons->ww = sw;
- mons->mh = mons->wh = sh;
- updatebarpos(mons);
- }
- }
- if (dirty) {
- selmon = mons;
- selmon = wintomon(root);
- }
- return dirty;
-}
-
-void
-updatenumlockmask(void)
-{
- uint i, j;
- XModifierKeymap *modmap;
-
- numlockmask = 0;
- modmap = XGetModifierMapping(dpy);
- for (i = 0; i < 8; i++)
- for (j = 0; j < modmap->max_keypermod; j++)
- if (modmap->modifiermap[i * modmap->max_keypermod + j]
- == XKeysymToKeycode(dpy, XK_Num_Lock))
- numlockmask = (1 << i);
- XFreeModifiermap(modmap);
-}
-
-void
-updatestatus(void)
-{
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
- strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
-}
-
-pid_t
-winpid(Window w)
-{
- pid_t result = 0;
-
- xcb_res_client_id_spec_t spec = {0};
- spec.client = w;
- spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
-
- xcb_generic_error_t *e = NULL;
- xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
- xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
-
- if (!r)
- return (pid_t)0;
-
- xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
- for (; i.rem; xcb_res_client_id_value_next(&i)) {
- spec = i.data->spec;
- if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
- uint32_t *t = xcb_res_client_id_value_value(i.data);
- result = *t;
- break;
- }
- }
-
- free(r);
-
- if (result == (pid_t)-1)
- result = 0;
-
- return result;
-}
-
-Client *
-wintoclient(Window w)
-{
- Client *c;
- Monitor *m;
-
- for (m = mons; m; m = m->next)
- for (c = m->clients; c; c = c->next)
- if (c->win == w)
- return c;
- return nil;
-}
-
-Monitor *
-wintomon(Window w)
-{
- int x, y;
- Client *c;
- Monitor *m;
-
- if (w == root && getrootptr(&x, &y))
- return recttomon(x, y, 1, 1);
- for (m = mons; m; m = m->next)
- if (w == m->barwin)
- return m;
- if ((c = wintoclient(w)))
- return c->mon;
- return selmon;
-}
-
-/* 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 *dpy, XErrorEvent *ee)
-{
- if (ee->error_code == BadWindow
- || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
- || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
- || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
- || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
- || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
- || (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
- || (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
- || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
- return 0;
- fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
- ee->request_code, ee->error_code);
- return xerrorxlib(dpy, ee); /* may call exit */
-}
-
-int
-xerrordummy(Display *dpy, XErrorEvent *ee)
-{
- return 0;
-}
-
-/* Startup Error handler to check if another window manager
- * is already running. */
-int
-xerrorstart(Display *dpy, XErrorEvent *ee)
-{
- fatal("dwm: another window manager is already running");
- return -1;
-}
-
-int
-main(int argc, char *argv[])
-{
- if (argc == 2 && !strcmp("-v", argv[1]))
- fatal("dwm-"VERSION);
- else if (argc != 1)
- fatal("usage: dwm [-v]");
- if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
- fputs("warning: no locale support\n", stderr);
- if (!(dpy = XOpenDisplay(nil)))
- fatal("dwm: cannot open display");
- if (!(xcon = XGetXCBConnection(dpy)))
- fatal("dwm: cannot get xcb connection");
-
- checkotherwm();
- setup();
-
-#ifdef __OpenBSD__
- if (pledge("stdio rpath proc exec", nil) == -1)
- fatal("pledge");
-#endif /* __OpenBSD__ */
-
- scan();
- run();
- cleanup();
-
- XCloseDisplay(dpy);
- return 0;
-}