summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2011-08-04 20:53:37 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2011-08-04 20:53:37 +0200
commit513c35dca9047f01f26ec1be5089b9e4dfd34648 (patch)
tree302991f29f21a76464656d461d78fe77ab9c697c
parentf067809af405f2703a9cf180ee9e1ed5bf183caa (diff)
parent912dd46a7e5aac20c685fcb424a484a44bb9c713 (diff)
downloadcwm-513c35dca9047f01f26ec1be5089b9e4dfd34648.tar.gz
cwm-513c35dca9047f01f26ec1be5089b9e4dfd34648.tar.xz
cwm-513c35dca9047f01f26ec1be5089b9e4dfd34648.zip
cvsimport
-rw-r--r--Makefile3
-rw-r--r--calmwm.c69
-rw-r--r--calmwm.h50
-rw-r--r--client.c91
-rw-r--r--conf.c42
-rw-r--r--cwmrc.520
-rw-r--r--font.c7
-rw-r--r--group.c6
-rw-r--r--kbfunc.c37
-rw-r--r--menu.c33
-rw-r--r--mousefunc.c37
-rw-r--r--parse.y19
-rw-r--r--search.c9
-rw-r--r--util.c9
-rw-r--r--xevents.c4
-rw-r--r--xutil.c4
16 files changed, 243 insertions, 197 deletions
diff --git a/Makefile b/Makefile
index c3efedb..6e787c0 100644
--- a/Makefile
+++ b/Makefile
@@ -24,12 +24,11 @@ CFLAGS+=	-Wall -O2 -g
 LDADD+=		-L${X11BASE}/lib -lXft -lXrender -lX11 -lxcb -lXau -lXdmcp \
 		-lfontconfig -lexpat -lfreetype -lz -lXinerama -lXrandr -lXext
 
-MANDIR=		${X11BASE}/man/cat
+MANDIR=		${X11BASE}/man/man
 MAN=		cwm.1 cwmrc.5
 
 CLEANFILES=	cwm.cat1 cwmrc.cat5
 
-
 all: $(PROG)
 
 clean:
diff --git a/calmwm.c b/calmwm.c
index a603fbd..8bfdff3 100644
--- a/calmwm.c
+++ b/calmwm.c
@@ -35,22 +35,22 @@
 
 Display				*X_Dpy;
 
-Cursor				 Cursor_move;
-Cursor				 Cursor_resize;
-Cursor				 Cursor_select;
 Cursor				 Cursor_default;
+Cursor				 Cursor_move;
+Cursor				 Cursor_normal;
 Cursor				 Cursor_question;
+Cursor				 Cursor_resize;
 
 struct screen_ctx_q		 Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
 struct client_ctx_q		 Clientq = TAILQ_HEAD_INITIALIZER(Clientq);
 
 int				 HasXinerama, HasRandr, Randr_ev;
-int				 Starting;
 struct conf			 Conf;
 
 static void	sigchld_cb(int);
 static void	dpy_init(const char *);
 static int	x_errorhandler(Display *, XErrorEvent *);
+static int	x_wmerrorhandler(Display *, XErrorEvent *);
 static void	x_setup(void);
 static void	x_setupscreen(struct screen_ctx *, u_int);
 static void	x_teardown(void);
@@ -80,14 +80,12 @@ main(int argc, char **argv)
 	if (signal(SIGCHLD, sigchld_cb) == SIG_ERR)
 		err(1, "signal");
 
-	Starting = 1;
 	dpy_init(display_name);
 
 	bzero(&Conf, sizeof(Conf));
 	conf_setup(&Conf, conf_file);
 	xu_getatoms();
 	x_setup();
-	Starting = 0;
 
 	xev_loop();
 
@@ -101,10 +99,15 @@ dpy_init(const char *dpyname)
 {
 	int	i;
 
+	XSetErrorHandler(x_errorhandler);
+
 	if ((X_Dpy = XOpenDisplay(dpyname)) == NULL)
 		errx(1, "unable to open display \"%s\"",
 		    XDisplayName(dpyname));
 
+	XSetErrorHandler(x_wmerrorhandler);
+	XSelectInput(X_Dpy, DefaultRootWindow(X_Dpy), SubstructureRedirectMask);
+	XSync(X_Dpy, False);
 	XSetErrorHandler(x_errorhandler);
 
 	HasRandr = XRRQueryExtension(X_Dpy, &Randr_ev, &i);
@@ -117,6 +120,12 @@ x_setup(void)
 	struct keybinding	*kb;
 	int			 i;
 
+	Cursor_default = XCreateFontCursor(X_Dpy, XC_X_cursor);
+	Cursor_move = XCreateFontCursor(X_Dpy, XC_fleur);
+	Cursor_normal = XCreateFontCursor(X_Dpy, XC_left_ptr);
+	Cursor_question = XCreateFontCursor(X_Dpy, XC_question_arrow);
+	Cursor_resize = XCreateFontCursor(X_Dpy, XC_bottom_right_corner);
+
 	for (i = 0; i < ScreenCount(X_Dpy); i++) {
 		sc = xcalloc(1, sizeof(*sc));
 		x_setupscreen(sc, i);
@@ -129,12 +138,6 @@ x_setup(void)
 	 */
 	TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
 		conf_grab(&Conf, kb);
-
-	Cursor_move = XCreateFontCursor(X_Dpy, XC_fleur);
-	Cursor_resize = XCreateFontCursor(X_Dpy, XC_bottom_right_corner);
-	Cursor_select = XCreateFontCursor(X_Dpy, XC_hand1);
-	Cursor_default = XCreateFontCursor(X_Dpy, XC_X_cursor);
-	Cursor_question = XCreateFontCursor(X_Dpy, XC_question_arrow);
 }
 
 static void
@@ -176,11 +179,12 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
 
 	xu_setwmname(sc);
 
-	rootattr.event_mask = ChildMask|PropertyChangeMask|EnterWindowMask|
-	    LeaveWindowMask|ColormapChangeMask|ButtonMask;
+	rootattr.cursor = Cursor_normal;
+	rootattr.event_mask = CHILDMASK|PropertyChangeMask|EnterWindowMask|
+	    LeaveWindowMask|ColormapChangeMask|BUTTONMASK;
 
 	XChangeWindowAttributes(X_Dpy, sc->rootwin,
-	    CWEventMask, &rootattr);
+	    CWEventMask|CWCursor, &rootattr);
 
 	/* Deal with existing clients. */
 	XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins);
@@ -190,7 +194,7 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
 		if (winattr.override_redirect ||
 		    winattr.map_state != IsViewable)
 			continue;
-		client_new(wins[i], sc, winattr.map_state != IsUnmapped);
+		(void)client_new(wins[i], sc, winattr.map_state != IsUnmapped);
 	}
 	XFree(wins);
 
@@ -212,27 +216,25 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
 }
 
 static int
