summary refs log tree commit diff
diff options
context:
space:
mode:
authoroga <oga>2009-12-10 17:16:51 +0000
committeroga <oga>2009-12-10 17:16:51 +0000
commit134e777cf095ae292730e1c9d3f7967099878024 (patch)
tree80a226385db61bf2bdf72e0c0b3490f0930303e9
parentee7df6a95f80bebc9ec2d8571c1ff8ff2f53cfd0 (diff)
downloadcwm-134e777cf095ae292730e1c9d3f7967099878024.tar.gz
cwm-134e777cf095ae292730e1c9d3f7967099878024.tar.xz
cwm-134e777cf095ae292730e1c9d3f7967099878024.zip
finish unfucking the screen_ctx handling.
remove screen_current() it was utterly bogus when nscreens > 1.

pass a fake client_ctx in the case where there's no client and the
kbfunc or mousefunc doesn't need a real one, it just contains the
current screen, modify these functions so that they pass down the screen
context to their callees.

make groups per screen, it's the only way it makes sense in this regard.

ok okan@.
-rw-r--r--calmwm.c9
-rw-r--r--calmwm.h82
-rw-r--r--client.c4
-rw-r--r--group.c104
-rw-r--r--kbfunc.c68
-rw-r--r--menu.c6
-rw-r--r--mousefunc.c15
-rw-r--r--screen.c13
-rw-r--r--xevents.c26
9 files changed, 163 insertions, 164 deletions
diff --git a/calmwm.c b/calmwm.c
index 8cc62d5..4bd1567 100644
--- a/calmwm.c
+++ b/calmwm.c
@@ -30,8 +30,6 @@ Cursor				 Cursor_default;
 Cursor				 Cursor_question;
 
 struct screen_ctx_q		 Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
-struct screen_ctx		*Curscreen;
-
 struct client_ctx_q		 Clientq = TAILQ_HEAD_INITIALIZER(Clientq);
 
 int				 HasXinerama, HasRandr, Randr_ev;
@@ -73,8 +71,6 @@ main(int argc, char **argv)
 	Starting = 1;
 	dpy_init(display_name);
 
-	group_init();
-
 	bzero(&Conf, sizeof(Conf));
 	conf_setup(&Conf, conf_file);
 	xu_getatoms();
@@ -149,8 +145,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
 	int			 fake;
 	u_int			 ndesks = CALMWM_NGROUPS, nwins, i;
 
-	Curscreen = sc;
-
 	sc->which = which;
 	sc->rootwin = RootWindow(X_Dpy, sc->which);
 	sc->xmax = DisplayWidth(X_Dpy, sc->which);
@@ -158,6 +152,7 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
 
 	conf_color(&Conf, sc);
 
+	group_init(sc);
 	font_init(sc);
 	conf_font(&Conf, sc);
 
@@ -187,7 +182,7 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
 	}
 	XFree(wins);
 
-	screen_updatestackingorder();
+	screen_updatestackingorder(sc);
 
 	rootattr.event_mask = ChildMask|PropertyChangeMask|EnterWindowMask|
 	    LeaveWindowMask|ColormapChangeMask|ButtonMask;
