micromizing dwm step 1
This commit is contained in:
		
							parent
							
								
									2091200c95
								
							
						
					
					
						commit
						0235a84ef2
					
				
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							| @ -3,7 +3,7 @@ | |||||||
| 
 | 
 | ||||||
| include config.mk | include config.mk | ||||||
| 
 | 
 | ||||||
| SRC += bar.c client.c event.c main.c screen.c util.c | SRC = dwm.c | ||||||
| OBJ = ${SRC:.c=.o} | OBJ = ${SRC:.c=.o} | ||||||
| 
 | 
 | ||||||
| all: options dwm | all: options dwm | ||||||
| @ -18,7 +18,7 @@ options: | |||||||
| 	@echo CC $< | 	@echo CC $< | ||||||
| 	@${CC} -c ${CFLAGS} $< | 	@${CC} -c ${CFLAGS} $< | ||||||
| 
 | 
 | ||||||
| ${OBJ}: dwm.h config.h config.mk | ${OBJ}: config.h config.mk | ||||||
| 
 | 
 | ||||||
| dwm: ${OBJ} | dwm: ${OBJ} | ||||||
| 	@echo CC -o $@ | 	@echo CC -o $@ | ||||||
| @ -32,7 +32,7 @@ dist: clean | |||||||
| 	@echo creating dist tarball | 	@echo creating dist tarball | ||||||
| 	@mkdir -p dwm-${VERSION} | 	@mkdir -p dwm-${VERSION} | ||||||
| 	@cp -R LICENSE Makefile README config.h config.mk \
 | 	@cp -R LICENSE Makefile README config.h config.mk \
 | ||||||
| 		dwm.1 dwm.h tile.h ${SRC} dwm-${VERSION} | 		dwm.1 ${SRC} dwm-${VERSION} | ||||||
| 	@tar -cf dwm-${VERSION}.tar dwm-${VERSION} | 	@tar -cf dwm-${VERSION}.tar dwm-${VERSION} | ||||||
| 	@gzip dwm-${VERSION}.tar | 	@gzip dwm-${VERSION}.tar | ||||||
| 	@rm -rf dwm-${VERSION} | 	@rm -rf dwm-${VERSION} | ||||||
|  | |||||||
							
								
								
									
										263
									
								
								bar.c
									
									
									
									
									
								
							
							
						
						
									
										263
									
								
								bar.c
									
									
									
									
									
								
							| @ -1,263 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <string.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| 
 |  | ||||||
