X-Git-Url: https://git.xinqibao.xyz/dwm.git/blobdiff_plain/5a04edecb1eb3a49f659938f7d2eba11d42760ae..cdd6c3e820a360aaca1e8cd9c4b882bac1448261:/dwm.c?ds=sidebyside

diff --git a/dwm.c b/dwm.c
index a27a1ca..f61ce3b 100644
--- a/dwm.c
+++ b/dwm.c
@@ -25,8 +25,6 @@
  *
  * To understand everything else, start reading main().
  */
-#include "dwm.h"
-
 #include <errno.h>
 #include <locale.h>
 #include <stdarg.h>
@@ -41,6 +39,7 @@
 #include <X11/cursorfont.h>
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
+#include <X11/Xlib.h>
 #include <X11/Xproto.h>
 #include <X11/Xutil.h>
 
@@ -49,7 +48,58 @@
 #define CLEANMASK(mask)		(mask & ~(numlockmask | LockMask))
 #define MOUSEMASK		(BUTTONMASK | PointerMotionMask)
 
-/* local typedefs */
+/* enums */
+enum { BarTop, BarBot, BarOff };			/* bar position */
+enum { CurNormal, CurResize, CurMove, CurLast };	/* cursor */
+enum { ColBorder, ColFG, ColBG, ColLast };		/* color */
+enum { NetSupported, NetWMName, NetLast };		/* EWMH atoms */
+enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
+
+/* typedefs */
+typedef struct Client Client;
+struct Client {
+	char name[256];
+	int x, y, w, h;
+	int rx, ry, rw, rh; /* revert geometry */
+	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+	int minax, maxax, minay, maxay;
+	long flags;
+	unsigned int border, oldborder;
+	Bool isbanned, isfixed, ismax, isfloating, wasfloating;
+	Bool *tags;
+	Client *next;
+	Client *prev;
+	Client *snext;
+	Window win;
+};
+
+typedef struct {
+	int x, y, w, h;
+	unsigned long norm[ColLast];
+	unsigned long sel[ColLast];
+	Drawable drawable;
+	GC gc;
+	struct {
+		int ascent;
+		int descent;
+		int height;
+		XFontSet set;
+		XFontStruct *xfont;
+	} font;
+} DC; /* draw context */
+
+typedef struct {
+	unsigned long mod;
+	KeySym keysym;
+	void (*func)(const char *arg);
+	const char *arg;
+} Key;
+
+typedef struct {
+	const char *symbol;
+	void (*arrange)(void);
+} Layout;
+
 typedef struct {
 	const char *prop;
 	const char *tags;
@@ -61,6 +111,86 @@ typedef struct {
 	regex_t *tagregex;
 } Regs;
 
+/* function declarations */
+void applyrules(Client *c);
+void arrange(void);
+void attach(Client *c);
+void attachstack(Client *c);
+void ban(Client *c);
+void buttonpress(XEvent *e);
+void checkotherwm(void);
+void cleanup(void);
+void compileregs(void);
+void configure(Client *c);
+void configurenotify(XEvent *e);
+void configurerequest(XEvent *e);
+void destroynotify(XEvent *e);
+void detach(Client *c);
+void detachstack(Client *c);
+void drawbar(void);
+void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]);
+void drawtext(const char *text, unsigned long col[ColLast]);
+void *emallocz(unsigned int size);
+void enternotify(XEvent *e);
+void eprint(const char *errstr, ...);
+void expose(XEvent *e);
+void floating(void); /* default floating layout */
+void focus(Client *c);
+void focusnext(const char *arg);
+void focusprev(const char *arg);
+Client *getclient(Window w);
+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);
+unsigned int idxoftag(const char *tag);
+void initfont(const char *fontstr);
+Bool isarrange(void (*func)());
+Bool isoccupied(unsigned int t);
+Bool isprotodel(Client *c);
+Bool isvisible(Client *c);
+void keypress(XEvent *e);
+void killclient(const char *arg);
+void leavenotify(XEvent *e);
+void manage(Window w, XWindowAttributes *wa);
+void mappingnotify(XEvent *e);
+void maprequest(XEvent *e);
+void movemouse(Client *c);
+Client *nexttiled(Client *c);
+void propertynotify(XEvent *e);
+void quit(const char *arg);
+void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
+void resizemouse(Client *c);
+void restack(void);
+void run(void);
+void scan(void);
+void setclientstate(Client *c, long state);
+void setlayout(const char *arg);
+void setmwfact(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 togglebar(const char *arg);
+void togglefloating(const char *arg);
+void togglemax(const char *arg);
+void toggletag(const char *arg);
+void toggleview(const char *arg);
+void unban(Client *c);
+void unmanage(Client *c);
+void unmapnotify(XEvent *e);
+void updatebarpos(void);
+void updatesizehints(Client *c);
+void updatetitle(Client *c);
+void view(const char *arg);
+void viewprevtag(const char *arg);	/* views previous selected tags */
+int xerror(Display *dpy, XErrorEvent *ee);
+int xerrordummy(Display *dsply, XErrorEvent *ee);
+int xerrorstart(Display *dsply, XErrorEvent *ee);
+void zoom(const char *arg);
+
 /* variables */
 char stext[256];
 double mwfact;
@@ -102,12 +232,11 @@ Regs *regs = NULL;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
-/* Statically define the number of tags. */
-unsigned int ntags = sizeof tags / sizeof tags[0];
-Bool seltags[sizeof tags / sizeof tags[0]] = {[0] = True};
-Bool prevtags[sizeof tags / sizeof tags[0]] = {[0] = True};
+#define NTAGS (sizeof tags / sizeof tags[0])
+Bool seltags[NTAGS] = {[0] = True};
+Bool prevtags[NTAGS] = {[0] = True};
 
-/* functions*/
+/* function implementations */
 void
 applyrules(Client *c) {
 	static char buf[512];
@@ -124,7 +253,7 @@ applyrules(Client *c) {
 	for(i = 0; i < nrules; i++)
 		if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
 			c->isfloating = rules[i].isfloating;
-			for(j = 0; regs[i].tagregex && j < ntags; j++) {
+			for(j = 0; regs[i].tagregex && j < NTAGS; j++) {
 				if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
 					matched = True;
 					c->tags[j] = True;
@@ -183,7 +312,7 @@ buttonpress(XEvent *e) {
 
 	if(barwin == ev->window) {
 		x = 0;
-		for(i = 0; i < ntags; i++) {
+		for(i = 0; i < NTAGS; i++) {
 			x += textw(tags[i]);
 			if(ev->x < x) {
 				if(ev->button == Button1) {
@@ -216,7 +345,7 @@ buttonpress(XEvent *e) {
 			movemouse(c);
 		}
 		else if(ev->button == Button2) {
-			if(ISTILE && !c->isfixed && c->isfloating)
+			if((ISTILE) && !c->isfixed && c->isfloating)
 				togglefloating(NULL);
 			else
 				zoom(NULL);
@@ -407,7 +536,7 @@ drawbar(void) {
 	int i, x;
 
 	dc.x = dc.y = 0;
-	for(i = 0; i < ntags; i++) {
+	for(i = 0; i < NTAGS; i++) {
 		dc.w = textw(tags[i]);
 		if(seltags[i]) {
 			drawtext(tags[i], dc.sel);
@@ -717,10 +846,8 @@ unsigned int
 idxoftag(const char *tag) {
 	unsigned int i;
 
-	for(i = 0; i < ntags; i++)
-		if(tags[i] == tag)
-			return i;
-	return 0;
+	for(i = 0; (i < NTAGS) && (tags[i] != tag); i++);
+	return (i < NTAGS) ? i : 0;
 }
 
 void
@@ -800,7 +927,7 @@ Bool
 isvisible(Client *c) {
 	unsigned int i;
 
-	for(i = 0; i < ntags; i++)
+	for(i = 0; i < NTAGS; i++)
 		if(c->tags[i] && seltags[i])
 			return True;
 	return False;
@@ -1010,7 +1137,7 @@ propertynotify(XEvent *e) {
 			default: break;
 			case XA_WM_TRANSIENT_FOR:
 				XGetTransientForHint(dpy, c->win, &trans);
-				if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
+				if(!c->isfloating && (c->isfloating = (NULL != getclient(trans))))
 					arrange();
 				break;
 			case XA_WM_NORMAL_HINTS:
@@ -1032,43 +1159,45 @@ quit(const char *arg) {
 
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
-	double dx, dy, max, min, ratio;
 	XWindowChanges wc;
 
 	if(sizehints) {
-		if(c->minay > 0 && c->maxay > 0 && (h - c->baseh) > 0 && (w - c->basew) > 0) {
-			dx = (double)(w - c->basew);
-			dy = (double)(h - c->baseh);
-			min = (double)(c->minax) / (double)(c->minay);
-			max = (double)(c->maxax) / (double)(c->maxay);
-			ratio = dx / dy;
-			if(max > 0 && min > 0 && ratio > 0) {
-				if(ratio < min) {
-					dy = (dx * min + dy) / (min * min + 1);
-					dx = dy * min;
-					w = (int)dx + c->basew;
-					h = (int)dy + c->baseh;
-				}
-				else if(ratio > max) {
-					dy = (dx * min + dy) / (max * max + 1);
-					dx = dy * min;
-					w = (int)dx + c->basew;
-					h = (int)dy + c->baseh;
-				}
-			}
+		/* set minimum possible */
+		if (w < 1)
+			w = 1;
+		if (h < 1)
+			h = 1;
+
+		/* temporarily remove base dimensions */
+		w -= c->basew;
+		h -= c->baseh;
+
+		/* adjust for aspect limits */
+		if (c->minay > 0 && c->maxay > 0 && c->minax > 0 && c->maxax > 0) {
+			if (w * c->maxay > h * c->maxax)
+				w = h * c->maxax / c->maxay;
+			else if (w * c->minay < h * c->minax)
+				h = w * c->minay / c->minax;
 		}
-		if(c->minw && w < c->minw)
+
+		/* adjust for increment value */
+		if(c->incw)
+			w -= w % c->incw;
+		if(c->inch)
+			h -= h % c->inch;
+
+		/* restore base dimensions */
+		w += c->basew;
+		h += c->baseh;
+
+		if(c->minw > 0 && w < c->minw)
 			w = c->minw;
-		if(c->minh && h < c->minh)
+		if(c->minh > 0 && h < c->minh)
 			h = c->minh;
-		if(c->maxw && w > c->maxw)
+		if(c->maxw > 0 && w > c->maxw)
 			w = c->maxw;
-		if(c->maxh && h > c->maxh)
+		if(c->maxh > 0 && h > c->maxh)
 			h = c->maxh;
-		if(c->incw)
-			w -= (w - c->basew) % c->incw;
-		if(c->inch)
-			h -= (h - c->baseh) % c->inch;
 	}
 	if(w <= 0 || h <= 0)
 		return;
@@ -1270,7 +1399,7 @@ void
 setmwfact(const char *arg) {
 	double delta;
 
-	if(!ISTILE)
+	if(!(ISTILE))
 		return;
 	/* arg handling, manipulate mwfact */
 	if(arg == NULL)
@@ -1410,11 +1539,9 @@ tag(const char *arg) {
 
 	if(!sel)
 		return;
-	for(i = 0; i < ntags; i++)
-		sel->tags[i] = arg == NULL;
-	i = idxoftag(arg);
-	if(i >= 0 && i < ntags)
-		sel->tags[i] = True;
+	for(i = 0; i < NTAGS; i++)
+		sel->tags[i] = (NULL == arg);
+	sel->tags[idxoftag(arg)] = True;
 	arrange();
 }
 
@@ -1468,7 +1595,9 @@ tile(void) {
 			else
 				nh = th - 2 * c->border;
 		}
-		resize(c, nx, ny, nw, nh, RESIZEHINTS);
+		resize(c, nx, ny, nw, nh, True);
+		if((c->h < bh) || (c->h > nh)) /* client doesn't accept geometry */
+			resize(c, nx, ny, nw, nh, False);
 		if(n > 1 && th != wah)
 			ny = c->y + c->h + 2 * c->border;
 	}
@@ -1530,9 +1659,9 @@ toggletag(const char *arg) {
 		return;
 	i = idxoftag(arg);
 	sel->tags[i] = !sel->tags[i];
-	for(j = 0; j < ntags && !sel->tags[j]; j++);
-	if(j == ntags)
-		sel->tags[i] = True;
+	for(j = 0; j < NTAGS && !sel->tags[j]; j++);
+	if(j == NTAGS)
+		sel->tags[i] = True; /* at least one tag must be enabled */
 	arrange();
 }
 
@@ -1542,8 +1671,8 @@ toggleview(const char *arg) {
 
 	i = idxoftag(arg);
 	seltags[i] = !seltags[i];
-	for(j = 0; j < ntags && !seltags[j]; j++);
-	if(j == ntags)
+	for(j = 0; j < NTAGS && !seltags[j]; j++);
+	if(j == NTAGS)
 		seltags[i] = True; /* at least one tag must be viewed */
 	arrange();
 }
@@ -1709,11 +1838,9 @@ view(const char *arg) {
 	unsigned int i;
 
 	memcpy(prevtags, seltags, sizeof seltags);
-	for(i = 0; i < ntags; i++)
+	for(i = 0; i < NTAGS; i++)
 		seltags[i] = arg == NULL;
-	i = idxoftag(arg);
-	if(i >= 0 && i < ntags)
-		seltags[i] = True;
+	seltags[idxoftag(arg)] = True;
 	arrange();
 }
 
@@ -1731,7 +1858,7 @@ void
 zoom(const char *arg) {
 	Client *c;
 
-	if(!sel || !ISTILE || sel->isfloating)
+	if(!sel || !(ISTILE) || sel->isfloating)
 		return;
 	if((c = sel) == nexttiled(clients))
 		if(!(c = nexttiled(c->next)))