summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--calmwm.c27
-rw-r--r--calmwm.h242
-rw-r--r--client.c12
-rw-r--r--conf.c306
-rw-r--r--group.c22
-rw-r--r--kbfunc.c336
-rw-r--r--mousefunc.c6
-rw-r--r--screen.c8
-rw-r--r--search.c4
-rw-r--r--xevents.c50
10 files changed, 508 insertions, 505 deletions
diff --git a/calmwm.c b/calmwm.c
index a6c5bc4..25df3b8 100644
--- a/calmwm.c
+++ b/calmwm.c
@@ -36,18 +36,14 @@
 
 #include "calmwm.h"
 
-Display				*X_Dpy;
-Time				 Last_Event_Time = CurrentTime;
-Atom				 cwmh[CWMH_NITEMS];
-Atom				 ewmh[EWMH_NITEMS];
-
-struct screen_ctx_q		 Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
-
-int				 HasRandr, Randr_ev;
-struct conf			 Conf;
-const char			*homedir;
-char				*wm_argv;
-volatile sig_atomic_t		 cwm_status;
+Display			*X_Dpy;
+Time			 Last_Event_Time = CurrentTime;
+Atom			 cwmh[CWMH_NITEMS];
+Atom			 ewmh[EWMH_NITEMS];
+struct screen_q		 Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
+struct conf		 Conf;
+const char		*homedir;
+volatile sig_atomic_t	 cwm_status;
 
 static void	sighdlr(int);
 static int	x_errorhandler(Display *, XErrorEvent *);
@@ -67,7 +63,7 @@ main(int argc, char **argv)
 		warnx("no locale support");
 	mbtowc(NULL, NULL, MB_CUR_MAX);
 
-	wm_argv = u_argv(argv);
+	Conf.wm_argv = u_argv(argv);
 	while ((ch = getopt(argc, argv, "c:d:")) != -1) {
 		switch (ch) {
 		case 'c':
@@ -107,6 +103,7 @@ main(int argc, char **argv)
 	}
 
 	conf_init(&Conf);
+
 	if (conf_path && (parse_config(conf_path, &Conf) == -1))
 		warnx("config file %s has errors", conf_path);
 	free(conf_path);
@@ -121,7 +118,7 @@ main(int argc, char **argv)
 		xev_process();
 	x_teardown();
 	if (cwm_status == CWM_EXEC_WM)
-		u_exec(wm_argv);
+		u_exec(Conf.wm_argv);
 
 	return(0);
 }
@@ -139,7 +136,7 @@ x_init(const char *dpyname)
 	XSync(X_Dpy, False);
 	XSetErrorHandler(x_errorhandler);
 
-	HasRandr = XRRQueryExtension(X_Dpy, &Randr_ev, &i);
+	Conf.xrandr = XRRQueryExtension(X_Dpy, &Conf.xrandr_event_base, &i);
 
 	conf_atoms();
 	conf_cursor(&Conf);
diff --git a/calmwm.h b/calmwm.h
index c8a7f70..f6542a7 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -57,41 +57,14 @@
 #define CWM_BIGAMOUNT		0x0010
 #define DIRECTIONMASK	(CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
 
