Browse Source

rearranged several stuff

Anselm R. Garbe 20 năm trước cách đây
mục cha
commit
dba23062ba
10 tập tin đã thay đổi với 442 bổ sung và 444 xóa
  1. 1 1
      Makefile
  2. 87 58
      client.c
  3. 24 13
      draw.c
  4. 22 14
      dwm.h
  5. 80 9
      event.c
  6. 0 192
      key.c
  7. 56 56
      main.c
  8. 0 100
      screen.c
  9. 171 0
      tag.c
  10. 1 1
      util.c

+ 1 - 1
Makefile

@@ -3,7 +3,7 @@
 
 include config.mk
 
-SRC = client.c draw.c event.c key.c main.c screen.c util.c
+SRC = client.c draw.c event.c main.c tag.c util.c
 OBJ = ${SRC:.c=.o}
 MAN1 = dwm.1 
 BIN = dwm

+ 87 - 58
client.c

@@ -11,18 +11,6 @@
 
 #include "dwm.h"
 
-static Rule rule[] = {
-	/* class			instance	tags						floating */
-	{ "Firefox-bin",	"Gecko",	{ [Twww] = "www" },			False },
-};
-
-Client *
-getnext(Client *c)
-{
-	for(; c && !c->tags[tsel]; c = c->next);
-	return c;
-}
-
 void
 ban(Client *c)
 {
@@ -31,7 +19,7 @@ ban(Client *c)
 }
 
 static void
-resize_title(Client *c)
+resizetitle(Client *c)
 {
 	int i;
 
@@ -72,7 +60,7 @@ settitle(Client *c)
 		}
 	}
 	XFree(name.value);
-	resize_title(c);
+	resizetitle(c);
 }
 
 void
@@ -143,42 +131,6 @@ focus(Client *c)
 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 }
 
-static void
-init_tags(Client *c)
-{
-	XClassHint ch;
-	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
-	unsigned int i, j;
-	Bool matched = False;
-
-	if(!len) {
-		c->tags[tsel] = tags[tsel];
-		return;
-	}
-
-	if(XGetClassHint(dpy, c->win, &ch)) {
-		if(ch.res_class && ch.res_name) {
-			for(i = 0; i < len; i++)
-				if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
-					&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
-				{
-					for(j = 0; j < TLast; j++)
-						c->tags[j] = rule[i].tags[j];
-					c->floating = rule[i].floating;
-					matched = True;
-					break;
-				}
-		}
-		if(ch.res_class)
-			XFree(ch.res_class);
-		if(ch.res_name)
-			XFree(ch.res_name);
-	}
-
-	if(!matched)
-		c->tags[tsel] = tags[tsel];
-}
-
 void
 manage(Window w, XWindowAttributes *wa)
 {
@@ -196,7 +148,7 @@ manage(Window w, XWindowAttributes *wa)
 	c->h = wa->height;
 	c->th = bh;
 	c->border = 1;
-	c->proto = proto(c->win);
+	c->proto = getproto(c->win);
 	setsize(c);
 	XSelectInput(dpy, c->win,
 			StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
@@ -211,7 +163,7 @@ manage(Window w, XWindowAttributes *wa)
 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
 
 	settitle(c);
-	init_tags(c);
+	settags(c);
 
 	for(l = &clients; *l; l = &(*l)->next);
 	c->next = *l; /* *l == nil */
@@ -224,8 +176,8 @@ manage(Window w, XWindowAttributes *wa)
 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
 			GrabModeAsync, GrabModeSync, None, None);
 
-	if(!c->floating)
-		c->floating = trans
+	if(!c->dofloat)
+		c->dofloat = trans
 			|| ((c->maxw == c->minw) && (c->maxh == c->minh));
 
 	arrange(NULL);
@@ -321,7 +273,7 @@ resize(Client *c, Bool inc)
 		c->w = c->maxw;
 	if(c->maxh && c->h > c->maxh)
 		c->h = c->maxh;
-	resize_title(c);
+	resizetitle(c);
 	XSetWindowBorderWidth(dpy, c->win, 1);
 	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
 	e.type = ConfigureNotify;
@@ -339,7 +291,7 @@ resize(Client *c, Bool inc)
 }
 
 static int
-dummy_xerror(Display *dsply, XErrorEvent *err)
+xerrordummy(Display *dsply, XErrorEvent *ee)
 {
 	return 0;
 }
@@ -350,7 +302,7 @@ unmanage(Client *c)
 	Client **l;
 
 	XGrabServer(dpy);
