JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
implemented reapply for re-applying the tagging rules during runtime, Mod-r
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index f5f7c99..0af37d6 100644 (file)
--- a/dwm.c
+++ b/dwm.c
 /* macros */
 #define BUTTONMASK             (ButtonPressMask | ButtonReleaseMask)
 #define CLEANMASK(mask)                (mask & ~(numlockmask | LockMask))
+#define LENGTH(x)              (sizeof x / sizeof x[0])
+#define MAXTAGLEN              16
 #define MOUSEMASK              (BUTTONMASK | PointerMotionMask)
 
+
 /* enums */
 enum { BarTop, BarBot, BarOff };                       /* bar position */
 enum { CurNormal, CurResize, CurMove, CurLast };       /* cursor */
@@ -134,6 +137,7 @@ void eprint(const char *errstr, ...);
 void expose(XEvent *e);
 void floating(void); /* default floating layout */
 void focus(Client *c);
+void focusin(XEvent *e);
 void focusnext(const char *arg);
 void focusprev(const char *arg);
 Client *getclient(Window w);
@@ -141,6 +145,7 @@ unsigned long getcolor(const char *colstr);
 long getstate(Window w);
 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
 void grabbuttons(Client *c, Bool focused);
+void grabkeys(void);
 unsigned int idxoftag(const char *tag);
 void initfont(const char *fontstr);
 Bool isoccupied(unsigned int t);
@@ -156,6 +161,7 @@ void movemouse(Client *c);
 Client *nexttiled(Client *c);
 void propertynotify(XEvent *e);
 void quit(const char *arg);
+void reapply(const char *arg);
 void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
 void resizemouse(Client *c);
 void restack(void);
