JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
it's debug season for upcoming dwm 5.8, so only use this if you really want to run...
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 8ddc072..88d80b2 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -41,6 +41,7 @@
 #endif /* XINERAMA */
 
 /* macros */
+#define D                       if(1)
 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask))
 #define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
@@ -121,7 +122,7 @@ typedef struct {
 } Layout;
 
 struct Monitor {
-       const char *ltsymbol;
+       char ltsymbol[16];
        float mfact;
        int num;
        int by;               /* bar geometry */
@@ -152,13 +153,14 @@ typedef struct {
 /* function declarations */
 static void applyrules(Client *c);
 static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
-static void arrange(void);
+static void arrange(Monitor *m);
+static void arrangemon(Monitor *m);
 static void attach(Client *c);
 static void attachstack(Client *c);
 static void buttonpress(XEvent *e);
 static void checkotherwm(void);
 static void cleanup(void);
-static void cleanupmons(void);
+static void cleanupmon(Monitor *mon);
 static void clearurgent(Client *c);
 static void configure(Client *c);
 static void configurenotify(XEvent *e);
@@ -379,18 +381,24 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) {
 }
 
 void
-arrange(void) {
-       Monitor *m;
-
-       for(m = mons; m; m = m->next)
+arrange(Monitor *m) {
+       if(m)
+               showhide(m->stack);
+       else for(m = mons; m; m = m->next)
                showhide(m->stack);
        focus(NULL);
-       for(m = mons; m; m = m->next) {
-               m->ltsymbol = m->lt[m->sellt]->symbol;
-               if(m->lt[m->sellt]->arrange)
-                       m->lt[m->sellt]->arrange(m);
-               restack(m);
-       }
+       if(m)
+               arrangemon(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);
+       restack(m);
 }
 
 void
@@ -480,22 +488,25 @@ cleanup(void) {
        XFreeCursor(dpy, cursor[CurNormal]);
        XFreeCursor(dpy, cursor[CurResize]);
        XFreeCursor(dpy, cursor[CurMove]);
-       cleanupmons();
+       while(mons)
+               cleanupmon(mons);
        XSync(dpy, False);
        XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
 }
 
 void
-cleanupmons(void) {
+cleanupmon(Monitor *mon) {
        Monitor *m;
 
-       while(mons) {
-               m = mons->next;
-               XUnmapWindow(dpy, mons->barwin);
-               XDestroyWindow(dpy, mons->barwin);
-               free(mons);
-               mons = 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
@@ -543,7 +554,7 @@ configurenotify(XEvent *e) {
                        updatebars();
                        for(m = mons; m; m = m->next)
                                XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
-                       arrange();
+                       arrange(NULL);
                }
        }
 }
@@ -605,7 +616,7 @@ createmon(void) {
        m->topbar = topbar;
        m->lt[0] = &layouts[0];
        m->lt[1] = &layouts[1 % LENGTH(layouts)];
-       m->ltsymbol = layouts[0].symbol;
+       strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
        return m;
 }
 
@@ -804,8 +815,8 @@ void
 focus(Client *c) {
        if(!c || !ISVISIBLE(c))
                for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
-       if(selmon->sel)
-               unfocus(selmon->sel);
+//     if(selmon->sel)
+//             unfocus(selmon->sel);
        if(c) {
                if(c->mon != selmon)
                        selmon = c->mon;
@@ -1136,7 +1147,7 @@ manage(Window w, XWindowAttributes *wa) {
        XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
        XMapWindow(dpy, c->win);
        setclientstate(c, NormalState);
-       arrange();
+       arrange(c->mon);
 }
 
 void
@@ -1163,17 +1174,14 @@ maprequest(XEvent *e) {
 
 void
 monocle(Monitor *m) {
-       static char ntext[8];
        unsigned int n = 0;
        Client *c;
 
        for(c = m->clients; c; c = c->next)
                if(ISVISIBLE(c))
                        n++;
-       if(n > 0) { /* override layout symbol */
-               snprintf(ntext, sizeof ntext, "[%d]", n);
-               m->ltsymbol = ntext;
-       }
+       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, False);
 }
@@ -1265,7 +1273,7 @@ propertynotify(XEvent *e) {
                case XA_WM_TRANSIENT_FOR:
                        XGetTransientForHint(dpy, c->win, &trans);
                        if(!c->isfloating && (c->isfloating = (wintoclient(trans) != NULL)))
-                               arrange();
+                               arrange(c->mon);
                        break;
                case XA_WM_NORMAL_HINTS:
                        updatesizehints(c);
@@ -1360,7 +1368,7 @@ restack(Monitor *m) {
        XEvent ev;
        XWindowChanges wc;
 
-       drawbars();
+       drawbar(m);
        if(!m->sel)
                return;
        if(m->sel->isfloating || !m->lt[m->sellt]->arrange)
@@ -1381,12 +1389,27 @@ restack(Monitor *m) {
 void
 run(void) {
        XEvent ev;
-
+       static const char *evname[LASTEvent] = {
+               [ButtonPress] = "buttonpress",
+               [ConfigureRequest] = "configurerequest",
+               [ConfigureNotify] = "configurenotify",
+               [DestroyNotify] = "destroynotify",
+               [EnterNotify] = "enternotify",
+               [Expose] = "expose",
+               [FocusIn] = "focusin",
+               [KeyPress] = "keypress",
+               [MappingNotify] = "mappingnotify",
+               [MapRequest] = "maprequest",
+               [PropertyNotify] = "propertynotify",
+               [UnmapNotify] = "unmapnotify"
+       };
        /* main event loop */
        XSync(dpy, False);
-       while(running && !XNextEvent(dpy, &ev))
+       while(running && !XNextEvent(dpy, &ev)) {
+               D fprintf(stderr, "run event %s\n", evname[ev.type]);
                if(handler[ev.type])
                        handler[ev.type](&ev); /* call handler */
+       }
 }
 
 void
@@ -1427,7 +1450,7 @@ sendmon(Client *c, Monitor *m) {
        attach(c);
        attachstack(c);
        focus(NULL);
-       arrange();
+       arrange(NULL);
 }
 
 void
@@ -1444,10 +1467,11 @@ setlayout(const Arg *arg) {
                selmon->sellt ^= 1;
        if(arg && arg->v)
                selmon->lt[selmon->sellt] = (Layout *)arg->v;
+       strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
        if(selmon->sel)
-               arrange();
+               arrange(selmon);
        else
-               drawbars();
+               drawbar(selmon);
 }
 
 /* arg > 1.0 will set mfact absolutly */
@@ -1461,7 +1485,7 @@ setmfact(const Arg *arg) {
        if(f < 0.1 || f > 0.9)
                return;
        selmon->mfact = f;
-       arrange();
+       arrange(selmon);
 }
 
 void
@@ -1558,7 +1582,7 @@ void
 tag(const Arg *arg) {
        if(selmon->sel && arg->ui & TAGMASK) {
                selmon->sel->tags = arg->ui & TAGMASK;
-               arrange();
+               arrange(selmon);
        }
 }
 
@@ -1615,7 +1639,7 @@ togglebar(const Arg *arg) {
        selmon->showbar = !selmon->showbar;
        updatebarpos(selmon);
        XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
-       arrange();
+       arrange(selmon);
 }
 
 void
@@ -1626,7 +1650,7 @@ togglefloating(const Arg *arg) {
        if(selmon->sel->isfloating)
                resize(selmon->sel, selmon->sel->x, selmon->sel->y,
                       selmon->sel->w, selmon->sel->h, False);
-       arrange();
+       arrange(selmon);
 }
 
 void
@@ -1638,7 +1662,7 @@ toggletag(const Arg *arg) {
        newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
        if(newtags) {
                selmon->sel->tags = newtags;
-               arrange();
+               arrange(selmon);
        }
 }
 
@@ -1648,7 +1672,7 @@ toggleview(const Arg *arg) {
 
        if(newtagset) {
                selmon->tagset[selmon->seltags] = newtagset;
-               arrange();
+               arrange(selmon);
        }
 }
 
@@ -1663,6 +1687,7 @@ unfocus(Client *c) {
 
 void
 unmanage(Client *c, Bool destroyed) {
+       Monitor *m = c->mon;
        XWindowChanges wc;
 
        /* The server grab construct avoids race conditions. */
@@ -1681,7 +1706,7 @@ unmanage(Client *c, Bool destroyed) {
        }
        free(c);
        focus(NULL);
-       arrange();
+       arrange(m);
 }
 
 void
@@ -1730,6 +1755,7 @@ updategeom(void) {
 #ifdef XINERAMA
        if(XineramaIsActive(dpy)) {
                int i, j, n, nn;
+               Client *c;
                Monitor *m;
                XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
                XineramaScreenInfo *unique = NULL;
@@ -1758,7 +1784,7 @@ updategeom(void) {
                                    || unique[i].width != m->mw || unique[i].height != m->mh))
                                {
                                        dirty = True;
-                                       m->num = unique[i].screen_number;
+                                       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;
@@ -1766,9 +1792,22 @@ updategeom(void) {
                                        updatebarpos(m);
                                }
                }
-               else { /* less monitors available */
-                       cleanup();
-                       setup();
+               else { /* less monitors available nn < n */
+                       for(i = nn; i < n; i++) {
+                               for(m = mons; m && m->next; m = m->next);
+                               while(m->clients) {
+                                       dirty = True;
+                                       c = m->clients;
+                                       m->clients = c->next;
+                                       detachstack(c);
+                                       c->mon = mons;
+                                       attach(c);
+                                       attachstack(c);
+                               }
+                               if(m == selmon)
+                                       selmon = mons;
+                               cleanupmon(m);
+                       }
                }
                free(unique);
        }
@@ -1894,7 +1933,7 @@ view(const Arg *arg) {
        selmon->seltags ^= 1; /* toggle sel tagset */
        if(arg->ui & TAGMASK)
                selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
-       arrange();
+       arrange(selmon);
 }
 
 Client *
@@ -1972,7 +2011,7 @@ zoom(const Arg *arg) {
        detach(c);
        attach(c);
        focus(c);
-       arrange();
+       arrange(c->mon);
 }
 
 int