+x_wmerrorhandler(Display *dpy, XErrorEvent *e)
+{
+	errx(1, "root window unavailable - perhaps another wm is running?");
+
+	return (0);
+}
+static int
 x_errorhandler(Display *dpy, XErrorEvent *e)
 {
-#ifdef DEBUG
-	{
-		char msg[80], number[80], req[80];
+#if DEBUG
+	char msg[80], number[80], req[80];
 
-		XGetErrorText(X_Dpy, e->error_code, msg, sizeof(msg));
-		snprintf(number, sizeof(number), "%d", e->request_code);
-		XGetErrorDatabaseText(X_Dpy, "XRequest", number,
-		    "<unknown>", req, sizeof(req));
+	XGetErrorText(X_Dpy, e->error_code, msg, sizeof(msg));
+	(void)snprintf(number, sizeof(number), "%d", e->request_code);
+	XGetErrorDatabaseText(X_Dpy, "XRequest", number,
+	    "<unknown>", req, sizeof(req));
 
-		warnx("%s(0x%x): %s", req, (u_int)e->resourceid, msg);
-	}
+	warnx("%s(0x%x): %s", req, (u_int)e->resourceid, msg);
 #endif
-
-	if (Starting &&
-	    e->error_code == BadAccess &&
-	    e->request_code == X_GrabKey)
-		errx(1, "root window unavailable - perhaps another "
-		    "wm is running?");
-
 	return (0);
 }
 
@@ -256,6 +258,7 @@ usage(void)
 {
 	extern char	*__progname;
 
-	fprintf(stderr, "usage: %s [-c file] [-d display]\n", __progname);
+	(void)fprintf(stderr, "usage: %s [-c file] [-d display]\n",
+	    __progname);
 	exit(1);
 }
diff --git a/calmwm.h b/calmwm.h
index 5a7605d..16e52b2 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -51,15 +51,15 @@ size_t strlcat(char *, const char *, size_t);
 #define	CONFFILE	".cwmrc"
 #define	WMNAME	 	"CWM"
 
-#define ChildMask	(SubstructureRedirectMask|SubstructureNotifyMask)
-#define ButtonMask	(ButtonPressMask|ButtonReleaseMask)
-#define MouseMask	(ButtonMask|PointerMotionMask)
-#define KeyMask		(KeyPressMask|ExposureMask)
-#define MenuMask 	(ButtonMask|ButtonMotionMask|ExposureMask| \
+#define CHILDMASK	(SubstructureRedirectMask|SubstructureNotifyMask)
+#define BUTTONMASK	(ButtonPressMask|ButtonReleaseMask)
+#define MOUSEMASK	(BUTTONMASK|PointerMotionMask)
+#define KEYMASK		(KeyPressMask|ExposureMask)
+#define MENUMASK 	(BUTTONMASK|ButtonMotionMask|ExposureMask| \
 			PointerMotionMask)
-#define MenuGrabMask	(ButtonMask|ButtonMotionMask|StructureNotifyMask|\
+#define MENUGRABMASK	(BUTTONMASK|ButtonMotionMask|StructureNotifyMask|\
 			PointerMotionMask)
-#define SearchMask	(KeyPressMask|ExposureMask)
+#define SEARCHMASK	(KeyPressMask|ExposureMask)
 
 /* kb movement */
 #define CWM_MOVE		0x0001
@@ -75,14 +75,10 @@ size_t strlcat(char *, const char *, size_t);
 #define	CWM_EXEC_PROGRAM	0x0001
 #define	CWM_EXEC_WM		0x0002
 
-/* client cycle */
+/* cycle */
 #define CWM_CYCLE		0
 #define CWM_RCYCLE		1
 
