]> git.armaanb.net Git - dwm.git/blobdiff - dwm.c
cleanup
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 421bf27a3fef45495c6ee1a81b24a9024d5ccdcf..3f80b632eca1fbc8b700d9334dde12b997f7dfad 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -3,7 +3,7 @@
  * dynamic window manager is designed like any other X client as well. It is
  * driven through handling X events. In contrast to other X clients, a window
  * manager selects for SubstructureRedirectMask on the root window, to receive
- * events about window (dis-)appearance.  Only one X connection at a time is
+ * events about window (dis-)appearance. Only one X connection at a time is
  * allowed to select for this event mask.
  *
  * The event handlers of dwm are organized in an array which is accessed
@@ -11,7 +11,7 @@
  * in O(1) time.
  *
  * Each child of the root window is called a client, except windows which have
- * set the override_redirect flag.  Clients are organized in a linked client
+ * set the override_redirect flag. Clients are organized in a linked client
  * list on each monitor, the focus history is remembered through a stack list
  * on each monitor. Each client contains a bit array to indicate the tags of a
  * client.
@@ -60,8 +60,8 @@
 
 /* enums */
 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
-enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
-enum { NetSupported, NetWMName, NetWMState,
+enum { SchemeNorm, SchemeSel }; /* color schemes */
+enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
        NetWMFullscreen, NetActiveWindow, NetWMWindowType,
        NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
@@ -153,7 +153,6 @@ static void buttonpress(XEvent *e);
 static void checkotherwm(void);
 static void cleanup(void);
 static void cleanupmon(Monitor *mon);
-static void clearurgent(Client *c);
 static void clientmessage(XEvent *e);
 static void configure(Client *c);
 static void configurenotify(XEvent *e);
@@ -204,6 +203,7 @@ static void setfullscreen(Client *c, int fullscreen);
 static void setlayout(const Arg *arg);
 static void setmfact(const Arg *arg);
 static void setup(void);
+static void seturgent(Client *c, int urg);
 static void showhide(Client *c);
 static void sigchld(int unused);
 static void spawn(const Arg *arg);
@@ -263,11 +263,11 @@ static void (*handler[LASTEvent]) (XEvent *) = {
 static Atom wmatom[WMLast], netatom[NetLast];
 static int running = 1;
 static Cur *cursor[CurLast];
-static Scm scheme[SchemeLast];
+static Scm *scheme;
 static Display *dpy;
 static Drw *drw;
 static Monitor *mons, *selmon;
-static Window root;
+static Window root, wmcheckwin;
 
 /* configuration, allows nested code to access above variables */
 #include "config.h"
@@ -483,8 +483,9 @@ cleanup(void)
                cleanupmon(mons);
        for (i = 0; i < CurLast; i++)
                drw_cur_free(drw, cursor[i]);
-       for (i = 0; i < SchemeLast; i++)
+       for (i = 0; i < LENGTH(colors); i++)
                free(scheme[i]);
+       XDestroyWindow(dpy, wmcheckwin);
        drw_free(drw);
        XSync(dpy, False);
        XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
@@ -507,19 +508,6 @@ cleanupmon(Monitor *mon)
        free(mon);
 }
 
-void
-clearurgent(Client *c)
-{
-       XWMHints *wmh;
-
-       c->isurgent = 0;
-       if (!(wmh = XGetWMHints(dpy, c->win)))
-               return;
-       wmh->flags &= ~XUrgencyHint;
-       XSetWMHints(dpy, c->win, wmh);
-       XFree(wmh);
-}
-
 void
 clientmessage(XEvent *e)
 {
@@ -529,15 +517,13 @@ clientmessage(XEvent *e)
        if (!c)
                return;
        if (cme->message_type == netatom[NetWMState]) {
-               if (cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen])
+               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 (!ISVISIBLE(c)) {
-                       c->mon->seltags ^= 1;
-                       c->mon->tagset[c->mon->seltags] = c->tags;
-               }
-               pop(c);
+               if (c != selmon->sel && !c->isurgent)
+                       seturgent(c, 1);
        }
 }
 
@@ -717,8 +703,8 @@ drawbar(Monitor *m)
        /* 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]);
-               sw = TEXTW(stext) - lrpad / 2; /* no right padding so status text hugs the corner */
-               drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2 - 2, stext, 0);
+               sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+               drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
        }
 
        for (c = m->clients; c; c = c->next) {
@@ -798,14 +784,13 @@ focus(Client *c)
 {
        if (!c || !ISVISIBLE(c))
                for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
-       /* was if (selmon->sel) */
        if (selmon->sel && selmon->sel != c)
                unfocus(selmon->sel, 0);
        if (c) {
                if (c->mon != selmon)
                        selmon = c->mon;
                if (c->isurgent)
-                       clearurgent(c);
+                       seturgent(c, 0);
                detachstack(c);
                attachstack(c);
                grabbuttons(c, 1);
@@ -819,7 +804,7 @@ focus(Client *c)
        drawbars();
 }
 
-/* there are some broken focus acquiring clients */
+/* there are some broken focus acquiring clients needing extra handling */
 void
 focusin(XEvent *e)
 {
@@ -838,8 +823,7 @@ focusmon(const Arg *arg)
                return;
        if ((m = dirtomon(arg->i)) == selmon)
                return;
-       unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues
-                                       in gedit and anjuta */
+       unfocus(selmon->sel, 0);
        selmon = m;
        focus(NULL);
 }
@@ -976,7 +960,7 @@ grabkeys(void)
                        if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
                                for (j = 0; j < LENGTH(modifiers); j++)
                                        XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
-                                                True, GrabModeAsync, GrabModeAsync);
+                                                True, GrabModeAsync, GrabModeAsync);
        }
 }
 