diff --git a/calmwm.h b/calmwm.h
index 0dc1ffe..9ca583f 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -59,31 +59,48 @@ struct color {
 struct client_ctx;
 
 TAILQ_HEAD(cycle_entry_q, client_ctx);
+TAILQ_HEAD(group_ctx_q, group_ctx);
+TAILQ_HEAD(client_ctx_q, client_ctx);
+
+#define CALMWM_NGROUPS 9
+struct group_ctx {
+	TAILQ_ENTRY(group_ctx)	 entry;
+	struct client_ctx_q	 clients;
+	const char		*name;
+	int			 shortcut;
+	int			 hidden;
+	int			 nhidden;
+	int			 highstack;
+};
 
 struct screen_ctx {
-	TAILQ_ENTRY(screen_ctx)	entry;
+	TAILQ_ENTRY(screen_ctx)	 entry;
 
-	u_int		 which;
-	Window		 rootwin;
-	Window		 menuwin;
+	u_int			 which;
+	Window			 rootwin;
+	Window			 menuwin;
 
-	struct color	 color[CWM_COLOR_MAX];
-	GC		 gc;
+	struct color		 color[CWM_COLOR_MAX];
+	GC			 gc;
 
-	int		 altpersist;
+	int			 altpersist;
 
-	int		 xmax;
-	int		 ymax;
+	int			 xmax;
+	int			 ymax;
 
-	struct cycle_entry_q mruq;
+	struct cycle_entry_q	 mruq;
 
-	XftDraw		*xftdraw;
-	XftColor	 xftcolor;
-	XftFont		*font;
-	u_int		 fontheight;
+	XftDraw			*xftdraw;
+	XftColor		 xftcolor;
+	XftFont			*font;
+	u_int			 fontheight;
 
-	int		 xinerama_no;
-	XineramaScreenInfo *xinerama;
+	int			 xinerama_no;
+	XineramaScreenInfo	*xinerama;
+	struct group_ctx	*group_active;
+	struct group_ctx	 groups[CALMWM_NGROUPS];
+	int			 group_hideall;
+	struct group_ctx_q	 groupq;
 };
 
 TAILQ_HEAD(screen_ctx_q, screen_ctx);
@@ -157,23 +174,8 @@ struct client_ctx {
 	char			*app_cliarg;
 };
 
-TAILQ_HEAD(client_ctx_q, client_ctx);
-
 extern const char *shortcut_to_name[];
 
-#define CALMWM_NGROUPS 9
-struct group_ctx {
-	TAILQ_ENTRY(group_ctx)	 entry;
-	struct client_ctx_q	 clients;
-	const char		*name;
-	int			 shortcut;
-	int			 hidden;
-	int			 nhidden;
-	int			 highstack;
-};
-
-TAILQ_HEAD(group_ctx_q, group_ctx);
-
 /* Autogroups */
 struct autogroupwin {
 	TAILQ_ENTRY(autogroupwin) entry;
@@ -354,11 +356,12 @@ void			 client_vertmaximize(struct client_ctx *);
 void			 client_horizmaximize(struct client_ctx *);
 void			 client_map(struct client_ctx *);
 void			 client_mtf(struct client_ctx *);
-struct client_ctx	*client_cycle(int);
+struct client_ctx	*client_cycle(struct screen_ctx *, int);
 void			 client_getsizehints(struct client_ctx *);
 void			 client_applysizehints(struct client_ctx *);
 
-struct menu  		*menu_filter(struct menu_q *, char *, char *, int,
+struct menu  		*menu_filter(struct screen_ctx *, struct menu_q *,
+			     char *, char *, int,
 			     void (*)(struct menu_q *, struct menu_q *, char *),
 			     void (*)(struct menu *, int));
 void			 menu_init(struct screen_ctx *);
@@ -397,8 +400,7 @@ void			*xcalloc(size_t, size_t);
 char			*xstrdup(const char *);
 
 struct screen_ctx	*screen_fromroot(Window);
-struct screen_ctx	*screen_current(void);
-void			 screen_updatestackingorder(void);
+void			 screen_updatestackingorder(struct screen_ctx *);
 void			 screen_init_xinerama(struct screen_ctx *);
 XineramaScreenInfo	*screen_find_xinerama(struct screen_ctx *, int, int);
 
@@ -471,14 +473,14 @@ void			 search_match_text(struct menu_q *, struct menu_q *,
 void			 search_match_exec(struct menu_q *, struct menu_q *,
 			     char *);
 
-void			 group_init(void);
-void			 group_hidetoggle(int);
-void			 group_only(int);
-void			 group_cycle(int);
+void			 group_init(struct screen_ctx *);
+void			 group_hidetoggle(struct screen_ctx *, int);
+void			 group_only(struct screen_ctx *, int);
+void			 group_cycle(struct screen_ctx *, int);
 void			 group_sticky(struct client_ctx *);
 void			 group_client_delete(struct client_ctx *);
 void			 group_menu(XButtonEvent *);
-void			 group_alltoggle(void);
+void			 group_alltoggle(struct screen_ctx *);
 void			 group_sticky_toggle_enter(struct client_ctx *);
 void			 group_sticky_toggle_exit(struct client_ctx *);
 void			 group_autogroup(struct client_ctx *);
diff --git a/client.c b/client.c
index 1d4118b..2701f80 100644
--- a/client.c
+++ b/client.c
@@ -548,14 +548,12 @@ match:
 }
 
 struct client_ctx *
-client_cycle(int reverse)
+client_cycle(struct screen_ctx *sc, int reverse)
 {
 	struct client_ctx	*oldcc, *newcc;
-	struct screen_ctx	*sc;
 	int			 again = 1;
 
 	oldcc = client_current();
-	sc = screen_current();
 
 	/* If no windows then you cant cycle */
 	if (TAILQ_EMPTY(&sc->mruq))
diff --git a/group.c b/group.c
index 86aedc2..6b20027 100644
--- a/group.c
+++ b/group.c
@@ -24,15 +24,10 @@
 
 static void		 group_add(struct group_ctx *, struct client_ctx *);
 static void		 group_remove(struct client_ctx *);
-static void		 group_hide(struct group_ctx *);
-static void		 group_show(struct group_ctx *);
+static void		 group_hide(struct screen_ctx *, struct group_ctx *);
+static void		 group_show(struct screen_ctx *, struct group_ctx *);
 static void		 group_fix_hidden_state(struct group_ctx *);
 
-struct group_ctx	*Group_active = NULL;
-struct group_ctx	 Groups[CALMWM_NGROUPS];
-int			 Grouphideall = 0;
-struct group_ctx_q	 Groupq;
-
 const char *shortcut_to_name[] = {
 	"nogroup", "one", "two", "three", "four", "five", "six",
 	"seven", "eight", "nine"
@@ -72,11 +67,11 @@ group_remove(struct client_ctx *cc)
 }
 
 static void
-group_hide(struct group_ctx *gc)
+group_hide(struct screen_ctx *sc, struct group_ctx *gc)
 {
 	struct client_ctx	*cc;
 
-	screen_updatestackingorder();
+	screen_updatestackingorder(sc);
 
 	gc->nhidden = 0;
 	gc->highstack = 0;
@@ -90,7 +85,7 @@ group_hide(struct group_ctx *gc)
 }
 
 static void
-group_show(struct group_ctx *gc)
+group_show(struct screen_ctx *sc, struct group_ctx *gc)
 {
 	struct client_ctx	*cc;
 	Window			*winlist;
@@ -123,36 +118,40 @@ group_show(struct group_ctx *gc)
 	xfree(winlist);
 
 	gc->hidden = 0;
-	Group_active = gc;
+	sc->group_active = gc;
 }
 
 void
-group_init(void)
+group_init(struct screen_ctx *sc)
 {
 	int	 i;
 
-	TAILQ_INIT(&Groupq);
+	TAILQ_INIT(&sc->groupq);
+	sc->group_hideall = 0;
+	sc->group_active = NULL;
 
 	for (i = 0; i < CALMWM_NGROUPS; i++) {
-		TAILQ_INIT(&Groups[i].clients);
-		Groups[i].hidden = 0;
-		Groups[i].shortcut = i + 1;
-		Groups[i].name = shortcut_to_name[Groups[i].shortcut];
-		TAILQ_INSERT_TAIL(&Groupq, &Groups[i], entry);
+		TAILQ_INIT(&sc->groups[i].clients);
+		sc->groups[i].hidden = 0;
+		sc->groups[i].shortcut = i + 1;
+		sc->groups[i].name = shortcut_to_name[sc->groups[i].shortcut];
+		TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry);
 	}
 
-	Group_active = &Groups[0];
+	sc->group_active = &sc->groups[0];
 }
 
 void
 group_movetogroup(struct client_ctx *cc, int idx)
 {
+	struct screen_ctx	*sc = cc->sc;
+
 	if (idx < 0 || idx >= CALMWM_NGROUPS)
 		err(1, "group_movetogroup: index out of range (%d)", idx);
 
-	if(Group_active != &Groups[idx])
+	if(sc->group_active != &sc->groups[idx])
 		client_hide(cc);
-	group_add(&Groups[idx], cc);
+	group_add(&sc->groups[idx], cc);
 }
 
 /*
@@ -161,9 +160,10 @@ group_movetogroup(struct client_ctx *cc, int idx)
 void
 group_sticky_toggle_enter(struct client_ctx *cc)
 {
+	struct screen_ctx	*sc = cc->sc;
 	struct group_ctx	*gc;
 
-	gc = Group_active;
+	gc = sc->group_active;
 
 	if (gc == cc->group) {
 		group_remove(cc);
@@ -202,28 +202,29 @@ group_fix_hidden_state(struct group_ctx *gc)
 }
 
 void
-group_hidetoggle(int idx)
+group_hidetoggle(struct screen_ctx *sc, int idx)
 {
 	struct group_ctx	*gc;
 
 	if (idx < 0 || idx >= CALMWM_NGROUPS)
 		err(1, "group_hidetoggle: index out of range (%d)", idx);
 
-	gc = &Groups[idx];
+	gc = &sc->groups[idx];
 
 	group_fix_hidden_state(gc);
 
 	if (gc->hidden)
-		group_show(gc);
+		group_show(sc, gc);
 	else {
-		group_hide(gc);
+		group_hide(sc, gc);
+		/* XXX wtf? */
 		if (TAILQ_EMPTY(&gc->clients))
-			Group_active = gc;
+			sc->group_active = gc;
 	}
 }
 
 void
-group_only(int idx)
+group_only(struct screen_ctx *sc, int idx)
 {
 	int	 i;
 
@@ -232,9 +233,9 @@ group_only(int idx)
 
 	for (i = 0; i < CALMWM_NGROUPS; i++) {
 		if (i == idx)
-			group_show(&Groups[i]);
+			group_show(sc, &sc->groups[i]);
 		else
-			group_hide(&Groups[i]);
+			group_hide(sc, &sc->groups[i]);
 	}
 }
 
@@ -242,37 +243,37 @@ group_only(int idx)
  * Cycle through active groups.  If none exist, then just stay put.
  */
 void
-group_cycle(int reverse)
+group_cycle(struct screen_ctx *sc, int reverse)
 {
 	struct group_ctx	*gc, *showgroup = NULL;
 
-	assert(Group_active != NULL);
+	assert(sc->group_active != NULL);
 
-	gc = Group_active;
+	gc = sc->group_active;
 	for (;;) {
 		gc = reverse ? TAILQ_PREV(gc, group_ctx_q, entry) :
 		    TAILQ_NEXT(gc, entry);
 		if (gc == NULL)
-			gc = reverse ? TAILQ_LAST(&Groupq, group_ctx_q) :
-			    TAILQ_FIRST(&Groupq);
-		if (gc == Group_active)
+			gc = reverse ? TAILQ_LAST(&sc->groupq, group_ctx_q) :
+			    TAILQ_FIRST(&sc->groupq);
+		if (gc == sc->group_active)
 			break;
 
 		if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL)
 			showgroup = gc;
 		else if (!gc->hidden)
-			group_hide(gc);
+			group_hide(sc, gc);
 	}
 
 	if (showgroup == NULL)
 		return;
 
-	group_hide(Group_active);
+	group_hide(sc, sc->group_active);
 
 	if (showgroup->hidden)
-		group_show(showgroup);
+		group_show(sc, showgroup);
 	else
-		Group_active = showgroup;
+		sc->group_active = showgroup;
 }
 
 /* called when a client is deleted */