-/* group cycle */
-#define CWM_CYCLEGROUP		0
-#define CWM_RCYCLEGROUP		1
-
 #define KBTOGROUP(X) ((X) - 1)
 
 union arg {
@@ -91,7 +87,7 @@ union arg {
 };
 
 enum cwmcolor {
-	CWM_COLOR_BORDOR_ACTIVE,
+	CWM_COLOR_BORDER_ACTIVE,
 	CWM_COLOR_BORDER_INACTIVE,
 	CWM_COLOR_BORDER_GROUP,
 	CWM_COLOR_BORDER_UNGROUP,
@@ -152,13 +148,10 @@ struct client_ctx {
 	int			 xproto;
 #define CLIENT_HIDDEN			0x0001
 #define CLIENT_IGNORE			0x0002
-#define CLIENT_DOMAXIMIZE		0x0004
-#define CLIENT_MAXIMIZED		0x0008
-#define CLIENT_DOVMAXIMIZE		0x0010
-#define CLIENT_VMAXIMIZED		0x0020
-#define CLIENT_DOHMAXIMIZE		0x0040
-#define CLIENT_HMAXIMIZED		0x0080
-#define CLIENT_FREEZE			0x0100
+#define CLIENT_MAXIMIZED		0x0004
+#define CLIENT_VMAXIMIZED		0x0008
+#define CLIENT_HMAXIMIZED		0x0010
+#define CLIENT_FREEZE			0x0020
 	int			 flags;
 	int			 state;
 	int			 active;
@@ -219,7 +212,6 @@ struct screen_ctx {
 	XftColor		 xftcolor;
 	XftDraw			*xftdraw;
 	XftFont			*font;
-	u_int			 fontheight;
 	int			 xinerama_no;
 	XineramaScreenInfo	*xinerama;
 #define CALMWM_NGROUPS		 9
@@ -289,6 +281,8 @@ struct conf {
 	int			 bwidth;
 #define	CONF_MAMOUNT			1
 	int			 mamount;
+#define	CONF_SNAPDIST			0
+	int			 snapdist;
 	struct gap		 gap;
 #define CONF_COLOR_ACTIVEBORDER		"#CCCCCC"
 #define CONF_COLOR_INACTIVEBORDER	"#666666"
@@ -319,8 +313,8 @@ __dead void		 usage(void);
 
 void			 client_applysizehints(struct client_ctx *);
 struct client_ctx	*client_current(void);
-struct client_ctx	*client_cycle(struct screen_ctx *, int);
-int			 client_delete(struct client_ctx *);
+void			 client_cycle(struct screen_ctx *, int);
+void			 client_delete(struct client_ctx *);
 void			 client_draw_border(struct client_ctx *);
 struct client_ctx	*client_find(Window);
 void			 client_freeze(struct client_ctx *);
@@ -341,6 +335,7 @@ void			 client_resize(struct client_ctx *);
 void			 client_send_delete(struct client_ctx *);
 void			 client_setactive(struct client_ctx *, int);
 void			 client_setname(struct client_ctx *);
+int			 client_snapcalc(int, int, int, int, int);
 void			 client_unhide(struct client_ctx *);
 void			 client_vertmaximize(struct client_ctx *);
 void			 client_warp(struct client_ctx *);
@@ -418,6 +413,7 @@ void			 mousefunc_window_grouptoggle(struct client_ctx *,
 void			 mousefunc_window_hide(struct client_ctx *, void *);
 void			 mousefunc_window_lower(struct client_ctx *, void *);
 void			 mousefunc_window_move(struct client_ctx *, void *);
+void			 mousefunc_window_raise(struct client_ctx *, void *);
 void			 mousefunc_window_resize(struct client_ctx *, void *);
 
 struct menu  		*menu_filter(struct screen_ctx *, struct menu_q *,
@@ -475,7 +471,7 @@ void			 xu_setstate(struct client_ctx *, int);
 void			 xu_setwmname(struct screen_ctx *);
 
 void			 u_exec(char *);
-int			 u_spawn(char *);
+void			 u_spawn(char *);
 
 void			*xcalloc(size_t, size_t);
 void			 xfree(void *);
@@ -485,11 +481,11 @@ char			*xstrdup(const char *);
 /* Externs */
 extern Display				*X_Dpy;
 
-extern Cursor				 Cursor_move;
-extern Cursor				 Cursor_resize;
-extern Cursor				 Cursor_select;
 extern Cursor				 Cursor_default;
+extern Cursor				 Cursor_move;
+extern Cursor				 Cursor_normal;
 extern Cursor				 Cursor_question;
+extern Cursor				 Cursor_resize;
 
 extern struct screen_ctx_q		 Screenq;
 extern struct client_ctx_q		 Clientq;
diff --git a/client.c b/client.c
index a18ffcc..a55bd42 100644
--- a/client.c
+++ b/client.c
@@ -137,7 +137,7 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
 	return (cc);
 }
 
-int
+void
 client_delete(struct client_ctx *cc)
 {
 	struct screen_ctx	*sc = cc->sc;
@@ -189,8 +189,6 @@ client_delete(struct client_ctx *cc)
 
 	client_freehints(cc);
 	xfree(cc);
-
-	return (0);
 }
 
 void
@@ -285,6 +283,8 @@ client_maximize(struct client_ctx *cc)
 
 	if (cc->flags & CLIENT_MAXIMIZED) {
 		cc->geom = cc->savegeom;
+		cc->bwidth = Conf.bwidth;
+		cc->flags &= ~CLIENT_MAXIMIZED;
 	} else {
 		if (!(cc->flags & (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)))
 			cc->savegeom = cc->geom;
@@ -310,7 +310,8 @@ calc:
 		cc->geom.y = y_org + sc->gap.top;
 		cc->geom.height = ymax - (sc->gap.top + sc->gap.bottom);
 		cc->geom.width = xmax - (sc->gap.left + sc->gap.right);
-		cc->flags |= CLIENT_DOMAXIMIZE;
+		cc->bwidth = 0;
+		cc->flags |= CLIENT_MAXIMIZED;
 	}
 
 	client_resize(cc);
@@ -326,7 +327,10 @@ client_vertmaximize(struct client_ctx *cc)
 		return;
 
 	if (cc->flags & CLIENT_VMAXIMIZED) {
-		cc->geom = cc->savegeom;
+		cc->geom.y = cc->savegeom.y;
+		cc->geom.height = cc->savegeom.height;
+		cc->bwidth = Conf.bwidth;
+		cc->flags &= ~CLIENT_VMAXIMIZED;
 	} else {
 		if (!(cc->flags & (CLIENT_MAXIMIZED | CLIENT_HMAXIMIZED)))
 			cc->savegeom = cc->geom;
@@ -344,7 +348,7 @@ calc:
 		cc->geom.y = y_org + sc->gap.top;
 		cc->geom.height = ymax - (cc->bwidth * 2) - (sc->gap.top +
 		    sc->gap.bottom);
-		cc->flags |= CLIENT_DOVMAXIMIZE;
+		cc->flags |= CLIENT_VMAXIMIZED;
 	}
 
 	client_resize(cc);
@@ -360,7 +364,10 @@ client_horizmaximize(struct client_ctx *cc)
 		return;
 
 	if (cc->flags & CLIENT_HMAXIMIZED) {
-		cc->geom = cc->savegeom;
+		cc->geom.x = cc->savegeom.x;
+		cc->geom.width = cc->savegeom.width;
+		cc->bwidth = Conf.bwidth;
+		cc->flags &= ~CLIENT_HMAXIMIZED;
 	} else {
 		if (!(cc->flags & (CLIENT_MAXIMIZED | CLIENT_VMAXIMIZED)))
 			cc->savegeom = cc->geom;
@@ -378,7 +385,7 @@ calc:
 		cc->geom.x = x_org + sc->gap.left;
 		cc->geom.width = xmax - (cc->bwidth * 2) - (sc->gap.left +
 		    sc->gap.right);
-		cc->flags |= CLIENT_DOHMAXIMIZE;
+		cc->flags |= CLIENT_HMAXIMIZED;
 	}
 
 	client_resize(cc);
@@ -387,23 +394,6 @@ calc:
 void
 client_resize(struct client_ctx *cc)
 {
-	cc->flags &= ~(CLIENT_MAXIMIZED | CLIENT_VMAXIMIZED |
-	    CLIENT_HMAXIMIZED);
-
-	if (cc->flags & CLIENT_DOMAXIMIZE) {
-		cc->bwidth = 0;
-		cc->flags &= ~CLIENT_DOMAXIMIZE;
-		cc->flags |= CLIENT_MAXIMIZED;
-	} else if (cc->flags & CLIENT_DOVMAXIMIZE) {
-		cc->flags &= ~CLIENT_DOVMAXIMIZE;
-		cc->flags |= CLIENT_VMAXIMIZED;
-	} else if (cc->flags & CLIENT_DOHMAXIMIZE) {
-		cc->flags &= ~CLIENT_DOHMAXIMIZE;
-		cc->flags |= CLIENT_HMAXIMIZED;
-	} else {
-		cc->bwidth = Conf.bwidth;
-	}
-
 	client_draw_border(cc);
 
 	XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x,
@@ -414,11 +404,6 @@ client_resize(struct client_ctx *cc)
 void
 client_move(struct client_ctx *cc)
 {
-	if (cc->flags & CLIENT_VMAXIMIZED)
-		cc->savegeom.x = cc->geom.x;
-	if (cc->flags & CLIENT_HMAXIMIZED)
-		cc->savegeom.y = cc->geom.y;
-
 	XMoveWindow(X_Dpy, cc->win, cc->geom.x, cc->geom.y);
 	xu_configure(cc);
 }
@@ -504,7 +489,7 @@ client_draw_border(struct client_ctx *cc)
 			pixel = sc->color[CWM_COLOR_BORDER_UNGROUP].pixel;
 			break;
 		default:
-			pixel = sc->color[CWM_COLOR_BORDOR_ACTIVE].pixel;
+			pixel = sc->color[CWM_COLOR_BORDER_ACTIVE].pixel;
 			break;
 		}
 	else
@@ -550,9 +535,8 @@ client_setname(struct client_ctx *cc)
 	char		*newname;
 
 	if (!xu_getstrprop(cc->win, _NET_WM_NAME, &newname))
-		xu_getstrprop(cc->win, XA_WM_NAME, &newname);
-	if (newname == NULL)
-		newname = emptystring;
+		if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname))
+			newname = emptystring;
 
 	TAILQ_FOREACH(wn, &cc->nameq, entry)
 		if (strcmp(wn->name, newname) == 0) {
@@ -580,11 +564,9 @@ match:
 		xfree(wn);
 		cc->nameqlen--;
 	}
-
-	return;
 }
 
-struct client_ctx *
+void
 client_cycle(struct screen_ctx *sc, int reverse)
 {
 	struct client_ctx	*oldcc, *newcc;
@@ -594,7 +576,7 @@ client_cycle(struct screen_ctx *sc, int reverse)
 
 	/* If no windows then you cant cycle */
 	if (TAILQ_EMPTY(&sc->mruq))
-		return (NULL);
+		return;
 
 	if (oldcc == NULL)
 		oldcc = (reverse ? TAILQ_LAST(&sc->mruq, cycle_entry_q) :
@@ -614,7 +596,7 @@ client_cycle(struct screen_ctx *sc, int reverse)
 		/* Is oldcc the only non-hidden window? */
 		if (newcc == oldcc) {
 			if (again)
-				return (NULL);	/* No windows visible. */
+				return;	/* No windows visible. */
 
 			break;
 		}
@@ -624,8 +606,6 @@ client_cycle(struct screen_ctx *sc, int reverse)
 	sc->altpersist = 1;
 	client_ptrsave(oldcc);
 	client_ptrwarp(newcc);
-
-	return (newcc);
 }
 
 static struct client_ctx *
@@ -862,3 +842,32 @@ client_inbound(struct client_ctx *cc, int x, int y)
 	return (x < cc->geom.width && x >= 0 &&
 	    y < cc->geom.height && y >= 0);
 }
+
+int
+client_snapcalc(int n, int dn, int nmax, int bwidth, int snapdist)
+{
+	int	 n0, n1, s0, s1;
+
+	s0 = s1 = 0;
+	n0 = n;
+	n1 = n + dn + (bwidth * 2);
+
+	if (abs(n0) <= snapdist)
+		s0 = -n0;
+
+	if (nmax - snapdist <= n1 && n1 <= nmax + snapdist)
+		s1 = nmax - n1;
+
+	/* possible to snap in both directions */
+	if (s0 != 0 && s1 != 0)
+		if (abs(s0) < abs(s1))
+			return s0;
+		else
+			return s1;
+	else if (s0 != 0)
+		return s0;
+	else if (s1 != 0)
+		return s1;
+	else
+		return 0;
+}
diff --git a/conf.c b/conf.c
index 593bc00..ecdc578 100644
--- a/conf.c
+++ b/conf.c
@@ -48,14 +48,14 @@ conf_cmd_add(struct conf *c, char *image, char *label, int flags)
 	/* "term" and "lock" have special meanings. */
 
 	if (strcmp(label, "term") == 0)
-		strlcpy(c->termpath, image, sizeof(c->termpath));
+		(void)strlcpy(c->termpath, image, sizeof(c->termpath));
 	else if (strcmp(label, "lock") == 0)
-		strlcpy(c->lockpath, image, sizeof(c->lockpath));
+		(void)strlcpy(c->lockpath, image, sizeof(c->lockpath));
 	else {
 		struct cmd *cmd = xmalloc(sizeof(*cmd));
 		cmd->flags = flags;
-		strlcpy(cmd->image, image, sizeof(cmd->image));
-		strlcpy(cmd->label, label, sizeof(cmd->label));
+		(void)strlcpy(cmd->image, image, sizeof(cmd->image));
+		(void)strlcpy(cmd->label, label, sizeof(cmd->label));
 		TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
 	}
 }
@@ -70,7 +70,6 @@ void
 conf_font(struct conf *c, struct screen_ctx *sc)
 {
 	sc->font = font_make(sc, c->DefaultFontName);
-	sc->fontheight = font_ascent(sc) + font_descent(sc) + 1;
 }
 
 void
@@ -95,13 +94,13 @@ conf_reload(struct conf *c)
 		return;
 	}
 
-	TAILQ_FOREACH(cc, &Clientq, entry)
-		client_draw_border(cc);
 	TAILQ_FOREACH(sc, &Screenq, entry) {
 		conf_gap(c, sc);
 		conf_color(c, sc);
 		conf_font(c, sc);
 	}
+	TAILQ_FOREACH(cc, &Clientq, entry)
+		client_draw_border(cc);
 }
 
 static struct {
@@ -185,6 +184,7 @@ conf_init(struct conf *c)
 	c->flags = 0;
 	c->bwidth = CONF_BWIDTH;
 	c->mamount = CONF_MAMOUNT;
+	c->snapdist = CONF_SNAPDIST;
 
 	TAILQ_INIT(&c->ignoreq);
 	TAILQ_INIT(&c->cmdq);
@@ -199,10 +199,10 @@ conf_init(struct conf *c)
 		conf_mousebind(c, m_binds[i].key, m_binds[i].func);
 
 	/* Default term/lock */
-	strlcpy(c->termpath, "xterm", sizeof(c->termpath));
-	strlcpy(c->lockpath, "xlock", sizeof(c->lockpath));
+	(void)strlcpy(c->termpath, "xterm", sizeof(c->termpath));
+	(void)strlcpy(c->lockpath, "xlock", sizeof(c->lockpath));
 
-	c->color[CWM_COLOR_BORDOR_ACTIVE].name =
+	c->color[CWM_COLOR_BORDER_ACTIVE].name =
 	    xstrdup(CONF_COLOR_ACTIVEBORDER);
 	c->color[CWM_COLOR_BORDER_INACTIVE].name =
 	    xstrdup(CONF_COLOR_INACTIVEBORDER);
@@ -273,17 +273,19 @@ conf_setup(struct conf *c, const char *conf_file)
 		if (home == NULL)
 			errx(1, "No HOME directory.");
 
-		snprintf(c->conf_path, sizeof(c->conf_path), "%s/%s", home,
-		    CONFFILE);
+		(void)snprintf(c->conf_path, sizeof(c->conf_path), "%s/%s",
+		    home, CONFFILE);
 	} else
 		if (stat(conf_file, &sb) == -1 || !(sb.st_mode & S_IFREG))
 			errx(1, "%s: %s", conf_file, strerror(errno));
 		else
