On Thu, Apr 01, 2010 at 03:31:15AM +0100, Edd Barrett wrote: > Works well here, but the dmenu does not follow colour scheme.
This diff fixes the colour scheme of dmenu by treating the alt_wm feature as a custom_spawn, meaning it goes through the $some_color expansions just like normal dmenu does. So this adds a config variable 'program[alt_wm_menu]' which defaults to dmenu with colours matching the current scheme :) I updated the manual to reflect this. What do you think? Tested i386. 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 3 Apr 2010 16:20:47 -0000 @@ -79,6 +79,12 @@ 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. The menu program specified by the 'alt_wm_menu' program is +used to show the specified executables as choices of alternative window +managers. When one is selected, scrotwm will replace itself with the selected +executable. .It Cm color_focus Border color of the currently focussed window. .It Cm color_unfocus @@ -192,6 +198,8 @@ xlock initscreen.sh .It Cm menu dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color +.It Cm alt_wm_menu +dmenu \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color .El .Pp Custom programs in the configuration file are specified as follows: @@ -259,6 +267,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 +353,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 3 Apr 2010 16:20:50 -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(struct swm_region *r, char **args); +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,150 @@ restart(struct swm_region *r, union arg *args) quit(NULL, NULL); } +/* execute a new window manager */ +void +exec_alt_wm(struct swm_region *r, char **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)) { + fprintf(stderr, "exec_alt_wm: no alt_wms specified\n"); + return; + } + + if ((pipe(fd) == -1) || (pipe(fd1) == -1)) + err(1, "exec_alt_wm: cannot pipe"); + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + err(1, "exec_alt_wm: cannot 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: cannot 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: cannot malloc\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: cannot 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: cannot dup2"); + + if (dup2(fd1[1], STDOUT_FILENO) == -1) + err(1, "exec_alt_wm: cannot dup2"); + + if (execvp(args[0], args) == -1) + err(1, "exec_alt_wm: cannot execvp"); + + _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, + "exec_alt_wm: 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: cannot read"); + + if (i != 0) + snprintf(new_wm, i + 1, + "%s%s", new_wm, buf); + pipe_read += i; + } while (i != 0); /* until EOF */ + free(buf); + + 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; + + alarm(0); /* cancel any alarms */ + + if (execlp(new_wm, new_wm, (char *) 0) == -1) + warn("exec_alt_wm: cannot execlp new wm: %s", new_wm); + + alarm(bar_delay); /* put back alarm if we failed */ + free(new_wm); + } +} + +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 +2622,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 +2696,7 @@ struct keyfunc { union arg args; } keyfuncs[kf_invalid + 1] = { /* name function argument */ + { "exec_alt_wm", legacyfunc, {0} }, { "cycle_layout", cycle_layout, {0} }, { "stack_reset", stack_config, {.id = SWM_ARG_ID_STACKRESET} }, { "master_shrink", stack_config, {.id = SWM_ARG_ID_MASTERSHRINK} }, @@ -2726,7 +2882,13 @@ spawn_custom(struct swm_region *r, union arg *args, ch #endif a.argv = real_args; - spawn(r, &a); + + /* alt_wm_menu is a special case as it needs much piping etc... */ + if (!strcasecmp(spawn_name, "alt_wm_menu")) + exec_alt_wm(r, real_args); + else + spawn(r, &a); + for (i = 0; i < prog->argc; i++) free(real_args[i]); free(real_args); @@ -2868,6 +3030,12 @@ setup_spawn(void) " -nf $bar_font_color" " -sb $bar_border" " -sf $bar_color", 0); + setconfspawn("alt_wm_menu", "dmenu" + " -fn $bar_font" + " -nb $bar_color" + " -nf $bar_font_color" + " -sb $bar_border" + " -sf $bar_color", 0); } /* key bindings */ @@ -3080,6 +3248,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_spawn_custom, "alt_wm_menu"); 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 +3520,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 +3590,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 +3650,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 +4826,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,6 +4934,7 @@ main(int argc, char *argv[]) } done: bar_extra_stop(); + free_alt_wm_list(); XCloseDisplay(display); 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 3 Apr 2010 16:20:50 -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 -- Best Regards Edd Barrett http://www.theunixzoo.co.uk