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.
This commit is contained in:
okan 2017-12-29 20:03:46 +00:00
parent 43db5b55ea
commit 6e7dbf5bb7
7 changed files with 109 additions and 39 deletions

View File

@ -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);

33
conf.c
View File

@ -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)
{

2
cwm.1
View File

@ -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

View File

@ -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

View File

@ -545,6 +545,33 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
menuq_clear(&menuq);
}
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)
{
@ -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)

13
parse.y
View File

@ -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;

View File

@ -227,6 +227,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)
{
@ -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);
}