| /* static */ |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) { |  | ||||||
| 	int x; |  | ||||||
| 	XGCValues gcv; |  | ||||||
| 	XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |  | ||||||
| 
 |  | ||||||
| 	gcv.foreground = col[ColFG]; |  | ||||||
| 	XChangeGC(dpy, dc.gc, GCForeground, &gcv); |  | ||||||
| 	x = (dc.font.ascent + dc.font.descent + 2) / 4; |  | ||||||
| 	r.x = dc.x + 1; |  | ||||||
| 	r.y = dc.y + 1; |  | ||||||
| 	if(filled) { |  | ||||||
| 		r.width = r.height = x + 1; |  | ||||||
| 		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |  | ||||||
| 	} |  | ||||||
| 	else if(empty) { |  | ||||||
| 		r.width = r.height = x; |  | ||||||
| 		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned long |  | ||||||
| initcolor(const char *colstr) { |  | ||||||
| 	Colormap cmap = DefaultColormap(dpy, screen); |  | ||||||
| 	XColor color; |  | ||||||
| 
 |  | ||||||
| 	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |  | ||||||
| 		eprint("error, cannot allocate color '%s'\n", colstr); |  | ||||||
| 	return color.pixel; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| initfont(const char *fontstr) { |  | ||||||
| 	char *def, **missing; |  | ||||||
| 	int i, n; |  | ||||||
| 
 |  | ||||||
| 	missing = NULL; |  | ||||||
| 	if(dc.font.set) |  | ||||||
| 		XFreeFontSet(dpy, dc.font.set); |  | ||||||
| 	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); |  | ||||||
| 	if(missing) { |  | ||||||
| 		while(n--) |  | ||||||
| 			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]); |  | ||||||
| 		XFreeStringList(missing); |  | ||||||
| 	} |  | ||||||
| 	if(dc.font.set) { |  | ||||||
| 		XFontSetExtents *font_extents; |  | ||||||
| 		XFontStruct **xfonts; |  | ||||||
| 		char **font_names; |  | ||||||
| 		dc.font.ascent = dc.font.descent = 0; |  | ||||||
| 		font_extents = XExtentsOfFontSet(dc.font.set); |  | ||||||
| 		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); |  | ||||||
| 		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { |  | ||||||
| 			if(dc.font.ascent < (*xfonts)->ascent) |  | ||||||
| 				dc.font.ascent = (*xfonts)->ascent; |  | ||||||
| 			if(dc.font.descent < (*xfonts)->descent) |  | ||||||
| 				dc.font.descent = (*xfonts)->descent; |  | ||||||
| 			xfonts++; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		if(dc.font.xfont) |  | ||||||
| 			XFreeFont(dpy, dc.font.xfont); |  | ||||||
| 		dc.font.xfont = NULL; |  | ||||||
| 		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) |  | ||||||
| 		|| !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) |  | ||||||
| 			eprint("error, cannot load font: '%s'\n", fontstr); |  | ||||||
| 		dc.font.ascent = dc.font.xfont->ascent; |  | ||||||
| 		dc.font.descent = dc.font.xfont->descent; |  | ||||||
| 	} |  | ||||||
| 	dc.font.height = dc.font.ascent + dc.font.descent; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static Bool |  | ||||||
| isoccupied(unsigned int t) { |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	for(c = clients; c; c = c->next) |  | ||||||
| 		if(c->tags[t]) |  | ||||||
| 			return True; |  | ||||||
| 	return False; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned int |  | ||||||
| textnw(const char *text, unsigned int len) { |  | ||||||
| 	XRectangle r; |  | ||||||
| 
 |  | ||||||
| 	if(dc.font.set) { |  | ||||||
| 		XmbTextExtents(dc.font.set, text, len, NULL, &r); |  | ||||||
| 		return r.width; |  | ||||||
| 	} |  | ||||||
| 	return XTextWidth(dc.font.xfont, text, len); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| drawtext(const char *text, unsigned long col[ColLast]) { |  | ||||||
| 	int x, y, w, h; |  | ||||||
| 	static char buf[256]; |  | ||||||
| 	unsigned int len, olen; |  | ||||||
| 	XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |  | ||||||
| 
 |  | ||||||
| 	XSetForeground(dpy, dc.gc, col[ColBG]); |  | ||||||
| 	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |  | ||||||
| 	if(!text) |  | ||||||
| 		return; |  | ||||||
| 	w = 0; |  | ||||||
| 	olen = len = strlen(text); |  | ||||||
| 	if(len >= sizeof buf) |  | ||||||
| 		len = sizeof buf - 1; |  | ||||||
| 	memcpy(buf, text, len); |  | ||||||
| 	buf[len] = 0; |  | ||||||
| 	h = dc.font.ascent + dc.font.descent; |  | ||||||
| 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; |  | ||||||
| 	x = dc.x + (h / 2); |  | ||||||
| 	/* shorten text if necessary */ |  | ||||||
| 	while(len && (w = textnw(buf, len)) > dc.w - h) |  | ||||||
| 		buf[--len] = 0; |  | ||||||
| 	if(len < olen) { |  | ||||||
| 		if(len > 1) |  | ||||||
| 			buf[len - 1] = '.'; |  | ||||||
| 		if(len > 2) |  | ||||||
| 			buf[len - 2] = '.'; |  | ||||||
| 		if(len > 3) |  | ||||||
| 			buf[len - 3] = '.'; |  | ||||||
| 	} |  | ||||||
| 	if(w > dc.w) |  | ||||||
| 		return; /* too long */ |  | ||||||
| 	XSetForeground(dpy, dc.gc, col[ColFG]); |  | ||||||
| 	if(dc.font.set) |  | ||||||
| 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); |  | ||||||
| 	else |  | ||||||
| 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| unsigned int bh; |  | ||||||
| unsigned int bpos = BARPOS; |  | ||||||
| DC dc = {0}; |  | ||||||
| Window barwin; |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| drawbar(void) { |  | ||||||
| 	int i, x; |  | ||||||
| 
 |  | ||||||
| 	dc.x = dc.y = 0; |  | ||||||
| 	for(i = 0; i < ntags; i++) { |  | ||||||
| 		dc.w = textw(tags[i]); |  | ||||||
| 		if(seltags[i]) { |  | ||||||
| 			drawtext(tags[i], dc.sel); |  | ||||||
| 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel); |  | ||||||
| 		} |  | ||||||
| 		else { |  | ||||||
| 			drawtext(tags[i], dc.norm); |  | ||||||
| 			drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm); |  | ||||||
| 		} |  | ||||||
| 		dc.x += dc.w; |  | ||||||
| 	} |  | ||||||
| 	dc.w = blw; |  | ||||||
| 	drawtext(getsymbol(), dc.norm); |  | ||||||
| 	x = dc.x + dc.w; |  | ||||||
| 	dc.w = textw(stext); |  | ||||||
| 	dc.x = sw - dc.w; |  | ||||||
| 	if(dc.x < x) { |  | ||||||
| 		dc.x = x; |  | ||||||
| 		dc.w = sw - x; |  | ||||||
| 	} |  | ||||||
| 	drawtext(stext, dc.norm); |  | ||||||
| 	if((dc.w = dc.x - x) > bh) { |  | ||||||
| 		dc.x = x; |  | ||||||
| 		if(sel) { |  | ||||||
| 			drawtext(sel->name, dc.sel); |  | ||||||
| 			drawsquare(sel->ismax, sel->isfloating, dc.sel); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 			drawtext(NULL, dc.norm); |  | ||||||
| 	} |  | ||||||
| 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0); |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| initstyle(void) { |  | ||||||
| 	dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR); |  | ||||||
| 	dc.norm[ColBG] = initcolor(NORMBGCOLOR); |  | ||||||
| 	dc.norm[ColFG] = initcolor(NORMFGCOLOR); |  | ||||||
| 	dc.sel[ColBorder] = initcolor(SELBORDERCOLOR); |  | ||||||
| 	dc.sel[ColBG] = initcolor(SELBGCOLOR); |  | ||||||
| 	dc.sel[ColFG] = initcolor(SELFGCOLOR); |  | ||||||
| 	initfont(FONT); |  | ||||||
| 	dc.h = bh = dc.font.height + 2; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| initbar(void) { |  | ||||||
| 	XSetWindowAttributes wa; |  | ||||||
| 
 |  | ||||||
| 	wa.override_redirect = 1; |  | ||||||
| 	wa.background_pixmap = ParentRelative; |  | ||||||
| 	wa.event_mask = ButtonPressMask | ExposureMask; |  | ||||||
| 	barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0, |  | ||||||
| 			DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), |  | ||||||
| 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |  | ||||||
| 	XDefineCursor(dpy, barwin, cursor[CurNormal]); |  | ||||||
| 	updatebarpos(); |  | ||||||
| 	XMapRaised(dpy, barwin); |  | ||||||
| 	strcpy(stext, "dwm-"VERSION); |  | ||||||
| 	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); |  | ||||||
| 	dc.gc = XCreateGC(dpy, root, 0, 0); |  | ||||||
| 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |  | ||||||
| 	if(!dc.font.set) |  | ||||||
| 		XSetFont(dpy, dc.gc, dc.font.xfont->fid); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| unsigned int |  | ||||||
| textw(const char *text) { |  | ||||||
| 	return textnw(text, strlen(text)) + dc.font.height; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| togglebar(const char *arg) { |  | ||||||
| 	if(bpos == BarOff) |  | ||||||
| 		bpos = (BARPOS == BarOff) ? BarTop : BARPOS; |  | ||||||
| 	else |  | ||||||
| 		bpos = BarOff; |  | ||||||
| 	updatebarpos(); |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| updatebarpos(void) { |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	wax = sx; |  | ||||||
| 	way = sy; |  | ||||||
| 	wah = sh; |  | ||||||
| 	waw = sw; |  | ||||||
| 	switch(bpos) { |  | ||||||
| 	default: |  | ||||||
| 		wah -= bh; |  | ||||||
| 		way += bh; |  | ||||||
| 		XMoveWindow(dpy, barwin, sx, sy); |  | ||||||
| 		break; |  | ||||||
| 	case BarBot: |  | ||||||
| 		wah -= bh; |  | ||||||
| 		XMoveWindow(dpy, barwin, sx, sy + wah); |  | ||||||
| 		break; |  | ||||||
| 	case BarOff: |  | ||||||
| 		XMoveWindow(dpy, barwin, sx, sy - bh); |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
							
								
								
									
										386
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										386
									
								
								client.c
									
									
									
									
									
								
							| @ -1,386 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <X11/Xutil.h> |  | ||||||
| 
 |  | ||||||
| /* static */ |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| attachstack(Client *c) { |  | ||||||
| 	c->snext = stack; |  | ||||||
| 	stack = c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| detachstack(Client *c) { |  | ||||||
| 	Client **tc; |  | ||||||
| 
 |  | ||||||
| 	for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); |  | ||||||
| 	*tc = c->snext; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| grabbuttons(Client *c, Bool focused) { |  | ||||||
| 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |  | ||||||
| 
 |  | ||||||
| 	if(focused) { |  | ||||||
| 		XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 
 |  | ||||||
| 		XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 
 |  | ||||||
| 		XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 		XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, |  | ||||||
| 				GrabModeAsync, GrabModeSync, None, None); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static Bool |  | ||||||
| isprotodel(Client *c) { |  | ||||||
| 	int i, n; |  | ||||||
| 	Atom *protocols; |  | ||||||
| 	Bool ret = False; |  | ||||||
| 
 |  | ||||||
| 	if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { |  | ||||||
| 		for(i = 0; !ret && i < n; i++) |  | ||||||
| 			if(protocols[i] == wmatom[WMDelete]) |  | ||||||
| 				ret = True; |  | ||||||
| 		XFree(protocols); |  | ||||||
| 	} |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| setclientstate(Client *c, long state) { |  | ||||||
| 	long data[] = {state, None}; |  | ||||||
| 
 |  | ||||||
| 	XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, |  | ||||||
| 			PropModeReplace, (unsigned char *)data, 2); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int |  | ||||||
| xerrordummy(Display *dsply, XErrorEvent *ee) { |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| attach(Client *c) { |  | ||||||
| 	if(clients) |  | ||||||
| 		clients->prev = c; |  | ||||||
| 	c->next = clients; |  | ||||||
| 	clients = c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| ban(Client *c) { |  | ||||||
| 	if(c->isbanned) |  | ||||||
| 		return; |  | ||||||
| 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |  | ||||||
| 	c->isbanned = True; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| configure(Client *c) { |  | ||||||
| 	XConfigureEvent ce; |  | ||||||
| 
 |  | ||||||
| 	ce.type = ConfigureNotify; |  | ||||||
| 	ce.display = dpy; |  | ||||||
| 	ce.event = c->win; |  | ||||||
| 	ce.window = c->win; |  | ||||||
| 	ce.x = c->x; |  | ||||||
| 	ce.y = c->y; |  | ||||||
| 	ce.width = c->w; |  | ||||||
| 	ce.height = c->h; |  | ||||||
| 	ce.border_width = c->border; |  | ||||||
| 	ce.above = None; |  | ||||||
| 	ce.override_redirect = False; |  | ||||||
| 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| detach(Client *c) { |  | ||||||
| 	if(c->prev) |  | ||||||
| 		c->prev->next = c->next; |  | ||||||
| 	if(c->next) |  | ||||||
| 		c->next->prev = c->prev; |  | ||||||
| 	if(c == clients) |  | ||||||
| 		clients = c->next; |  | ||||||
| 	c->next = c->prev = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| focus(Client *c) { |  | ||||||
| 	if((!c && selscreen) || (c && !isvisible(c))) |  | ||||||
| 		for(c = stack; c && !isvisible(c); c = c->snext); |  | ||||||
| 	if(sel && sel != c) { |  | ||||||
| 		grabbuttons(sel, False); |  | ||||||
| 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); |  | ||||||
| 	} |  | ||||||
| 	if(c) { |  | ||||||
| 		detachstack(c); |  | ||||||
| 		attachstack(c); |  | ||||||
| 		grabbuttons(c, True); |  | ||||||
| 	} |  | ||||||
| 	sel = c; |  | ||||||
| 	drawbar(); |  | ||||||
| 	if(!selscreen) |  | ||||||
| 		return; |  | ||||||
| 	if(c) { |  | ||||||
| 		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |  | ||||||
| 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| killclient(const char *arg) { |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	if(!sel) |  | ||||||
| 		return; |  | ||||||
| 	if(isprotodel(sel)) { |  | ||||||
| 		ev.type = ClientMessage; |  | ||||||
| 		ev.xclient.window = sel->win; |  | ||||||
| 		ev.xclient.message_type = wmatom[WMProtocols]; |  | ||||||
| 		ev.xclient.format = 32; |  | ||||||
| 		ev.xclient.data.l[0] = wmatom[WMDelete]; |  | ||||||
| 		ev.xclient.data.l[1] = CurrentTime; |  | ||||||
| 		XSendEvent(dpy, sel->win, False, NoEventMask, &ev); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		XKillClient(dpy, sel->win); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| manage(Window w, XWindowAttributes *wa) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 	Client *c, *t = NULL; |  | ||||||
| 	Window trans; |  | ||||||
| 	Status rettrans; |  | ||||||
| 	XWindowChanges wc; |  | ||||||
| 
 |  | ||||||
| 	c = emallocz(sizeof(Client)); |  | ||||||
| 	c->tags = emallocz(ntags * sizeof(Bool)); |  | ||||||
| 	c->win = w; |  | ||||||
| 	c->x = wa->x; |  | ||||||
| 	c->y = wa->y; |  | ||||||
| 	c->w = wa->width; |  | ||||||
| 	c->h = wa->height; |  | ||||||
| 	c->oldborder = wa->border_width; |  | ||||||
| 	if(c->w == sw && c->h == sh) { |  | ||||||
| 		c->x = sx; |  | ||||||
| 		c->y = sy; |  | ||||||
| 		c->border = wa->border_width; |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		if(c->x + c->w + 2 * c->border > wax + waw) |  | ||||||
| 			c->x = wax + waw - c->w - 2 * c->border; |  | ||||||
| 		if(c->y + c->h + 2 * c->border > way + wah) |  | ||||||
| 			c->y = way + wah - c->h - 2 * c->border; |  | ||||||
| 		if(c->x < wax) |  | ||||||
| 			c->x = wax; |  | ||||||
| 		if(c->y < way) |  | ||||||
| 			c->y = way; |  | ||||||
| 		c->border = BORDERPX; |  | ||||||
| 	} |  | ||||||
| 	wc.border_width = c->border; |  | ||||||
| 	XConfigureWindow(dpy, w, CWBorderWidth, &wc); |  | ||||||
| 	XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |  | ||||||
| 	configure(c); /* propagates border_width, if size doesn't change */ |  | ||||||
| 	updatesizehints(c); |  | ||||||
| 	XSelectInput(dpy, w, |  | ||||||
| 		StructureNotifyMask | PropertyChangeMask | EnterWindowMask); |  | ||||||
| 	grabbuttons(c, False); |  | ||||||
| 	updatetitle(c); |  | ||||||
| 	if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) |  | ||||||
| 		for(t = clients; t && t->win != trans; t = t->next); |  | ||||||
| 	if(t) |  | ||||||
| 		for(i = 0; i < ntags; i++) |  | ||||||
| 			c->tags[i] = t->tags[i]; |  | ||||||
| 	applyrules(c); |  | ||||||
| 	if(!c->isfloating) |  | ||||||
| 		c->isfloating = (rettrans == Success) || c->isfixed; |  | ||||||
| 	attach(c); |  | ||||||
| 	attachstack(c); |  | ||||||
| 	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); /* some windows require this */ |  | ||||||
| 	ban(c); |  | ||||||
| 	XMapWindow(dpy, c->win); |  | ||||||
| 	setclientstate(c, NormalState); |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if(c->minw && w < c->minw) |  | ||||||
| 			w = c->minw; |  | ||||||
| 		if(c->minh && h < c->minh) |  | ||||||
| 			h = c->minh; |  | ||||||
| 		if(c->maxw && w > c->maxw) |  | ||||||
| 			w = c->maxw; |  | ||||||
| 		if(c->maxh && 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; |  | ||||||
| 	/* offscreen appearance fixes */ |  | ||||||
| 	if(x > sw) |  | ||||||
| 		x = sw - w - 2 * c->border; |  | ||||||
| 	if(y > sh) |  | ||||||
| 		y = sh - h - 2 * c->border; |  | ||||||
| 	if(x + w + 2 * c->border < sx) |  | ||||||
| 		x = sx; |  | ||||||
| 	if(y + h + 2 * c->border < sy) |  | ||||||
| 		y = sy; |  | ||||||
| 	if(c->x != x || c->y != y || c->w != w || c->h != h) { |  | ||||||
| 		c->x = wc.x = x; |  | ||||||
| 		c->y = wc.y = y; |  | ||||||
| 		c->w = wc.width = w; |  | ||||||
| 		c->h = wc.height = h; |  | ||||||
| 		wc.border_width = c->border; |  | ||||||
| 		XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); |  | ||||||
| 		configure(c); |  | ||||||
| 		XSync(dpy, False); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| unban(Client *c) { |  | ||||||
| 	if(!c->isbanned) |  | ||||||
| 		return; |  | ||||||
| 	XMoveWindow(dpy, c->win, c->x, c->y); |  | ||||||
| 	c->isbanned = False; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| unmanage(Client *c) { |  | ||||||
| 	XWindowChanges wc; |  | ||||||
| 
 |  | ||||||
| 	wc.border_width = c->oldborder; |  | ||||||
| 	/* The server grab construct avoids race conditions. */ |  | ||||||
| 	XGrabServer(dpy); |  | ||||||
| 	XSetErrorHandler(xerrordummy); |  | ||||||
| 	XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ |  | ||||||
| 	detach(c); |  | ||||||
| 	detachstack(c); |  | ||||||
| 	if(sel == c) |  | ||||||
| 		focus(NULL); |  | ||||||
| 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |  | ||||||
| 	setclientstate(c, WithdrawnState); |  | ||||||
| 	free(c->tags); |  | ||||||
| 	free(c); |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	XSetErrorHandler(xerror); |  | ||||||
| 	XUngrabServer(dpy); |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| updatesizehints(Client *c) { |  | ||||||
| 	long msize; |  | ||||||
| 	XSizeHints size; |  | ||||||
| 
 |  | ||||||
| 	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |  | ||||||
| 		size.flags = PSize; |  | ||||||
| 	c->flags = size.flags; |  | ||||||
| 	if(c->flags & PBaseSize) { |  | ||||||
| 		c->basew = size.base_width; |  | ||||||
| 		c->baseh = size.base_height; |  | ||||||
| 	} |  | ||||||
| 	else if(c->flags & PMinSize) { |  | ||||||
| 		c->basew = size.min_width; |  | ||||||
| 		c->baseh = size.min_height; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		c->basew = c->baseh = 0; |  | ||||||
| 	if(c->flags & PResizeInc) { |  | ||||||
| 		c->incw = size.width_inc; |  | ||||||
| 		c->inch = size.height_inc; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		c->incw = c->inch = 0; |  | ||||||
| 	if(c->flags & PMaxSize) { |  | ||||||
| 		c->maxw = size.max_width; |  | ||||||
| 		c->maxh = size.max_height; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		c->maxw = c->maxh = 0; |  | ||||||
| 	if(c->flags & PMinSize) { |  | ||||||
| 		c->minw = size.min_width; |  | ||||||
| 		c->minh = size.min_height; |  | ||||||
| 	} |  | ||||||
| 	else if(c->flags & PBaseSize) { |  | ||||||
| 		c->minw = size.base_width; |  | ||||||
| 		c->minh = size.base_height; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		c->minw = c->minh = 0; |  | ||||||
| 	if(c->flags & PAspect) { |  | ||||||
| 		c->minax = size.min_aspect.x; |  | ||||||
| 		c->maxax = size.max_aspect.x; |  | ||||||
| 		c->minay = size.min_aspect.y; |  | ||||||
| 		c->maxay = size.max_aspect.y; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		c->minax = c->maxax = c->minay = c->maxay = 0; |  | ||||||
| 	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh |  | ||||||
| 			&& c->maxw == c->minw && c->maxh == c->minh); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| updatetitle(Client *c) { |  | ||||||
| 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) |  | ||||||
| 		gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name); |  | ||||||
| } |  | ||||||
							
								
								
									
										26
									
								
								config.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								config.h
									
									
									
									
									
								
							| @ -12,24 +12,20 @@ | |||||||
| #define SELFGCOLOR		"#fff" | #define SELFGCOLOR		"#fff" | ||||||
| 
 | 
 | ||||||
| /* tagging */ | /* tagging */ | ||||||
| #define TAGS \ | static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; | ||||||
| const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; | static Rule rules[] = { | ||||||
| #define RULES \ | 	/* class:instance:title regex	tags regex	isfloating */ | ||||||
| static Rule rules[] = { \ | 	{ "Firefox",			"3",		False }, | ||||||
| 	/* class:instance:title regex	tags regex	isfloating */ \ | 	{ "Gimp",			NULL,		True }, | ||||||
| 	{ "Firefox",			"3",		False }, \ | 	{ "MPlayer",			NULL,		True }, | ||||||
| 	{ "Gimp",			NULL,		True }, \ | 	{ "Acroread",			NULL,		True }, | ||||||
| 	{ "MPlayer",			NULL,		True }, \ |  | ||||||
| 	{ "Acroread",			NULL,		True }, \ |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* layout(s) */ | /* layout(s) */ | ||||||
| #include "tile.h" | static Layout layouts[] = { | ||||||
| #define LAYOUTS \ | 	/* symbol		function */ | ||||||
| static Layout layouts[] = { \ | 	{ "[]=",		tile }, /* first entry is default */ | ||||||
| 	/* symbol		function */ \ | 	{ "><>",		floating }, | ||||||
| 	{ "[]=",		tile }, /* first entry is default */ \ |  | ||||||
| 	{ "><>",		floating }, \ |  | ||||||
| }; | }; | ||||||
| #define RESIZEHINTS		True	/* False - respect size hints in tiled resizals */ | #define RESIZEHINTS		True	/* False - respect size hints in tiled resizals */ | ||||||
| #define MWFACT			0.6	/* master width factor [0.1 .. 0.9] */ | #define MWFACT			0.6	/* master width factor [0.1 .. 0.9] */ | ||||||
|  | |||||||
| @ -3,9 +3,6 @@ VERSION = 4.5 | |||||||
| 
 | 
 | ||||||
| # Customize below to fit your system
 | # Customize below to fit your system
 | ||||||
| 
 | 
 | ||||||
| # additional layouts beside floating
 |  | ||||||
| SRC = tile.c |  | ||||||
| 
 |  | ||||||
| # paths
 | # paths
 | ||||||
| PREFIX = /usr/local | PREFIX = /usr/local | ||||||
| MANPREFIX = ${PREFIX}/share/man | MANPREFIX = ${PREFIX}/share/man | ||||||
|  | |||||||
							
								
								
									
										147
									
								
								dwm.h
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								dwm.h
									
									
									
									
									
								
							| @ -1,147 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details.
 |  | ||||||
|  * |  | ||||||
|  * dynamic window manager is designed like any other X client as well. It is |  | ||||||
|  * driven through handling X events. In contrast to other X clients, a window |  | ||||||
|  * manager selects for SubstructureRedirectMask on the root window, to receive |  | ||||||
|  * events about window (dis-)appearance.  Only one X connection at a time is |  | ||||||
|  * allowed to select for this event mask. |  | ||||||
|  * |  | ||||||
|  * Calls to fetch an X event from the event queue are blocking.  Due reading |  | ||||||
|  * status text from standard input, a select()-driven main loop has been |  | ||||||
|  * implemented which selects for reads on the X connection and STDIN_FILENO to |  | ||||||
|  * handle all data smoothly. The event handlers of dwm are organized in an |  | ||||||
|  * array which is accessed whenever a new event has been fetched. This allows |  | ||||||
|  * event dispatching in O(1) time. |  | ||||||
|  * |  | ||||||
|  * Each child of the root window is called a client, except windows which have |  | ||||||
|  * set the override_redirect flag.  Clients are organized in a global |  | ||||||
|  * doubly-linked client list, the focus history is remembered through a global |  | ||||||
|  * stack list. Each client contains an array of Bools of the same size as the |  | ||||||
|  * global tags array to indicate the tags of a client.  For each client dwm |  | ||||||
|  * creates a small title window, which is resized whenever the (_NET_)WM_NAME |  | ||||||
|  * properties are updated or the client is moved/resized. |  | ||||||
|  * |  | ||||||
|  * Keys and tagging rules are organized as arrays and defined in the config.h |  | ||||||
|  * file. These arrays are kept static in event.o and tag.o respectively, |  | ||||||
|  * because no other part of dwm needs access to them.  The current layout is |  | ||||||
|  * represented by the lt pointer. |  | ||||||
|  * |  | ||||||
|  * To understand everything else, start reading main.c:main(). |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include "config.h" |  | ||||||
| #include <X11/Xlib.h> |  | ||||||
| 
 |  | ||||||
| /* mask shorthands, used in event.c and client.c */ |  | ||||||
| #define BUTTONMASK		(ButtonPressMask | ButtonReleaseMask) |  | ||||||
| 
 |  | ||||||
| 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 */ |  | ||||||
| 
 |  | ||||||
| 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; |  | ||||||
| 	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 */ |  | ||||||
| 
 |  | ||||||
| extern const char *tags[];			/* all tags */ |  | ||||||
| extern char stext[256];				/* status text */ |  | ||||||
| extern int screen, sx, sy, sw, sh;		/* screen geometry */ |  | ||||||
| extern int wax, way, wah, waw;			/* windowarea geometry */ |  | ||||||
| extern unsigned int bh, blw, bpos;		/* bar height, bar layout label width, bar position */ |  | ||||||
| extern unsigned int ntags, numlockmask;		/* number of tags, numlock mask */ |  | ||||||
| extern void (*handler[LASTEvent])(XEvent *);	/* event handler */ |  | ||||||
| extern Atom wmatom[WMLast], netatom[NetLast]; |  | ||||||
| extern Bool selscreen, *seltags;		/* seltags is array of Bool */ |  | ||||||
| extern Client *clients, *sel, *stack;		/* global client list and stack */ |  | ||||||
| extern Cursor cursor[CurLast]; |  | ||||||
| extern DC dc;					/* global draw context */ |  | ||||||
| extern Display *dpy; |  | ||||||
| extern Window root, barwin; |  | ||||||
| 
 |  | ||||||
| /* bar.c */ |  | ||||||
| void drawbar(void);			/* draw the bar */ |  | ||||||
| void initbar(void);			/* initializes the bar */ |  | ||||||
| void initstyle(void);			/* initializes colors and font */ |  | ||||||
| unsigned int textw(const char *text);	/* return the width of text in px*/ |  | ||||||
| void togglebar(const char *arg);	/* shows/hides the bar */ |  | ||||||
| void updatebarpos(void);		/* updates the bar position */ |  | ||||||
| 
 |  | ||||||
| /* client.c */ |  | ||||||
| void attach(Client *c);			/* attaches c to global client list */ |  | ||||||
| void ban(Client *c);			/* bans c */ |  | ||||||
| void configure(Client *c);		/* send synthetic configure event */ |  | ||||||
| void detach(Client *c);			/* detaches c from global client list */ |  | ||||||
| void focus(Client *c);			/* focus c if visible && !NULL, or focus top visible */ |  | ||||||
| void killclient(const char *arg);	/* kill sel  nicely */ |  | ||||||
| void manage(Window w, XWindowAttributes *wa);	/* manage new client */ |  | ||||||
| void resize(Client *c, int x, int y, |  | ||||||
| 		int w, int h, Bool sizehints);	/* resize with given coordinates c*/ |  | ||||||
| void unban(Client *c);			/* unbans c */ |  | ||||||
| void unmanage(Client *c);		/* unmanage c */ |  | ||||||
| void updatesizehints(Client *c);	/* update the size hint variables of c */ |  | ||||||
| void updatetitle(Client *c);		/* update the name of c */ |  | ||||||
| 
 |  | ||||||
| /* event.c */ |  | ||||||
| void grabkeys(void);			/* grab all keys defined in config.h */ |  | ||||||
| 
 |  | ||||||
| /* main.c */ |  | ||||||
| Bool gettextprop(Window w, Atom atom, |  | ||||||
| 		char *text, unsigned int size); /* return text property, UTF-8 compliant */ |  | ||||||
| void quit(const char *arg);			/* quit dwm nicely */ |  | ||||||
| int xerror(Display *dsply, XErrorEvent *ee);	/* dwm's X error handler */ |  | ||||||
| 
 |  | ||||||
| /* screen.c */ |  | ||||||
| void applyrules(Client *c);		/* applies rules to c */ |  | ||||||
| void arrange(void);			/* arranges all windows depending on the layout in use */ |  | ||||||
| void compileregs(void);			/* initialize regexps of rules defined in config.h */ |  | ||||||
| void focusnext(const char *arg);	/* focuses next visible client */ |  | ||||||
| void focusprev(const char *arg);	/* focuses prev visible client */ |  | ||||||
| const char *getsymbol(void);		/* returns symbol of enabled layout */ |  | ||||||
| void initlayouts(void);			/* initialize layout array */ |  | ||||||
| Bool isarrange(void (*func)());		/* returns True if func is the layout function in use */ |  | ||||||
| Bool isfloating(void);			/* returns True if floating layout is enabled */ |  | ||||||
| Bool isvisible(Client *c);		/* returns True if client is visible */ |  | ||||||
| Client *nexttiled(Client *c);		/* returns tiled successor of c */ |  | ||||||
| void restack(void);			/* restores z layers of all clients */ |  | ||||||
| void setlayout(const char *arg);	/* sets layout, NULL means next layout */ |  | ||||||
| void tag(const char *arg);		/* tags sel with arg's index */ |  | ||||||
| void togglefloating(const char *arg);	/* toggles sel between floating/tiled state */ |  | ||||||
| void togglemax(const char *arg);	/* toggles maximization of floating client */ |  | ||||||
| void toggletag(const char *arg);	/* toggles sel tags with arg's index */ |  | ||||||
| void toggleview(const char *arg);	/* toggles the tag with arg's index (in)visible */ |  | ||||||
| void view(const char *arg);		/* views the tag with arg's index */ |  | ||||||
| 
 |  | ||||||
| /* util.c */ |  | ||||||
| void *emallocz(unsigned int size);	/* allocates zero-initialized memory, exits on error */ |  | ||||||
| void eprint(const char *errstr, ...);	/* prints errstr and exits with 1 */ |  | ||||||
| void spawn(const char *arg);		/* forks a new subprocess with arg's cmd */ |  | ||||||
							
								
								
									
										375
									
								
								event.c
									
									
									
									
									
								
							
							
						
						
									
										375
									
								
								event.c
									
									
									
									
									
								
							| @ -1,375 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <X11/keysym.h> |  | ||||||
| #include <X11/Xatom.h> |  | ||||||
| #include <X11/Xutil.h> |  | ||||||
| 
 |  | ||||||
| /* static */ |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
| 	unsigned long mod; |  | ||||||
| 	KeySym keysym; |  | ||||||
| 	void (*func)(const char *arg); |  | ||||||
| 	const char *arg; |  | ||||||
| } Key; |  | ||||||
| 
 |  | ||||||
| #define CLEANMASK(mask)		(mask & ~(numlockmask | LockMask)) |  | ||||||
| #define MOUSEMASK		(BUTTONMASK | PointerMotionMask) |  | ||||||
| 
 |  | ||||||
| static Client * |  | ||||||
| getclient(Window w) { |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	for(c = clients; c && c->win != w; c = c->next); |  | ||||||
| 	return c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| movemouse(Client *c) { |  | ||||||
| 	int x1, y1, ocx, ocy, di, nx, ny; |  | ||||||
| 	unsigned int dui; |  | ||||||
| 	Window dummy; |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	ocx = nx = c->x; |  | ||||||
| 	ocy = ny = c->y; |  | ||||||
| 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |  | ||||||
| 			None, cursor[CurMove], CurrentTime) != GrabSuccess) |  | ||||||
| 		return; |  | ||||||
| 	c->ismax = False; |  | ||||||
| 	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); |  | ||||||
| 	for(;;) { |  | ||||||
| 		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); |  | ||||||
| 		switch (ev.type) { |  | ||||||
| 		case ButtonRelease: |  | ||||||
| 			XUngrabPointer(dpy, CurrentTime); |  | ||||||
| 			return; |  | ||||||
| 		case ConfigureRequest: |  | ||||||
| 		case Expose: |  | ||||||
| 		case MapRequest: |  | ||||||
| 			handler[ev.type](&ev); |  | ||||||
| 			break; |  | ||||||
| 		case MotionNotify: |  | ||||||
| 			XSync(dpy, False); |  | ||||||
| 			nx = ocx + (ev.xmotion.x - x1); |  | ||||||
| 			ny = ocy + (ev.xmotion.y - y1); |  | ||||||
| 			if(abs(wax + nx) < SNAP) |  | ||||||
| 				nx = wax; |  | ||||||
| 			else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP) |  | ||||||
| 				nx = wax + waw - c->w - 2 * c->border; |  | ||||||
| 			if(abs(way - ny) < SNAP) |  | ||||||
| 				ny = way; |  | ||||||
| 			else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP) |  | ||||||
| 				ny = way + wah - c->h - 2 * c->border; |  | ||||||
| 			resize(c, nx, ny, c->w, c->h, False); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| resizemouse(Client *c) { |  | ||||||
| 	int ocx, ocy; |  | ||||||
| 	int nw, nh; |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	ocx = c->x; |  | ||||||
| 	ocy = c->y; |  | ||||||
| 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |  | ||||||
| 			None, cursor[CurResize], CurrentTime) != GrabSuccess) |  | ||||||
| 		return; |  | ||||||
| 	c->ismax = False; |  | ||||||
| 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1); |  | ||||||
| 	for(;;) { |  | ||||||
| 		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); |  | ||||||
| 		switch(ev.type) { |  | ||||||
| 		case ButtonRelease: |  | ||||||
| 			XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, |  | ||||||
| 					c->w + c->border - 1, c->h + c->border - 1); |  | ||||||
| 			XUngrabPointer(dpy, CurrentTime); |  | ||||||
| 			while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |  | ||||||
| 			return; |  | ||||||
| 		case ConfigureRequest: |  | ||||||
| 		case Expose: |  | ||||||
| 		case MapRequest: |  | ||||||
| 			handler[ev.type](&ev); |  | ||||||
| 			break; |  | ||||||
| 		case MotionNotify: |  | ||||||
| 			XSync(dpy, False); |  | ||||||
| 			if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) |  | ||||||
| 				nw = 1; |  | ||||||
| 			if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |  | ||||||
| 				nh = 1; |  | ||||||
| 			resize(c, c->x, c->y, nw, nh, True); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| buttonpress(XEvent *e) { |  | ||||||
| 	unsigned int i, x; |  | ||||||
| 	Client *c; |  | ||||||
| 	XButtonPressedEvent *ev = &e->xbutton; |  | ||||||
| 
 |  | ||||||
| 	if(barwin == ev->window) { |  | ||||||
| 		x = 0; |  | ||||||
| 		for(i = 0; i < ntags; i++) { |  | ||||||
| 			x += textw(tags[i]); |  | ||||||
| 			if(ev->x < x) { |  | ||||||
| 				if(ev->button == Button1) { |  | ||||||
| 					if(ev->state & MODKEY) |  | ||||||
| 						tag(tags[i]); |  | ||||||
| 					else |  | ||||||
| 						view(tags[i]); |  | ||||||
| 				} |  | ||||||
| 				else if(ev->button == Button3) { |  | ||||||
| 					if(ev->state & MODKEY) |  | ||||||
| 						toggletag(tags[i]); |  | ||||||
| 					else |  | ||||||
| 						toggleview(tags[i]); |  | ||||||
| 				} |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if((ev->x < x + blw) && ev->button == Button1) |  | ||||||
| 			setlayout(NULL); |  | ||||||
| 	} |  | ||||||
| 	else if((c = getclient(ev->window))) { |  | ||||||
| 		focus(c); |  | ||||||
| 		if(CLEANMASK(ev->state) != MODKEY) |  | ||||||
| 			return; |  | ||||||
| 		if(ev->button == Button1 && (isfloating() || c->isfloating)) { |  | ||||||
| 			restack(); |  | ||||||
| 			movemouse(c); |  | ||||||
| 		} |  | ||||||
| 		else if(ev->button == Button2) |  | ||||||
| 			zoom(NULL); |  | ||||||
| 		else if(ev->button == Button3 |  | ||||||
| 		&& (isfloating() || c->isfloating) && !c->isfixed) |  | ||||||
| 		{ |  | ||||||
| 			restack(); |  | ||||||
| 			resizemouse(c); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| configurerequest(XEvent *e) { |  | ||||||
| 	Client *c; |  | ||||||
| 	XConfigureRequestEvent *ev = &e->xconfigurerequest; |  | ||||||
| 	XWindowChanges wc; |  | ||||||
| 
 |  | ||||||
| 	if((c = getclient(ev->window))) { |  | ||||||
| 		c->ismax = False; |  | ||||||
| 		if(ev->value_mask & CWBorderWidth) |  | ||||||
| 			c->border = ev->border_width; |  | ||||||
| 		if(c->isfixed || c->isfloating || isfloating()) { |  | ||||||
| 			if(ev->value_mask & CWX) |  | ||||||
| 				c->x = ev->x; |  | ||||||
| 			if(ev->value_mask & CWY) |  | ||||||
| 				c->y = ev->y; |  | ||||||
| 			if(ev->value_mask & CWWidth) |  | ||||||
| 				c->w = ev->width; |  | ||||||
| 			if(ev->value_mask & CWHeight) |  | ||||||
| 				c->h = ev->height; |  | ||||||
| 			if((c->x + c->w) > sw && c->isfloating) |  | ||||||
| 				c->x = sw / 2 - c->w / 2; /* center in x direction */ |  | ||||||
| 			if((c->y + c->h) > sh && c->isfloating) |  | ||||||
| 				c->y = sh / 2 - c->h / 2; /* center in y direction */ |  | ||||||
| 			if((ev->value_mask & (CWX | CWY)) |  | ||||||
| 			&& !(ev->value_mask & (CWWidth | CWHeight))) |  | ||||||
| 				configure(c); |  | ||||||
| 			if(isvisible(c)) |  | ||||||
| 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 			configure(c); |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		wc.x = ev->x; |  | ||||||
| 		wc.y = ev->y; |  | ||||||
| 		wc.width = ev->width; |  | ||||||
| 		wc.height = ev->height; |  | ||||||
| 		wc.border_width = ev->border_width; |  | ||||||
| 		wc.sibling = ev->above; |  | ||||||
| 		wc.stack_mode = ev->detail; |  | ||||||
| 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); |  | ||||||
| 	} |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| configurenotify(XEvent *e) { |  | ||||||
| 	XConfigureEvent *ev = &e->xconfigure; |  | ||||||
| 
 |  | ||||||
| 	if (ev->window == root && (ev->width != sw || ev->height != sh)) { |  | ||||||
| 		sw = ev->width; |  | ||||||
| 		sh = ev->height; |  | ||||||
| 		XFreePixmap(dpy, dc.drawable); |  | ||||||
| 		dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); |  | ||||||
| 		XResizeWindow(dpy, barwin, sw, bh); |  | ||||||
| 		updatebarpos(); |  | ||||||
| 		arrange(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| destroynotify(XEvent *e) { |  | ||||||
| 	Client *c; |  | ||||||
| 	XDestroyWindowEvent *ev = &e->xdestroywindow; |  | ||||||
| 
 |  | ||||||
| 	if((c = getclient(ev->window))) |  | ||||||
| 		unmanage(c); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| enternotify(XEvent *e) { |  | ||||||
| 	Client *c; |  | ||||||
| 	XCrossingEvent *ev = &e->xcrossing; |  | ||||||
| 
 |  | ||||||
| 	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) |  | ||||||
| 		return; |  | ||||||
| 	if((c = getclient(ev->window))) |  | ||||||
| 		focus(c); |  | ||||||
| 	else if(ev->window == root) { |  | ||||||
| 		selscreen = True; |  | ||||||
| 		focus(NULL); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| expose(XEvent *e) { |  | ||||||
| 	XExposeEvent *ev = &e->xexpose; |  | ||||||
| 
 |  | ||||||
| 	if(ev->count == 0) { |  | ||||||
| 		if(barwin == ev->window) |  | ||||||
| 			drawbar(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| keypress(XEvent *e) { |  | ||||||
| 	KEYS |  | ||||||
| 	unsigned int len = sizeof keys / sizeof keys[0]; |  | ||||||
| 	unsigned int i; |  | ||||||
| 	KeySym keysym; |  | ||||||
| 	XKeyEvent *ev = &e->xkey; |  | ||||||
| 
 |  | ||||||
| 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); |  | ||||||
| 	for(i = 0; i < len; i++) |  | ||||||
| 		if(keysym == keys[i].keysym |  | ||||||
| 		&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)) |  | ||||||
| 		{ |  | ||||||
| 			if(keys[i].func) |  | ||||||
| 				keys[i].func(keys[i].arg); |  | ||||||
| 		} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| leavenotify(XEvent *e) { |  | ||||||
| 	XCrossingEvent *ev = &e->xcrossing; |  | ||||||
| 
 |  | ||||||
| 	if((ev->window == root) && !ev->same_screen) { |  | ||||||
| 		selscreen = False; |  | ||||||
| 		focus(NULL); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| mappingnotify(XEvent *e) { |  | ||||||
| 	XMappingEvent *ev = &e->xmapping; |  | ||||||
| 
 |  | ||||||
| 	XRefreshKeyboardMapping(ev); |  | ||||||
| 	if(ev->request == MappingKeyboard) |  | ||||||
| 		grabkeys(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| maprequest(XEvent *e) { |  | ||||||
| 	static XWindowAttributes wa; |  | ||||||
| 	XMapRequestEvent *ev = &e->xmaprequest; |  | ||||||
| 
 |  | ||||||
| 	if(!XGetWindowAttributes(dpy, ev->window, &wa)) |  | ||||||
| 		return; |  | ||||||
| 	if(wa.override_redirect) |  | ||||||
| 		return; |  | ||||||
| 	if(!getclient(ev->window)) |  | ||||||
| 		manage(ev->window, &wa); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| propertynotify(XEvent *e) { |  | ||||||
| 	Client *c; |  | ||||||
| 	Window trans; |  | ||||||
| 	XPropertyEvent *ev = &e->xproperty; |  | ||||||
| 
 |  | ||||||
| 	if(ev->state == PropertyDelete) |  | ||||||
| 		return; /* ignore */ |  | ||||||
| 	if((c = getclient(ev->window))) { |  | ||||||
| 		switch (ev->atom) { |  | ||||||
| 			default: break; |  | ||||||
| 			case XA_WM_TRANSIENT_FOR: |  | ||||||
| 				XGetTransientForHint(dpy, c->win, &trans); |  | ||||||
| 				if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL))) |  | ||||||
| 					arrange(); |  | ||||||
| 				break; |  | ||||||
| 			case XA_WM_NORMAL_HINTS: |  | ||||||
| 				updatesizehints(c); |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { |  | ||||||
| 			updatetitle(c); |  | ||||||
| 			if(c == sel) |  | ||||||
| 				drawbar(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| unmapnotify(XEvent *e) { |  | ||||||
| 	Client *c; |  | ||||||
| 	XUnmapEvent *ev = &e->xunmap; |  | ||||||
| 
 |  | ||||||
| 	if((c = getclient(ev->window))) |  | ||||||
| 		unmanage(c); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| void (*handler[LASTEvent]) (XEvent *) = { |  | ||||||
| 	[ButtonPress] = buttonpress, |  | ||||||
| 	[ConfigureRequest] = configurerequest, |  | ||||||
| 	[ConfigureNotify] = configurenotify, |  | ||||||
| 	[DestroyNotify] = destroynotify, |  | ||||||
| 	[EnterNotify] = enternotify, |  | ||||||
| 	[LeaveNotify] = leavenotify, |  | ||||||
| 	[Expose] = expose, |  | ||||||
| 	[KeyPress] = keypress, |  | ||||||
| 	[MappingNotify] = mappingnotify, |  | ||||||
| 	[MapRequest] = maprequest, |  | ||||||
| 	[PropertyNotify] = propertynotify, |  | ||||||
| 	[UnmapNotify] = unmapnotify |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| grabkeys(void) { |  | ||||||
| 	KEYS |  | ||||||
| 	unsigned int len = sizeof keys / sizeof keys[0]; |  | ||||||
| 	unsigned int i; |  | ||||||
| 	KeyCode code; |  | ||||||
| 
 |  | ||||||
| 	XUngrabKey(dpy, AnyKey, AnyModifier, root); |  | ||||||
| 	for(i = 0; i < len; i++) { |  | ||||||
| 		code = XKeysymToKeycode(dpy, keys[i].keysym); |  | ||||||
| 		XGrabKey(dpy, code, keys[i].mod, root, True, |  | ||||||
| 				GrabModeAsync, GrabModeAsync); |  | ||||||
| 		XGrabKey(dpy, code, keys[i].mod | LockMask, root, True, |  | ||||||
| 				GrabModeAsync, GrabModeAsync); |  | ||||||
| 		XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True, |  | ||||||
| 				GrabModeAsync, GrabModeAsync); |  | ||||||
| 		XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True, |  | ||||||
| 				GrabModeAsync, GrabModeAsync); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										296
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										296
									
								
								main.c
									
									
									
									
									
								
							| @ -1,296 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <errno.h> |  | ||||||
| #include <locale.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
| #include <unistd.h> |  | ||||||
| #include <sys/select.h> |  | ||||||
| #include <X11/cursorfont.h> |  | ||||||
| #include <X11/keysym.h> |  | ||||||
| #include <X11/Xatom.h> |  | ||||||
| #include <X11/Xproto.h> |  | ||||||
| #include <X11/Xutil.h> |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| char stext[256]; |  | ||||||
| int screen, sx, sy, sw, sh, wax, way, waw, wah; |  | ||||||
| unsigned int ntags; |  | ||||||
| unsigned int numlockmask = 0; |  | ||||||
| Atom wmatom[WMLast], netatom[NetLast]; |  | ||||||
| Bool *seltags; |  | ||||||
| Bool selscreen = True; |  | ||||||
| Client *clients = NULL; |  | ||||||
| Client *sel = NULL; |  | ||||||
| Client *stack = NULL; |  | ||||||
| Cursor cursor[CurLast]; |  | ||||||
| Display *dpy; |  | ||||||
| Window root; |  | ||||||
| 
 |  | ||||||
| /* static */ |  | ||||||
| 
 |  | ||||||
| static int (*xerrorxlib)(Display *, XErrorEvent *); |  | ||||||
| static Bool otherwm, readin; |  | ||||||
| static Bool running = True; |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| cleanup(void) { |  | ||||||
| 	close(STDIN_FILENO); |  | ||||||
| 	while(stack) { |  | ||||||
| 		unban(stack); |  | ||||||
| 		unmanage(stack); |  | ||||||
| 	} |  | ||||||
| 	if(dc.font.set) |  | ||||||
| 		XFreeFontSet(dpy, dc.font.set); |  | ||||||
| 	else |  | ||||||
| 		XFreeFont(dpy, dc.font.xfont); |  | ||||||
| 	XUngrabKey(dpy, AnyKey, AnyModifier, root); |  | ||||||
| 	XFreePixmap(dpy, dc.drawable); |  | ||||||
| 	XFreeGC(dpy, dc.gc); |  | ||||||
| 	XDestroyWindow(dpy, barwin); |  | ||||||
| 	XFreeCursor(dpy, cursor[CurNormal]); |  | ||||||
| 	XFreeCursor(dpy, cursor[CurResize]); |  | ||||||
| 	XFreeCursor(dpy, cursor[CurMove]); |  | ||||||
| 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	free(seltags); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static long |  | ||||||
| getstate(Window w) { |  | ||||||
| 	int format, status; |  | ||||||
| 	long result = -1; |  | ||||||
| 	unsigned char *p = NULL; |  | ||||||
| 	unsigned long n, extra; |  | ||||||
| 	Atom real; |  | ||||||
| 
 |  | ||||||
| 	status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], |  | ||||||
| 			&real, &format, &n, &extra, (unsigned char **)&p); |  | ||||||
| 	if(status != Success) |  | ||||||
| 		return -1; |  | ||||||
| 	if(n != 0) |  | ||||||
| 		result = *p; |  | ||||||
| 	XFree(p); |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| scan(void) { |  | ||||||
| 	unsigned int i, num; |  | ||||||
| 	Window *wins, d1, d2; |  | ||||||
| 	XWindowAttributes wa; |  | ||||||
| 
 |  | ||||||
| 	wins = NULL; |  | ||||||
| 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { |  | ||||||
| 		for(i = 0; i < num; i++) { |  | ||||||
| 			if(!XGetWindowAttributes(dpy, wins[i], &wa) |  | ||||||
| 			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) |  | ||||||
| 				continue; |  | ||||||
| 			if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState) |  | ||||||
| 				manage(wins[i], &wa); |  | ||||||
| 		} |  | ||||||
| 		for(i = 0; i < num; i++) { /* now the transients */ |  | ||||||
| 			if(!XGetWindowAttributes(dpy, wins[i], &wa)) |  | ||||||
| 				continue; |  | ||||||
| 			if(XGetTransientForHint(dpy, wins[i], &d1) |  | ||||||
| 			&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) |  | ||||||
| 				manage(wins[i], &wa); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if(wins) |  | ||||||
| 		XFree(wins); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| setup(void) { |  | ||||||
| 	int i, j; |  | ||||||
| 	unsigned int mask; |  | ||||||
| 	Window w; |  | ||||||
| 	XModifierKeymap *modmap; |  | ||||||
| 	XSetWindowAttributes wa; |  | ||||||
| 
 |  | ||||||
| 	/* init atoms */ |  | ||||||
| 	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |  | ||||||
| 	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |  | ||||||
| 	wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False); |  | ||||||
| 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |  | ||||||
| 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |  | ||||||
| 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |  | ||||||
| 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |  | ||||||
| 			PropModeReplace, (unsigned char *) netatom, NetLast); |  | ||||||
| 	/* init cursors */ |  | ||||||
| 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |  | ||||||
| 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |  | ||||||
| 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |  | ||||||
| 	/* init modifier map */ |  | ||||||
| 	modmap = XGetModifierMapping(dpy); |  | ||||||
| 	for (i = 0; i < 8; i++) |  | ||||||
| 		for (j = 0; j < modmap->max_keypermod; j++) { |  | ||||||
| 			if(modmap->modifiermap[i * modmap->max_keypermod + j] |  | ||||||
| 					== XKeysymToKeycode(dpy, XK_Num_Lock)) |  | ||||||
| 				numlockmask = (1 << i); |  | ||||||
| 		} |  | ||||||
| 	XFreeModifiermap(modmap); |  | ||||||
| 	/* select for events */ |  | ||||||
| 	wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |  | ||||||
| 		| EnterWindowMask | LeaveWindowMask | StructureNotifyMask; |  | ||||||
| 	wa.cursor = cursor[CurNormal]; |  | ||||||
| 	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); |  | ||||||
| 	XSelectInput(dpy, root, wa.event_mask); |  | ||||||
| 	grabkeys(); |  | ||||||
| 	compileregs(); |  | ||||||
| 	for(ntags = 0; tags[ntags]; ntags++); |  | ||||||
| 	seltags = emallocz(sizeof(Bool) * ntags); |  | ||||||
| 	seltags[0] = True; |  | ||||||
| 	/* geometry */ |  | ||||||
| 	sx = sy = 0; |  | ||||||
| 	sw = DisplayWidth(dpy, screen); |  | ||||||
| 	sh = DisplayHeight(dpy, screen); |  | ||||||
| 	initstyle(); |  | ||||||
| 	initlayouts(); |  | ||||||
| 	initbar(); |  | ||||||
| 	/* multihead support */ |  | ||||||
| 	selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Startup Error handler to check if another window manager |  | ||||||
|  * is already running. |  | ||||||
|  */ |  | ||||||
| static int |  | ||||||
| xerrorstart(Display *dsply, XErrorEvent *ee) { |  | ||||||
| 	otherwm = True; |  | ||||||
| 	return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| Bool |  | ||||||
| gettextprop(Window w, Atom atom, char *text, unsigned int size) { |  | ||||||
| 	char **list = NULL; |  | ||||||
| 	int n; |  | ||||||
| 	XTextProperty name; |  | ||||||
| 
 |  | ||||||
| 	if(!text || size == 0) |  | ||||||
| 		return False; |  | ||||||
| 	text[0] = '\0'; |  | ||||||
| 	XGetTextProperty(dpy, w, &name, atom); |  | ||||||
| 	if(!name.nitems) |  | ||||||
| 		return False; |  | ||||||
| 	if(name.encoding == XA_STRING) |  | ||||||
| 		strncpy(text, (char *)name.value, size - 1); |  | ||||||
| 	else { |  | ||||||
| 		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success |  | ||||||
| 		&& n > 0 && *list) |  | ||||||
| 		{ |  | ||||||
| 			strncpy(text, *list, size - 1); |  | ||||||
| 			XFreeStringList(list); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	text[size - 1] = '\0'; |  | ||||||
| 	XFree(name.value); |  | ||||||
| 	return True; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| quit(const char *arg) { |  | ||||||
| 	readin = running = False; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* There's no way to check accesses to destroyed windows, thus those cases are
 |  | ||||||
|  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs |  | ||||||
|  * default error handler, which may call exit. |  | ||||||
|  */ |  | ||||||
| int |  | ||||||
| xerror(Display *dpy, XErrorEvent *ee) { |  | ||||||
| 	if(ee->error_code == BadWindow |  | ||||||
| 	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) |  | ||||||
| 	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) |  | ||||||
| 	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) |  | ||||||
| 	|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) |  | ||||||
| 	|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) |  | ||||||
| 	|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess) |  | ||||||
| 	|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) |  | ||||||
| 		return 0; |  | ||||||
| 	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", |  | ||||||
| 		ee->request_code, ee->error_code); |  | ||||||
| 	return xerrorxlib(dpy, ee); /* may call exit */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| main(int argc, char *argv[]) { |  | ||||||
| 	char *p; |  | ||||||
| 	int r, xfd; |  | ||||||
| 	fd_set rd; |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	if(argc == 2 && !strcmp("-v", argv[1])) |  | ||||||
| 		eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n"); |  | ||||||
| 	else if(argc != 1) |  | ||||||
| 		eprint("usage: dwm [-v]\n"); |  | ||||||
| 	setlocale(LC_CTYPE, ""); |  | ||||||
| 	if(!(dpy = XOpenDisplay(0))) |  | ||||||
| 		eprint("dwm: cannot open display\n"); |  | ||||||
| 	xfd = ConnectionNumber(dpy); |  | ||||||
| 	screen = DefaultScreen(dpy); |  | ||||||
| 	root = RootWindow(dpy, screen); |  | ||||||
| 	otherwm = False; |  | ||||||
| 	XSetErrorHandler(xerrorstart); |  | ||||||
| 	/* this causes an error if some other window manager is running */ |  | ||||||
| 	XSelectInput(dpy, root, SubstructureRedirectMask); |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	if(otherwm) |  | ||||||
| 		eprint("dwm: another window manager is already running\n"); |  | ||||||
| 
 |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	XSetErrorHandler(NULL); |  | ||||||
| 	xerrorxlib = XSetErrorHandler(xerror); |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	setup(); |  | ||||||
| 	drawbar(); |  | ||||||
| 	scan(); |  | ||||||
| 
 |  | ||||||
| 	/* main event loop, also reads status text from stdin */ |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	readin = True; |  | ||||||
| 	while(running) { |  | ||||||
| 		FD_ZERO(&rd); |  | ||||||
| 		if(readin) |  | ||||||
| 			FD_SET(STDIN_FILENO, &rd); |  | ||||||
| 		FD_SET(xfd, &rd); |  | ||||||
| 		if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) { |  | ||||||
| 			if(errno == EINTR) |  | ||||||
| 				continue; |  | ||||||
| 			eprint("select failed\n"); |  | ||||||
| 		} |  | ||||||
| 		if(FD_ISSET(STDIN_FILENO, &rd)) { |  | ||||||
| 			switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) { |  | ||||||
| 			case -1: |  | ||||||
| 				strncpy(stext, strerror(errno), sizeof stext - 1); |  | ||||||
| 				stext[sizeof stext - 1] = '\0'; |  | ||||||
| 				readin = False; |  | ||||||
| 				break; |  | ||||||
| 			case 0: |  | ||||||
| 				strncpy(stext, "EOF", 4); |  | ||||||
| 				readin = False; |  | ||||||
| 				break; |  | ||||||
| 			default: |  | ||||||
| 				for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0'); |  | ||||||
| 				for(; p >= stext && *p != '\n'; --p); |  | ||||||
| 				if(p > stext) |  | ||||||
| 					strncpy(stext, p + 1, sizeof stext); |  | ||||||
| 			} |  | ||||||
| 			drawbar(); |  | ||||||
| 		} |  | ||||||
| 		while(XPending(dpy)) { |  | ||||||
| 			XNextEvent(dpy, &ev); |  | ||||||
| 			if(handler[ev.type]) |  | ||||||
| 				(handler[ev.type])(&ev); /* call handler */ |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	cleanup(); |  | ||||||
| 	XCloseDisplay(dpy); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
							
								
								
									
										340
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										340
									
								
								screen.c
									
									
									
									
									
								
							| @ -1,340 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <regex.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
| #include <X11/Xutil.h> |  | ||||||
| 
 |  | ||||||
| /* static */ |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
| 	const char *symbol; |  | ||||||
| 	void (*arrange)(void); |  | ||||||
| } Layout; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
| 	const char *prop; |  | ||||||
| 	const char *tags; |  | ||||||
| 	Bool isfloating; |  | ||||||
| } Rule; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
| 	regex_t *propregex; |  | ||||||
| 	regex_t *tagregex; |  | ||||||
| } Regs; |  | ||||||
| 
 |  | ||||||
| TAGS |  | ||||||
| RULES |  | ||||||
| 
 |  | ||||||
| static unsigned int nrules = 0; |  | ||||||
| static unsigned int nlayouts = 0; |  | ||||||
| static unsigned int ltidx = 0; /* default */ |  | ||||||
| static Regs *regs = NULL; |  | ||||||
| 
 |  | ||||||
| static unsigned int |  | ||||||
| idxoftag(const char *tag) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 
 |  | ||||||
| 	for(i = 0; i < ntags; i++) |  | ||||||
| 		if(tags[i] == tag) |  | ||||||
| 			return i; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| floating(void) { /* default floating layout */ |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	for(c = clients; c; c = c->next) |  | ||||||
| 		if(isvisible(c)) |  | ||||||
| 			resize(c, c->x, c->y, c->w, c->h, True); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LAYOUTS |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| unsigned int blw = 0; |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| applyrules(Client *c) { |  | ||||||
| 	static char buf[512]; |  | ||||||
| 	unsigned int i, j; |  | ||||||
| 	regmatch_t tmp; |  | ||||||
| 	Bool matched = False; |  | ||||||
| 	XClassHint ch = { 0 }; |  | ||||||
| 
 |  | ||||||
| 	/* rule matching */ |  | ||||||
| 	XGetClassHint(dpy, c->win, &ch); |  | ||||||
| 	snprintf(buf, sizeof buf, "%s:%s:%s", |  | ||||||
| 			ch.res_class ? ch.res_class : "", |  | ||||||
| 			ch.res_name ? ch.res_name : "", c->name); |  | ||||||
| 	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++) { |  | ||||||
| 				if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |  | ||||||
| 					matched = True; |  | ||||||
| 					c->tags[j] = True; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	if(ch.res_class) |  | ||||||
| 		XFree(ch.res_class); |  | ||||||
| 	if(ch.res_name) |  | ||||||
| 		XFree(ch.res_name); |  | ||||||
| 	if(!matched) |  | ||||||
| 		for(i = 0; i < ntags; i++) |  | ||||||
| 			c->tags[i] = seltags[i]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| arrange(void) { |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	for(c = clients; c; c = c->next) |  | ||||||
| 		if(isvisible(c)) |  | ||||||
| 			unban(c); |  | ||||||
| 		else |  | ||||||
| 			ban(c); |  | ||||||
| 	layouts[ltidx].arrange(); |  | ||||||
| 	focus(NULL); |  | ||||||
| 	restack(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| compileregs(void) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 	regex_t *reg; |  | ||||||
| 
 |  | ||||||
| 	if(regs) |  | ||||||
| 		return; |  | ||||||
| 	nrules = sizeof rules / sizeof rules[0]; |  | ||||||
| 	regs = emallocz(nrules * sizeof(Regs)); |  | ||||||
| 	for(i = 0; i < nrules; i++) { |  | ||||||
| 		if(rules[i].prop) { |  | ||||||
| 			reg = emallocz(sizeof(regex_t)); |  | ||||||
| 			if(regcomp(reg, rules[i].prop, REG_EXTENDED)) |  | ||||||
| 				free(reg); |  | ||||||
| 			else |  | ||||||
| 				regs[i].propregex = reg; |  | ||||||
| 		} |  | ||||||
| 		if(rules[i].tags) { |  | ||||||
| 			reg = emallocz(sizeof(regex_t)); |  | ||||||
| 			if(regcomp(reg, rules[i].tags, REG_EXTENDED)) |  | ||||||
| 				free(reg); |  | ||||||
| 			else |  | ||||||
| 				regs[i].tagregex = reg; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| focusnext(const char *arg) { |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	if(!sel) |  | ||||||
| 		return; |  | ||||||
| 	for(c = sel->next; c && !isvisible(c); c = c->next); |  | ||||||
| 	if(!c) |  | ||||||
| 		for(c = clients; c && !isvisible(c); c = c->next); |  | ||||||
| 	if(c) { |  | ||||||
| 		focus(c); |  | ||||||
| 		restack(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| focusprev(const char *arg) { |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	if(!sel) |  | ||||||
| 		return; |  | ||||||
| 	for(c = sel->prev; c && !isvisible(c); c = c->prev); |  | ||||||
| 	if(!c) { |  | ||||||
| 		for(c = clients; c && c->next; c = c->next); |  | ||||||
| 		for(; c && !isvisible(c); c = c->prev); |  | ||||||
| 	} |  | ||||||
| 	if(c) { |  | ||||||
| 		focus(c); |  | ||||||
| 		restack(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const char * |  | ||||||
| getsymbol(void) |  | ||||||
| { |  | ||||||
| 	return layouts[ltidx].symbol; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| initlayouts(void) { |  | ||||||
| 	unsigned int i, w; |  | ||||||
| 
 |  | ||||||
| 	nlayouts = sizeof layouts / sizeof layouts[0]; |  | ||||||
| 	for(blw = i = 0; i < nlayouts; i++) { |  | ||||||
| 		w = textw(layouts[i].symbol); |  | ||||||
| 		if(w > blw) |  | ||||||
| 			blw = w; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Bool |  | ||||||
| isfloating(void) { |  | ||||||
| 	return layouts[ltidx].arrange == floating; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Bool |  | ||||||
| isarrange(void (*func)()) |  | ||||||
| { |  | ||||||
| 	return func == layouts[ltidx].arrange; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Bool |  | ||||||
| isvisible(Client *c) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 
 |  | ||||||
| 	for(i = 0; i < ntags; i++) |  | ||||||
| 		if(c->tags[i] && seltags[i]) |  | ||||||
| 			return True; |  | ||||||
| 	return False; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Client * |  | ||||||
| nexttiled(Client *c) { |  | ||||||
| 	for(; c && (c->isfloating || !isvisible(c)); c = c->next); |  | ||||||
| 	return c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| restack(void) { |  | ||||||
| 	Client *c; |  | ||||||
| 	XEvent ev; |  | ||||||
| 	XWindowChanges wc; |  | ||||||
| 
 |  | ||||||
| 	drawbar(); |  | ||||||
| 	if(!sel) |  | ||||||
| 		return; |  | ||||||
| 	if(sel->isfloating || isfloating()) |  | ||||||
| 		XRaiseWindow(dpy, sel->win); |  | ||||||
| 	if(!isfloating()) { |  | ||||||
| 		wc.stack_mode = Below; |  | ||||||
| 		wc.sibling = barwin; |  | ||||||
| 		if(!sel->isfloating) { |  | ||||||
| 			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc); |  | ||||||
| 			wc.sibling = sel->win; |  | ||||||
| 		} |  | ||||||
| 		for(c = nexttiled(clients); c; c = nexttiled(c->next)) { |  | ||||||
| 			if(c == sel) |  | ||||||
| 				continue; |  | ||||||
| 			XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); |  | ||||||
| 			wc.sibling = c->win; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	XSync(dpy, False); |  | ||||||
| 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| setlayout(const char *arg) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 
 |  | ||||||
| 	if(!arg) { |  | ||||||
| 		if(++ltidx == nlayouts) |  | ||||||
| 			ltidx = 0;; |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		for(i = 0; i < nlayouts; i++) |  | ||||||
| 			if(!strcmp(arg, layouts[i].symbol)) |  | ||||||
| 				break; |  | ||||||
| 		if(i == nlayouts) |  | ||||||
| 			return; |  | ||||||
| 		ltidx = i; |  | ||||||
| 	} |  | ||||||
| 	if(sel) |  | ||||||
| 		arrange(); |  | ||||||
| 	else |  | ||||||
| 		drawbar(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| tag(const char *arg) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 
 |  | ||||||
| 	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; |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| togglefloating(const char *arg) { |  | ||||||
| 	if(!sel) |  | ||||||
| 		return; |  | ||||||
| 	sel->isfloating = !sel->isfloating; |  | ||||||
| 	if(sel->isfloating) |  | ||||||
| 		resize(sel, sel->x, sel->y, sel->w, sel->h, True); |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| togglemax(const char *arg) { |  | ||||||
| 	XEvent ev; |  | ||||||
| 
 |  | ||||||
| 	if(!sel || (!isfloating() && !sel->isfloating) || sel->isfixed) |  | ||||||
| 		return; |  | ||||||
| 	if((sel->ismax = !sel->ismax)) { |  | ||||||
| 		sel->rx = sel->x; |  | ||||||
| 		sel->ry = sel->y; |  | ||||||
| 		sel->rw = sel->w; |  | ||||||
| 		sel->rh = sel->h; |  | ||||||
| 		resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True); |  | ||||||
| 	drawbar(); |  | ||||||
| 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| toggletag(const char *arg) { |  | ||||||
| 	unsigned int i, j; |  | ||||||
| 
 |  | ||||||
| 	if(!sel) |  | ||||||
| 		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; |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| toggleview(const char *arg) { |  | ||||||
| 	unsigned int i, j; |  | ||||||
| 
 |  | ||||||
| 	i = idxoftag(arg); |  | ||||||
| 	seltags[i] = !seltags[i]; |  | ||||||
| 	for(j = 0; j < ntags && !seltags[j]; j++); |  | ||||||
| 	if(j == ntags) |  | ||||||
| 		seltags[i] = True; /* cannot toggle last view */ |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| view(const char *arg) { |  | ||||||
| 	unsigned int i; |  | ||||||
| 
 |  | ||||||
| 	for(i = 0; i < ntags; i++) |  | ||||||
| 		seltags[i] = arg == NULL; |  | ||||||
| 	i = idxoftag(arg); |  | ||||||
| 	if(i >= 0 && i < ntags) |  | ||||||
| 		seltags[i] = True; |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
							
								
								
									
										85
									
								
								tile.c
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								tile.c
									
									
									
									
									
								
							| @ -1,85 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <stdio.h> |  | ||||||
| 
 |  | ||||||
| /* static */ |  | ||||||
| 
 |  | ||||||
| static double mwfact = MWFACT; |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| setmwfact(const char *arg) { |  | ||||||
| 	double delta; |  | ||||||
| 
 |  | ||||||
| 	if(!isarrange(tile)) |  | ||||||
| 		return; |  | ||||||
| 	/* arg handling, manipulate mwfact */ |  | ||||||
| 	if(arg == NULL) |  | ||||||
| 		mwfact = MWFACT; |  | ||||||
| 	else if(1 == sscanf(arg, "%lf", &delta)) { |  | ||||||
| 		if(arg[0] != '+' && arg[0] != '-') |  | ||||||
| 			mwfact = delta; |  | ||||||
| 		else |  | ||||||
| 			mwfact += delta; |  | ||||||
| 		if(mwfact < 0.1) |  | ||||||
| 			mwfact = 0.1; |  | ||||||
| 		else if(mwfact > 0.9) |  | ||||||
| 			mwfact = 0.9; |  | ||||||
| 	} |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| tile(void) { |  | ||||||
| 	unsigned int i, n, nx, ny, nw, nh, mw, th; |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |  | ||||||
| 		n++; |  | ||||||
| 
 |  | ||||||
| 	/* window geoms */ |  | ||||||
| 	mw = (n == 1) ? waw : mwfact * waw; |  | ||||||
| 	th = (n > 1) ? wah / (n - 1) : 0; |  | ||||||
| 	if(n > 1 && th < bh) |  | ||||||
| 		th = wah; |  | ||||||
| 
 |  | ||||||
| 	nx = wax; |  | ||||||
| 	ny = way; |  | ||||||
| 	for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next), i++) { |  | ||||||
| 		c->ismax = False; |  | ||||||
| 		if(i == 0) { /* master */ |  | ||||||
| 			nw = mw - 2 * c->border; |  | ||||||
| 			nh = wah - 2 * c->border; |  | ||||||
| 		} |  | ||||||
| 		else {  /* tile window */ |  | ||||||
| 			if(i == 1) { |  | ||||||
| 				ny = way; |  | ||||||
| 				nx += mw; |  | ||||||
| 			} |  | ||||||
| 			nw = waw - mw - 2 * c->border; |  | ||||||
| 			if(i + 1 == n) /* remainder */ |  | ||||||
| 				nh = (way + wah) - ny - 2 * c->border; |  | ||||||
| 			else |  | ||||||
| 				nh = th - 2 * c->border; |  | ||||||
| 		} |  | ||||||
| 		resize(c, nx, ny, nw, nh, RESIZEHINTS); |  | ||||||
| 		if(n > 1 && th != wah) |  | ||||||
| 			ny += nh + 2 * c->border; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| zoom(const char *arg) { |  | ||||||
| 	Client *c; |  | ||||||
| 
 |  | ||||||
| 	if(!sel || !isarrange(tile) || sel->isfloating) |  | ||||||
| 		return; |  | ||||||
| 	if((c = sel) == nexttiled(clients)) |  | ||||||
| 		if(!(c = nexttiled(c->next))) |  | ||||||
| 			return; |  | ||||||
| 	detach(c); |  | ||||||
| 	attach(c); |  | ||||||
| 	focus(c); |  | ||||||
| 	arrange(); |  | ||||||
| } |  | ||||||
							
								
								
									
										6
									
								
								tile.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tile.h
									
									
									
									
									
								
							| @ -1,6 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| 
 |  | ||||||
| /* tile.c */ |  | ||||||
| void setmwfact(const char *arg);	/* sets master width factor */ |  | ||||||
| void tile(void);			/* arranges all windows tiled */ |  | ||||||
| void zoom(const char *arg);		/* zooms the focused client to master area, arg is ignored */ |  | ||||||
							
								
								
									
										52
									
								
								util.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								util.c
									
									
									
									
									
								
							| @ -1,52 +0,0 @@ | |||||||
| /* See LICENSE file for copyright and license details. */ |  | ||||||
| #include "dwm.h" |  | ||||||
| #include <stdarg.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <sys/wait.h> |  | ||||||
| #include <unistd.h> |  | ||||||
| 
 |  | ||||||
| /* extern */ |  | ||||||
| 
 |  | ||||||
| void * |  | ||||||
| emallocz(unsigned int size) { |  | ||||||
| 	void *res = calloc(1, size); |  | ||||||
| 
 |  | ||||||
| 	if(!res) |  | ||||||
| 		eprint("fatal: could not malloc() %u bytes\n", size); |  | ||||||
| 	return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| eprint(const char *errstr, ...) { |  | ||||||
| 	va_list ap; |  | ||||||
| 
 |  | ||||||
| 	va_start(ap, errstr); |  | ||||||
| 	vfprintf(stderr, errstr, ap); |  | ||||||
| 	va_end(ap); |  | ||||||
| 	exit(EXIT_FAILURE); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| spawn(const char *arg) { |  | ||||||
| 	static char *shell = NULL; |  | ||||||
| 
 |  | ||||||
| 	if(!shell && !(shell = getenv("SHELL"))) |  | ||||||
| 		shell = "/bin/sh"; |  | ||||||
| 	if(!arg) |  | ||||||
| 		return; |  | ||||||
| 	/* The double-fork construct avoids zombie processes and keeps the code
 |  | ||||||
| 	 * clean from stupid signal handlers. */ |  | ||||||
| 	if(fork() == 0) { |  | ||||||
| 		if(fork() == 0) { |  | ||||||
| 			if(dpy) |  | ||||||
| 				close(ConnectionNumber(dpy)); |  | ||||||
| 			setsid(); |  | ||||||
| 			execl(shell, shell, "-c", arg, (char *)NULL); |  | ||||||
| 			fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg); |  | ||||||
| 			perror(" failed"); |  | ||||||
| 		} |  | ||||||
| 		exit(0); |  | ||||||
| 	} |  | ||||||
| 	wait(0); |  | ||||||
| } |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anselm R. Garbe
						Anselm R. Garbe