summary refs log tree commit diff
diff options
context:
space:
mode:
authorokan <okan>2017-12-29 20:03:46 +0000
committerokan <okan>2017-12-29 20:03:46 +0000
commit6e7dbf5bb71d56bb3443f57cb6b8707a291fe0d2 (patch)
tree6e842f14936d6a213a69c49587ce62cb92512925
parent43db5b55eaae67515ae926c0d195c1ef6aa4b607 (diff)
downloadcwm-6e7dbf5bb71d56bb3443f57cb6b8707a291fe0d2.tar.gz
cwm-6e7dbf5bb71d56bb3443f57cb6b8707a291fe0d2.tar.xz
cwm-6e7dbf5bb71d56bb3443f57cb6b8707a291fe0d2.zip
Convert menu-exec-wm from an abritrary exec menu, into a config-based menu from
which one may configure (wm <name> <path_and_args>) (and choose) specific
window managers to replace the running one. 'wm cwm cwm' is included by
default.

No objections and seems sensible to sthen.
-rw-r--r--calmwm.h12
-rw-r--r--conf.c33
-rw-r--r--cwm.12
-rw-r--r--cwmrc.56
-rw-r--r--kbfunc.c58
-rw-r--r--parse.y13
-rw-r--r--search.c24
7 files changed, 109 insertions, 39 deletions
diff --git a/calmwm.h b/calmwm.h
index d289ceb..0913a76 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -255,11 +255,8 @@ struct cmd_ctx {
 	char			 path[PATH_MAX];
 };
 TAILQ_HEAD(cmd_q, cmd_ctx);
+TAILQ_HEAD(wm_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
@@ -284,6 +281,7 @@ struct conf {
 	struct autogroup_q	 autogroupq;
 	struct ignore_q		 ignoreq;
 	struct cmd_q		 cmdq;
+	struct wm_q		 wmq;
 	int			 ngroups;
 	int			 stickygroups;
 	int			 nameqlen;
@@ -457,10 +455,13 @@ void			 search_match_cmd(struct menu_q *, struct menu_q *,
 			     char *);
 void			 search_match_group(struct menu_q *, struct menu_q *,
 			     char *);
+void			 search_match_wm(struct menu_q *, struct menu_q *,
+			     char *);
 void			 search_print_client(struct menu *, int);
 void			 search_print_cmd(struct menu *, int);
 void			 search_print_group(struct menu *, int);
 void			 search_print_text(struct menu *, int);
+void			 search_print_wm(struct menu *, int);
 
 struct region_ctx	*region_find(struct screen_ctx *, int, int);
 struct geom		 screen_apply_gap(struct screen_ctx *, struct geom);
@@ -500,6 +501,7 @@ void			 kbfunc_group_alltoggle(void *, struct cargs *);
 void			 kbfunc_menu_client(void *, struct cargs *);
 void			 kbfunc_menu_cmd(void *, struct cargs *);
 void			 kbfunc_menu_group(void *, struct cargs *);
+void			 kbfunc_menu_wm(void *, struct cargs *);
 void			 kbfunc_menu_exec(void *, struct cargs *);
 void			 kbfunc_menu_ssh(void *, struct cargs *);
 void			 kbfunc_client_menu_label(void *, struct cargs *);
@@ -529,6 +531,8 @@ void			 conf_clear(struct conf *);
 void			 conf_client(struct client_ctx *);
 int			 conf_cmd_add(struct conf *, const char *,
 			     const char *);
+int			 conf_wm_add(struct conf *, const char *,
+			     const char *);
 void			 conf_cursor(struct conf *);
 void			 conf_grab_kbd(Window);
 void			 conf_grab_mouse(Window);
diff --git a/conf.c b/conf.c
index 9668e94..9ef730f 100644
--- a/conf.c
+++ b/conf.c
@@ -193,10 +193,8 @@ static const struct {
 	    CWM_MENU_WINDOW_ALL },
 	{ "menu-window-hidden", kbfunc_menu_client, CWM_CONTEXT_SC,
 	    CWM_MENU_WINDOW_HIDDEN },
-	{ "menu-exec", kbfunc_menu_exec, CWM_CONTEXT_SC,
-	    CWM_MENU_EXEC_EXEC },
-	{ "menu-exec-wm", kbfunc_menu_exec, CWM_CONTEXT_SC,
-	    CWM_MENU_EXEC_WM },
+	{ "menu-exec", kbfunc_menu_exec, CWM_CONTEXT_SC, 0 },
+	{ "menu-exec-wm", kbfunc_menu_wm, CWM_CONTEXT_SC, 0 },
 
 	{ "terminal", kbfunc_exec_term, CWM_CONTEXT_SC, 0 },
 	{ "lock", kbfunc_exec_lock, CWM_CONTEXT_SC, 0 },
@@ -298,6 +296,7 @@ conf_init(struct conf *c)
 
 	TAILQ_INIT(&c->ignoreq);
 	TAILQ_INIT(&c->cmdq);
+	TAILQ_INIT(&c->wmq);
 	TAILQ_INIT(&c->keybindq);
 	TAILQ_INIT(&c->autogroupq);
 	TAILQ_INIT(&c->mousebindq);
@@ -314,6 +313,8 @@ conf_init(struct conf *c)
 	conf_cmd_add(c, "lock", "xlock");
 	conf_cmd_add(c, "term", "xterm");
 
+	conf_wm_add(c, "cwm", "cwm");
+
 	(void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s",
 	    c->homedir, ".ssh/known_hosts");
 
@@ -327,7 +328,7 @@ conf_clear(struct conf *c)
 	struct autogroup	*ag;
 	struct bind_ctx		*kb, *mb;
 	struct winname		*wn;
-	struct cmd_ctx		*cmd;
+	struct cmd_ctx		*cmd, *wm;
 	int			 i;
 
 	while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) {
@@ -335,6 +336,11 @@ conf_clear(struct conf *c)
 		free(cmd->name);
 		free(cmd);
 	}
+	while ((wm = TAILQ_FIRST(&c->wmq)) != NULL) {
+		TAILQ_REMOVE(&c->wmq, wm, entry);
+		free(wm->name);
+		free(wm);
+	}
 	while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) {
 		TAILQ_REMOVE(&c->keybindq, kb, entry);
 		free(kb);
@@ -393,6 +399,23 @@ conf_cmd_remove(struct conf *c, const char *name)
 	}
 }
 