-			strlcpy(c->conf_path, conf_file, sizeof(c->conf_path));
+			(void)strlcpy(c->conf_path, conf_file,
+			    sizeof(c->conf_path));
 
 	conf_init(c);
 
-	(void)parse_config(c->conf_path, c);
+	if (parse_config(c->conf_path, c) == -1)
+		warnx("config file %s has errors, not loading", c->conf_path);
 }
 
 void
@@ -356,8 +358,8 @@ static struct {
 	{ "movetogroup9", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
 	    {.i = 9} },
 	{ "nogroup", kbfunc_client_nogroup, 0, {0} },
-	{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLEGROUP} },
-	{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLEGROUP} },
+	{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLE} },
+	{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLE} },
 	{ "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, {0}},
 	{ "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} },
 	{ "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} },
@@ -415,7 +417,6 @@ static struct {
 	    {.i = (CWM_LEFT|CWM_PTRMOVE|CWM_BIGMOVE)} },
 	{ "bigptrmoveright", kbfunc_moveresize, 0,
 	    {.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} },
-	{ NULL, NULL, 0, {0}},
 };
 
 /*
@@ -504,7 +505,7 @@ conf_bindname(struct conf *c, char *name, char *binding)
 	if (strcmp("unmap", binding) == 0)
 		return;
 
-	for (iter = 0; name_to_kbfunc[iter].tag != NULL; iter++) {
+	for (iter = 0; iter < nitems(name_to_kbfunc); iter++) {
 		if (strcmp(name_to_kbfunc[iter].tag, binding) != 0)
 			continue;
 
@@ -521,7 +522,6 @@ conf_bindname(struct conf *c, char *name, char *binding)
 	current_binding->flags = 0;
 	conf_grab(c, current_binding);
 	TAILQ_INSERT_TAIL(&c->keybindingq, current_binding, entry);
-	return;
 }
 
 static void
@@ -556,11 +556,11 @@ static struct {
 	{ "window_grouptoggle", mousefunc_window_grouptoggle,
 	    MOUSEBIND_CTX_WIN },
 	{ "window_lower", mousefunc_window_lower, MOUSEBIND_CTX_WIN },
+	{ "window_raise", mousefunc_window_raise, MOUSEBIND_CTX_WIN },
 	{ "window_hide", mousefunc_window_hide, MOUSEBIND_CTX_WIN },
 	{ "menu_group", mousefunc_menu_group, MOUSEBIND_CTX_ROOT },
 	{ "menu_unhide", mousefunc_menu_unhide, MOUSEBIND_CTX_ROOT },
 	{ "menu_cmd", mousefunc_menu_cmd, MOUSEBIND_CTX_ROOT },
-	{ NULL, NULL, 0 },
 };
 
 void
@@ -596,7 +596,7 @@ conf_mousebind(struct conf *c, char *name, char *binding)
 	if (strcmp("unmap", binding) == 0)
 		return;
 
-	for (iter = 0; name_to_mousefunc[iter].tag != NULL; iter++) {
+	for (iter = 0; iter < nitems(name_to_mousefunc); iter++) {
 		if (strcmp(name_to_mousefunc[iter].tag, binding) != 0)
 			continue;
 
diff --git a/cwmrc.5 b/cwmrc.5
index a0544ff..c7dbf7f 100644
--- a/cwmrc.5
+++ b/cwmrc.5
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: September 25 2010 $
+.Dd $Mdocdate: June 24 2011 $
 .Dt CWMRC 5
 .Os
 .Sh NAME
@@ -24,7 +24,19 @@
 This manual page describes the
 .Xr cwm 1
 configuration file.
-The following options are accepted in the configuration file:
+.Pp
+The current line can be extended over multiple lines using a backslash
+.Pq Sq \e .
+Comments can be put anywhere in the file using a hash mark
+.Pq Sq # ,
+and extend to the end of the current line.
+Care should be taken when commenting out multi-line text:
+the comment is effective until the end of the entire block.
+.Pp
+Arguments containing whitespace should be surrounded by double quotes
+.Pq \&" .
+.Pp
+The following options are accepted:
 .Pp
 .Bl -tag -width Ds -compact
 .It Ic autogroup Ar group windowname
@@ -277,6 +289,8 @@ Reverse cycle through groups.
 Forward cycle through windows.
 .It rcycle
 Reverse cycle through windows.
+.It snapdist
+Minimum distance to snap-to adjacent edge.
 .It delete
 Delete current window.
 .It hide
@@ -400,6 +414,8 @@ Move current window.
 Resize current window.
 .It window_lower
 Lower current window.
+.It window_raise
+Raise current window.
 .It window_hide
 Hide current window.
 .It window_grouptoggle
diff --git a/font.c b/font.c
index 47c7348..cc24eaf 100644
--- a/font.c
+++ b/font.c
@@ -45,7 +45,7 @@ font_descent(struct screen_ctx *sc)
 u_int
 font_height(struct screen_ctx *sc)
 {
-	return (sc->fontheight);
+	return (sc->font->height + 1);
 }
 
 void
@@ -66,7 +66,7 @@ font_width(struct screen_ctx *sc, const char *text, int len)
 {
 	XGlyphInfo	 extents;
 
-	XftTextExtents8(X_Dpy, sc->font, (const XftChar8*)text,
+	XftTextExtentsUtf8(X_Dpy, sc->font, (const FcChar8*)text,
 	    len, &extents);
 
 	return (extents.xOff);
@@ -77,8 +77,7 @@ font_draw(struct screen_ctx *sc, const char *text, int len,
     Drawable d, int x, int y)
 {
 	XftDrawChange(sc->xftdraw, d);
-	/* Really needs to be UTF8'd. */
-	XftDrawString8(sc->xftdraw, &sc->xftcolor, sc->font, x, y,
+	XftDrawStringUtf8(sc->xftdraw, &sc->xftcolor, sc->font, x, y,
 	    (const FcChar8*)text, len);
 }
 
diff --git a/group.c b/group.c
index 42cdbe7..e8d23e8 100644
--- a/group.c
+++ b/group.c
@@ -377,10 +377,10 @@ group_menu(XButtonEvent *e)
 
 		mi = xcalloc(1, sizeof(*mi));
 		if (gc->hidden)
-			snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
+			(void)snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
 			    gc->shortcut, sc->group_names[i]);
 		else
-			snprintf(mi->text, sizeof(mi->text), "%d: %s",
+			(void)snprintf(mi->text, sizeof(mi->text), "%d: %s",
 			    gc->shortcut, sc->group_names[i]);
 		mi->ctx = gc;
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
@@ -533,7 +533,7 @@ group_set_names(struct screen_ctx *sc)
 	tlen = len;
 	for (i = 0; i < sc->group_nonames; i++) {
 		slen = strlen(sc->group_names[i]) + 1;
-		strlcpy(q, sc->group_names[i], tlen);
+		(void)strlcpy(q, sc->group_names[i], tlen);
 		tlen -= slen;
 		q += slen;
 	}
diff --git a/kbfunc.c b/kbfunc.c
index fc70bc9..59a648a 100644
--- a/kbfunc.c
+++ b/kbfunc.c
@@ -25,6 +25,7 @@
 #include <err.h>
 #include <errno.h>
 #include <paths.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -35,7 +36,7 @@
 #define KNOWN_HOSTS	".ssh/known_hosts"
 #define HASH_MARKER	"|1|"
 
-extern int		_xev_quit;
+extern sig_atomic_t	xev_quit;
 
 void
 kbfunc_client_lower(struct client_ctx *cc, union arg *arg)
@@ -49,8 +50,8 @@ kbfunc_client_raise(struct client_ctx *cc, union arg *arg)
 	client_raise(cc);
 }
 
-#define typemask	(CWM_MOVE | CWM_RESIZE | CWM_PTRMOVE)
-#define movemask	(CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
+#define TYPEMASK	(CWM_MOVE | CWM_RESIZE | CWM_PTRMOVE)
+#define MOVEMASK	(CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
 void
 kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
 {
@@ -72,7 +73,7 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
 		amt = amt * 10;
 	}
 
-	switch (flags & movemask) {
+	switch (flags & MOVEMASK) {
 	case CWM_UP:
 		my -= amt;
 		break;
@@ -86,7 +87,7 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
 		mx -= amt;
 		break;
 	}
-	switch (flags & typemask) {
+	switch (flags & TYPEMASK) {
 	case CWM_MOVE:
 		cc->geom.y += my;
 		if (cc->geom.y + cc->geom.height < 0)
@@ -100,6 +101,13 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
 		if (cc->geom.x > cc->sc->xmax - 1)
 			cc->geom.x = cc->sc->xmax - 1;
 
+		cc->geom.x += client_snapcalc(cc->geom.x,
+		    cc->geom.width, cc->sc->xmax,
+		    cc->bwidth, Conf.snapdist);
+		cc->geom.y += client_snapcalc(cc->geom.y,
+		    cc->geom.height, cc->sc->ymax,
+		    cc->bwidth, Conf.snapdist);
+
 		client_move(cc);
 		xu_ptr_getpos(cc->win, &x, &y);
 		cc->ptr.y = y + my;
@@ -150,7 +158,7 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg)
 
 	TAILQ_FOREACH(cc, &Clientq, entry) {
 		mi = xcalloc(1, sizeof(*mi));
-		strlcpy(mi->text, cc->name, sizeof(mi->text));
+		(void)strlcpy(mi->text, cc->name, sizeof(mi->text));
 		mi->ctx = cc;
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
 	}
@@ -185,7 +193,7 @@ kbfunc_menu_search(struct client_ctx *cc, union arg *arg)
 
 	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
 		mi = xcalloc(1, sizeof(*mi));
-		strlcpy(mi->text, cmd->label, sizeof(mi->text));
+		(void)strlcpy(mi->text, cmd->label, sizeof(mi->text));
 		mi->ctx = cmd;
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
 	}
@@ -284,7 +292,7 @@ kbfunc_exec(struct client_ctx *cc, union arg *arg)
 			/* skip everything but regular files and symlinks */
 			if (dp->d_type != DT_REG && dp->d_type != DT_LNK)
 				continue;
-			memset(tpath, '\0', sizeof(tpath));
+			(void)memset(tpath, '\0', sizeof(tpath));
 			l = snprintf(tpath, sizeof(tpath), "%s/%s", paths[i],
 			    dp->d_name);
 			/* check for truncation etc */
@@ -292,7 +300,8 @@ kbfunc_exec(struct client_ctx *cc, union arg *arg)
 				continue;
 			if (access(tpath, X_OK) == 0) {
 				mi = xcalloc(1, sizeof(*mi));
-				strlcpy(mi->text, dp->d_name, sizeof(mi->text));
+				(void)strlcpy(mi->text,
+				    dp->d_name, sizeof(mi->text));
 				TAILQ_INSERT_TAIL(&menuq, mi, entry);
 			}
 		}
@@ -359,7 +368,7 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
 		else {
 			/* EOF without EOL, copy and add the NUL */
 			lbuf = xmalloc(len + 1);
-			memcpy(lbuf, buf, len);
+			(void)memcpy(lbuf, buf, len);
 			lbuf[len] = '\0';
 			buf = lbuf;
 		}
@@ -372,13 +381,13 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
 		/* ignore badness */
 		if (p - buf + 1 > sizeof(hostbuf))
 			continue;
-		(void) strlcpy(hostbuf, buf, p - buf + 1);
+		(void)strlcpy(hostbuf, buf, p - buf + 1);
 		mi = xcalloc(1, sizeof(*mi));
-		(void) strlcpy(mi->text, hostbuf, sizeof(mi->text));
+		(void)strlcpy(mi->text, hostbuf, sizeof(mi->text));
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
 	}
 	xfree(lbuf);
