On Sun, Mar 07, 2010 at 10:21:39PM +0000, Edd Barrett wrote: > Hi guys, > > I have had this patch sitting around in my $HOME for a while. It allows the > user > to exit scrotwm to another window manager (one of the ones they define in > ~/.scrotwm.conf) via a dmenu. The idea was taken from cwm. > > What do you think? > > OK to put into scrotwm?
What happens if you are using a different menu program, or have no menu program installed at all? I don't like harcoding to dmenu. Aside from that it's a nice idea. > -- > Best Regards > Edd Barrett > > http://www.theunixzoo.co.uk > opencvs server: Diffing inside . > Index: scrotwm.1 > =================================================================== > RCS file: /scrotwm/scrotwm/scrotwm.1,v > retrieving revision 1.28 > diff -N -u -p -u scrotwm.1 > --- scrotwm.1 7 Oct 2009 03:19:11 -0000 1.28 > +++ scrotwm.1 21 Feb 2010 20:19:12 -0000 > @@ -79,6 +79,8 @@ Enabling or disabling an option is done by using 1 or > The file supports the following keywords: > .Pp > .Bl -tag -width "title_class_enabledXXX" -offset indent -compact > +.It Cm alt_wms > +A comma separated list of alternative window managers for use with > exec_alt_wm. > .It Cm color_focus > Border color of the currently focussed window. > .It Cm color_unfocus > @@ -259,6 +261,8 @@ The default key bindings are described below: > term > .It Cm M-p > menu > +.It Cm M-r > +exec_alt_wm > .It Cm M-S-q > quit > .It Cm M-q > @@ -343,6 +347,8 @@ Menu > (see > .Sx PROGRAMS > above) > +.It Cm exec_alt_wm > +Execute an alternative window manager > .It Cm quit > Quit > .Nm > Index: scrotwm.c > =================================================================== > RCS file: /scrotwm/scrotwm/scrotwm.c,v > retrieving revision 1.281 > diff -N -u -p -u scrotwm.c > --- scrotwm.c 13 Jan 2010 23:22:31 -0000 1.281 > +++ scrotwm.c 21 Feb 2010 20:19:13 -0000 > @@ -179,6 +179,7 @@ int cycle_visible = 0; > int term_width = 0; > int font_adjusted = 0; > unsigned int mod_key = MODKEY; > +int ret_status = -1; /* store return status of fork/exec */ > > /* dialog windows */ > double dialog_ratio = .6; > @@ -385,6 +386,15 @@ struct quirk { > int quirks_size = 0, quirks_length = 0; > struct quirk *quirks = NULL; > > +/* alternative window managers */ > +struct alt_wm { > + SLIST_ENTRY(alt_wm) entries; > + char *wm; > +}; > +SLIST_HEAD(head, alt_wm) alt_wms; > +void exec_alt_wm(); > +void free_alt_wm_list(); > + > /* events */ > #ifdef SWM_DEBUG > void > @@ -587,7 +597,7 @@ sighdlr(int sig) > > switch (sig) { > case SIGCHLD: > - while ((pid = waitpid(WAIT_ANY, NULL, WNOHANG)) != -1) { > + while ((pid = waitpid(WAIT_ANY, &ret_status, WNOHANG)) != -1) { > DNPRINTF(SWM_D_MISC, "reaping: %d\n", pid); > if (pid <= 0) > break; > @@ -1135,6 +1145,148 @@ restart(struct swm_region *r, union arg *args) > quit(NULL, NULL); > } > > +/* execute a new window manager */ > +void > +exec_alt_wm(struct swm_region *r, union arg *args) > +{ > + int fd[2], fd1[2], pipe_written = 0; > + int pipe_read = 0, found_choice = 0; > + int max_wm_len = -1, cur_wm_len; > + int pipe_in_sz = 0, i, pid; > + char *new_wm = NULL, *buf = NULL, *pipe_in; > + struct alt_wm *wm_node; > + > + if (SLIST_EMPTY(&alt_wms)) > + return; > + > + if ((pipe(fd) == -1) || (pipe(fd1) == -1)) > + err(1, "exec_alt_wm: pipe fail"); > + > + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) > + err(1, "exec_alt_wm: could not disable SIGPIPE"); > + > + /* work out how many wms and the longest name */ > + SLIST_FOREACH(wm_node, &alt_wms, entries) { > + cur_wm_len = strlen(wm_node->wm); > + pipe_in_sz = pipe_in_sz + cur_wm_len + 1; /* +1 \n */ > + if (max_wm_len < cur_wm_len) > + max_wm_len = cur_wm_len; > + } > + pipe_in_sz ++; /* \0 */ > + > + pid = fork(); > + switch (pid) { > + case -1: > + err(1, "exec_alt_wm: can't fork"); > + break; > + case 0: /* we are the child */ > + close(fd1[0]); > + > + /* build \n delimited records for dmenu */ > + pipe_in = malloc(pipe_in_sz); > + if (pipe_in == NULL) > + err(1, "exec_alt_wm: malloc failed\n"); > + > + memset(pipe_in, 0, pipe_in_sz); > + > + SLIST_FOREACH(wm_node, &alt_wms, entries) > + snprintf(pipe_in, pipe_in_sz, "%s%s\n", > + pipe_in, wm_node->wm); > + > + while (pipe_written != pipe_in_sz) { > + i = write(fd[1], pipe_in + pipe_written, > + pipe_in_sz - pipe_written); > + > + if (i == -1) { > + err(1, "alt_wm: can't write"); > + i = 0; /* try again */ > + } > + pipe_written += i; > + } > + close(fd[1]); > + free(pipe_in); > + > + /* replace stdin/stdout */ > + if (dup2(fd[0], STDIN_FILENO) == -1) > + err(1, "exec_alt_wm: can't dup2"); > + > + if (dup2(fd1[1], STDOUT_FILENO) == -1) > + err(1, "exec_alt_wm: can't dup2(2)"); > + > + if (execlp("dmenu", "dmenu", (char *)0) == -1) > + err(1, "exec_alt_wm: can't execlp"); > + > + _exit(0); > + break; > + default: /* parent */ > + close(fd[1]); > + close(fd1[1]); > + > + /* This will always be interrupted by signal handler */ > + if ((wait(NULL) == -1) && (errno != EINTR)) > + err(1, "exec_alt_wm: wait failed"); > + else if (ret_status != 0) { > + fprintf(stderr, > + "scrotwm: dmenu returned non-zero (%d)\n", > + ret_status); > + return; > + } > + > + buf = malloc(max_wm_len + 1); > + new_wm = malloc(max_wm_len + 1); > + if ((buf == NULL) || (new_wm == NULL)) > + err(1, "exec_alt_wm: cannot malloc()"); > + > + memset(buf, 0, max_wm_len + 1); > + memset(new_wm, 0, max_wm_len + 1); > + > + do { > + i = read(fd1[0], buf, max_wm_len - pipe_read + 1); > + if (i == -1) > + err(1, "exec_alt_wm: can't read"); > + > + if (i != 0) > + snprintf(new_wm, i + 1, > + "%s%s", new_wm, buf); > + pipe_read += i; > + } while (i != 0); /* until EOF */ > + > + if (pipe_read == 0) /* user probably pressed escape */ > + return; > + > + /* check what was typed was one of the choices */ > + SLIST_FOREACH(wm_node, &alt_wms, entries) > + if (strcmp(wm_node->wm, new_wm) == 0) > + found_choice = 1; > + > + if (!found_choice) > + return; > + > + free(buf); > + free(new_wm); > + alarm(0); /* cancel any alarms */ > + > + if (execlp(new_wm, new_wm, (char *) 0) == -1) > + warn("exec_alt_wm: can't execlp new wm: %s", new_wm); > + > + alarm(bar_delay); /* put back alarm if we failed */ > + } > +} > + > +void > +free_alt_wm_list() > +{ > + struct alt_wm *n; > + > + while (!SLIST_EMPTY(&alt_wms)) { > + n = SLIST_FIRST(&alt_wms); > + printf("free: %s\n", n->wm); > + SLIST_REMOVE_HEAD(&alt_wms, entries); > + free(n->wm); > + free(n); > + } > +} > + > struct swm_region * > root_to_region(Window root) > { > @@ -2468,6 +2620,7 @@ move(struct ws_win *win, union arg *args) > > /* user/key callable function IDs */ > enum keyfuncid { > + kf_alt_wm, > kf_cycle_layout, > kf_stack_reset, > kf_master_shrink, > @@ -2541,6 +2694,7 @@ struct keyfunc { > union arg args; > } keyfuncs[kf_invalid + 1] = { > /* name function argument */ > + { "exec_alt_wm", exec_alt_wm, {0} }, > { "cycle_layout", cycle_layout, {0} }, > { "stack_reset", stack_config, {.id = SWM_ARG_ID_STACKRESET} }, > { "master_shrink", stack_config, {.id = SWM_ARG_ID_MASTERSHRINK} > }, > @@ -3080,6 +3234,7 @@ setup_keys(void) > setkeybinding(MODKEY, XK_p, kf_spawn_custom, > "menu"); > setkeybinding(MODKEY|ShiftMask, XK_q, kf_quit, NULL); > setkeybinding(MODKEY, XK_q, kf_restart, NULL); > + setkeybinding(MODKEY, XK_r, kf_alt_wm, NULL); > setkeybinding(MODKEY, XK_m, kf_focus_main, NULL); > setkeybinding(MODKEY, XK_1, kf_ws_1, NULL); > setkeybinding(MODKEY, XK_2, kf_ws_2, NULL); > @@ -3351,12 +3506,16 @@ enum { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, > SWM_S_STACK > SWM_S_CLOCK_ENABLED, SWM_S_CLOCK_FORMAT, SWM_S_CYCLE_EMPTY, > SWM_S_CYCLE_VISIBLE, SWM_S_SS_ENABLED, SWM_S_TERM_WIDTH, > SWM_S_TITLE_CLASS_ENABLED, SWM_S_TITLE_NAME_ENABLED, SWM_S_BAR_FONT, > - SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM, SWM_S_SS_APP, SWM_S_DIALOG_RATIO > + SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM, SWM_S_SS_APP, SWM_S_DIALOG_RATIO, > + SWM_S_ALT_WMS > }; > > int > setconfvalue(char *selector, char *value, int flags) > { > + char *wm; > + struct alt_wm *wm_node; > + > switch (flags) { > case SWM_S_BAR_DELAY: > bar_delay = atoi(value); > @@ -3417,6 +3576,23 @@ setconfvalue(char *selector, char *value, int flags) > if (dialog_ratio > 1.0 || dialog_ratio <= .3) > dialog_ratio = .6; > break; > + case SWM_S_ALT_WMS: > + for (wm = strtok(value, ","); wm != NULL; > + wm = strtok(NULL, ",")) { > + wm_node = malloc(sizeof(struct alt_wm)); > + if (wm_node == NULL) { > + fprintf(stderr, "setconfvalue: malloc > failed\n"); > + perror(" failed"); > + quit(NULL, NULL); > + } > + > + wm_node->wm = strdup(wm); > + if (wm_node->wm == NULL) > + err(1, "setconfvalue: can't strdup wm name"); > + > + SLIST_INSERT_HEAD(&alt_wms, wm_node, entries); > + } > + break; > default: > return (1); > } > @@ -3460,6 +3636,7 @@ struct config_option { > int funcflags; > }; > struct config_option configopt[] = { > + { "alt_wms", setconfvalue, SWM_S_ALT_WMS }, > { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, > { "bar_border", setconfcolor, SWM_S_COLOR_BAR_BORDER > }, > { "bar_color", setconfcolor, SWM_S_COLOR_BAR }, > @@ -4635,6 +4812,9 @@ main(int argc, char *argv[]) > adelete = XInternAtom(display, "WM_DELETE_WINDOW", False); > takefocus = XInternAtom(display, "WM_TAKE_FOCUS", False); > > + /* init list of alternative wms */ > + SLIST_INIT(&alt_wms); > + > /* look for local and global conf file */ > pwd = getpwuid(getuid()); > if (pwd == NULL) > @@ -4740,7 +4920,7 @@ main(int argc, char *argv[]) > } > done: > bar_extra_stop(); > - > + free_alt_wm_list(); > XCloseDisplay(display); > > return (0); > Index: scrotwm.conf > =================================================================== > RCS file: /scrotwm/scrotwm/scrotwm.conf,v > retrieving revision 1.23 > diff -N -u -p -u scrotwm.conf > --- scrotwm.conf 13 Jan 2010 21:48:35 -0000 1.23 > +++ scrotwm.conf 21 Feb 2010 20:19:13 -0000 > @@ -55,6 +55,7 @@ dialog_ratio = 0.6 > #bind[swap_prev] = MOD+Shift+k > #bind[spawn_term] = MOD+Shift+Return > #bind[menu] = MOD+p > +#bind[exec_alt_wm] = MOD+r > #bind[quit] = MOD+Shift+q > #bind[restart] = MOD+q > #bind[focus_main] = MOD+m > @@ -114,3 +115,6 @@ dialog_ratio = 0.6 > # EXAMPLE: define firefox program and bind to key > # program[firefox] = firefox http://scrotwm.org/ > # bind[firefox] = MOD+f > + > +# alternative window managers > +alt_wms = cwm,fvwm > opencvs server: Diffing inside html > opencvs server: Diffing inside lib > opencvs server: Diffing inside linux > opencvs server: Diffing inside osx > opencvs server: Diffing inside port > opencvs server: Diffing inside port/patches > opencvs server: Diffing inside port/pkg -- Darrin Chandler | Phoenix BSD User Group | MetaBUG [email protected] | http://phxbug.org/ | http://metabug.org/ http://www.stilyagin.com/ | Daemons in the Desert | Global BUG Federation