@@ -289,15 +290,17 @@ group_client_delete(struct client_ctx *cc)
 void
 group_menu(XButtonEvent *e)
 {
+	struct screen_ctx	*sc;
 	struct group_ctx	*gc;
 	struct menu		*mi;
 	struct menu_q		 menuq;
 	int			 i;
 
+	sc = screen_fromroot(e->root);
 	TAILQ_INIT(&menuq);
 
 	for (i = 0; i < CALMWM_NGROUPS; i++) {
-		gc = &Groups[i];
+		gc = &sc->groups[i];
 
 		if (TAILQ_EMPTY(&gc->clients))
 			continue;
@@ -316,14 +319,14 @@ group_menu(XButtonEvent *e)
 	if (TAILQ_EMPTY(&menuq))
 		return;
 
-	mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
+	mi = menu_filter(sc, &menuq, NULL, NULL, 0, NULL, NULL);
 
 	if (mi == NULL || mi->ctx == NULL)
 		goto cleanup;
 
 	gc = (struct group_ctx *)mi->ctx;
 
-	(gc->hidden) ? group_show(gc) : group_hide(gc);
+	(gc->hidden) ? group_show(sc, gc) : group_hide(sc, gc);
 
 cleanup:
 	while ((mi = TAILQ_FIRST(&menuq)) != NULL) {
@@ -333,23 +336,24 @@ cleanup:
 }
 
 void
-group_alltoggle(void)
+group_alltoggle(struct screen_ctx *sc)
 {
 	int	 i;
 
 	for (i = 0; i < CALMWM_NGROUPS; i++) {
-		if (Grouphideall)
-			group_show(&Groups[i]);
+		if (sc->group_hideall)
+			group_show(sc, &sc->groups[i]);
 		else
-			group_hide(&Groups[i]);
+			group_hide(sc, &sc->groups[i]);
 	}
 
-	Grouphideall = (Grouphideall) ? 0 : 1;
+	sc->group_hideall = (!sc->group_hideall);
 }
 
 void
 group_autogroup(struct client_ctx *cc)
 {
+	struct screen_ctx	*sc = cc->sc;
 	struct autogroupwin	*aw;
 	struct group_ctx	*gc;
 	unsigned char		*grpstr = NULL;
@@ -375,7 +379,7 @@ group_autogroup(struct client_ctx *cc)
 	if (strncmp("nogroup", group, 7) == 0)
 		return;
 
-	TAILQ_FOREACH(gc, &Groupq, entry) {
+	TAILQ_FOREACH(gc, &sc->groupq, entry) {
 		if (strcmp(shortcut_to_name[gc->shortcut], group) == 0) {
 			group_add(gc, cc);
 			return;
@@ -383,6 +387,6 @@ group_autogroup(struct client_ctx *cc)
 	}
 
 	if (Conf.flags & CONF_STICKY_GROUPS)
-		group_add(Group_active, cc);
+		group_add(sc->group_active, cc);
 
 }
diff --git a/kbfunc.c b/kbfunc.c
index c6c9ac1..c9377cd 100644
--- a/kbfunc.c
+++ b/kbfunc.c
@@ -126,10 +126,12 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
 void
 kbfunc_client_search(struct client_ctx *cc, union arg *arg)
 {
+	struct screen_ctx	*sc;
 	struct client_ctx	*old_cc;
 	struct menu		*mi;
 	struct menu_q		 menuq;
 
+	sc = cc->sc;
 	old_cc = client_current();
 
 	TAILQ_INIT(&menuq);
@@ -141,7 +143,7 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg)
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
 	}
 
-	if ((mi = menu_filter(&menuq, "window", NULL, 0,
+	if ((mi = menu_filter(sc, &menuq, "window", NULL, 0,
 	    search_match_client, search_print_client)) != NULL) {
 		cc = (struct client_ctx *)mi->ctx;
 		if (cc->flags & CLIENT_HIDDEN)
@@ -161,10 +163,12 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg)
 void
 kbfunc_menu_search(struct client_ctx *cc, union arg *arg)
 {
-	struct cmd	*cmd;
-	struct menu	*mi;
-	struct menu_q	 menuq;
+	struct screen_ctx	*sc;
+	struct cmd		*cmd;
+	struct menu		*mi;
+	struct menu_q		 menuq;
 
+	sc = cc->sc;
 	TAILQ_INIT(&menuq);
 
 	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
@@ -174,7 +178,7 @@ kbfunc_menu_search(struct client_ctx *cc, union arg *arg)
 		TAILQ_INSERT_TAIL(&menuq, mi, entry);
 	}
 
-	if ((mi = menu_filter(&menuq, "application", NULL, 0,
+	if ((mi = menu_filter(sc, &menuq, "application", NULL, 0,
 	    search_match_text, NULL)) != NULL)
 		u_spawn(((struct cmd *)mi->ctx)->image);
 
@@ -189,13 +193,13 @@ kbfunc_client_cycle(struct client_ctx *cc, union arg *arg)
 {
 	struct screen_ctx	*sc;
 
-	sc = screen_current();
+	sc = cc->sc;
 
 	/* XXX for X apps that ignore events */
 	XGrabKeyboard(X_Dpy, sc->rootwin, True,
 	    GrabModeAsync, GrabModeAsync, CurrentTime);
 
-	client_cycle(arg->i);
+	client_cycle(sc, arg->i);
 }
 
 void
@@ -226,15 +230,16 @@ void
 kbfunc_exec(struct client_ctx *cc, union arg *arg)
 {
 #define NPATHS 256
-	char		**ap, *paths[NPATHS], *path, *pathcpy, *label;
-	char		 tpath[MAXPATHLEN];
-	int		 l, i;
-	DIR		*dirp;
-	struct dirent	*dp;
-	struct menu	*mi;
-	struct menu_q	 menuq;
+	struct screen_ctx	*sc;
+	char			**ap, *paths[NPATHS], *path, *pathcpy, *label;
+	char			 tpath[MAXPATHLEN];
+	DIR			*dirp;
+	struct dirent		*dp;
+	struct menu		*mi;
+	struct menu_q		 menuq;
+	int			 l, i, cmd = arg->i;
 
-	int cmd = arg->i;
+	sc = cc->sc;
 	switch (cmd) {
 		case CWM_EXEC_PROGRAM:
 			label = "exec";
@@ -283,7 +288,7 @@ kbfunc_exec(struct client_ctx *cc, union arg *arg)
 	}
 	xfree(path);
 
-	if ((mi = menu_filter(&menuq, label, NULL, 1,
+	if ((mi = menu_filter(sc, &menuq, label, NULL, 1,
 	    search_match_exec, NULL)) != NULL) {
 		if (mi->text[0] == '\0')
 			goto out;
@@ -312,14 +317,17 @@ out:
 void
 kbfunc_ssh(struct client_ctx *cc, union arg *arg)
 {
-	struct menu	*mi;
-	struct menu_q	 menuq;
-	FILE		*fp;
-	char		*buf, *lbuf, *p, *home;
-	char		 hostbuf[MAXHOSTNAMELEN], filename[MAXPATHLEN];
-	char		 cmd[256];
-	int		 l;
-	size_t		 len;
+	struct screen_ctx	*sc;
+	struct menu		*mi;
+	struct menu_q		 menuq;
+	FILE			*fp;
+	char			*buf, *lbuf, *p, *home;
+	char			 hostbuf[MAXHOSTNAMELEN], filename[MAXPATHLEN];
+	char			 cmd[256];
+	int			 l;
+	size_t			 len;
+
+	sc = cc->sc;
 
 	if ((home = getenv("HOME")) == NULL)
 		return;
@@ -360,7 +368,7 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
 	xfree(lbuf);
 	fclose(fp);
 
-	if ((mi = menu_filter(&menuq, "ssh", NULL, 1,
+	if ((mi = menu_filter(sc, &menuq, "ssh", NULL, 1,
 	    search_match_exec, NULL)) != NULL) {
 		if (mi->text[0] == '\0')
 			goto out;
@@ -389,7 +397,7 @@ kbfunc_client_label(struct client_ctx *cc, union arg *arg)
 
 	current = cc->label;
 
-	if ((mi = menu_filter(&menuq, "label", current, 1,
+	if ((mi = menu_filter(cc->sc, &menuq, "label", current, 1,
 	    search_match_text, NULL)) != NULL) {
 		if (cc->label != NULL)
 			xfree(cc->label);
@@ -407,25 +415,25 @@ kbfunc_client_delete(struct client_ctx *cc, union arg *arg)
 void
 kbfunc_client_group(struct client_ctx *cc, union arg *arg)
 {
-	group_hidetoggle(KBTOGROUP(arg->i));
+	group_hidetoggle(cc->sc, KBTOGROUP(arg->i));
 }
 
 void
 kbfunc_client_grouponly(struct client_ctx *cc, union arg *arg)
 {
-	group_only(KBTOGROUP(arg->i));
+	group_only(cc->sc, KBTOGROUP(arg->i));
 }
 
 void
 kbfunc_client_cyclegroup(struct client_ctx *cc, union arg *arg)
 {
-	group_cycle(arg->i);
+	group_cycle(cc->sc, arg->i);
 }
 
 void
 kbfunc_client_nogroup(struct client_ctx *cc, union arg *arg)
 {
-	group_alltoggle();
+	group_alltoggle(cc->sc);
 }
 
 void
diff --git a/menu.c b/menu.c
index 2ac0d13..69f0588 100644
--- a/menu.c
+++ b/menu.c
@@ -69,11 +69,11 @@ menu_init(struct screen_ctx *sc)
 }
 
 struct menu *
-menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
+menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
+    char *initial, int dummy,
     void (*match)(struct menu_q *, struct menu_q *, char *),
     void (*print)(struct menu *, int))
 {
-	struct screen_ctx	*sc;
 	struct menu_ctx		 mc;
 	struct menu_q		 resultq;
 	struct menu		*mi = NULL;
@@ -81,8 +81,6 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
 	Window			 focuswin;
 	int			 evmask, focusrevert;
 
-	sc = screen_current();
-
 	TAILQ_INIT(&resultq);
 
 	bzero(&mc, sizeof(mc));
diff --git a/mousefunc.c b/mousefunc.c
index c0b3b1a..b66f64c 100644
--- a/mousefunc.c
+++ b/mousefunc.c
@@ -198,11 +198,13 @@ mousefunc_menu_group(struct client_ctx *cc, void *arg)
 void
 mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
 {
+	struct screen_ctx	*sc;
 	struct client_ctx	*old_cc;
 	struct menu		*mi;
 	struct menu_q		 menuq;
 	char			*wname;
 
+	sc = cc->sc;
 	old_cc = client_current();
 
 	TAILQ_INIT(&menuq);
@@ -221,7 +223,7 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
 	if (TAILQ_EMPTY(&menuq))
 		return;
 
-	mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
+	mi = menu_filter(sc, &menuq, NULL, NULL, 0, NULL, NULL);
 	if (mi != NULL) {
 		cc = (struct client_ctx *)mi->ctx;
 		client_unhide(cc);
@@ -240,9 +242,12 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
 void
 mousefunc_menu_cmd(struct client_ctx *cc, void *arg)
 {
-	struct menu	*mi;
-	struct menu_q	 menuq;
-	struct cmd	*cmd;
+	struct screen_ctx	*sc;
+	struct menu		*mi;
+	struct menu_q		 menuq;
+	struct cmd		*cmd;
+
+	sc = cc->sc;
 
 	TAILQ_INIT(&menuq);
 	TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
@@ -254,7 +259,7 @@ mousefunc_menu_cmd(struct client_ctx *cc, void *arg)
 	if (TAILQ_EMPTY(&menuq))
 		return;
 
-	mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
+	mi = menu_filter(sc, &menuq, NULL, NULL, 0, NULL, NULL);
 	if (mi != NULL)
 		u_spawn(((struct cmd *)mi->ctx)->image);
 	else
diff --git a/screen.c b/screen.c
index 6372362..6f73f2f 100644
--- a/screen.c
+++ b/screen.c
@@ -21,8 +21,6 @@
 #include "headers.h"
 #include "calmwm.h"
 
-extern struct screen_ctx	*Curscreen;
-
 struct screen_ctx *
 screen_fromroot(Window rootwin)
 {
@@ -36,22 +34,13 @@ screen_fromroot(Window rootwin)
 	return (TAILQ_FIRST(&Screenq));
 }
 
-struct screen_ctx *
-screen_current(void)
-{
-	return (Curscreen);
-}
-
 void
-screen_updatestackingorder(void)
+screen_updatestackingorder(struct screen_ctx *sc)
 {
 	Window			*wins, w0, w1;
-	struct screen_ctx	*sc;
 	struct client_ctx	*cc;
 	u_int			 nwins, i, s;
 
-	sc = screen_current();
-
 	if (!XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins))
 		return;
 
diff --git a/xevents.c b/xevents.c
index 8d24468..39586b1 100644
--- a/xevents.c
+++ b/xevents.c
@@ -227,7 +227,7 @@ static void
 xev_handle_buttonpress(XEvent *ee)
 {
 	XButtonEvent		*e = &ee->xbutton;
-	struct client_ctx	*cc;
+	struct client_ctx	*cc, fakecc;
 	struct screen_ctx	*sc;
 	struct mousebinding	*mb;
 
@@ -244,15 +244,13 @@ xev_handle_buttonpress(XEvent *ee)
 
 	if (mb == NULL)
 		return;
-
 	if (mb->context == MOUSEBIND_CTX_ROOT) {
 		if (e->window != sc->rootwin)
 			return;
-	} else if (mb->context == MOUSEBIND_CTX_WIN) {
-		cc = client_find(e->window);
-		if (cc == NULL)
-			return;
-	}
+		cc = &fakecc;
+		cc->sc = screen_fromroot(e->window);
+	} else if (cc == NULL) /* (mb->context == MOUSEBIND_CTX_WIN */
+		return;
 
 	(*mb->callback)(cc, e);
 }
@@ -270,7 +268,7 @@ static void
 xev_handle_keypress(XEvent *ee)
 {
 	XKeyEvent		*e = &ee->xkey;
-	struct client_ctx	*cc = NULL;
+	struct client_ctx	*cc = NULL, fakecc;
 	struct keybinding	*kb;
 	KeySym			 keysym, skeysym;
 	int			 modshift;
@@ -298,12 +296,14 @@ xev_handle_keypress(XEvent *ee)
 
 	if (kb == NULL)
 		return;
-
-	if ((kb->flags & (KBFLAG_NEEDCLIENT)) &&
-	    (cc = client_find(e->window)) == NULL &&
-	    (cc = client_current()) == NULL)
-		if (kb->flags & KBFLAG_NEEDCLIENT)
+	if (kb->flags & KBFLAG_NEEDCLIENT) {
+		if (((cc = client_find(e->window)) == NULL) &&
+		    (cc = client_current()) == NULL)
 			return;
+	} else {
+		cc = &fakecc;
+		cc->sc = screen_fromroot(e->window);
+	}
 
 	(*kb->callback)(cc, &kb->argument);
 }