X-Git-Url: https://git.xinqibao.xyz/dwm.git/blobdiff_plain/fa5ae54bbb7f890540f4700809e00497018e0239..a73ff905b04a5f1dab6e0aface03317a81528a95:/dwm.c?ds=inline

diff --git a/dwm.c b/dwm.c
index 88e0b1b..26ec20b 100644
--- a/dwm.c
+++ b/dwm.c
@@ -1,4 +1,4 @@
-#define XINULATOR /* debug, simulates dual head */
+//#define XINULATOR /* debug, simulates dual head */
 /* See LICENSE file for copyright and license details.
  *
  * dynamic window manager is designed like any other X client as well. It is
@@ -211,6 +211,7 @@ static void togglebar(const Arg *arg);
 static void togglefloating(const Arg *arg);
 static void toggletag(const Arg *arg);
 static void toggleview(const Arg *arg);
+static void unfocus(Client *c);
 static void unmanage(Client *c);
 static void unmapnotify(XEvent *e);
 static void updategeom(void);
@@ -391,9 +392,20 @@ buttonpress(XEvent *e) {
 	unsigned int i, x, click;
 	Arg arg = {0};
 	Client *c;
+	Monitor *m;
 	XButtonPressedEvent *ev = &e->xbutton;
 
 	click = ClkRootWin;
+	/* focus monitor if necessary */
+	for(m = mons; m; m = m->next)
+		if(ev->window == m->barwin) {
+			if(m != selmon) {
+				unfocus(selmon->stack);
+				selmon = m;
+				focus(NULL);
+			}
+			break;
+		}
 	if(ev->window == selmon->barwin && ev->x >= selmon->btx) {
 		i = 0;
 		x = selmon->btx;
@@ -644,7 +656,7 @@ drawbar(Monitor *m) {
 	}
 	else
 		x = dc.x;
-	if(m == selmon) {
+	if(m == selmon) { /* status is only drawn on selected monitor */
 		dc.w = TEXTW(stext);
 		dc.x = m->ww - dc.w;
 		if(dc.x < x) {
@@ -652,20 +664,19 @@ drawbar(Monitor *m) {
 			dc.w = m->ww - x;
 		}
 		drawtext(stext, dc.norm, False);
-		if((dc.w = dc.x - x) > bh) {
-			dc.x = x;
-			if(selmon->sel) {
-				drawtext(selmon->sel->name, dc.sel, False);
-				drawsquare(selmon->sel->isfixed, selmon->sel->isfloating, False, dc.sel);
-			}
-			else
-				drawtext(NULL, dc.norm, False);
-		}
 	}
 	else {
+		dc.x = m->ww;
+	}
+	if((dc.w = dc.x - x) > bh) {
 		dc.x = x;
-		dc.w = m->ww - x;
-		drawtext(NULL, dc.norm, False);
+		if(m->sel) {
+			col = m == selmon ? dc.sel : dc.norm;
+			drawtext(m->sel->name, col, False);
+			drawsquare(m->sel->isfixed, m->sel->isfloating, False, col);
+		}
+		else
+			drawtext(NULL, dc.norm, False);
 	}
 	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
 	XSync(dpy, False);
@@ -758,11 +769,11 @@ void
 focus(Client *c) {
 	if(!c || !ISVISIBLE(c))
 		for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
-	if(selmon->sel && selmon->sel != c) {
-		grabbuttons(selmon->sel, False);
-		XSetWindowBorder(dpy, selmon->sel->win, dc.norm[ColBorder]);
-	}
+	if(selmon->sel)
+		unfocus(selmon->sel);
 	if(c) {
+		if(c->mon != selmon)
+			selmon = c->mon;
 		if(c->isurgent)
 			clearurgent(c);
 		detachstack(c);
@@ -793,8 +804,13 @@ focusmon(const Arg *arg) {
 
 	for(i = 0, m = mons; m; m = m->next, i++)
 		if(i == arg->ui) {
-			selmon = m;
-			focus(NULL);
+			if(m->stack)
+				focus(m->stack);
+			else {
+				unfocus(selmon->stack);
+				selmon = m;
+				focus(NULL);
+			}
 			drawbars();
 			break;
 		}
@@ -829,12 +845,14 @@ focusstack(const Arg *arg) {
 
 Client *
 getclient(Window w) {
-	Client *c = NULL;
+	Client *c;
 	Monitor *m;
 
 	for(m = mons; m; m = m->next)
-		for(c = m->clients; c && c->win != w; c = c->next);
-	return c;
+		for(c = m->clients; c; c = c->next)
+			if(c->win == w)
+				return c;
+	return NULL;
 }
 
 unsigned long
@@ -1045,8 +1063,8 @@ manage(Window w, XWindowAttributes *wa) {
 			c->y = sy + sh - HEIGHT(c);
 		c->x = MAX(c->x, sx);
 		/* only fix client y-offset, if the client center might cover the bar */
-		c->y = MAX(c->y, ((selmon->by == 0) && (c->x + (c->w / 2) >= selmon->wx)
-		           && (c->x + (c->w / 2) < selmon->wx + selmon->ww)) ? bh : sy);
+		c->y = MAX(c->y, ((c->mon->by == 0) && (c->x + (c->w / 2) >= c->mon->wx)
+		           && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : sy);
 		c->bw = borderpx;
 	}
 
@@ -1212,8 +1230,7 @@ resize(Client *c, int x, int y, int w, int h) {
 		c->w = wc.width = w;
 		c->h = wc.height = h;
 		wc.border_width = c->bw;
-		XConfigureWindow(dpy, c->win,
-				CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
+		XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
 		configure(c);
 		XSync(dpy, False);
 	}
@@ -1271,10 +1288,10 @@ restack(Monitor *m) {
 	XWindowChanges wc;
 
 	drawbars();
-	if(!selmon->sel)
+	if(!m->sel)
 		return;
-	if(m == selmon && (selmon->sel->isfloating || !lt[m->sellt]->arrange))
-		XRaiseWindow(dpy, selmon->sel->win);
+	if(m->sel->isfloating || !lt[m->sellt]->arrange)
+		XRaiseWindow(dpy, m->sel->win);
 	if(lt[m->sellt]->arrange) {
 		wc.stack_mode = Below;
 		wc.sibling = m->barwin;
@@ -1485,10 +1502,12 @@ tagmon(const Arg *arg) {
 			detach(c);
 			detachstack(c);
 			c->mon = m;
+			c->tags = m->seltags; /* assign tags of target monitor */
 			attach(c);
 			attachstack(c);
-			selmon->sel = selmon->stack;
 			m->sel = c;
+			for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
+			selmon->sel = c;
 			arrange();
 			break;
 		}
@@ -1582,6 +1601,15 @@ toggleview(const Arg *arg) {
 	}
 }
 
+void
+unfocus(Client *c) {
+	if(!c)
+		return;
+	grabbuttons(c, False);
+	XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
+	XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
+}
+
 void
 unmanage(Client *c) {
 	XWindowChanges wc;
@@ -1594,7 +1622,10 @@ unmanage(Client *c) {
 	detach(c);
 	detachstack(c);
 	if(c->mon->sel == c) {
-		c->mon->sel = c->mon->stack;
+		/* TODO: consider separate the next code into a function or into detachstack? */
+		Client *tc;
+		for(tc = c->mon->stack; tc && !ISVISIBLE(tc); tc = tc->snext);
+		c->mon->sel = tc;
 		focus(NULL);
 	}
 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
@@ -1649,9 +1680,11 @@ updatebarpos(Monitor *m) {
 
 void
 updategeom(void) {
-	int i, n = 1;
+	int i, di, n = 1, x, y;
+	unsigned int dui;
 	Client *c;
 	Monitor *newmons = NULL, *m, *tm;
+	Window dummy;
 
 #ifdef XINULATOR
 	n = 2;
@@ -1720,42 +1753,27 @@ updategeom(void) {
 		m->showbar = showbar;
 		m->topbar = topbar;
 		updatebarpos(m);
-		/* reassign all clients with same screen number */
-		for(tm = mons; tm; tm = tm->next)
-			if(tm->screen_number == m->screen_number) {
-				m->clients = tm->clients;
-				m->sel = m->stack = tm->stack;
-				tm->clients = NULL;
-				tm->stack = NULL;
-				for(c = m->clients; c; c = c->next)
-					c->mon = m;
-			}
 	}
 
 	/* reassign left over clients of disappeared monitors */
-	for(tm = mons; tm; tm = tm->next) {
-		while((c = tm->clients)) {
-			detach(c);
+	for(tm = mons; tm; tm = tm->next)
+		while(tm->clients) {
+			c = tm->clients;
+			tm->clients = c->next;
 			detachstack(c);
 			c->mon = newmons;
 			attach(c);
 			attachstack(c);
 		}
-	}
 
 	/* select focused monitor */
-	if(!selmon) {
-		selmon = newmons;
-		int di, x, y;
-		unsigned int dui;
-		Window dummy;
-		if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) 
-			for(m = newmons; m; m = m->next)
-				if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) {
-					selmon = m;
-					break;
-				}
-	}
+	selmon = newmons;
+	if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) 
+		for(m = newmons; m; m = m->next)
+			if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) {
+				selmon = m;
+				break;
+			}
 
 	/* final assignment of new monitors */
 	cleanupmons();