-	fclose(fp);
+	(void)fclose(fp);
 
 	if ((mi = menu_filter(sc, &menuq, "ssh", NULL, 1,
 	    search_match_exec, NULL)) != NULL) {
@@ -491,7 +500,7 @@ kbfunc_client_freeze(struct client_ctx *cc, union arg *arg)
 void
 kbfunc_quit_wm(struct client_ctx *cc, union arg *arg)
 {
-	_xev_quit = 1;
+	xev_quit = 1;
 }
 
 void
diff --git a/menu.c b/menu.c
index 660ff8b..072da10 100644
--- a/menu.c
+++ b/menu.c
@@ -31,8 +31,8 @@
 
 #include "calmwm.h"
 
-#define PROMPT_SCHAR	'»'
-#define PROMPT_ECHAR	'«'
+#define PROMPT_SCHAR	"\xc2\xbb"
+#define PROMPT_ECHAR	"\xc2\xab"
 
 enum ctltype {
 	CTL_NONE = -1,
@@ -76,8 +76,9 @@ menu_init(struct screen_ctx *sc)
 {
 	XGCValues	 gv;
 
-	sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1, 0,
-	    sc->color[CWM_COLOR_BG_MENU].pixel,
+	sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
+	    Conf.bwidth,
+	    sc->color[CWM_COLOR_FG_MENU].pixel,
 	    sc->color[CWM_COLOR_BG_MENU].pixel);
 
 	gv.foreground =
@@ -113,21 +114,21 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
 	ysave = mc.y;
 
 	if (prompt == NULL) {
-		evmask = MenuMask;
+		evmask = MENUMASK;
 		mc.promptstr[0] = '\0';
 		mc.list = 1;
 	} else {
-		evmask = MenuMask | KeyMask; /* only accept keys if prompt */
-		snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%c", prompt,
-		    PROMPT_SCHAR);
-		snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%c", mc.promptstr,
-		    mc.searchstr, PROMPT_ECHAR);
+		evmask = MENUMASK | KEYMASK; /* only accept keys if prompt */
+		(void)snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%s",
+		    prompt, PROMPT_SCHAR);
+		(void)snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%s",
+		    mc.promptstr, mc.searchstr, PROMPT_ECHAR);
 		mc.width = font_width(sc, mc.dispstr, strlen(mc.dispstr));
 		mc.hasprompt = 1;
 	}
 
 	if (initial != NULL)
