X-Git-Url: https://git.xinqibao.xyz/dwm.git/blobdiff_plain/549726869bd88f70727ecae8a28161700395b20b..103fb58a445bc849acdd32c694f013846ab863ee:/dwm.c

diff --git a/dwm.c b/dwm.c
index d9db7fd..2f1dbf8 100644
--- a/dwm.c
+++ b/dwm.c
@@ -39,6 +39,9 @@
 #include <X11/Xlib.h>
 #include <X11/Xproto.h>
 #include <X11/Xutil.h>
+#ifdef XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
 
 /* macros */
 #define MAX(a, b)       ((a) > (b) ? (a) : (b))
@@ -50,7 +53,6 @@
 #define MOUSEMASK       (BUTTONMASK|PointerMotionMask)
 
 /* enums */
-enum { BarTop, BarBot, BarOff, BarLast };               /* bar appearance */
 enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
 enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
@@ -162,11 +164,14 @@ void restack(void);
 void run(void);
 void scan(void);
 void setclientstate(Client *c, long state);
+void setmfact(const char *arg);
 void setup(void);
 void spawn(const char *arg);
 void tag(const char *arg);
 unsigned int textnw(const char *text, unsigned int len);
 unsigned int textw(const char *text);
+void tile(void);
+void tileresize(Client *c, int x, int y, int w, int h);
 void togglebar(const char *arg);
 void togglefloating(const char *arg);
 void togglelayout(const char *arg);
@@ -178,6 +183,7 @@ void unmapnotify(XEvent *e);
 void updatebar(void);
 void updategeom(void);
 void updatesizehints(Client *c);
+void updatetilegeom(void);
 void updatetitle(Client *c);
 void updatewmhints(Client *c);
 void view(const char *arg);
@@ -191,6 +197,7 @@ void zoom(const char *arg);
 char stext[256];
 int screen, sx, sy, sw, sh;
 int bx, by, bw, bh, blw, wx, wy, ww, wh;
+int mx, my, mw, mh, tx, ty, tw, th;
 int seltags = 0;
 int (*xerrorxlib)(Display *, XErrorEvent *);
 unsigned int numlockmask = 0;
@@ -335,10 +342,8 @@ buttonpress(XEvent *e) {
 			restack();
 			movemouse(c);
 		}