-	XSetErrorHandler(dummy_xerror);
+	XSetErrorHandler(xerrordummy);
 
 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
 	XDestroyWindow(dpy, c->title);
@@ -374,7 +326,7 @@ unmanage(Client *c)
 }
 
 Client *
-gettitle(Window w)
+getctitle(Window w)
 {
 	Client *c;
 	for(c = clients; c; c = c->next)
@@ -392,3 +344,80 @@ getclient(Window w)
 			return c;
 	return NULL;
 }
+
+void
+zoom(Arg *arg)
+{
+	Client **l, *c;
+
+	if(!sel)
+		return;
+
+	if(sel == getnext(clients) && sel->next)  {
+		if((c = getnext(sel->next)))
+			sel = c;
+	}
+
+	for(l = &clients; *l && *l != sel; l = &(*l)->next);
+	*l = sel->next;
+
+	sel->next = clients; /* pop */
+	clients = sel;
+	arrange(NULL);
+	focus(sel);
+}
+
+void
+maximize(Arg *arg)
+{
+	if(!sel)
+		return;
+	sel->x = sx;
+	sel->y = sy + bh;
+	sel->w = sw - 2 * sel->border;
+	sel->h = sh - 2 * sel->border - bh;
+	higher(sel);
+	resize(sel, False);
+}
+
+void
+focusprev(Arg *arg)
+{
+	Client *c;
+
+	if(!sel)
+		return;
+
+	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
+		higher(c);
+		focus(c);
+	}
+}
+
+void
+focusnext(Arg *arg)
+{
+	Client *c;
+   
+	if(!sel)
+		return;
+
+	if(!(c = getnext(sel->next)))
+		c = getnext(clients);
+	if(c) {
+		higher(c);
+		c->revert = sel;
+		focus(c);
+	}
+}
+
+void
+killclient(Arg *arg)
+{
+	if(!sel)
+		return;
+	if(sel->proto & WM_PROTOCOL_DELWIN)
+		sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
+	else
+		XKillClient(dpy, sel->win);
+}

+ 24 - 13
draw.c

@@ -10,34 +10,43 @@
 
 #include "dwm.h"
 