-		strlcpy(mc.searchstr, initial, sizeof(mc.searchstr));
+		(void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr));
 	else
 		mc.searchstr[0] = '\0';
 
@@ -140,7 +141,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
 	XSelectInput(X_Dpy, sc->menuwin, evmask);
 	XMapRaised(X_Dpy, sc->menuwin);
 
-	if (xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_question) < 0) {
+	if (xu_ptr_grab(sc->menuwin, MENUGRABMASK, Cursor_question) < 0) {
 		XUnmapWindow(X_Dpy, sc->menuwin);
 		return (NULL);
 	}
@@ -268,7 +269,7 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
 		str[0] = chr;
 		str[1] = '\0';
 		mc->changed = 1;
-		strlcat(mc->searchstr, str, sizeof(mc->searchstr));
+		(void)strlcat(mc->searchstr, str, sizeof(mc->searchstr));
 	}
 
 	mc->noresult = 0;
@@ -312,7 +313,7 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
 	mc->width = 0;
 	dy = 0;
 	if (mc->hasprompt) {
-		snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%c",
+		(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s",
 		    mc->promptstr, mc->searchstr, PROMPT_ECHAR);
 		mc->width = font_width(sc, mc->dispstr, strlen(mc->dispstr));
 		dy = font_height(sc);
@@ -405,11 +406,11 @@ menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
 		XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0,
 		    font_height(sc) * mc->prev, mc->width, font_height(sc));
 	if (mc->entry != -1) {
-		xu_ptr_regrab(MenuGrabMask, Cursor_select);
+		(void)xu_ptr_regrab(MENUGRABMASK, Cursor_normal);
 		XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0,
 		    font_height(sc) * mc->entry, mc->width, font_height(sc));
 	} else