-		else if(ev->button == Button2) {
-			if(lt->arrange && c->isfloating)
-				togglefloating(NULL);
-		}
+		else if(ev->button == Button2)
+			togglefloating(NULL);
 		else if(ev->button == Button3 && !c->isfixed) {
 			restack();
 			resizemouse(c);
@@ -955,12 +960,12 @@ manage(Window w, XWindowAttributes *wa) {
 		c->bw = wa->border_width;
 	}
 	else {
-		if(c->x + c->w + 2 * c->bw > wx + ww)
-			c->x = wx + ww - c->w - 2 * c->bw;
-		if(c->y + c->h + 2 * c->bw > wy + wh)
-			c->y = wy + wh - c->h - 2 * c->bw;
-		c->x = MAX(c->x, wx);
-		c->y = MAX(c->y, wy);
+		if(c->x + c->w + 2 * c->bw > sx + sw)
+			c->x = sx + sw - c->w - 2 * c->bw;
+		if(c->y + c->h + 2 * c->bw > sy + sh)
+			c->y = sy + sh - c->h - 2 * c->bw;
+		c->x = MAX(c->x, sx);
+		c->y = MAX(c->y, by == 0 ? bh : sy);
 		c->bw = borderpx;
 	}
 
@@ -1039,16 +1044,19 @@ movemouse(Client *c) {
 			XSync(dpy, False);
 			nx = ocx + (ev.xmotion.x - x1);
 			ny = ocy + (ev.xmotion.y - y1);
-			if(abs(wx - nx) < snap)
-				nx = wx;
-			else if(abs((wx + ww) - (nx + c->w + 2 * c->bw)) < snap)
-				nx = wx + ww - c->w - 2 * c->bw;
-			if(abs(wy - ny) < snap)
-				ny = wy;
-			else if(abs((wy + wh) - (ny + c->h + 2 * c->bw)) < snap)
-				ny = wy + wh - c->h - 2 * c->bw;
-			if(!c->isfloating && lt->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
-				togglefloating(NULL);
+			if(snap && nx >= wx && nx <= wx + ww
+			        && ny >= wy && ny <= wy + wh) {
+				if(abs(wx - nx) < snap)
+					nx = wx;
+				else if(abs((wx + ww) - (nx + c->w + 2 * c->bw)) < snap)
+					nx = wx + ww - c->w - 2 * c->bw;
+				if(abs(wy - ny) < snap)
+					ny = wy;
+				else if(abs((wy + wh) - (ny + c->h + 2 * c->bw)) < snap)
+					ny = wy + wh - c->h - 2 * c->bw;
+				if(!c->isfloating && lt->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
+					togglefloating(NULL);
+			}
 			if(!lt->arrange || c->isfloating)
 				resize(c, nx, ny, c->w, c->h, False);
 			break;
@@ -1193,8 +1201,12 @@ resizemouse(Client *c) {
 			XSync(dpy, False);
 			nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
 			nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
-			if(!c->isfloating && lt->arrange && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) {
-				togglefloating(NULL);
+
+			if(snap && nw >= wx && nw <= wx + ww
+			        && nh >= wy && nh <= wy + wh) {
+				if(!c->isfloating && lt->arrange
+				   && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
+					togglefloating(NULL);
 			}
 			if(!lt->arrange || c->isfloating)
 				resize(c, c->x, c->y, nw, nh, True);
@@ -1322,6 +1334,24 @@ setclientstate(Client *c, long state) {
 			PropModeReplace, (unsigned char *)data, 2);
 }
 
+void
+setmfact(const char *arg) {
+	double d;
+
+	if(!arg || lt->arrange != tile)
+		return;
+	else {
+		d = strtod(arg, NULL);
+		if(arg[0] == '-' || arg[0] == '+')
+			d += mfact;
+		if(d < 0.1 || d > 0.9)
+			return;
+		mfact = d;
+	}
+	updatetilegeom();
+	arrange();
+}
+
 void
 setup(void) {
 	unsigned int i, w;
@@ -1456,6 +1486,53 @@ textw(const char *text) {
 	return textnw(text, strlen(text)) + dc.font.height;
 }
 
+void
+tile(void) {
+	int x, y, h, w;
+	unsigned int i, n;
+	Client *c;
+
+	for(n = 0, c = nextunfloating(clients); c; c = nextunfloating(c->next), n++);
+	if(n == 0)
+		return;
+
+	/* master */
+	c = nextunfloating(clients);
+
+	if(n == 1)
+		tileresize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw);
+	else
+		tileresize(c, mx, my, mw - 2 * c->bw, mh - 2 * c->bw);
+
+	if(--n == 0)
+		return;
+
+	/* tile stack */
+	x = (tx > c->x + c->w) ? c->x + c->w + 2 * c->bw : tw;
+	y = ty;
+	w = (tx > c->x + c->w) ? wx + ww - x : tw;
+	h = th / n;
+	if(h < bh)
+		h = th;
+
+	for(i = 0, c = nextunfloating(c->next); c; c = nextunfloating(c->next), i++) {
+		if(i + 1 == n) /* remainder */
+			tileresize(c, x, y, w - 2 * c->bw, (ty + th) - y - 2 * c->bw);
+		else
+			tileresize(c, x, y, w - 2 * c->bw, h - 2 * c->bw);
+		if(h != th)
+			y = c->y + c->h + 2 * c->bw;
+	}
+}
+
+void
+tileresize(Client *c, int x, int y, int w, int h) {
+	resize(c, x, y, w, h, resizehints);
+	if(resizehints && ((c->h < bh) || (c->h > h) || (c->w < bh) || (c->w > w)))
+		/* client doesn't accept size constraints */
+		resize(c, x, y, w, h, False);
+}
+
 void
 togglebar(const char *arg) {
 	showbar = !showbar;
@@ -1572,22 +1649,32 @@ updatebar(void) {
 
 void
 updategeom(void) {
-	unsigned int i;
-
-#ifdef DEFGEOM /* define your own if you are Xinerama user */
-	DEFGEOM
-#else
-	/* bar geometry*/
-	bx = 0;
-	by = showbar ? (topbar ? 0 : sh - bh) : -bh;
-	bw = sw;
+	int i;
+#ifdef XINERAMA
+	XineramaScreenInfo *info = NULL;
 
 	/* window area geometry */
-	wx = sx;
-	wy = showbar && topbar ? sy + bh : sy;
-	ww = sw;
-	wh = showbar ? sh - bh : sh;
+	if(XineramaIsActive(dpy)) {
+		info = XineramaQueryScreens(dpy, &i);
+		wx = info[0].x_org;
+		wy = showbar && topbar ? info[0].y_org + bh : info[0].y_org;
+		ww = info[0].width;
+		wh = showbar ? info[0].height - bh : info[0].height;
+		XFree(info);
+	}
+	else
 #endif
+	{
+		wx = sx;
+		wy = showbar && topbar ? sy + bh : sy;
+		ww = sw;
+		wh = showbar ? sh - bh : sh;
+	}
+
+	/* bar geometry */
+	bx = wx;
+	by = showbar ? (topbar ? wy - bh : wy + wh) : -bh;
+	bw = ww;
 
 	/* update layout geometries */
 	for(i = 0; i < LENGTH(layouts); i++)
@@ -1647,6 +1734,21 @@ updatesizehints(Client *c) {
 			&& c->maxw == c->minw && c->maxh == c->minh);
 }
 
+void
+updatetilegeom(void) {
+	/* master area geometry */
+	mx = wx;
+	my = wy;
+	mw = mfact * ww;
+	mh = wh;
+
+	/* tile area geometry */
+	tx = mx + mw;
+	ty = wy;
+	tw = ww - mw;
+	th = wh;
+}
+
 void
 updatetitle(Client *c) {
 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
@@ -1713,6 +1815,21 @@ xerrorstart(Display *dpy, XErrorEvent *ee) {
 	return -1;
 }
 
+void
+zoom(const char *arg) {
+	Client *c = sel;
+
+	if(c == nextunfloating(clients))
+		if(!c || !(c = nextunfloating(c->next)))
+			return;
+	if(lt->arrange == tile && !sel->isfloating) {
+		detach(c);
+		attach(c);
+		focus(c);
+	}
+	arrange();
+}
+
 int
 main(int argc, char *argv[]) {
 	if(argc == 2 && !strcmp("-v", argv[1]))