@@ -1166,7 +1150,7 @@ movemouse(const Arg *arg)
        ocx = c->x;
        ocy = c->y;
        if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
-       None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
+           None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
                return;
        if (!getrootptr(&x, &y))
                return;
@@ -1449,7 +1433,7 @@ setclientstate(Client *c, long state)
        long data[] = { state, None };
 
        XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
-                       PropModeReplace, (unsigned char *)data, 2);
+                       PropModeReplace, (unsigned char *)data, 2);
 }
 
 int
@@ -1531,7 +1515,7 @@ setlayout(const Arg *arg)
                drawbar(selmon);
 }
 
-/* arg > 1.0 will set mfact absolutly */
+/* arg > 1.0 will set mfact absolutely */
 void
 setmfact(const Arg *arg)
 {
@@ -1549,7 +1533,9 @@ setmfact(const Arg *arg)
 void
 setup(void)
 {
+       int i;
        XSetWindowAttributes wa;
+       Atom utf8string;
 
        /* clean up any zombies immediately */
        sigchld(0);
@@ -1566,6 +1552,7 @@ setup(void)
        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);
@@ -1574,6 +1561,7 @@ setup(void)
        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[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
@@ -1583,25 +1571,49 @@ setup(void)
        cursor[CurResize] = drw_cur_create(drw, XC_sizing);
        cursor[CurMove] = drw_cur_create(drw, XC_fleur);
        /* init appearance */
-       scheme[SchemeNorm] = drw_scm_create(drw, colors[SchemeNorm], 3);
-       scheme[SchemeSel] = drw_scm_create(drw, colors[SchemeSel], 3);
+       scheme = ecalloc(LENGTH(colors), sizeof(Scm));
+       for (i = 0; i < LENGTH(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, (unsigned char *) &wmcheckwin, 1);
+       XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
+                       PropModeReplace, (unsigned char *) "dwm", 4);
+       XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
+                       PropModeReplace, (unsigned char *) &wmcheckwin, 1);
        /* EWMH support per view */
        XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
-                       PropModeReplace, (unsigned char *) netatom, NetLast);
+                       PropModeReplace, (unsigned char *) netatom, NetLast);
        XDeleteProperty(dpy, root, netatom[NetClientList]);
-       /* select for events */
+       /* select events */
        wa.cursor = cursor[CurNormal]->cursor;
-       wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask
-                       |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
+       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(NULL);
 }
 
+
+void
+seturgent(Client *c, int urg)
+{
+       XWMHints *wmh;
+
+       c->isurgent = urg;
+       if (!(wmh = XGetWMHints(dpy, c->win)))
+               return;
+       wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
+       XSetWMHints(dpy, c->win, wmh);
+       XFree(wmh);
+}
+
 void
 showhide(Client *c)
 {
@@ -1757,12 +1769,11 @@ unmanage(Client *c, int destroyed)
        Monitor *m = c->mon;
        XWindowChanges wc;
 
-       /* The server grab construct avoids race conditions. */
        detach(c);
        detachstack(c);
        if (!destroyed) {
                wc.border_width = c->oldbw;
-               XGrabServer(dpy);
+               XGrabServer(dpy); /* avoid race conditions */
                XSetErrorHandler(xerrordummy);
                XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
                XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
@@ -1859,8 +1870,8 @@ updategeom(void)
                                memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
                XFree(info);
                nn = j;
-               if (n <= nn) {
-                       for (i = 0; i < (nn - n); i++) { /* new monitors available */
+               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();
@@ -1869,8 +1880,8 @@ updategeom(void)
                        }
                        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))
+                               || 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;
@@ -1880,13 +1891,11 @@ updategeom(void)
                                        m->mh = m->wh = unique[i].height;
                                        updatebarpos(m);
                                }
-               } else {
-                       /* less monitors available nn < n */
+               } else { /* less monitors available nn < n */
                        for (i = nn; i < n; i++) {
                                for (m = mons; m && m->next; m = m->next);
-                               while (m->clients) {
+                               while ((c = m->clients)) {
                                        dirty = 1;
-                                       c = m->clients;
                                        m->clients = c->next;
                                        detachstack(c);
                                        c->mon = mons;
@@ -1901,8 +1910,7 @@ updategeom(void)
                free(unique);
        } else
 #endif /* XINERAMA */
-       /* default monitor setup */
-       {
+       { /* default monitor setup */
                if (!mons)
                        mons = createmon();
                if (mons->mw != sw || mons->mh != sh) {
@@ -1976,7 +1984,7 @@ updatesizehints(Client *c)
        } else
                c->maxa = c->mina = 0.0;
        c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
-                    && c->maxw == c->minw && c->maxh == c->minh);
+                     && c->maxw == c->minw && c->maxh == c->minh);
 }
 
 void
@@ -2070,8 +2078,8 @@ wintomon(Window w)
 }
 
 /* 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.  */
+ * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
+ * default error handler, which may call exit. */
 int
 xerror(Display *dpy, XErrorEvent *ee)
 {
@@ -2086,7 +2094,7 @@ xerror(Display *dpy, XErrorEvent *ee)
        || (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);
+               ee->request_code, ee->error_code);
        return xerrorxlib(dpy, ee); /* may call exit */
 }