I agree with dwc's assesment. You need to make sure dmenu is the magical tool.

On Mar 7, 2010, at 5:54 PM, Darrin Chandler <dwchand...@stilyagin.com> wrote:

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
dwchand...@stilyagin.com   |  http://phxbug.org/      |  http://metabug.org/
http://www.stilyagin.com/ | Daemons in the Desert | Global BUG Federation

Reply via email to