@@ -202,9 +208,10 @@ void (*handler[LASTEvent]) (XEvent *) = {
        [ConfigureNotify] = configurenotify,
        [DestroyNotify] = destroynotify,
        [EnterNotify] = enternotify,
-       [LeaveNotify] = leavenotify,
        [Expose] = expose,
+       [FocusIn] = focusin,
        [KeyPress] = keypress,
+       [LeaveNotify] = leavenotify,
        [MappingNotify] = mappingnotify,
        [MapRequest] = maprequest,
        [PropertyNotify] = propertynotify,
@@ -229,6 +236,8 @@ Regs *regs = NULL;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
+Bool prevtags[LENGTH(tags)];
+
 /* function implementations */
 void
 applyrules(Client *c) {
@@ -704,6 +713,14 @@ focus(Client *c) {
 }
 
 void
+focusin(XEvent *e) { /* there are some broken focus acquiring clients */
+       XFocusChangeEvent *ev = &e->xfocus;
+
+       if(sel && ev->window != sel->win)
+               XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
+}
+
+void
 focusnext(const char *arg) {
        Client *c;
 
@@ -834,6 +851,25 @@ grabbuttons(Client *c, Bool focused) {
                                GrabModeAsync, GrabModeSync, None, None);
 }
 
+void
+grabkeys(void)  {
+       unsigned int i;
+       KeyCode code;
+
+       XUngrabKey(dpy, AnyKey, AnyModifier, root);
+       for(i = 0; i < LENGTH(keys); i++) {
+               code = XKeysymToKeycode(dpy, keys[i].keysym);
+               XGrabKey(dpy, code, keys[i].mod, root, True,
+                               GrabModeAsync, GrabModeAsync);
+               XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
+                               GrabModeAsync, GrabModeAsync);
+               XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
+                               GrabModeAsync, GrabModeAsync);
+               XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
+                               GrabModeAsync, GrabModeAsync);
+       }
+}
+
 unsigned int
 idxoftag(const char *tag) {
        unsigned int i;
@@ -921,27 +957,10 @@ isvisible(Client *c) {
 
 void
 keypress(XEvent *e) {
-       KEYS
        unsigned int i;
-       KeyCode code;
        KeySym keysym;
        XKeyEvent *ev;
 
-       if(!e) { /* grabkeys */
-               XUngrabKey(dpy, AnyKey, AnyModifier, root);
-               for(i = 0; i < LENGTH(keys); i++) {
-                       code = XKeysymToKeycode(dpy, keys[i].keysym);
-                       XGrabKey(dpy, code, keys[i].mod, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-                       XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-                       XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-                       XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-               }
-               return;
-       }
        ev = &e->xkey;
        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
        for(i = 0; i < LENGTH(keys); i++)
@@ -1018,8 +1037,7 @@ manage(Window w, XWindowAttributes *wa) {
        XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
        configure(c); /* propagates border_width, if size doesn't change */
        updatesizehints(c);
-       XSelectInput(dpy, w,
-               StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
+       XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask);
        grabbuttons(c, False);
        updatetitle(c);
        if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
@@ -1044,7 +1062,7 @@ mappingnotify(XEvent *e) {
 
        XRefreshKeyboardMapping(ev);
        if(ev->request == MappingKeyboard)
-               keypress(NULL);
+               grabkeys();
 }
 
 void
@@ -1142,6 +1160,17 @@ quit(const char *arg) {
        readin = running = False;
 }
 
+void
+reapply(const char *arg) {
+       static Bool zerotags[LENGTH(tags)] = { 0 };
+       Client *c;
+
+       for(c = clients; c; c = c->next) {
+               memcpy(c->tags, zerotags, sizeof zerotags);
+               applyrules(c);
+       }
+       arrange();
+}
 
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
@@ -1279,6 +1308,7 @@ restack(void) {
 void
 run(void) {
        char *p;
+       char buf[sizeof stext];
        fd_set rd;
        int r, xfd;
        unsigned int len, offset;
@@ -1290,7 +1320,7 @@ run(void) {
        readin = True;
        offset = 0;
        len = sizeof stext - 1;
-       stext[len] = '\0'; /* 0-terminator is never touched */
+       buf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
        while(running) {
                FD_ZERO(&rd);
                if(readin)
@@ -1302,7 +1332,7 @@ run(void) {
                        eprint("select failed\n");
                }
                if(FD_ISSET(STDIN_FILENO, &rd)) {
-                       switch((r = read(STDIN_FILENO, stext + offset, len - offset))) {
+                       switch((r = read(STDIN_FILENO, buf + offset, len - offset))) {
                        case -1:
                                strncpy(stext, strerror(errno), len);
                                readin = False;
@@ -1312,14 +1342,18 @@ run(void) {
                                readin = False;
                                break;
                        default:
-                               stext[offset + r] = '\0';
-                               for(p = stext; *p && *p != '\n'; p++);
-                               if(*p == '\n') {
-                                       *p = '\0';
-                                       offset = 0;
-                               }
-                               else
-                                       offset = (offset + r < len - 1) ? offset + r : 0;
+                               for(p = buf + offset; r > 0; p++, r--, offset++)
+                                       if(*p == '\n' || *p == '\0') {
+                                               *p = '\0';
+                                               strncpy(stext, buf, len);
+                                               p += r - 1; /* p is buf + offset + r - 1 */
+                                               for(r = 0; *(p - r) && *(p - r) != '\n'; r++);
+                                               offset = r;
+                                               if(r)
+                                                       memmove(buf, p - r + 1, r);
+                                               break;
+                                       }
+                               break;
                        }
                        drawbar();
                }
@@ -1456,9 +1490,10 @@ setup(void) {
        XSelectInput(dpy, root, wa.event_mask);
 
        /* grab keys */
-       keypress(NULL);
+       grabkeys();
 
        /* init tags */
+       memcpy(prevtags, seltags, sizeof seltags);
        compileregs();
 
        /* init appearance */
@@ -1500,6 +1535,7 @@ setup(void) {
 
        /* multihead support */
        selscreen = XQueryPointer(dpy, root, &w, &w, &d, &d, &d, &d, &mask);
+
 }
 
 void
@@ -1841,11 +1877,11 @@ view(const char *arg) {
 
 void
 viewprevtag(const char *arg) {
-       static Bool tmptags[sizeof tags / sizeof tags[0]];
+       static Bool tmp[LENGTH(tags)];
 
-       memcpy(tmptags, seltags, sizeof seltags);
+       memcpy(tmp, seltags, sizeof seltags);
        memcpy(seltags, prevtags, sizeof seltags);
-       memcpy(prevtags, tmptags, sizeof seltags);
+       memcpy(prevtags, tmp, sizeof seltags);
        arrange();
 }