+int
+conf_wm_add(struct conf *c, const char *name, const char *path)
+{
+	struct cmd_ctx	*wm;
+
+	wm = xmalloc(sizeof(*wm));
+	wm->name = xstrdup(name);
+	if (strlcpy(wm->path, path, sizeof(wm->path)) >= sizeof(wm->path)) {
+		free(wm->name);
+		free(wm);
+		return(0);
+	}
+
+	TAILQ_INSERT_TAIL(&c->wmq, wm, entry);
+	return(1);
+}
+
 void
 conf_autogroup(struct conf *c, int num, const char *name, const char *class)
 {
diff --git a/cwm.1 b/cwm.1
index d8ffb07..5c258ca 100644
--- a/cwm.1
+++ b/cwm.1
@@ -143,7 +143,7 @@ will be executed via the configured terminal emulator.
 .It Ic CM-w
 Spawn
 .Dq exec WindowManager
-dialog, allowing a switch to another window manager.
+menu, allowing a switch to another window manager.
 .It Ic CMS-r
 Restart.
 .It Ic CMS-q
diff --git a/cwmrc.5 b/cwmrc.5
index 6851faa..2e16850 100644
--- a/cwmrc.5
+++ b/cwmrc.5
@@ -245,6 +245,12 @@ A special
 keyword
 .Dq all
 can be used to unbind all buttons.
+.It Ic wm Ar name path
+Every
+.Ar name
+entry is shown in the wm menu.
+When selected, the window manager is replaced by
+.Ar path .
 .El
 .Sh BIND FUNCTION LIST
 .Bl -tag -width 23n -compact
diff --git a/kbfunc.c b/kbfunc.c
index cf3f7e3..4fc0b4d 100644
--- a/kbfunc.c
+++ b/kbfunc.c
@@ -546,6 +546,33 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
 }
 
 void
+kbfunc_menu_wm(void *ctx, struct cargs *cargs)
+{
+	struct screen_ctx	*sc = ctx;
+	struct cmd_ctx		*wm;
+	struct menu		*mi;
+	struct menu_q		 menuq;
+	int			 mflags = 0;
+
+	if (cargs->xev == CWM_XEV_BTN)
+		mflags |= CWM_MENU_LIST;
+
+	TAILQ_INIT(&menuq);
+	TAILQ_FOREACH(wm, &Conf.wmq, entry)
+		menuq_add(&menuq, wm, NULL);
+
+	if ((mi = menu_filter(sc, &menuq, "wm", NULL, mflags,
+	    search_match_wm, search_print_wm)) != NULL) {
+		wm = (struct cmd_ctx *)mi->ctx;
+		free(Conf.wm_argv);
+		Conf.wm_argv = xstrdup(wm->path);
+		cwm_status = CWM_EXEC_WM;
+	}
+
+	menuq_clear(&menuq);
+}
+
+void
 kbfunc_menu_exec(void *ctx, struct cargs *cargs)
 {
 #define NPATHS 256
@@ -553,26 +580,13 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs)
 	char			**ap, *paths[NPATHS], *path, *pathcpy;
 	char			 tpath[PATH_MAX];
 	struct stat		 sb;