+void
+drawall()
+{
+	Client *c;
+
+	for(c = clients; c; c = getnext(c->next))
+		drawtitle(c);
+	drawstatus();
+}
+
 void
 drawstatus()
 {
 	int i;
+	Bool istile = arrange == dotile;
 
 	dc.x = dc.y = 0;
 	dc.w = bw;
-	drawtext(NULL, False, False);
+	drawtext(NULL, !istile, False);
 
-	if(arrange == floating) {
-		dc.w = textw("~");
-		drawtext("~", False, False);
-	}
-	else
-		dc.w = 0;
+	dc.w = 0;
 	for(i = 0; i < TLast; i++) {
 		dc.x += dc.w;
 		dc.w = textw(tags[i]);
-		drawtext(tags[i], i == tsel, True);
+		if(istile)
+			drawtext(tags[i], (i == tsel), True);
+		else
+			drawtext(tags[i], (i != tsel), True);
 	}
 	if(sel) {
 		dc.x += dc.w;
 		dc.w = textw(sel->name);
-		drawtext(sel->name, True, True);
+		drawtext(sel->name, istile, True);
 	}
 	dc.w = textw(stext);
 	dc.x = bx + bw - dc.w;
-	drawtext(stext, False, False);
+	drawtext(stext, !istile, False);
 
 	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
 	XFlush(dpy);
@@ -47,6 +56,8 @@ void
 drawtitle(Client *c)
 {
 	int i;
+	Bool istile = arrange == dotile;
+
 	if(c == sel) {
 		drawstatus();
 		XUnmapWindow(dpy, c->title);
@@ -64,12 +75,12 @@ drawtitle(Client *c)
 		if(c->tags[i]) {
 			dc.x += dc.w;
 			dc.w = textw(c->tags[i]);
-			drawtext(c->tags[i], False, True);
+			drawtext(c->tags[i], !istile, True);
 		}
 	}
 	dc.x += dc.w;
 	dc.w = textw(c->name);
-	drawtext(c->name, False, True);
+	drawtext(c->name, !istile, True);
 	XCopyArea(dpy, dc.drawable, c->title, dc.gc,
 			0, 0, c->tw, c->th, 0, 0);
 	XFlush(dpy);
@@ -215,7 +226,7 @@ setfont(const char *fontstr)
 		if (!dc.font.xfont)
 			dc.font.xfont = XLoadQueryFont(dpy, "fixed");
 		if (!dc.font.xfont)
-			error("error, cannot init 'fixed' font\n");
+			eprint("error, cannot init 'fixed' font\n");
 		dc.font.ascent = dc.font.xfont->ascent;
 		dc.font.descent = dc.font.xfont->descent;
 	}

+ 22 - 14
dwm.h

@@ -66,7 +66,7 @@ struct Client {
 	int grav;
 	unsigned int border;
 	long flags; 
-	Bool floating;
+	Bool dofloat;
 	Window win;
 	Window title;
 	Client *next;
@@ -77,7 +77,7 @@ struct Rule {
 	const char *class;
 	const char *instance;
 	char *tags[TLast];
-	Bool floating;
+	Bool dofloat;
 };
 
 struct Key {
@@ -103,6 +103,7 @@ extern DC dc;
 extern Client *clients, *sel;
 
 /* client.c */
+extern void ban(Client *c);
 extern void manage(Window w, XWindowAttributes *wa);
 extern void unmanage(Client *c);
 extern Client *getclient(Window w);
@@ -110,14 +111,18 @@ extern void focus(Client *c);
 extern void settitle(Client *c);
 extern void resize(Client *c, Bool inc);
 extern void setsize(Client *c);
-extern Client *gettitle(Window w);
+extern Client *getctitle(Window w);
 extern void higher(Client *c);
 extern void lower(Client *c);
 extern void gravitate(Client *c, Bool invert);
-extern void ban(Client *c);
-extern Client *getnext(Client *c);
+extern void zoom(Arg *arg);
+extern void maximize(Arg *arg);
+extern void focusprev(Arg *arg);
+extern void focusnext(Arg *arg);
+extern void killclient(Arg *arg);
 
 /* draw.c */
+extern void drawall();
 extern void drawstatus();
 extern void drawtitle(Client *c);
 extern void drawtext(const char *text, Bool invert, Bool border);
@@ -127,22 +132,25 @@ extern unsigned int textnw(char *text, unsigned int len);
 extern unsigned int textw(char *text);
 extern unsigned int texth(void);
 
-/* key.c */
+/* event.c */
 extern void grabkeys();
-extern void keypress(XEvent *e);
 
 /* main.c */
-extern int xerror(Display *dsply, XErrorEvent *e);
-extern void sendevent(Window w, Atom a, long value);
-extern int proto(Window w);
 extern void quit(Arg *arg);
+extern int xerror(Display *dsply, XErrorEvent *ee);
+extern void sendevent(Window w, Atom a, long value);
+extern int getproto(Window w);
 
-/* screen.c */
-extern void floating(Arg *arg);
-extern void tiling(Arg *arg);
+/* tag.c */
+extern Client *getnext(Client *c);
+extern void settags(Client *c);
+extern void dofloat(Arg *arg);
+extern void dotile(Arg *arg);
 extern void view(Arg *arg);
+extern void appendtag(Arg *arg);
+extern void replacetag(Arg *arg);
 
 /* util.c */
-extern void error(const char *errstr, ...);
+extern void eprint(const char *errstr, ...);
 extern void *emallocz(unsigned int size);
 extern void spawn(Arg *arg);

+ 80 - 9
event.c

@@ -16,6 +16,44 @@
 #define ButtonMask      (ButtonPressMask | ButtonReleaseMask)
 #define MouseMask       (ButtonMask | PointerMotionMask)
 
+/********** CUSTOMIZE **********/
+
+const char *term[] = { 
+	"urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
+	"-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
+};
+const char *browse[] = { "firefox", NULL };
+const char *xlock[] = { "xlock", NULL };
+
+Key key[] = {
+	/* modifier				key			function	arguments */
+	{ Mod1Mask,				XK_Return,	zoom,		{ 0 } },
+	{ Mod1Mask,				XK_k,		focusprev,		{ 0 } },
+	{ Mod1Mask,				XK_j,		focusnext,		{ 0 } }, 
+	{ Mod1Mask,				XK_m,		maximize,		{ 0 } }, 
+	{ Mod1Mask,				XK_0,		view,		{ .i = Tscratch } }, 
+	{ Mod1Mask,				XK_1,		view,		{ .i = Tdev } }, 
+	{ Mod1Mask,				XK_2,		view,		{ .i = Twww } }, 
+	{ Mod1Mask,				XK_3,		view,		{ .i = Twork } }, 
+	{ Mod1Mask,				XK_space,	dotile,		{ 0 } }, 
+	{ Mod1Mask|ShiftMask,	XK_space,	dofloat,	{ 0 } }, 
+	{ Mod1Mask|ShiftMask,	XK_0,		replacetag,		{ .i = Tscratch } }, 
+	{ Mod1Mask|ShiftMask,	XK_1,		replacetag,		{ .i = Tdev } }, 
+	{ Mod1Mask|ShiftMask,	XK_2,		replacetag,		{ .i = Twww } }, 
+	{ Mod1Mask|ShiftMask,	XK_3,		replacetag,		{ .i = Twork } }, 
+	{ Mod1Mask|ShiftMask,	XK_c,		killclient,		{ 0 } }, 
+	{ Mod1Mask|ShiftMask,	XK_q,		quit,		{ 0 } },
+	{ Mod1Mask|ShiftMask,	XK_Return,	spawn,		{ .argv = term } },
+	{ Mod1Mask|ShiftMask,	XK_w,		spawn,		{ .argv = browse } },
+	{ Mod1Mask|ShiftMask,	XK_l,		spawn,		{ .argv = xlock } },
+	{ ControlMask,			XK_0,		appendtag,	{ .i = Tscratch } }, 
+	{ ControlMask,			XK_1,		appendtag,	{ .i = Tdev } }, 
+	{ ControlMask,			XK_2,		appendtag,	{ .i = Twww } }, 
+	{ ControlMask,			XK_3,		appendtag,	{ .i = Twork } }, 
+};
+
+/********** CUSTOMIZE **********/
+
 /* local functions */
 static void buttonpress(XEvent *e);
 static void configurerequest(XEvent *e);
@@ -23,6 +61,7 @@ static void destroynotify(XEvent *e);
 static void enternotify(XEvent *e);
 static void leavenotify(XEvent *e);
 static void expose(XEvent *e);
+static void keypress(XEvent *e);
 static void maprequest(XEvent *e);
 static void propertynotify(XEvent *e);
 static void unmapnotify(XEvent *e);
@@ -40,8 +79,40 @@ void (*handler[LASTEvent]) (XEvent *) = {
 	[UnmapNotify] = unmapnotify
 };
 
+void
+grabkeys()
+{
+	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
+	unsigned int i;
+	KeyCode code;
+
+	for(i = 0; i < len; i++) {
+		code = XKeysymToKeycode(dpy, key[i].keysym);
+		XUngrabKey(dpy, code, key[i].mod, root);
+		XGrabKey(dpy, code, key[i].mod, root, True,
+				GrabModeAsync, GrabModeAsync);
+	}
+}
+
+static void
+keypress(XEvent *e)
+{
+	XKeyEvent *ev = &e->xkey;
+	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
+	unsigned int i;
+	KeySym keysym;
+
+	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+	for(i = 0; i < len; i++)
+		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
+			if(key[i].func)
+				key[i].func(&key[i].arg);
+			return;
+		}
+}
+
 static void
-mresize(Client *c)
+resizemouse(Client *c)
 {
 	XEvent ev;
 	int ocx, ocy;
@@ -75,7 +146,7 @@ mresize(Client *c)
 }
 
 static void
-mmove(Client *c)
+movemouse(Client *c)
 {
 	XEvent ev;
 	int x1, y1, ocx, ocy, di;
@@ -117,7 +188,7 @@ buttonpress(XEvent *e)
 	Client *c;
 
 	if(barwin == ev->window) {
-		x = (arrange == floating) ? textw("~") : 0;
+		x = (arrange == dofloat) ? textw("~") : 0;
 		for(a.i = 0; a.i < TLast; a.i++) {
 			x += textw(tags[a.i]);
 			if(ev->x < x) {
@@ -127,20 +198,20 @@ buttonpress(XEvent *e)
 		}
 	}
 	else if((c = getclient(ev->window))) {
-		if(arrange == tiling && !c->floating)
+		if(arrange == dotile && !c->dofloat)
 			return;
 		higher(c);
 		switch(ev->button) {
 		default:
 			break;
 		case Button1:
-			mmove(c);
+			movemouse(c);
 			break;
 		case Button2:
 			lower(c);
 			break;
 		case Button3:
-			mresize(c);
+			resizemouse(c);
 			break;
 		}
 	}
@@ -226,7 +297,7 @@ expose(XEvent *e)
 	if(ev->count == 0) {
 		if(barwin == ev->window)
 			drawstatus();
-		else if((c = gettitle(ev->window)))
+		else if((c = getctitle(ev->window)))
 			drawtitle(c);
 	}
 }
@@ -262,14 +333,14 @@ propertynotify(XEvent *e)
 
 	if((c = getclient(ev->window))) {
 		if(ev->atom == wm_atom[WMProtocols]) {
-			c->proto = proto(c->win);
+			c->proto = getproto(c->win);
 			return;
 		}
 		switch (ev->atom) {
 			default: break;
 			case XA_WM_TRANSIENT_FOR:
 				XGetTransientForHint(dpy, c->win, &trans);
-				if(!c->floating && (c->floating = (trans != 0)))
+				if(!c->dofloat && (c->dofloat = (trans != 0)))
 					arrange(NULL);
 				break;
 			case XA_WM_NORMAL_HINTS:

+ 0 - 192
key.c

@@ -1,192 +0,0 @@
-/*
- * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-
-#include "dwm.h"
-
-static void ckill(Arg *arg);
-static void nextc(Arg *arg);
-static void prevc(Arg *arg);
-static void max(Arg *arg);
-static void ttrunc(Arg *arg);
-static void tappend(Arg *arg);
-static void zoom(Arg *arg);
-
-/********** CUSTOMIZE **********/
-
-const char *term[] = { 
-	"urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
-	"-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
-};
-const char *browse[] = { "firefox", NULL };
-const char *xlock[] = { "xlock", NULL };
-
-Key key[] = {
-	/* modifier				key			function	arguments */
-	{ Mod1Mask,				XK_Return,	zoom,		{ 0 } },
-	{ Mod1Mask,				XK_k,		prevc,		{ 0 } },
-	{ Mod1Mask,				XK_j,		nextc,		{ 0 } }, 
-	{ Mod1Mask,				XK_m,		max,		{ 0 } }, 
-	{ Mod1Mask,				XK_0,		view,		{ .i = Tscratch } }, 
-	{ Mod1Mask,				XK_1,		view,		{ .i = Tdev } }, 
-	{ Mod1Mask,				XK_2,		view,		{ .i = Twww } }, 
-	{ Mod1Mask,				XK_3,		view,		{ .i = Twork } }, 
-	{ Mod1Mask,				XK_space,	tiling,		{ 0 } }, 
-	{ Mod1Mask|ShiftMask,	XK_space,	floating,	{ 0 } }, 
-	{ Mod1Mask|ShiftMask,	XK_0,		ttrunc,		{ .i = Tscratch } }, 
-	{ Mod1Mask|ShiftMask,	XK_1,		ttrunc,		{ .i = Tdev } }, 
-	{ Mod1Mask|ShiftMask,	XK_2,		ttrunc,		{ .i = Twww } }, 
-	{ Mod1Mask|ShiftMask,	XK_3,		ttrunc,		{ .i = Twork } }, 
-	{ Mod1Mask|ShiftMask,	XK_c,		ckill,		{ 0 } }, 
-	{ Mod1Mask|ShiftMask,	XK_q,		quit,		{ 0 } },
-	{ Mod1Mask|ShiftMask,	XK_Return,	spawn,		{ .argv = term } },
-	{ Mod1Mask|ShiftMask,	XK_w,		spawn,		{ .argv = browse } },
-	{ Mod1Mask|ShiftMask,	XK_l,		spawn,		{ .argv = xlock } },
-	{ ControlMask,			XK_0,		tappend,	{ .i = Tscratch } }, 
-	{ ControlMask,			XK_1,		tappend,	{ .i = Tdev } }, 
-	{ ControlMask,			XK_2,		tappend,	{ .i = Twww } }, 
-	{ ControlMask,			XK_3,		tappend,	{ .i = Twork } }, 
-};
-
-/********** CUSTOMIZE **********/
-
-void
-grabkeys()
-{
-	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
-	unsigned int i;
-	KeyCode code;
-
-	for(i = 0; i < len; i++) {
-		code = XKeysymToKeycode(dpy, key[i].keysym);
-		XUngrabKey(dpy, code, key[i].mod, root);
-		XGrabKey(dpy, code, key[i].mod, root, True,
-				GrabModeAsync, GrabModeAsync);
-	}
-}
-
-void
-keypress(XEvent *e)
-{
-	XKeyEvent *ev = &e->xkey;
-	static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
-	unsigned int i;
-	KeySym keysym;
-
-	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
-	for(i = 0; i < len; i++)
-		if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
-			if(key[i].func)
-				key[i].func(&key[i].arg);
-			return;
-		}
-}
-
-static void
-zoom(Arg *arg)
-{
-	Client **l, *c;
-
-	if(!sel)
-		return;
-
-	if(sel == getnext(clients) && sel->next)  {
-		if((c = getnext(sel->next)))
-			sel = c;
-	}
-
-	for(l = &clients; *l && *l != sel; l = &(*l)->next);
-	*l = sel->next;
-
-	sel->next = clients; /* pop */
-	clients = sel;
-	arrange(NULL);
-	focus(sel);
-}
-
-static void
-max(Arg *arg)
-{
-	if(!sel)
-		return;
-	sel->x = sx;
-	sel->y = sy + bh;
-	sel->w = sw - 2 * sel->border;
-	sel->h = sh - 2 * sel->border - bh;
-	higher(sel);
-	resize(sel, False);
-}
-
-static void
-tappend(Arg *arg)
-{
-	if(!sel)
-		return;
-
-	sel->tags[arg->i] = tags[arg->i];
-	arrange(NULL);
-}
-
-static void
-ttrunc(Arg *arg)
-{
-	int i;
-	if(!sel)
-		return;
-
-	for(i = 0; i < TLast; i++)
-		sel->tags[i] = NULL;
-	tappend(arg);
-}
-
-static void
-prevc(Arg *arg)
-{
-	Client *c;
-
-	if(!sel)
-		return;
-
-	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
-		higher(c);
-		focus(c);
-	}
-}
-
-static void
-nextc(Arg *arg)
-{
-	Client *c;
-   
-	if(!sel)
-		return;
-
-	if(!(c = getnext(sel->next)))
-		c = getnext(clients);
-	if(c) {
-		higher(c);
-		c->revert = sel;
-		focus(c);
-	}
-}
-
-static void
-ckill(Arg *arg)
-{
-	if(!sel)
-		return;
-	if(sel->proto & WM_PROTOCOL_DELWIN)
-		sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
-	else
-		XKillClient(dpy, sel->win);
-}
-

+ 56 - 56
main.c

@@ -43,16 +43,16 @@ DC dc = {0};
 Client *clients = NULL;
 Client *sel = NULL;
 
-static Bool other_wm_running;
+static Bool otherwm;
 static const char version[] =
 	"dwm-" VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
-static int (*x_xerror) (Display *, XErrorEvent *);
+static int (*xerrorxlib)(Display *, XErrorEvent *);
 
 static void
-usage() {	error("usage: dwm [-v]\n"); }
+usage() {	eprint("usage: dwm [-v]\n"); }
 
 static void
-scan_wins()
+scan()
 {
 	unsigned int i, num;
 	Window *wins;
@@ -73,6 +73,22 @@ scan_wins()
 		XFree(wins);
 }
 
+static void
+cleanup()
+{
+	while(sel) {
+		resize(sel, True);
+		unmanage(sel);
+	}
+	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+}
+
+void
+quit(Arg *arg)
+{
+	running = False;
+}
+
 static int
 win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
 {
@@ -94,7 +110,7 @@ win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
 }
 
 int
-proto(Window w)
+getproto(Window w)
 {
 	unsigned char *protocols;
 	long res;
@@ -128,59 +144,43 @@ sendevent(Window w, Atom a, long value)
 	XFlush(dpy);
 }
 
-/*
- * There's no way to check accesses to destroyed windows, thus
- * those cases are ignored (especially on UnmapNotify's).
- * Other types of errors call Xlib's default error handler, which
- * calls exit().
- */
-int
-xerror(Display *dpy, XErrorEvent *error)
-{
-	if(error->error_code == BadWindow
-			|| (error->request_code == X_SetInputFocus
-				&& error->error_code == BadMatch)
-			|| (error->request_code == X_PolyText8
-				&& error->error_code == BadDrawable)
-			|| (error->request_code == X_PolyFillRectangle
-				&& error->error_code == BadDrawable)
-			|| (error->request_code == X_PolySegment
-				&& error->error_code == BadDrawable)
-			|| (error->request_code == X_ConfigureWindow
-				&& error->error_code == BadMatch)
-			|| (error->request_code == X_GrabKey
-				&& error->error_code == BadAccess))
-		return 0;
-	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
-			error->request_code, error->error_code);
-	return x_xerror(dpy, error); /* may call exit() */
-}
-
 /*
  * Startup Error handler to check if another window manager
  * is already running.
  */
 static int
-startup_xerror(Display *dpy, XErrorEvent *error)
+xerrorstart(Display *dsply, XErrorEvent *ee)
 {
-	other_wm_running = True;
+	otherwm = True;
 	return -1;
 }
 
-static void
-cleanup()
-{
-	while(sel) {
-		resize(sel, True);
-		unmanage(sel);
-	}
-	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
-}
-
-void
-quit(Arg *arg)
+/*
+ * There's no way to check accesses to destroyed windows, thus
+ * those cases are ignored (especially on UnmapNotify's).
+ * Other types of errors call Xlib's default error handler, which
+ * calls exit().
+ */
+int
+xerror(Display *dpy, XErrorEvent *ee)
 {
-	running = False;
+	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))
+		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
@@ -208,23 +208,23 @@ main(int argc, char *argv[])
 
 	dpy = XOpenDisplay(0);
 	if(!dpy)
-		error("dwm: cannot connect X server\n");
+		eprint("dwm: cannot connect X server\n");
 
 	screen = DefaultScreen(dpy);
 	root = RootWindow(dpy, screen);
 
 	/* check if another WM is already running */
-	other_wm_running = False;
-	XSetErrorHandler(startup_xerror);
+	otherwm = False;
+	XSetErrorHandler(xerrorstart);
 	/* this causes an error if some other WM is running */
 	XSelectInput(dpy, root, SubstructureRedirectMask);
 	XFlush(dpy);
 
-	if(other_wm_running)
-		error("dwm: another window manager is already running\n");
+	if(otherwm)
+		eprint("dwm: another window manager is already running\n");
 
 	XSetErrorHandler(0);
-	x_xerror = XSetErrorHandler(xerror);
+	xerrorxlib = XSetErrorHandler(xerror);
 
 	/* init atoms */
 	wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
@@ -278,7 +278,7 @@ main(int argc, char *argv[])
 	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
 
 	strcpy(stext, "dwm-"VERSION);
-	scan_wins();
+	scan();
 
 	/* main event loop, reads status text from stdin as well */
 Mainloop:
@@ -292,7 +292,7 @@ Mainloop:
 		if(i == -1 && errno == EINTR)
 			continue;
 		if(i < 0)
-			error("select failed\n");
+			eprint("select failed\n");
 		else if(i > 0) {
 			if(FD_ISSET(ConnectionNumber(dpy), &rd)) {
 				while(XPending(dpy)) {

+ 0 - 100
screen.c

@@ -1,100 +0,0 @@
-/*
- * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
- * See LICENSE file for license details.
- */
-
-#include "dwm.h"
-
-void (*arrange)(Arg *) = tiling;
-
-void
-view(Arg *arg)
-{
-	Client *c;
-
-	tsel = arg->i;
-	arrange(NULL);
-
-	for(c = clients; c; c = getnext(c->next))
-		drawtitle(c);
-	drawstatus();
-}
-
-void
-floating(Arg *arg)
-{
-	Client *c;
-
-	arrange = floating;
-	for(c = clients; c; c = c->next) {
-		if(c->tags[tsel])
-			resize(c, True);
-		else
-			ban(c);
-	}
-	if(sel && !sel->tags[tsel]) {
-		if((sel = getnext(clients))) {
-			higher(sel);
-			focus(sel);
-		}
-	}
-	drawstatus();
-}
-
-void
-tiling(Arg *arg)
-{
-	Client *c;
-	int n, i, w, h;
-
-	w = sw - mw;
-	arrange = tiling;
-	for(n = 0, c = clients; c; c = c->next)
-		if(c->tags[tsel] && !c->floating)
-			n++;
-
-	if(n > 1)
-		h = (sh - bh) / (n - 1);
-	else
-		h = sh - bh;
-
-	for(i = 0, c = clients; c; c = c->next) {
-		if(c->tags[tsel]) {
-			if(c->floating) {
-				higher(c);
-				resize(c, True);
-				continue;
-			}
-			if(n == 1) {
-				c->x = sx;
-				c->y = sy + bh;
-				c->w = sw - 2 * c->border;
-				c->h = sh - 2 * c->border - bh;
-			}
-			else if(i == 0) {
-				c->x = sx;
-				c->y = sy + bh;
-				c->w = mw - 2 * c->border;
-				c->h = sh - 2 * c->border - bh;
-			}
-			else {
-				c->x = sx + mw;
-				c->y = sy + (i - 1) * h + bh;
-				c->w = w - 2 * c->border;
-				c->h = h - 2 * c->border;
-			}
-			resize(c, False);
-			i++;
-		}
-		else
-			ban(c);
-	}
-	if(!sel || (sel && !sel->tags[tsel])) {
-		if((sel = getnext(clients))) {
-			higher(sel);
-			focus(sel);
-		}
-	}
-	drawstatus();
-}
-

+ 171 - 0
tag.c

@@ -0,0 +1,171 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+#include "dwm.h"
+
+static Rule rule[] = {
+	/* class			instance	tags						dofloat */
+	{ "Firefox-bin",	"Gecko",	{ [Twww] = "www" },			False },
+};
+
+void (*arrange)(Arg *) = dotile;
+
+Client *
+getnext(Client *c)
+{
+	for(; c && !c->tags[tsel]; c = c->next);
+	return c;
+}
+
+void
+settags(Client *c)
+{
+	XClassHint ch;
+	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
+	unsigned int i, j;
+	Bool matched = False;
+
+	if(!len) {
+		c->tags[tsel] = tags[tsel];
+		return;
+	}
+
+	if(XGetClassHint(dpy, c->win, &ch)) {
+		if(ch.res_class && ch.res_name) {
+			for(i = 0; i < len; i++)
+				if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
+					&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
+				{
+					for(j = 0; j < TLast; j++)
+						c->tags[j] = rule[i].tags[j];
+					c->dofloat = rule[i].dofloat;
+					matched = True;
+					break;
+				}
+		}
+		if(ch.res_class)
+			XFree(ch.res_class);
+		if(ch.res_name)
+			XFree(ch.res_name);
+	}
+
+	if(!matched)
+		c->tags[tsel] = tags[tsel];
+}
+
+void
+view(Arg *arg)
+{
+	tsel = arg->i;
+	arrange(NULL);
+	drawall();
+}
+
+void
+dofloat(Arg *arg)
+{
+	Client *c;
+
+	arrange = dofloat;
+	for(c = clients; c; c = c->next) {
+		if(c->tags[tsel])
+			resize(c, True);
+		else
+			ban(c);
+	}
+	if(sel && !sel->tags[tsel]) {
+		if((sel = getnext(clients))) {
+			higher(sel);
+			focus(sel);
+		}
+	}
+	drawall();
+}
+
+void
+dotile(Arg *arg)
+{
+	Client *c;
+	int n, i, w, h;
+
+	w = sw - mw;
+	arrange = dotile;
+	for(n = 0, c = clients; c; c = c->next)
+		if(c->tags[tsel] && !c->dofloat)
+			n++;
+
+	if(n > 1)
+		h = (sh - bh) / (n - 1);
+	else
+		h = sh - bh;
+
+	for(i = 0, c = clients; c; c = c->next) {
+		if(c->tags[tsel]) {
+			if(c->dofloat) {
+				higher(c);
+				resize(c, True);
+				continue;
+			}
+			if(n == 1) {
+				c->x = sx;
+				c->y = sy + bh;
+				c->w = sw - 2 * c->border;
+				c->h = sh - 2 * c->border - bh;
+			}
+			else if(i == 0) {
+				c->x = sx;
+				c->y = sy + bh;
+				c->w = mw - 2 * c->border;
+				c->h = sh - 2 * c->border - bh;
+			}
+			else {
+				c->x = sx + mw;
+				c->y = sy + (i - 1) * h + bh;
+				c->w = w - 2 * c->border;
+				c->h = h - 2 * c->border;
+			}
+			resize(c, False);
+			i++;
+		}
+		else
+			ban(c);
+	}
+	if(!sel || (sel && !sel->tags[tsel])) {
+		if((sel = getnext(clients))) {
+			higher(sel);
+			focus(sel);
+		}
+	}
+	drawall();
+}
+
+void
+appendtag(Arg *arg)
+{
+	if(!sel)
+		return;
+
+	sel->tags[arg->i] = tags[arg->i];
+	arrange(NULL);
+}
+
+void
+replacetag(Arg *arg)
+{
+	int i;
+	if(!sel)
+		return;
+
+	for(i = 0; i < TLast; i++)
+		sel->tags[i] = NULL;
+	appendtag(arg);
+}
+

+ 1 - 1
util.c

@@ -13,7 +13,7 @@
 #include "dwm.h"
 
 void
-error(const char *errstr, ...) {
+eprint(const char *errstr, ...) {
 	va_list ap;
 	va_start(ap, errstr);
 	vfprintf(stderr, errstr, ap);