-		xu_ptr_regrab(MenuGrabMask, Cursor_default);
+		(void)xu_ptr_regrab(MENUGRABMASK, Cursor_default);
 }
 
 static struct menu *
diff --git a/mousefunc.c b/mousefunc.c
index 04c1931..6e697de 100644
--- a/mousefunc.c
+++ b/mousefunc.c
@@ -55,25 +55,23 @@ mousefunc_sweep_draw(struct client_ctx *cc)
 {
 	struct screen_ctx	*sc = cc->sc;
 	char			 asize[10]; /* fits "nnnnxnnnn\0" */
-	int			 width, height, width_size, width_name;
+	int			 width, width_size, width_name;
 
-	snprintf(asize, sizeof(asize), "%dx%d",
+	(void)snprintf(asize, sizeof(asize), "%dx%d",
 	    (cc->geom.width - cc->geom.basew) / cc->geom.incw,
 	    (cc->geom.height - cc->geom.baseh) / cc->geom.inch);
 	width_size = font_width(sc, asize, strlen(asize)) + 4;
 	width_name = font_width(sc, cc->name, strlen(cc->name)) + 4;
 	width = MAX(width_size, width_name);
-	height = font_ascent(sc) + font_descent(sc) + 1;
 
-	XMoveResizeWindow(X_Dpy, sc->menuwin, cc->geom.x, cc->geom.y,
-	    width, height * 2);
-	XMapWindow(X_Dpy, sc->menuwin);
 	XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0);
+	XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0, width, font_height(sc) * 2);
+	XMapWindow(X_Dpy, sc->menuwin);
 	XClearWindow(X_Dpy, sc->menuwin);
 	font_draw(sc, cc->name, strlen(cc->name), sc->menuwin,
 	    2, font_ascent(sc) + 1);
 	font_draw(sc, asize, strlen(asize), sc->menuwin,
-	    width / 2 - width_size / 2, height + font_ascent(sc) + 1);
+	    width / 2 - width_size / 2, font_height(sc) + font_ascent(sc) + 1);
 }
 
 void
@@ -90,14 +88,14 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg)
 	client_raise(cc);
 	client_ptrsave(cc);
 
