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

Reply via email to