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

Reply via email to