-	if (xu_ptr_grab(cc->win, MouseMask, Cursor_resize) < 0)
+	if (xu_ptr_grab(cc->win, MOUSEMASK, Cursor_resize) < 0)
 		return;
 
 	xu_ptr_setpos(cc->win, cc->geom.width, cc->geom.height);
 	mousefunc_sweep_draw(cc);
 
 	for (;;) {
-		XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
+		XMaskEvent(X_Dpy, MOUSEMASK|ExposureMask, &ev);
 
 		switch (ev.type) {
 		case Expose:
@@ -146,13 +144,13 @@ mousefunc_window_move(struct client_ctx *cc, void *arg)
 	if (cc->flags & CLIENT_FREEZE)
 		return;
 
-	if (xu_ptr_grab(cc->win, MouseMask, Cursor_move) < 0)
+	if (xu_ptr_grab(cc->win, MOUSEMASK, Cursor_move) < 0)
 		return;
 
 	xu_ptr_getpos(cc->win, &px, &py);
 
 	for (;;) {
-		XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
+		XMaskEvent(X_Dpy, MOUSEMASK|ExposureMask, &ev);
 
 		switch (ev.type) {
 		case Expose:
@@ -162,6 +160,13 @@ mousefunc_window_move(struct client_ctx *cc, void *arg)
 			cc->geom.x = ev.xmotion.x_root - px - cc->bwidth;
 			cc->geom.y = ev.xmotion.y_root - py - cc->bwidth;
 
+			cc->geom.x += client_snapcalc(cc->geom.x,
+			    cc->geom.width, cc->sc->xmax,
+			    cc->bwidth, Conf.snapdist);
+			cc->geom.y += client_snapcalc(cc->geom.y,
+			    cc->geom.height, cc->sc->ymax,
+			    cc->bwidth, Conf.snapdist);
+
 			/* don't move more than 60 times / second */
 			if ((ev.xmotion.time - time) > (1000 / 60)) {
 				time = ev.xmotion.time;
@@ -192,6 +197,12 @@ mousefunc_window_lower(struct client_ctx *cc, void *arg)
 }
 
 void
+mousefunc_window_raise(struct client_ctx *cc, void *arg)
+{
+	client_raise(cc);
+}
+
+void
 mousefunc_window_hide(struct client_ctx *cc, void *arg)
 {
 	client_hide(cc);
@@ -223,7 +234,7 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
 				continue;
 
 			mi = xcalloc(1, sizeof(*mi));
-			strlcpy(mi->text, wname, sizeof(mi->text));
+			(void)strlcpy(mi->text, wname, sizeof(mi->text));
 			mi->ctx = cc;
 			TAILQ_INSERT_TAIL(&menuq, mi, entry);
 		}
@@ -260,7 +271,7 @@ mousefunc_menu_cmd(struct client_ctx *cc, void *arg)
 	TAILQ_INIT(&menuq);
 	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
 		mi = xcalloc(1, sizeof(*mi));
-		strlcpy(mi->text, cmd->label, sizeof(mi->text));
+		(void)strlcpy(mi->text, cmd->label, sizeof(mi->text));
 		mi->ctx = cmd;
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
 	}
diff --git a/parse.y b/parse.y
index d86c4e1..a31a6c2 100644
--- a/parse.y
+++ b/parse.y
@@ -70,7 +70,7 @@ typedef struct {
 %token	FONTNAME STICKY GAP MOUSEBIND
 %token	AUTOGROUP BIND COMMAND IGNORE
 %token	YES NO BORDERWIDTH MOVEAMOUNT
-%token	COLOR
+%token	COLOR SNAPDIST
 %token	ACTIVEBORDER INACTIVEBORDER
 %token	GROUPBORDER UNGROUPBORDER
 %token	ERROR
@@ -120,6 +120,9 @@ main		: FONTNAME STRING		{
 		| MOVEAMOUNT NUMBER {
 			conf->mamount = $2;
 		}
+		| SNAPDIST NUMBER {
+			conf->snapdist = $2;
+		}
 		| COMMAND STRING string		{
 			conf_cmd_add(conf, $3, $2, 0);
 			free($2);
@@ -139,7 +142,7 @@ main		: FONTNAME STRING		{
 			struct winmatch	*wm;
 
 			wm = xcalloc(1, sizeof(*wm));
-			strlcpy(wm->title, $2, sizeof(wm->title));
+			(void)strlcpy(wm->title, $2, sizeof(wm->title));
 			TAILQ_INSERT_TAIL(&conf->ignoreq, wm, entry);
 
 			free($2);
@@ -166,8 +169,8 @@ color		: COLOR colors
 		;
 
 colors		: ACTIVEBORDER STRING {
-			free(conf->color[CWM_COLOR_BORDOR_ACTIVE].name);
-			conf->color[CWM_COLOR_BORDOR_ACTIVE].name = $2;
+			free(conf->color[CWM_COLOR_BORDER_ACTIVE].name);
+			conf->color[CWM_COLOR_BORDER_ACTIVE].name = $2;
 		}
 		| INACTIVEBORDER STRING {
 			free(conf->color[CWM_COLOR_BORDER_INACTIVE].name);
@@ -228,6 +231,7 @@ lookup(char *s)
 		{ "mousebind",		MOUSEBIND},
 		{ "moveamount",		MOVEAMOUNT},
 		{ "no",			NO},
+		{ "snapdist",		SNAPDIST},
 		{ "sticky",		STICKY},
 		{ "ungroupborder",	UNGROUPBORDER},
 		{ "yes",		YES}
@@ -498,7 +502,7 @@ parse_config(const char *filename, struct conf *xconf)
 		return (-1);
 	}
 
-	strlcpy(conf->conf_path, filename, sizeof(conf->conf_path));
+	(void)strlcpy(conf->conf_path, filename, sizeof(conf->conf_path));
 
 	conf_init(conf);
 
@@ -523,6 +527,7 @@ parse_config(const char *filename, struct conf *xconf)
 		xconf->flags = conf->flags;
 		xconf->bwidth = conf->bwidth;
 		xconf->mamount = conf->mamount;
+		xconf->snapdist = conf->snapdist;
 		xconf->gap = conf->gap;
 
 		while ((cmd = TAILQ_FIRST(&conf->cmdq)) != NULL) {
@@ -550,9 +555,9 @@ parse_config(const char *filename, struct conf *xconf)
 			TAILQ_INSERT_TAIL(&xconf->mousebindingq, mb, entry);
 		}
 
-		strlcpy(xconf->termpath, conf->termpath,
+		(void)strlcpy(xconf->termpath, conf->termpath,
 		    sizeof(xconf->termpath));
-		strlcpy(xconf->lockpath, conf->lockpath,
+		(void)strlcpy(xconf->lockpath, conf->lockpath,
 		    sizeof(xconf->lockpath));
 
 		for (i = 0; i < CWM_COLOR_MAX; i++)
diff --git a/search.c b/search.c
index 6ec37b5..8d58067 100644
--- a/search.c
+++ b/search.c
@@ -46,7 +46,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
 
 	TAILQ_INIT(resultq);
 
-	memset(tierp, 0, sizeof(tierp));
+	(void)memset(tierp, 0, sizeof(tierp));
 
 	/*
 	 * In order of rank:
@@ -134,7 +134,8 @@ search_print_client(struct menu *mi, int list)
 	if (list)
 		cc->matchname = cc->name;
 
-	snprintf(mi->print, sizeof(mi->print), "%c%s", flag, cc->matchname);
+	(void)snprintf(mi->print, sizeof(mi->print), "%c%s", flag,
+	    cc->matchname);
 
 	if (!list && cc->matchname != cc->name &&
 	    strlen(mi->print) < sizeof(mi->print) - 1) {
@@ -154,8 +155,8 @@ search_print_client(struct menu *mi, int list)
 			diff = strlen(cc->name);
 		}
 
-		strlcpy(buf, mi->print, sizeof(buf));
-		snprintf(mi->print, sizeof(mi->print),
+		(void)strlcpy(buf, mi->print, sizeof(buf));
+		(void)snprintf(mi->print, sizeof(mi->print),
 		    "%s:%.*s%s", buf, diff, cc->name, marker);
 	}
 }
diff --git a/util.c b/util.c
index be4b68a..54faaea 100644
--- a/util.c
+++ b/util.c
@@ -32,7 +32,7 @@
 
 #define MAXARGLEN 20
 
-int
+void
 u_spawn(char *argstr)
 {
 	switch (fork()) {
@@ -42,12 +42,9 @@ u_spawn(char *argstr)
 		break;
 	case -1:
 		warn("fork");
-		return (-1);
 	default:
 		break;
 	}
-
-	return (0);
 }
 
 void
@@ -79,6 +76,6 @@ u_exec(char *argstr)
 	}
 
 	*ap = NULL;
-	setsid();
-	execvp(args[0], args);
+	(void)setsid();
+	(void)execvp(args[0], args);
 }
diff --git a/xevents.c b/xevents.c
index 1cdd22e..9ee3c46 100644
--- a/xevents.c
+++ b/xevents.c
@@ -411,14 +411,14 @@ xev_handle_expose(XEvent *ee)
 		client_draw_border(cc);
 }
 
-volatile sig_atomic_t	_xev_quit = 0;
+volatile sig_atomic_t	xev_quit = 0;
 
 void
 xev_loop(void)
 {
 	XEvent		 e;
 
-	while (_xev_quit == 0) {
+	while (xev_quit == 0) {
 		XNextEvent(X_Dpy, &e);
 		if (e.type - Randr_ev == RRScreenChangeNotify)
 			xev_handle_randr(&e);
diff --git a/xutil.c b/xutil.c
index 3d0132d..84ef1d8 100644
--- a/xutil.c
+++ b/xutil.c
@@ -59,7 +59,7 @@ xu_btn_grab(Window win, int mask, u_int btn)
 	int	i;
 	for (i = 0; i < nitems(ign_mods); i++)
 		XGrabButton(X_Dpy, btn, (mask | ign_mods[i]), win,
-		    False, ButtonMask, GrabModeAsync,
+		    False, BUTTONMASK, GrabModeAsync,
 		    GrabModeSync, None, None);
 }
 
@@ -142,7 +142,7 @@ xu_sendmsg(Window win, Atom atm, long val)
 {
 	XEvent	 e;
 
-	memset(&e, 0, sizeof(e));
+	(void)memset(&e, 0, sizeof(e));
 	e.xclient.type = ClientMessage;
 	e.xclient.window = win;
 	e.xclient.message_type = atm;