JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
focus new master when closing master
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 5c25c24..f123400 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -184,6 +184,7 @@ static void monocle(Monitor *m);
 static void motionnotify(XEvent *e);
 static void movemouse(const Arg *arg);
 static Client *nexttiled(Client *c);
+static Client *nextvisible(Client *c);
 static void pop(Client *);
 static void propertynotify(XEvent *e);
 static void quit(const Arg *arg);
@@ -410,8 +411,13 @@ arrangemon(Monitor *m) {
 
 void
 attach(Client *c) {
-       c->next = c->mon->clients;
-       c->mon->clients = c;
+       if (c->mon->sel) {
+               c->next = c->mon->sel->next;
+               c->mon->sel->next = c;
+       } else {
+               c->next = c->mon->clients;
+               c->mon->clients = c;
+       }
 }
 
 void
@@ -676,16 +682,30 @@ detach(Client *c) {
        *tc = c->next;
 }
 
+// NOTE: the stack is for z-order and most-recently-focused
+// only mon->clients determines position in visible layout
 void
 detachstack(Client *c) {
-       Client **tc, *t;
-
-       for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
-       *tc = c->snext;
-
+       Client *prev = NULL, *next_sel = NULL, *i;
+       for(i = c->mon->stack; i && i != c; i = i->snext) {
+               prev = i;
+       }
        if(c == c->mon->sel) {
-               for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
-               c->mon->sel = t;
+               // find last visible window before c
+               // WARNING if you detach() before detachstack() this will select last visible window
+               for(i = nextvisible(c->mon->clients); i && i != c; i = nextvisible(i->next))
+                       next_sel = i;
+               // failing that, find first visible window (besides c)
+               if (!next_sel)
+                       for(i = nextvisible(c->mon->clients); i && i == c; i = nextvisible(i->next));
+                       if (i != c)
+                               next_sel = i;
+               c->mon->sel = next_sel;
+       }
+       if (prev) {
+               prev->snext = c->snext;
+       } else {
+               c->mon->stack = c->snext;
        }
 }
 
@@ -1085,7 +1105,7 @@ manage(Window w, XWindowAttributes *wa) {
        c->mon->sel = c;
        arrange(c->mon);
        XMapWindow(dpy, c->win);
-       focus(NULL);
+       focus(c);
 }
 
 void
@@ -1208,6 +1228,12 @@ nexttiled(Client *c) {
        return c;
 }
 
+Client *
+nextvisible(Client *c) {
+       for(; c && !ISVISIBLE(c); c = c->next);
+       return c;
+}
+
 void
 pop(Client *c) {
        detach(c);
@@ -1411,8 +1437,8 @@ sendmon(Client *c, Monitor *m) {
        if(c->mon == m)
                return;
        unfocus(c, True);
-       detach(c);
        detachstack(c);
+       detach(c);
        c->mon = m;
        c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
        attach(c);
@@ -1724,8 +1750,8 @@ unmanage(Client *c, Bool destroyed) {
        XWindowChanges wc;
 
        /* The server grab construct avoids race conditions. */
-       detach(c);
        detachstack(c);
+       detach(c);
        if(!destroyed) {
                wc.border_width = c->oldbw;
                XGrabServer(dpy);
@@ -1738,7 +1764,7 @@ unmanage(Client *c, Bool destroyed) {
                XUngrabServer(dpy);
        }
        free(c);
-       focus(NULL);
+       focus(selmon ? selmon->sel : NULL);
        updateclientlist();
        arrange(m);
 }