-#define CWM_CLIENT_CYCLE	0x0001
-#define CWM_CLIENT_RCYCLE	0x0002
-#define CWM_CLIENT_CYCLE_INGRP	0x0004
-
-#define CWM_CLIENT_TILE_HORIZ	0x0001
-#define CWM_CLIENT_TILE_VERT	0x0002
-
-#define CWM_MENU_EXEC		0x0001
-#define CWM_MENU_EXEC_WM	0x0002
-
-#define CWM_MENU_DUMMY		0x0001
-#define CWM_MENU_FILE		0x0002
-#define CWM_MENU_LIST		0x0004
-
-#define CWM_GAP			0x0001
-#define CWM_NOGAP		0x0002
-
-#define CWM_KEY			0x0001
-#define CWM_BTN			0x0002
-
-#define CWM_CONTEXT_NONE	0x0000
-#define CWM_CONTEXT_CLIENT	0x0001
-#define CWM_CONTEXT_SCREEN	0x0002
-
-#define CWM_QUIT		0x0000
-#define CWM_RUNNING		0x0001
-#define CWM_EXEC_WM		0x0002
-
-union arg {
-	char	*c;
-	int	 i;
-};
-union press {
-	KeySym		 keysym;
-	unsigned int	 button;
+#define CWM_CYCLE_FORWARD	0x0001
+#define CWM_CYCLE_REVERSE	0x0002
+#define CWM_CYCLE_INGROUP	0x0004
+
+enum cwm_status {
+	CWM_QUIT,
+	CWM_RUNNING,
+	CWM_EXEC_WM
 };
 
 enum cursor_font {
@@ -121,6 +94,10 @@ struct geom {
 	int		 h;
 };
 
+enum apply_gap {
+	CWM_NOGAP = 0,
+	CWM_GAP
+};
 struct gap {
 	int		 top;
 	int		 bottom;
@@ -132,7 +109,7 @@ struct winname {
 	TAILQ_ENTRY(winname)	 entry;
 	char			*name;
 };
-TAILQ_HEAD(winname_q, winname);
+TAILQ_HEAD(name_q, winname);
 TAILQ_HEAD(ignore_q, winname);
 
 struct client_ctx {
@@ -185,31 +162,31 @@ struct client_ctx {
 #define CLIENT_MAXIMIZED		(CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
 	int			 flags;
 	int			 stackingorder;
-	struct winname_q	 nameq;
+	struct name_q		 nameq;
 	char			*name;
 	char			*label;
 	char			*matchname;
 	XClassHint		ch;
 	XWMHints		*wmh;
 };
-TAILQ_HEAD(client_ctx_q, client_ctx);
+TAILQ_HEAD(client_q, client_ctx);
 
 struct group_ctx {
 	TAILQ_ENTRY(group_ctx)	 entry;
 	struct screen_ctx	*sc;
 	char			*name;
 	int			 num;
-	struct client_ctx_q	 clientq;
+	struct client_q		 clientq;
 };
-TAILQ_HEAD(group_ctx_q, group_ctx);
+TAILQ_HEAD(group_q, group_ctx);
 
-struct autogroupwin {
-	TAILQ_ENTRY(autogroupwin)	 entry;
-	char				*class;
-	char				*name;
-	int 				 num;
+struct autogroup {
+	TAILQ_ENTRY(autogroup)	 entry;
+	char			*class;
+	char			*name;
+	int 			 num;
 };
-TAILQ_HEAD(autogroupwin_q, autogroupwin);
+TAILQ_HEAD(autogroup_q, autogroup);
 
 struct region_ctx {
 	TAILQ_ENTRY(region_ctx)	 entry;
@@ -218,7 +195,7 @@ struct region_ctx {
 	struct geom		 view; /* viewable area */
 	struct geom		 work; /* workable area, gap-applied */
 };
-TAILQ_HEAD(region_ctx_q, region_ctx);
+TAILQ_HEAD(region_q, region_ctx);
 
 struct screen_ctx {
 	TAILQ_ENTRY(screen_ctx)	 entry;
@@ -230,9 +207,9 @@ struct screen_ctx {
 	struct geom		 view; /* viewable area */
 	struct geom		 work; /* workable area, gap-applied */
 	struct gap		 gap;
-	struct client_ctx_q	 clientq;
-	struct region_ctx_q	 regionq;
-	struct group_ctx_q	 groupq;
+	struct client_q		 clientq;
+	struct region_q		 regionq;
+	struct group_q		 groupq;
 	struct group_ctx	*group_active;
 	struct {
 		Window		 win;
@@ -241,25 +218,50 @@ struct screen_ctx {
 	XftColor		 xftcolor[CWM_COLOR_NITEMS];
 	XftFont			*xftfont;
 };
-TAILQ_HEAD(screen_ctx_q, screen_ctx);
+TAILQ_HEAD(screen_q, screen_ctx);
 
-struct binding {
-	TAILQ_ENTRY(binding)	 entry;
-	void			(*callback)(struct client_ctx *, union arg *, int);
+enum xev {
+	CWM_XEV_KEY,
+	CWM_XEV_BTN
+};
+union arg {
+	char	*c;
+	int	 i;
+};
+union press {
+	KeySym		 keysym;
+	unsigned int	 button;
+};
+enum context {
+	CWM_CONTEXT_NONE,
+	CWM_CONTEXT_CC,
+	CWM_CONTEXT_SC
+};
+struct bind_ctx {
+	TAILQ_ENTRY(bind_ctx)	 entry;
+	void			(*callback)(void *, union arg *, enum xev);
 	union arg		 argument;
 	unsigned int		 modmask;
 	union press		 press;
-	int			 context;
+	enum context		 context;
 };
-TAILQ_HEAD(keybinding_q, binding);
-TAILQ_HEAD(mousebinding_q, binding);
+TAILQ_HEAD(keybind_q, bind_ctx);
+TAILQ_HEAD(mousebind_q, bind_ctx);
 
-struct cmd {
-	TAILQ_ENTRY(cmd)	 entry;
+struct cmd_ctx {
+	TAILQ_ENTRY(cmd_ctx)	 entry;
 	char			*name;
 	char			 path[PATH_MAX];
 };
-TAILQ_HEAD(cmd_q, cmd);
+TAILQ_HEAD(cmd_q, cmd_ctx);
+
+enum menu_exec {
+	CWM_MENU_EXEC_EXEC,
+	CWM_MENU_EXEC_WM
+};
+#define CWM_MENU_DUMMY		0x0001
+#define CWM_MENU_FILE		0x0002
+#define CWM_MENU_LIST		0x0004
 
 struct menu {
 	TAILQ_ENTRY(menu)	 entry;
@@ -274,9 +276,9 @@ struct menu {
 TAILQ_HEAD(menu_q, menu);
 
 struct conf {
-	struct keybinding_q	 keybindingq;
-	struct mousebinding_q	 mousebindingq;
-	struct autogroupwin_q	 autogroupq;
+	struct keybind_q	 keybindq;
+	struct mousebind_q	 mousebindq;
+	struct autogroup_q	 autogroupq;
 	struct ignore_q		 ignoreq;
 	struct cmd_q		 cmdq;
 	int			 ngroups;
@@ -291,6 +293,9 @@ struct conf {
 	char			*font;
 	char			*wmname;
 	Cursor			 cursor[CF_NITEMS];
+	int			 xrandr;
+	int			 xrandr_event_base;
+	char			*wm_argv;
 };
 
 /* MWM hints */
@@ -321,15 +326,7 @@ struct mwm_hints {
 	unsigned long	decorations;
 };
 
-extern Display				*X_Dpy;
-extern Time				 Last_Event_Time;
-extern struct screen_ctx_q		 Screenq;
-extern struct conf			 Conf;
-extern char				*wm_argv;
-extern const char			*homedir;
-extern int				 HasRandr, Randr_ev;
-
-enum {
+enum cwmh {
 	WM_STATE,
 	WM_DELETE_WINDOW,
 	WM_TAKE_FOCUS,
@@ -339,7 +336,7 @@ enum {
 	WM_CHANGE_STATE,
 	CWMH_NITEMS
 };
-enum {
+enum ewmh {
 	_NET_SUPPORTED,
 	_NET_SUPPORTING_WM_CHECK,
 	_NET_ACTIVE_WINDOW,
@@ -367,13 +364,19 @@ enum {
 	_CWM_WM_STATE_FREEZE,
 	EWMH_NITEMS
 };
-enum {
+enum net_wm_state {
 	_NET_WM_STATE_REMOVE,
 	_NET_WM_STATE_ADD,
 	_NET_WM_STATE_TOGGLE
 };
+
+extern Display				*X_Dpy;
+extern Time				 Last_Event_Time;
 extern Atom				 cwmh[CWMH_NITEMS];
 extern Atom				 ewmh[EWMH_NITEMS];
+extern struct screen_q			 Screenq;
+extern struct conf			 Conf;
+extern const char			*homedir;
 
 __dead void		 usage(void);
 
@@ -451,57 +454,56 @@ void			 search_print_group(struct menu *, int);
 struct region_ctx	*region_find(struct screen_ctx *, int, int);
 struct geom		 screen_apply_gap(struct screen_ctx *, struct geom);
 struct screen_ctx	*screen_find(Window);
-struct geom		 screen_area(struct screen_ctx *, int, int, int);
+struct geom		 screen_area(struct screen_ctx *, int, int,
+			     enum apply_gap);
 void			 screen_init(int);
 void			 screen_update_geometry(struct screen_ctx *);
 void			 screen_updatestackingorder(struct screen_ctx *);
 void			 screen_assert_clients_within(struct screen_ctx *);
 
-void			 kbfunc_client_cycle(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_delete(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_hide(struct client_ctx *, union arg *, int);
-void			 kbfunc_menu_client_label(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_lower(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_move(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_movetogroup(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_client_raise(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_resize(struct client_ctx *, union arg *, int);
-void 			 kbfunc_client_tile(struct client_ctx *, union arg *, int);
-void			 kbfunc_client_toggle_group(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_client_toggle_freeze(struct client_ctx *,
-    			     union arg *, int);
-void			 kbfunc_client_toggle_fullscreen(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_client_toggle_hmaximize(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_client_toggle_maximize(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_client_toggle_sticky(struct client_ctx *,
-    			     union arg *, int);
-void			 kbfunc_client_toggle_vmaximize(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_cwm_status(struct client_ctx *, union arg *, int);
-void			 kbfunc_exec(struct client_ctx *, union arg *, int);
-void			 kbfunc_exec_lock(struct client_ctx *, union arg *, int);
-void			 kbfunc_exec_term(struct client_ctx *, union arg *, int);
-void			 kbfunc_group_alltoggle(struct client_ctx *,
-			     union arg *, int);
-void			 kbfunc_group_cycle(struct client_ctx *, union arg *, int);
-void			 kbfunc_group_only(struct client_ctx *, union arg *, int);
-void			 kbfunc_group_toggle(struct client_ctx *, union arg *, int);
-void			 kbfunc_menu_exec(struct client_ctx *, union arg *, int);
-void			 kbfunc_menu_client(struct client_ctx *, union arg *, int);
-void			 kbfunc_menu_cmd(struct client_ctx *, union arg *, int);
-void			 kbfunc_menu_group(struct client_ctx *, union arg *, int);
-void			 kbfunc_menu_ssh(struct client_ctx *, union arg *, int);
-void			 kbfunc_ptrmove(struct client_ctx *, union arg *, int);
-
-void			 mousefunc_client_move(struct client_ctx *,
-    			    union arg *, int);
-void			 mousefunc_client_resize(struct client_ctx *,
-    			    union arg *, int);
+void			 kbfunc_cwm_status(void *, union arg *, enum xev);
+void			 kbfunc_ptrmove(void *, union arg *, enum xev);
+void			 kbfunc_client_move(void *, union arg *, enum xev);
+void			 kbfunc_client_resize(void *, union arg *, enum xev);
+void			 kbfunc_client_delete(void *, union arg *, enum xev);
+void			 kbfunc_client_lower(void *, union arg *, enum xev);
+void			 kbfunc_client_raise(void *, union arg *, enum xev);
+void			 kbfunc_client_hide(void *, union arg *, enum xev);
+void			 kbfunc_client_toggle_freeze(void *,
+			     union arg *, enum xev);
+void			 kbfunc_client_toggle_sticky(void *,
+			     union arg *, enum xev);
+void			 kbfunc_client_toggle_fullscreen(void *,
+			     union arg *, enum xev);
+void			 kbfunc_client_toggle_maximize(void *,
+			     union arg *, enum xev);
+void			 kbfunc_client_toggle_hmaximize(void *,
+			     union arg *, enum xev);
+void			 kbfunc_client_toggle_vmaximize(void *,
+			     union arg *, enum xev);
+void 			 kbfunc_client_htile(void *, union arg *, enum xev);
+void 			 kbfunc_client_vtile(void *, union arg *, enum xev);
+void			 kbfunc_client_cycle(void *, union arg *, enum xev);
+void			 kbfunc_client_toggle_group(void *,
+			     union arg *, enum xev);
+void			 kbfunc_client_movetogroup(void *,
+			     union arg *, enum xev);
+void			 kbfunc_group_toggle(void *, union arg *, enum xev);
+void			 kbfunc_group_only(void *, union arg *, enum xev);
+void			 kbfunc_group_cycle(void *, union arg *, enum xev);
+void			 kbfunc_group_alltoggle(void *, union arg *, enum xev);
+void			 kbfunc_menu_client(void *, union arg *, enum xev);
+void			 kbfunc_menu_cmd(void *, union arg *, enum xev);
+void			 kbfunc_menu_group(void *, union arg *, enum xev);
+void			 kbfunc_menu_exec(void *, union arg *, enum xev);
+void			 kbfunc_menu_ssh(void *, union arg *, enum xev);
+void			 kbfunc_menu_client_label(void *, union arg *, enum xev);
+void			 kbfunc_exec_cmd(void *, union arg *, enum xev);
+void			 kbfunc_exec_lock(void *, union arg *, enum xev);
+void			 kbfunc_exec_term(void *, union arg *, enum xev);
+
+void			 mousefunc_client_move(void *, union arg *, enum xev);
+void			 mousefunc_client_resize(void *, union arg *, enum xev);
 
 void			 menu_windraw(struct screen_ctx *, Window,
 			     const char *, ...);
diff --git a/client.c b/client.c
index ab84b9a..58d7f88 100644
--- a/client.c
+++ b/client.c
@@ -653,20 +653,20 @@ client_cycle(struct screen_ctx *sc, int flags)
 
 	oldcc = client_current();
 	if (oldcc == NULL)
-		oldcc = (flags & CWM_CLIENT_RCYCLE) ?
-		    TAILQ_LAST(&sc->clientq, client_ctx_q) :
+		oldcc = (flags & CWM_CYCLE_REVERSE) ?
+		    TAILQ_LAST(&sc->clientq, client_q) :
 		    TAILQ_FIRST(&sc->clientq);
 
 	newcc = oldcc;
 	while (again) {
 		again = 0;
 
-		newcc = (flags & CWM_CLIENT_RCYCLE) ? client_prev(newcc) :
+		newcc = (flags & CWM_CYCLE_REVERSE) ? client_prev(newcc) :
 		    client_next(newcc);
 
 		/* Only cycle visible and non-ignored windows. */
 		if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE))
-		    || ((flags & CWM_CLIENT_CYCLE_INGRP) &&
+		    || ((flags & CWM_CYCLE_INGROUP) &&
 			(newcc->gc != oldcc->gc)))
 			again = 1;
 
@@ -721,8 +721,8 @@ client_prev(struct client_ctx *cc)
 	struct screen_ctx	*sc = cc->sc;
 	struct client_ctx	*newcc;
 
-	return(((newcc = TAILQ_PREV(cc, client_ctx_q, entry)) != NULL) ?
-	    newcc : TAILQ_LAST(&sc->clientq, client_ctx_q));
+	return(((newcc = TAILQ_PREV(cc, client_q, entry)) != NULL) ?
+	    newcc : TAILQ_LAST(&sc->clientq, client_q));
 }
 
 static void
diff --git a/conf.c b/conf.c
index 3d95fea..156bb71 100644
--- a/conf.c
+++ b/conf.c
@@ -34,13 +34,13 @@
 
 static const char	*conf_bind_getmask(const char *, unsigned int *);
 static void		 conf_cmd_remove(struct conf *, const char *);
-static void		 conf_unbind_kbd(struct conf *, struct binding *);
-static void		 conf_unbind_mouse(struct conf *, struct binding *);
+static void		 conf_unbind_kbd(struct conf *, struct bind_ctx *);
+static void		 conf_unbind_mouse(struct conf *, struct bind_ctx *);
 
 int
 conf_cmd_add(struct conf *c, const char *name, const char *path)
 {
-	struct cmd	*cmd;
+	struct cmd_ctx	*cmd;
 
 	cmd = xmalloc(sizeof(*cmd));
 
@@ -61,7 +61,7 @@ conf_cmd_add(struct conf *c, const char *name, const char *path)
 static void
 conf_cmd_remove(struct conf *c, const char *name)
 {
-	struct cmd	*cmd = NULL, *cmdnxt;
+	struct cmd_ctx	*cmd = NULL, *cmdnxt;
 
 	TAILQ_FOREACH_SAFE(cmd, &c->cmdq, entry, cmdnxt) {
 		if (strcmp(cmd->name, name) == 0) {
@@ -74,31 +74,31 @@ conf_cmd_remove(struct conf *c, const char *name)
 void
 conf_autogroup(struct conf *c, int num, const char *name, const char *class)
 {
-	struct autogroupwin	*aw;
+	struct autogroup	*ag;
 	char			*p;
 
-	aw = xmalloc(sizeof(*aw));
+	ag = xmalloc(sizeof(*ag));
 
 	if ((p = strchr(class, ',')) == NULL) {
 		if (name == NULL)
-			aw->name = NULL;
+			ag->name = NULL;
 		else
-			aw->name = xstrdup(name);
+			ag->name = xstrdup(name);
 
-		aw->class = xstrdup(class);
+		ag->class = xstrdup(class);
 	} else {
 		*(p++) = '\0';
 
 		if (name == NULL)
-			aw->name = xstrdup(class);
+			ag->name = xstrdup(class);
 		else
-			aw->name = xstrdup(name);
+			ag->name = xstrdup(name);
 
-		aw->class = xstrdup(p);
+		ag->class = xstrdup(p);
 	}
-	aw->num = num;
+	ag->num = num;
 
-	TAILQ_INSERT_TAIL(&c->autogroupq, aw, entry);
+	TAILQ_INSERT_TAIL(&c->autogroupq, ag, entry);
 }
 
 void
@@ -264,9 +264,9 @@ conf_init(struct conf *c)
 
 	TAILQ_INIT(&c->ignoreq);
 	TAILQ_INIT(&c->cmdq);
-	TAILQ_INIT(&c->keybindingq);
+	TAILQ_INIT(&c->keybindq);
 	TAILQ_INIT(&c->autogroupq);
-	TAILQ_INIT(&c->mousebindingq);
+	TAILQ_INIT(&c->mousebindq);
 
 	for (i = 0; i < nitems(kbd_binds); i++)
 		conf_bind_kbd(c, kbd_binds[i].key, kbd_binds[i].func);
@@ -290,10 +290,10 @@ conf_init(struct conf *c)
 void
 conf_clear(struct conf *c)
 {
-	struct autogroupwin	*aw;
-	struct binding		*kb, *mb;
+	struct autogroup	*ag;
+	struct bind_ctx		*kb, *mb;
 	struct winname		*wn;
-	struct cmd		*cmd;
+	struct cmd_ctx		*cmd;
 	int			 i;
 
 	while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) {
@@ -302,16 +302,16 @@ conf_clear(struct conf *c)
 		free(cmd);
 	}
 
-	while ((kb = TAILQ_FIRST(&c->keybindingq)) != NULL) {
-		TAILQ_REMOVE(&c->keybindingq, kb, entry);
+	while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) {
+		TAILQ_REMOVE(&c->keybindq, kb, entry);
 		free(kb);
 	}
 
-	while ((aw = TAILQ_FIRST(&c->autogroupq)) != NULL) {
-		TAILQ_REMOVE(&c->autogroupq, aw, entry);
-		free(aw->class);
-		free(aw->name);
-		free(aw);
+	while ((ag = TAILQ_FIRST(&c->autogroupq)) != NULL) {
+		TAILQ_REMOVE(&c->autogroupq, ag, entry);
+		free(ag->class);
+		free(ag->name);
+		free(ag);
 	}
 
 	while ((wn = TAILQ_FIRST(&c->ignoreq)) != NULL) {
@@ -320,8 +320,8 @@ conf_clear(struct conf *c)
 		free(wn);
 	}
 
-	while ((mb = TAILQ_FIRST(&c->mousebindingq)) != NULL) {
-		TAILQ_REMOVE(&c->mousebindingq, mb, entry);
+	while ((mb = TAILQ_FIRST(&c->mousebindq)) != NULL) {
+		TAILQ_REMOVE(&c->mousebindq, mb, entry);
 		free(mb);
 	}
 
@@ -351,147 +351,133 @@ conf_client(struct client_ctx *cc)
 
 static const struct {
 	const char	*tag;
-	void		 (*handler)(struct client_ctx *, union arg *, int);
+	void		 (*handler)(void *, union arg *, enum xev);
 	int		 context;
 	union arg	 argument;
 } name_to_func[] = {
-	{ "lower", kbfunc_client_lower, CWM_CONTEXT_CLIENT, {0} },
-	{ "raise", kbfunc_client_raise, CWM_CONTEXT_CLIENT, {0} },
-	{ "search", kbfunc_menu_client, CWM_CONTEXT_SCREEN, {0} },
-	{ "menusearch", kbfunc_menu_cmd, CWM_CONTEXT_SCREEN, {0} },
-	{ "groupsearch", kbfunc_menu_group, CWM_CONTEXT_SCREEN, {0} },
-	{ "hide", kbfunc_client_hide, CWM_CONTEXT_CLIENT, {0} },
-	{ "cycle", kbfunc_client_cycle, CWM_CONTEXT_SCREEN,
-	    {.i = CWM_CLIENT_CYCLE} },
-	{ "rcycle", kbfunc_client_cycle, CWM_CONTEXT_SCREEN,
-	    {.i = CWM_CLIENT_RCYCLE} },
-	{ "label", kbfunc_menu_client_label, CWM_CONTEXT_CLIENT, {0} },
-	{ "delete", kbfunc_client_delete, CWM_CONTEXT_CLIENT, {0} },
-	{ "group1", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 1} },
-	{ "group2", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 2} },
-	{ "group3", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 3} },
-	{ "group4", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 4} },
-	{ "group5", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 5} },
-	{ "group6", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 6} },
-	{ "group7", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 7} },
-	{ "group8", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 8} },
-	{ "group9", kbfunc_group_toggle, CWM_CONTEXT_SCREEN, {.i = 9} },
-	{ "grouponly1", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 1} },
-	{ "grouponly2", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 2} },
-	{ "grouponly3", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 3} },
-	{ "grouponly4", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 4} },
-	{ "grouponly5", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 5} },
-	{ "grouponly6", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 6} },
-	{ "grouponly7", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 7} },
-	{ "grouponly8", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 8} },
-	{ "grouponly9", kbfunc_group_only, CWM_CONTEXT_SCREEN, {.i = 9} },
-	{ "movetogroup1", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 1} },
-	{ "movetogroup2", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 2} },
-	{ "movetogroup3", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 3} },
-	{ "movetogroup4", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 4} },
-	{ "movetogroup5", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 5} },
-	{ "movetogroup6", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 6} },
-	{ "movetogroup7", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 7} },
-	{ "movetogroup8", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 8} },
-	{ "movetogroup9", kbfunc_client_movetogroup, CWM_CONTEXT_CLIENT,
-	    {.i = 9} },
-	{ "nogroup", kbfunc_group_alltoggle, CWM_CONTEXT_SCREEN, {0} },
-	{ "cyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SCREEN,
-	    {.i = CWM_CLIENT_CYCLE} },
-	{ "rcyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SCREEN,
-	    {.i = CWM_CLIENT_RCYCLE} },
-	{ "cycleingroup", kbfunc_client_cycle, CWM_CONTEXT_CLIENT,
-	    {.i = (CWM_CLIENT_CYCLE | CWM_CLIENT_CYCLE_INGRP)} },
-	{ "rcycleingroup", kbfunc_client_cycle, CWM_CONTEXT_CLIENT,
-	    {.i = (CWM_CLIENT_RCYCLE | CWM_CLIENT_CYCLE_INGRP)} },
-	{ "grouptoggle", kbfunc_client_toggle_group, CWM_CONTEXT_CLIENT, {0} },
-	{ "stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CLIENT, {0} },
-	{ "fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CLIENT,
-	    {0} },
-	{ "maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CLIENT, {0} },
-	{ "vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CLIENT,
-	    {0} },
-	{ "hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CLIENT,
-	    {0} },
-	{ "freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CLIENT, {0} },
-	{ "restart", kbfunc_cwm_status, CWM_CONTEXT_SCREEN,
-	    {.i = CWM_EXEC_WM} },
-	{ "quit", kbfunc_cwm_status, CWM_CONTEXT_SCREEN, {.i = CWM_QUIT} },
-	{ "exec", kbfunc_menu_exec, CWM_CONTEXT_SCREEN, {.i = CWM_MENU_EXEC} },
-	{ "exec_wm", kbfunc_menu_exec, CWM_CONTEXT_SCREEN,
+	{ "lower", kbfunc_client_lower, CWM_CONTEXT_CC, {0} },
+	{ "raise", kbfunc_client_raise, CWM_CONTEXT_CC, {0} },
+	{ "search", kbfunc_menu_client, CWM_CONTEXT_SC, {0} },
+	{ "menusearch", kbfunc_menu_cmd, CWM_CONTEXT_SC, {0} },
+	{ "groupsearch", kbfunc_menu_group, CWM_CONTEXT_SC, {0} },
+	{ "hide", kbfunc_client_hide, CWM_CONTEXT_CC, {0} },
+	{ "cycle", kbfunc_client_cycle, CWM_CONTEXT_SC,
+	    {.i = CWM_CYCLE_FORWARD} },
+	{ "rcycle", kbfunc_client_cycle, CWM_CONTEXT_SC,
+	    {.i = CWM_CYCLE_REVERSE} },
+	{ "label", kbfunc_menu_client_label, CWM_CONTEXT_CC, {0} },
+	{ "delete", kbfunc_client_delete, CWM_CONTEXT_CC, {0} },
+	{ "group1", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 1} },
+	{ "group2", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 2} },
+	{ "group3", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 3} },
+	{ "group4", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 4} },
+	{ "group5", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 5} },
+	{ "group6", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 6} },
+	{ "group7", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 7} },
+	{ "group8", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 8} },
+	{ "group9", kbfunc_group_toggle, CWM_CONTEXT_SC, {.i = 9} },
+	{ "grouponly1", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 1} },
+	{ "grouponly2", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 2} },
+	{ "grouponly3", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 3} },
+	{ "grouponly4", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 4} },
+	{ "grouponly5", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 5} },
+	{ "grouponly6", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 6} },
+	{ "grouponly7", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 7} },
+	{ "grouponly8", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 8} },
+	{ "grouponly9", kbfunc_group_only, CWM_CONTEXT_SC, {.i = 9} },
+	{ "movetogroup1", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 1} },
+	{ "movetogroup2", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 2} },
+	{ "movetogroup3", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 3} },
+	{ "movetogroup4", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 4} },
+	{ "movetogroup5", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 5} },
+	{ "movetogroup6", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 6} },
+	{ "movetogroup7", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 7} },
+	{ "movetogroup8", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 8} },
+	{ "movetogroup9", kbfunc_client_movetogroup, CWM_CONTEXT_CC, {.i = 9} },
+	{ "nogroup", kbfunc_group_alltoggle, CWM_CONTEXT_SC, {0} },
+	{ "cyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SC,
+	    {.i = CWM_CYCLE_FORWARD} },
+	{ "rcyclegroup", kbfunc_group_cycle, CWM_CONTEXT_SC,
+	    {.i = CWM_CYCLE_REVERSE} },
+	{ "cycleingroup", kbfunc_client_cycle, CWM_CONTEXT_SC,
+	    {.i = (CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP)} },
+	{ "rcycleingroup", kbfunc_client_cycle, CWM_CONTEXT_SC,
+	    {.i = (CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP)} },
+	{ "grouptoggle", kbfunc_client_toggle_group, CWM_CONTEXT_CC, {0} },
+	{ "stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CC, {0} },
+	{ "fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CC, {0} },
+	{ "maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CC, {0} },
+	{ "vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CC, {0} },
+	{ "hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CC, {0} },
+	{ "freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CC, {0} },
+	{ "restart", kbfunc_cwm_status, CWM_CONTEXT_SC, {.i = CWM_EXEC_WM} },
+	{ "quit", kbfunc_cwm_status, CWM_CONTEXT_SC, {.i = CWM_QUIT} },
+	{ "exec", kbfunc_menu_exec, CWM_CONTEXT_SC,
+	    {.i = CWM_MENU_EXEC_EXEC} },
+	{ "exec_wm", kbfunc_menu_exec, CWM_CONTEXT_SC,
 	    {.i = CWM_MENU_EXEC_WM} },
-	{ "ssh", kbfunc_menu_ssh, CWM_CONTEXT_SCREEN, {0} },
-	{ "terminal", kbfunc_exec_term, CWM_CONTEXT_SCREEN, {0} },
-	{ "lock", kbfunc_exec_lock, CWM_CONTEXT_SCREEN, {0} },
-	{ "moveup", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "ssh", kbfunc_menu_ssh, CWM_CONTEXT_SC, {0} },
+	{ "terminal", kbfunc_exec_term, CWM_CONTEXT_SC, {0} },
+	{ "lock", kbfunc_exec_lock, CWM_CONTEXT_SC, {0} },
+	{ "moveup", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_UP)} },
-	{ "movedown", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "movedown", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_DOWN)} },
-	{ "moveright", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "moveright", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_RIGHT)} },
-	{ "moveleft", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "moveleft", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_LEFT)} },
-	{ "bigmoveup", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "bigmoveup", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_UP | CWM_BIGAMOUNT)} },
-	{ "bigmovedown", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "bigmovedown", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_DOWN | CWM_BIGAMOUNT)} },
-	{ "bigmoveright", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "bigmoveright", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} },
-	{ "bigmoveleft", kbfunc_client_move, CWM_CONTEXT_CLIENT,
+	{ "bigmoveleft", kbfunc_client_move, CWM_CONTEXT_CC,
 	    {.i = (CWM_LEFT | CWM_BIGAMOUNT)} },
-	{ "resizeup", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "resizeup", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_UP)} },
-	{ "resizedown", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "resizedown", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_DOWN)} },
-	{ "resizeright", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "resizeright", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_RIGHT)} },
-	{ "resizeleft", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "resizeleft", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_LEFT)} },
-	{ "bigresizeup", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "bigresizeup", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_UP | CWM_BIGAMOUNT)} },
-	{ "bigresizedown", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "bigresizedown", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_DOWN | CWM_BIGAMOUNT)} },
-	{ "bigresizeright", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "bigresizeright", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} },
-	{ "bigresizeleft", kbfunc_client_resize, CWM_CONTEXT_CLIENT,
+	{ "bigresizeleft", kbfunc_client_resize, CWM_CONTEXT_CC,
 	    {.i = (CWM_LEFT | CWM_BIGAMOUNT)} },
-	{ "ptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "ptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_UP)} },
-	{ "ptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "ptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_DOWN)} },
-	{ "ptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "ptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_LEFT)} },
-	{ "ptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "ptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_RIGHT)} },
-	{ "bigptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "bigptrmoveup", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_UP | CWM_BIGAMOUNT)} },
-	{ "bigptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "bigptrmovedown", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_DOWN | CWM_BIGAMOUNT)} },
-	{ "bigptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "bigptrmoveleft", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_LEFT | CWM_BIGAMOUNT)} },
-	{ "bigptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SCREEN,
+	{ "bigptrmoveright", kbfunc_ptrmove, CWM_CONTEXT_SC,
 	    {.i = (CWM_RIGHT | CWM_BIGAMOUNT)} },
-	{ "htile", kbfunc_client_tile, CWM_CONTEXT_CLIENT,
-	    {.i = CWM_CLIENT_TILE_HORIZ} },
-	{ "vtile", kbfunc_client_tile, CWM_CONTEXT_CLIENT,
-	    {.i = CWM_CLIENT_TILE_VERT} },
-	{ "window_lower", kbfunc_client_lower, CWM_CONTEXT_CLIENT, {0} },
-	{ "window_raise", kbfunc_client_raise, CWM_CONTEXT_CLIENT, {0} },
-	{ "window_hide", kbfunc_client_hide, CWM_CONTEXT_CLIENT, {0} },
-	{ "window_move", mousefunc_client_move, CWM_CONTEXT_CLIENT, {0} },
-	{ "window_resize", mousefunc_client_resize, CWM_CONTEXT_CLIENT, {0} },
-	{ "window_grouptoggle", kbfunc_client_toggle_group, CWM_CONTEXT_CLIENT, {0} },
-	{ "menu_group", kbfunc_menu_group, CWM_CONTEXT_SCREEN, {0} },
-	{ "menu_unhide", kbfunc_menu_client, CWM_CONTEXT_SCREEN, {0} },
-	{ "menu_cmd", kbfunc_menu_cmd, CWM_CONTEXT_SCREEN, {0} },
+	{ "htile", kbfunc_client_htile, CWM_CONTEXT_CC, {0} },
+	{ "vtile", kbfunc_client_vtile, CWM_CONTEXT_CC, {0} },
+	{ "window_lower", kbfunc_client_lower, CWM_CONTEXT_CC, {0} },
+	{ "window_raise", kbfunc_client_raise, CWM_CONTEXT_CC, {0} },
+	{ "window_hide", kbfunc_client_hide, CWM_CONTEXT_CC, {0} },
+	{ "window_move", mousefunc_client_move, CWM_CONTEXT_CC, {0} },
+	{ "window_resize", mousefunc_client_resize, CWM_CONTEXT_CC, {0} },
+	{ "window_grouptoggle", kbfunc_client_toggle_group, CWM_CONTEXT_CC, {0} },
+	{ "menu_group", kbfunc_menu_group, CWM_CONTEXT_SC, {0} },
+	{ "menu_unhide", kbfunc_menu_client, CWM_CONTEXT_SC, {0} },
+	{ "menu_cmd", kbfunc_menu_cmd, CWM_CONTEXT_SC, {0} },
 };
 
 static const struct {
@@ -526,7 +512,7 @@ conf_bind_getmask(const char *name, unsigned int *mask)
 int
 conf_bind_kbd(struct conf *c, const char *bind, const char *cmd)
 {
-	struct binding	*kb;
+	struct bind_ctx	*kb;
 	const char	*key;
 	unsigned int	 i;
 
@@ -555,28 +541,28 @@ conf_bind_kbd(struct conf *c, const char *bind, const char *cmd)
 		kb->callback = name_to_func[i].handler;
 		kb->context = name_to_func[i].context;
 		kb->argument = name_to_func[i].argument;
-		TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry);
+		TAILQ_INSERT_TAIL(&c->keybindq, kb, entry);
 		return(1);
 	}
 
-	kb->callback = kbfunc_exec;
+	kb->callback = kbfunc_exec_cmd;
 	kb->context = CWM_CONTEXT_NONE;
 	kb->argument.c = xstrdup(cmd);
-	TAILQ_INSERT_TAIL(&c->keybindingq, kb, entry);
+	TAILQ_INSERT_TAIL(&c->keybindq, kb, entry);
 	return(1);
 }
 
 static void
-conf_unbind_kbd(struct conf *c, struct binding *unbind)
+conf_unbind_kbd(struct conf *c, struct bind_ctx *unbind)
 {
-	struct binding	*key = NULL, *keynxt;
+	struct bind_ctx	*key = NULL, *keynxt;
 
-	TAILQ_FOREACH_SAFE(key, &c->keybindingq, entry, keynxt) {
+	TAILQ_FOREACH_SAFE(key, &c->keybindq, entry, keynxt) {
 		if (key->modmask != unbind->modmask)
 			continue;
 
 		if (key->press.keysym == unbind->press.keysym) {
-			TAILQ_REMOVE(&c->keybindingq, key, entry);
+			TAILQ_REMOVE(&c->keybindq, key, entry);
 			if (key->context == CWM_CONTEXT_NONE)
 				free(key->argument.c);
 			free(key);
@@ -587,7 +573,7 @@ conf_unbind_kbd(struct conf *c, struct binding *unbind)
 int
 conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
 {
-	struct binding	*mb;
+	struct bind_ctx	*mb;
 	const char	*button, *errstr;
 	unsigned int	 i;
 
@@ -616,7 +602,7 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
 		mb->callback = name_to_func[i].handler;
 		mb->context = name_to_func[i].context;
 		mb->argument = name_to_func[i].argument;
-		TAILQ_INSERT_TAIL(&c->mousebindingq, mb, entry);
+		TAILQ_INSERT_TAIL(&c->mousebindq, mb, entry);
 		return(1);
 	}
 
@@ -624,16 +610,16 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd)
 }
 
 static void
-conf_unbind_mouse(struct conf *c, struct binding *unbind)
+conf_unbind_mouse(struct conf *c, struct bind_ctx *unbind)
 {
-	struct binding		*mb = NULL, *mbnxt;
+	struct bind_ctx		*mb = NULL, *mbnxt;
 
-	TAILQ_FOREACH_SAFE(mb, &c->mousebindingq, entry, mbnxt) {
+	TAILQ_FOREACH_SAFE(mb, &c->mousebindq, entry, mbnxt) {
 		if (mb->modmask != unbind->modmask)
 			continue;
 
 		if (mb->press.button == unbind->press.button) {
-			TAILQ_REMOVE(&c->mousebindingq, mb, entry);
+			TAILQ_REMOVE(&c->mousebindq, mb, entry);
 			free(mb);
 		}
 	}
@@ -660,13 +646,13 @@ static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
 void
 conf_grab_mouse(Window win)
 {
-	struct binding	*mb;
+	struct bind_ctx	*mb;
 	unsigned int	i;
 
 	XUngrabButton(X_Dpy, AnyButton, AnyModifier, win);
 
-	TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) {
-		if (mb->context != CWM_CONTEXT_CLIENT)
+	TAILQ_FOREACH(mb, &Conf.mousebindq, entry) {
+		if (mb->context != CWM_CONTEXT_CC)
 			continue;
 		for (i = 0; i < nitems(ign_mods); i++) {
 			XGrabButton(X_Dpy, mb->press.button,
@@ -681,13 +667,13 @@ conf_grab_mouse(Window win)
 void
 conf_grab_kbd(Window win)
 {
-	struct binding	*kb;
+	struct bind_ctx	*kb;
 	KeyCode		 kc;
 	unsigned int	 i;
 
 	XUngrabKey(X_Dpy, AnyKey, AnyModifier, win);
 
-	TAILQ_FOREACH(kb, &Conf.keybindingq, entry) {
+	TAILQ_FOREACH(kb, &Conf.keybindq, entry) {
 		kc = XKeysymToKeycode(X_Dpy, kb->press.keysym);
 		if ((XkbKeycodeToKeysym(X_Dpy, kc, 0, 0) != kb->press.keysym) &&
 		    (XkbKeycodeToKeysym(X_Dpy, kc, 0, 1) == kb->press.keysym))
diff --git a/group.c b/group.c
index 36fd397..ec368de 100644
--- a/group.c
+++ b/group.c
@@ -265,7 +265,7 @@ group_cycle(struct screen_ctx *sc, int flags)
 
 	newgc = oldgc;
 	for (;;) {
-		newgc = (flags & CWM_CLIENT_RCYCLE) ? group_prev(newgc) :
+		newgc = (flags & CWM_CYCLE_REVERSE) ? group_prev(newgc) :
 		    group_next(newgc);
 
 		if (newgc == oldgc)
@@ -304,8 +304,8 @@ group_prev(struct group_ctx *gc)
 	struct screen_ctx	*sc = gc->sc;
 	struct group_ctx	*newgc;
 
-	return(((newgc = TAILQ_PREV(gc, group_ctx_q, entry)) != NULL) ?
-	    newgc : TAILQ_LAST(&sc->groupq, group_ctx_q));
+	return(((newgc = TAILQ_PREV(gc, group_q, entry)) != NULL) ?
+	    newgc : TAILQ_LAST(&sc->groupq, group_q));
 }
 
 void
@@ -351,21 +351,21 @@ int
 group_autogroup(struct client_ctx *cc)
 {
 	struct screen_ctx	*sc = cc->sc;
-	struct autogroupwin	*aw;
+	struct autogroup	*ag;
 	struct group_ctx	*gc;
 	int			 num = -1, both_match = 0;
 
 	if (cc->ch.res_class == NULL || cc->ch.res_name == NULL)
 		return(0);
 
-	TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
-		if (strcmp(aw->class, cc->ch.res_class) == 0) {
-			if ((aw->name != NULL) &&
-			    (strcmp(aw->name, cc->ch.res_name) == 0)) {
-				num = aw->num;
+	TAILQ_FOREACH(ag, &Conf.autogroupq, entry) {
+		if (strcmp(ag->class, cc->ch.res_class) == 0) {
+			if ((ag->name != NULL) &&
+			    (strcmp(ag->name, cc->ch.res_name) == 0)) {
+				num = ag->num;
 				both_match = 1;
-			} else if (aw->name == NULL && !both_match)
-				num = aw->num;
+			} else if (ag->name == NULL && !both_match)
+				num = ag->num;
 		}
 	}
 
diff --git a/kbfunc.c b/kbfunc.c
index 5225e04..ef2334f 100644
--- a/kbfunc.c
+++ b/kbfunc.c
@@ -41,16 +41,9 @@ extern sig_atomic_t	 cwm_status;
 static void kbfunc_amount(int, int, unsigned int *, unsigned int *);
 
 void
-kbfunc_client_lower(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_cwm_status(void *ctx, union arg *arg, enum xev xev)
 {
-	client_ptrsave(cc);
-	client_lower(cc);
-}
-
-void
-kbfunc_client_raise(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_raise(cc);
+	cwm_status = arg->i;
 }
 
 static void
@@ -78,9 +71,9 @@ kbfunc_amount(int flags, int amt, unsigned int *mx, unsigned int *my)
 }
 
 void
-kbfunc_ptrmove(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_ptrmove(void *ctx, union arg *arg, enum xev xev)
 {
-	struct screen_ctx	*sc = cc->sc;
+	struct screen_ctx	*sc = ctx;
 	int			 x, y;
 	unsigned int		 mx = 0, my = 0;
 
@@ -91,8 +84,9 @@ kbfunc_ptrmove(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_client_move(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_client_move(void *ctx, union arg *arg, enum xev xev)
 {
+	struct client_ctx	*cc = ctx;
 	struct screen_ctx	*sc = cc->sc;
 	struct geom		 area;
 	int			 x, y, px, py;
@@ -144,8 +138,9 @@ kbfunc_client_move(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_client_resize(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_client_resize(void *ctx, union arg *arg, enum xev xev)
 {
+	struct client_ctx	*cc = ctx;
 	unsigned int		 mx = 0, my = 0;
 	int			 amt = 1;
 
@@ -173,13 +168,136 @@ kbfunc_client_resize(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_menu_client(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_client_delete(void *ctx, union arg *arg, enum xev xev)
 {
-	struct screen_ctx	*sc = cc->sc;
-	struct client_ctx	*old_cc;
+	client_send_delete(ctx);
+}
+
+void
+kbfunc_client_lower(void *ctx, union arg *arg, enum xev xev)
+{
+	client_ptrsave(ctx);
+	client_lower(ctx);
+}
+
+void
+kbfunc_client_raise(void *ctx, union arg *arg, enum xev xev)
+{
+	client_raise(ctx);
+}
+
+void
+kbfunc_client_hide(void *ctx, union arg *arg, enum xev xev)
+{
+	client_hide(ctx);
+}
+
+void
+kbfunc_client_toggle_freeze(void *ctx, union arg *arg, enum xev xev)
+{
+	client_toggle_freeze(ctx);
+}
+
+void
+kbfunc_client_toggle_sticky(void *ctx, union arg *arg, enum xev xev)
+{
+	client_toggle_sticky(ctx);
+}
+
+void
+kbfunc_client_toggle_fullscreen(void *ctx, union arg *arg, enum xev xev)
+{
+	client_toggle_fullscreen(ctx);
+}
+
+void
+kbfunc_client_toggle_maximize(void *ctx, union arg *arg, enum xev xev)
+{
+	client_toggle_maximize(ctx);
+}
+
+void
+kbfunc_client_toggle_hmaximize(void *ctx, union arg *arg, enum xev xev)
+{
+	client_toggle_hmaximize(ctx);
+}
+
+void
+kbfunc_client_toggle_vmaximize(void *ctx, union arg *arg, enum xev xev)
+{
+	client_toggle_vmaximize(ctx);
+}
+
+void
+kbfunc_client_htile(void *ctx, union arg *arg, enum xev xev)
+{
+	client_htile(ctx);
+}
+
+void
+kbfunc_client_vtile(void *ctx, union arg *arg, enum xev xev)
+{
+	client_vtile(ctx);
+}
+
+void
+kbfunc_client_cycle(void *ctx, union arg *arg, enum xev xev)
+{
+	client_cycle(ctx, arg->i);
+}
+
+void
+kbfunc_client_toggle_group(void *ctx, union arg *arg, enum xev xev)
+{
+	struct client_ctx	*cc = ctx;
+
+	if (xev == CWM_XEV_KEY) {
+		/* For X apps that steal events. */
+		XGrabKeyboard(X_Dpy, cc->win, True,
+		    GrabModeAsync, GrabModeAsync, CurrentTime);
+	}
+
+	group_toggle_membership_enter(cc);
+}
+
+void
+kbfunc_client_movetogroup(void *ctx, union arg *arg, enum xev xev)
+{
+	group_movetogroup(ctx, arg->i);
+}
+
+void
+kbfunc_group_toggle(void *ctx, union arg *arg, enum xev xev)
+{
+	group_hidetoggle(ctx, arg->i);
+}
+
+void
+kbfunc_group_only(void *ctx, union arg *arg, enum xev xev)
+{
+	group_only(ctx, arg->i);
+}
+
+void
+kbfunc_group_cycle(void *ctx, union arg *arg, enum xev xev)
+{
+	group_cycle(ctx, arg->i);
+}
+
+void
+kbfunc_group_alltoggle(void *ctx, union arg *arg, enum xev xev)
+{
+	group_alltoggle(ctx);
+}
+
+void
+kbfunc_menu_client(void *ctx, union arg *arg, enum xev xev)
+{
+	struct screen_ctx	*sc = ctx;
+	struct client_ctx	*cc, *old_cc;
 	struct menu		*mi;
 	struct menu_q		 menuq;
-	int			 m = (xev == CWM_BTN);
+	int			 m = (xev == CWM_XEV_BTN);
 
 	old_cc = client_current();
 
@@ -210,13 +328,13 @@ kbfunc_menu_client(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_menu_cmd(void *ctx, union arg *arg, enum xev xev)
 {
-	struct screen_ctx	*sc = cc->sc;
-	struct cmd		*cmd;
+	struct screen_ctx	*sc = ctx;
+	struct cmd_ctx		*cmd;
 	struct menu		*mi;
 	struct menu_q		 menuq;
-	int			 m = (xev == CWM_BTN);
+	int			 m = (xev == CWM_XEV_BTN);
 
 	TAILQ_INIT(&menuq);
 	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
@@ -231,7 +349,7 @@ kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg, int xev)
 	    (m) ? NULL : "application", NULL,
 	    (m) ? CWM_MENU_LIST : 0,
 	    search_match_text, search_print_cmd)) != NULL) {
-		cmd = (struct cmd *)mi->ctx;
+		cmd = (struct cmd_ctx *)mi->ctx;
 		u_spawn(cmd->path);
 	}
 
@@ -239,13 +357,13 @@ kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_menu_group(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_menu_group(void *ctx, union arg *arg, enum xev xev)
 {
-	struct screen_ctx	*sc = cc->sc;
+	struct screen_ctx	*sc = ctx;
 	struct group_ctx	*gc;
 	struct menu		*mi;
 	struct menu_q		 menuq;
-	int			 m = (xev == CWM_BTN);
+	int			 m = (xev == CWM_XEV_BTN);
 
 	TAILQ_INIT(&menuq);
 	TAILQ_FOREACH(gc, &sc->groupq, entry) {
@@ -266,50 +384,10 @@ kbfunc_menu_group(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_client_cycle(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_cycle(cc->sc, arg->i);
-}
-
-void
-kbfunc_client_hide(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_hide(cc);
-}
-
-void
-kbfunc_exec(struct client_ctx *cc, union arg *arg, int xev)
-{
-	u_spawn(arg->c);
-}
-
-void
-kbfunc_exec_term(struct client_ctx *cc, union arg *arg, int xev)
-{
-	struct cmd *cmd;
-
-	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
-		if (strcmp(cmd->name, "term") == 0)
-			u_spawn(cmd->path);
-	}
-}
-
-void
-kbfunc_exec_lock(struct client_ctx *cc, union arg *arg, int xev)
-{
-	struct cmd *cmd;
-
-	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
-		if (strcmp(cmd->name, "lock") == 0)
-			u_spawn(cmd->path);
-	}
-}
-
-void
-kbfunc_menu_exec(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_menu_exec(void *ctx, union arg *arg, enum xev xev)
 {
 #define NPATHS 256
-	struct screen_ctx	*sc = cc->sc;
+	struct screen_ctx	*sc = ctx;
 	char			**ap, *paths[NPATHS], *path, *pathcpy;
 	char			 tpath[PATH_MAX];
 	const char		*label;
@@ -320,7 +398,7 @@ kbfunc_menu_exec(struct client_ctx *cc, union arg *arg, int xev)
 	int			 l, i, cmd = arg->i;
 
 	switch (cmd) {
-	case CWM_MENU_EXEC:
+	case CWM_MENU_EXEC_EXEC:
 		label = "exec";
 		break;
 	case CWM_MENU_EXEC_WM:
@@ -328,7 +406,7 @@ kbfunc_menu_exec(struct client_ctx *cc, union arg *arg, int xev)
 		break;
 	default:
 		errx(1, "kbfunc_menu_exec: invalid cmd %d", cmd);
-		/*NOTREACHED*/
+		/* NOTREACHED */
 	}
 
 	TAILQ_INIT(&menuq);
@@ -369,17 +447,17 @@ kbfunc_menu_exec(struct client_ctx *cc, union arg *arg, int xev)
 		if (mi->text[0] == '\0')
 			goto out;
 		switch (cmd) {
-		case CWM_MENU_EXEC:
+		case CWM_MENU_EXEC_EXEC:
 			u_spawn(mi->text);
 			break;
 		case CWM_MENU_EXEC_WM:
 			cwm_status = CWM_EXEC_WM;
-			free(wm_argv);
-			wm_argv = xstrdup(mi->text);
+			free(Conf.wm_argv);
+			Conf.wm_argv = xstrdup(mi->text);
 			break;
 		default:
 			errx(1, "kb_func: egad, cmd changed value!");
-			break;
+			/* NOTREACHED */
 		}
 	}
 out:
@@ -389,10 +467,10 @@ out:
 }
 
 void
-kbfunc_menu_ssh(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_menu_ssh(void *ctx, union arg *arg, enum xev xev)
 {
-	struct screen_ctx	*sc = cc->sc;
-	struct cmd		*cmd;
+	struct screen_ctx	*sc = ctx;
+	struct cmd_ctx		*cmd;
 	struct menu		*mi;
 	struct menu_q		 menuq;
 	FILE			*fp;
@@ -456,10 +534,11 @@ out:
 }
 
 void
-kbfunc_menu_client_label(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_menu_client_label(void *ctx, union arg *arg, enum xev xev)
 {
-	struct menu	*mi;
-	struct menu_q	 menuq;
+	struct client_ctx	*cc = ctx;
+	struct menu		*mi;
+	struct menu_q		 menuq;
 
 	TAILQ_INIT(&menuq);
 
@@ -475,104 +554,29 @@ kbfunc_menu_client_label(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-kbfunc_client_delete(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_exec_cmd(void *ctx, union arg *arg, enum xev xev)
 {
-	client_send_delete(cc);
-}
-
-void
-kbfunc_group_toggle(struct client_ctx *cc, union arg *arg, int xev)
-{
-	group_hidetoggle(cc->sc, arg->i);
-}
-
-void
-kbfunc_group_only(struct client_ctx *cc, union arg *arg, int xev)
-{
-	group_only(cc->sc, arg->i);
-}
-
-void
-kbfunc_group_cycle(struct client_ctx *cc, union arg *arg, int xev)
-{
-	group_cycle(cc->sc, arg->i);
+	u_spawn(arg->c);
 }
 
 void
-kbfunc_group_alltoggle(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_exec_term(void *ctx, union arg *arg, enum xev xev)
 {
-	group_alltoggle(cc->sc);
-}
+	struct cmd_ctx	*cmd;
 
-void
-kbfunc_client_toggle_group(struct client_ctx *cc, union arg *arg, int xev)
-{
-	if (xev == CWM_KEY) {
-		/* For X apps that steal events. */
-		XGrabKeyboard(X_Dpy, cc->win, True,
-		    GrabModeAsync, GrabModeAsync, CurrentTime);
+	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
+		if (strcmp(cmd->name, "term") == 0)
+			u_spawn(cmd->path);
 	}
-
-	group_toggle_membership_enter(cc);
-}
-
-void
-kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg, int xev)
-{
-	group_movetogroup(cc, arg->i);
-}
-
-void
-kbfunc_client_toggle_sticky(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_toggle_sticky(cc);
 }
 
 void
-kbfunc_client_toggle_fullscreen(struct client_ctx *cc, union arg *arg, int xev)
+kbfunc_exec_lock(void *ctx, union arg *arg, enum xev xev)
 {
-	client_toggle_fullscreen(cc);
-}
-
-void
-kbfunc_client_toggle_maximize(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_toggle_maximize(cc);
-}
+	struct cmd_ctx	*cmd;
 
-void
-kbfunc_client_toggle_vmaximize(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_toggle_vmaximize(cc);
-}
-
-void
-kbfunc_client_toggle_hmaximize(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_toggle_hmaximize(cc);
-}
-
-void
-kbfunc_client_toggle_freeze(struct client_ctx *cc, union arg *arg, int xev)
-{
-	client_toggle_freeze(cc);
-}
-
-void
-kbfunc_cwm_status(struct client_ctx *cc, union arg *arg, int xev)
-{
-	cwm_status = arg->i;
-}
-
-void
-kbfunc_client_tile(struct client_ctx *cc, union arg *arg, int xev)
-{
-	switch (arg->i) {
-	case CWM_CLIENT_TILE_HORIZ:
-		client_htile(cc);
-		break;
-	case CWM_CLIENT_TILE_VERT:
-		client_vtile(cc);
-		break;
+	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
+		if (strcmp(cmd->name, "lock") == 0)
+			u_spawn(cmd->path);
 	}
 }
diff --git a/mousefunc.c b/mousefunc.c
index 27b1d65..23c5c42 100644
--- a/mousefunc.c
+++ b/mousefunc.c
@@ -33,8 +33,9 @@
 #include "calmwm.h"
 
 void
-mousefunc_client_resize(struct client_ctx *cc, union arg *arg, int xev)
+mousefunc_client_resize(void *ctx, union arg *arg, enum xev xev)
 {
+	struct client_ctx	*cc = ctx;
 	XEvent			 ev;
 	Time			 ltime = 0;
 	struct screen_ctx	*sc = cc->sc;
@@ -88,8 +89,9 @@ mousefunc_client_resize(struct client_ctx *cc, union arg *arg, int xev)
 }
 
 void
-mousefunc_client_move(struct client_ctx *cc, union arg *arg, int xev)
+mousefunc_client_move(void *ctx, union arg *arg, enum xev xev)
 {
+	struct client_ctx	*cc = ctx;
 	XEvent			 ev;
 	Time			 ltime = 0;
 	struct screen_ctx	*sc = cc->sc;
diff --git a/screen.c b/screen.c
index b9f1ac9..4badf65 100644
--- a/screen.c
+++ b/screen.c
@@ -84,7 +84,7 @@ screen_init(int which)
 	}
 	screen_updatestackingorder(sc);
 
-	if (HasRandr)
+	if (Conf.xrandr)
 		XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask);
 
 	TAILQ_INSERT_TAIL(&Screenq, sc, entry);
@@ -140,7 +140,7 @@ region_find(struct screen_ctx *sc, int x, int y)
 }
 
 struct geom
-screen_area(struct screen_ctx *sc, int x, int y, int flags)
+screen_area(struct screen_ctx *sc, int x, int y, enum apply_gap apply_gap)
 {
 	struct region_ctx	*rc;
 	struct geom		 area = sc->work;
@@ -152,7 +152,7 @@ screen_area(struct screen_ctx *sc, int x, int y, int flags)
 			break;
 		}
 	}
-	if (flags & CWM_GAP)
+	if (apply_gap)
 		area = screen_apply_gap(sc, area);
 	return(area);
 }
@@ -173,7 +173,7 @@ screen_update_geometry(struct screen_ctx *sc)
 		free(rc);
 	}
 
-	if (HasRandr) {
+	if (Conf.xrandr) {
 		XRRScreenResources *sr;
 		XRRCrtcInfo *ci;
 		int i;
diff --git a/search.c b/search.c
index f52d87d..efc2e73 100644
--- a/search.c
+++ b/search.c
@@ -72,7 +72,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
 
 		/* Then, on window names. */
 		if (tier < 0) {
-			TAILQ_FOREACH_REVERSE(wn, &cc->nameq, winname_q, entry)
+			TAILQ_FOREACH_REVERSE(wn, &cc->nameq, name_q, entry)
 				if (strsubmatch(search, wn->name, 0)) {
 					cc->matchname = wn->name;
 					tier = 2;
@@ -126,7 +126,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
 void
 search_print_cmd(struct menu *mi, int i)
 {
-	struct cmd	*cmd = (struct cmd *)mi->ctx;
+	struct cmd_ctx	*cmd = (struct cmd_ctx *)mi->ctx;
 
 	(void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);
 }
diff --git a/xevents.c b/xevents.c
index 3388063..946ea98 100644
--- a/xevents.c
+++ b/xevents.c
@@ -220,31 +220,37 @@ static void
 xev_handle_buttonpress(XEvent *ee)
 {
 	XButtonEvent		*e = &ee->xbutton;
-	struct client_ctx	*cc, fakecc;
-	struct binding		*mb;
+	struct client_ctx	*cc;
+	struct screen_ctx	*sc;
+	struct bind_ctx		*mb;
 
 	e->state &= ~IGNOREMODMASK;
 
-	TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) {
+	TAILQ_FOREACH(mb, &Conf.mousebindq, entry) {
 		if (e->button == mb->press.button && e->state == mb->modmask)
 			break;
 	}
 
 	if (mb == NULL)
 		return;
-	if (mb->context == CWM_CONTEXT_CLIENT) {
+	switch (mb->context) {
+	case CWM_CONTEXT_CC:
 		if (((cc = client_find(e->window)) == NULL) &&
 		    (cc = client_current()) == NULL)
 			return;
-	} else {
+		(*mb->callback)(cc, &mb->argument, CWM_XEV_BTN);
+		break;
+	case CWM_CONTEXT_SC:
 		if (e->window != e->root)
 			return;
-		cc = &fakecc;
-		if ((cc->sc = screen_find(e->window)) == NULL)
+		if ((sc = screen_find(e->window)) == NULL)
 			return;
+		(*mb->callback)(sc, &mb->argument, CWM_XEV_BTN);
+		break;
+	case CWM_CONTEXT_NONE:
+		(*mb->callback)(NULL, &mb->argument, CWM_XEV_BTN);
+		break;
 	}
-
-	(*mb->callback)(cc, &mb->argument, CWM_BTN);
 }
 
 static void
@@ -263,8 +269,9 @@ static void
 xev_handle_keypress(XEvent *ee)
 {
 	XKeyEvent		*e = &ee->xkey;
-	struct client_ctx	*cc = NULL, fakecc;
-	struct binding		*kb;
+	struct client_ctx	*cc;
+	struct screen_ctx	*sc;
+	struct bind_ctx		*kb;
 	KeySym			 keysym, skeysym;
 	unsigned int		 modshift;
 
@@ -273,7 +280,7 @@ xev_handle_keypress(XEvent *ee)
 
 	e->state &= ~IGNOREMODMASK;
 
-	TAILQ_FOREACH(kb, &Conf.keybindingq, entry) {
+	TAILQ_FOREACH(kb, &Conf.keybindq, entry) {
 		if (keysym != kb->press.keysym && skeysym == kb->press.keysym)
 			modshift = ShiftMask;
 		else
@@ -288,17 +295,22 @@ xev_handle_keypress(XEvent *ee)
 
 	if (kb == NULL)
 		return;
-	if (kb->context == CWM_CONTEXT_CLIENT) {
+	switch (kb->context) {
+	case CWM_CONTEXT_CC:
 		if (((cc = client_find(e->window)) == NULL) &&
 		    (cc = client_current()) == NULL)
 			return;
-	} else {
-		cc = &fakecc;
-		if ((cc->sc = screen_find(e->window)) == NULL)
+		(*kb->callback)(cc, &kb->argument, CWM_XEV_KEY);
+		break;
+	case CWM_CONTEXT_SC:
+		if ((sc = screen_find(e->window)) == NULL)
 			return;
+		(*kb->callback)(sc, &kb->argument, CWM_XEV_KEY);
+		break;
+	case CWM_CONTEXT_NONE:
+		(*kb->callback)(NULL, &kb->argument, CWM_XEV_KEY);
+		break;
 	}
-
-	(*kb->callback)(cc, &kb->argument, CWM_KEY);
 }
 
 /*
@@ -424,7 +436,7 @@ xev_process(void)
 	XEvent		 e;
 
 	XNextEvent(X_Dpy, &e);
-	if (e.type - Randr_ev == RRScreenChangeNotify)
+	if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify)
 		xev_handle_randr(&e);
 	else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
 		(*xev_handlers[e.type])(&e);