-	const char		*label;
 	DIR			*dirp;
 	struct dirent		*dp;
 	struct menu		*mi;
 	struct menu_q		 menuq;
-	int			 l, i, cmd = cargs->flag;
+	int			 l, i;
 	int			 mflags = (CWM_MENU_DUMMY | CWM_MENU_FILE);
 
-	switch (cmd) {
-	case CWM_MENU_EXEC_EXEC:
-		label = "exec";
-		break;
-	case CWM_MENU_EXEC_WM:
-		label = "wm";
-		break;
-	default:
-		errx(1, "%s: invalid cmd %d", __func__, cmd);
-		/* NOTREACHED */
-	}
-
 	TAILQ_INIT(&menuq);
 
 	if ((path = getenv("PATH")) == NULL)
@@ -611,23 +625,11 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs)
 	}
 	free(path);
 
-	if ((mi = menu_filter(sc, &menuq, label, NULL, mflags,
+	if ((mi = menu_filter(sc, &menuq, "exec", NULL, mflags,
 	    search_match_exec, search_print_text)) != NULL) {
 		if (mi->text[0] == '\0')
 			goto out;
-		switch (cmd) {
-		case CWM_MENU_EXEC_EXEC:
-			u_spawn(mi->text);
-			break;
-		case CWM_MENU_EXEC_WM:
-			cwm_status = CWM_EXEC_WM;
-			free(Conf.wm_argv);
-			Conf.wm_argv = xstrdup(mi->text);
-			break;
-		default:
-			errx(1, "%s: egad, cmd changed value!", __func__);
-			/* NOTREACHED */
-		}
+		u_spawn(mi->text);
 	}
 out:
 	if (mi != NULL && mi->dummy)
diff --git a/parse.y b/parse.y
index 0c9606a..fbc19ed 100644
--- a/parse.y
+++ b/parse.y
@@ -70,7 +70,7 @@ typedef struct {
 
 %token	BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE
 %token	FONTNAME STICKY GAP
-%token	AUTOGROUP COMMAND IGNORE
+%token	AUTOGROUP COMMAND IGNORE WM
 %token	YES NO BORDERWIDTH MOVEAMOUNT
 %token	COLOR SNAPDIST
 %token	ACTIVEBORDER INACTIVEBORDER URGENCYBORDER
@@ -146,6 +146,16 @@ main		: FONTNAME STRING		{
 			free($2);
 			free($3);
 		}
+		| WM STRING string	{
+			if (!conf_wm_add(conf, $2, $3)) {
+				yyerror("wm name/path too long");
+				free($2);
+				free($3);
+				YYERROR;
+			}
+			free($2);
+			free($3);
+		}
 		| AUTOGROUP NUMBER STRING	{
 			if ($2 < 0 || $2 > 9) {
 				yyerror("invalid autogroup");
@@ -317,6 +327,7 @@ lookup(char *s)
 		{ "unbind-mouse",	UNBINDMOUSE},
 		{ "ungroupborder",	UNGROUPBORDER},
 		{ "urgencyborder",	URGENCYBORDER},
+		{ "wm",			WM},
 		{ "yes",		YES}
 	};
 	const struct keywords	*p;
diff --git a/search.c b/search.c
index 59aa841..7d3bd21 100644
--- a/search.c
+++ b/search.c
@@ -228,6 +228,21 @@ search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
 }
 
 void
+search_match_wm(struct menu_q *menuq, struct menu_q *resultq, char *search)
+{
+	struct menu		*mi;
+	struct cmd_ctx		*wm;
+
+	TAILQ_INIT(resultq);
+	TAILQ_FOREACH(mi, menuq, entry) {
+		wm = (struct cmd_ctx *)mi->ctx;
+		if ((match_substr(search, wm->name, 0)) ||
+		    (match_substr(search, wm->path, 0)))
+			TAILQ_INSERT_TAIL(resultq, mi, resultentry);
+	}
+}
+
+void
 search_print_client(struct menu *mi, int listing)
 {
 	struct client_ctx	*cc = (struct client_ctx *)mi->ctx;
@@ -266,3 +281,12 @@ search_print_text(struct menu *mi, int listing)
 {
 	(void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text);
 }
+
+void
+search_print_wm(struct menu *mi, int listing)
+{
+	struct cmd_ctx		*wm = (struct cmd_ctx *)mi->ctx;
+
+	(void)snprintf(mi->print, sizeof(mi->print), "%s [%s]",
+	    wm->name, wm->path);
+}