JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Add comment and link to man page. Turns out a lot of people don't know
[spectrwm.git] / scrotwm.c
index 4e9ecfd..10806c9 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -332,8 +332,10 @@ struct layout {
        { NULL,                 NULL,                   0,      NULL  },
 };
 
-/* position of max_stack mode in the layouts array */
-#define SWM_MAX_STACK          2
+/* position of max_stack mode in the layouts array, index into layouts! */
+#define SWM_V_STACK            (0)
+#define SWM_H_STACK            (1)
+#define SWM_MAX_STACK          (2)
 
 #define SWM_H_SLICE            (32)
 #define SWM_V_SLICE            (32)
@@ -341,6 +343,7 @@ struct layout {
 /* define work spaces */
 struct workspace {
        int                     idx;            /* workspace index */
+       int                     always_raise;   /* raise windows on focus */
        struct layout           *cur_layout;    /* current layout handlers */
        struct ws_win           *focus;         /* may be NULL */
        struct ws_win           *focus_prev;    /* may be NULL */
@@ -1957,11 +1960,11 @@ focus_win(struct ws_win *win)
                if (win->java == 0)
                        XSetInputFocus(display, win->id,
                            RevertToParent, CurrentTime);
-               XMapRaised(display, win->id);
                grabbuttons(win, 1);
                XSetWindowBorder(display, win->id,
                    win->ws->r->s->c[SWM_S_COLOR_FOCUS].color);
-               if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS)
+               if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
+                   win->ws->always_raise)
                        XMapRaised(display, win->id);
 
                XChangeProperty(display, win->s->root,
@@ -3000,6 +3003,19 @@ send_to_ws(struct swm_region *r, union arg *args)
 }
 
 void
+raise_toggle(struct swm_region *r, union arg *args)
+{
+       if (r && r->ws == NULL)
+               return;
+
+       r->ws->always_raise = !r->ws->always_raise;
+
+       /* bring floaters back to top */
+       if (r->ws->always_raise == 0)
+               stack();
+}
+
+void
 iconify(struct swm_region *r, union arg *args)
 {
        union arg a;
@@ -3484,6 +3500,7 @@ enum keyfuncid {
        kf_spawn_custom,
        kf_iconify,
        kf_uniconify,
+       kf_raise_toggle,
        kf_dumpwins, /* MUST BE LAST */
        kf_invalid
 };
@@ -3560,6 +3577,7 @@ struct keyfunc {
        { "spawn_custom",       dummykeyfunc,   {0} },
        { "iconify",            iconify,        {0} },
        { "uniconify",          uniconify,      {0} },
+       { "raise_toggle",       raise_toggle,   {0} },
        { "dumpwins",           dumpwins,       {0} }, /* MUST BE LAST */
        { "invalid key func",   NULL,           {0} },
 };
@@ -4151,6 +4169,7 @@ setup_keys(void)
        setkeybinding(MODKEY|ShiftMask, XK_i,           kf_spawn_custom,        "initscr");
        setkeybinding(MODKEY,           XK_w,           kf_iconify,     NULL);
        setkeybinding(MODKEY|ShiftMask, XK_w,           kf_uniconify,   NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_r,           kf_raise_toggle,NULL);
 #ifdef SWM_DEBUG
        setkeybinding(MODKEY|ShiftMask, XK_d,           kf_dumpwins,    NULL);
 #endif
@@ -4524,8 +4543,9 @@ setautorun(char *selector, char *value, int flags)
 {
        int                     ws_id;
        char                    s[1024];
+       char                    *ap, *sp = s;
        union arg               a;
-       char                    *real_args[] = { NULL, NULL };
+       int                     argc = 0;
        long                    pid;
        struct pid_e            *p;
 
@@ -4533,11 +4553,11 @@ setautorun(char *selector, char *value, int flags)
                return (0);
 
        bzero(s, sizeof s);
-       if (sscanf(value, "ws[%d]:%1023s", &ws_id, s) != 2)
-               errx(1, "invalid autorun entry, should be 'ws:command'\n");
+       if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2)
+               errx(1, "invalid autorun entry, should be 'ws[<idx>]:command'\n");
        ws_id--;
        if (ws_id < 0 || ws_id >= SWM_WS_MAX)
-               errx(1, "invalid workspace %d\n", ws_id + 1);
+               errx(1, "autorun: invalid workspace %d\n", ws_id + 1);
 
        /*
         * This is a little intricate
@@ -4546,13 +4566,27 @@ setautorun(char *selector, char *value, int flags)
         * used before AND not claimed by manage_window.  We get away with
         * altering it in the parent after INSERT because this can not be a race
         */
-       real_args[0] = s;
-       a.argv = real_args; /* XXX this sucks and should have args for real */
+       a.argv = NULL;
+       while ((ap = strsep(&sp, " \t")) != NULL) {
+               if (*ap == '\0')
+                       continue;
+               DNPRINTF(SWM_D_SPAWN, "setautorun: arg [%s]\n", ap);
+               argc++;
+               if ((a.argv = realloc(a.argv, argc * sizeof(char *))) == NULL)
+                       err(1, "setautorun: realloc");
+               a.argv[argc - 1] = ap;
+       }
+
+       if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL)
+               err(1, "setautorun: realloc");
+       a.argv[argc] = NULL;
+
        if ((pid = fork()) == 0) {
                spawn(ws_id, &a, 1);
                /* NOTREACHED */
                _exit(1);
        }
+       free(a.argv);
 
        /* parent */
        p = find_pid(pid);
@@ -4569,11 +4603,76 @@ setautorun(char *selector, char *value, int flags)
        return (0);
 }
 
+int
+setlayout(char *selector, char *value, int flags)
+{
+       int                     ws_id, st, i, x, mg, ma, si, raise;
+       char                    s[1024];
+       struct workspace        *ws;
+
+       if (getenv("SWM_STARTED"))
+               return (0);
+
+       bzero(s, sizeof s);
+       if (sscanf(value, "ws[%d]:%d:%d:%d:%d:%1023c",
+           &ws_id, &mg, &ma, &si, &raise, s) != 6)
+               errx(1, "invalid layout entry, should be 'ws[<idx>]:"
+                   "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
+                   "<type>'\n");
+       ws_id--;
+       if (ws_id < 0 || ws_id >= SWM_WS_MAX)
+               errx(1, "layout: invalid workspace %d\n", ws_id + 1);
+
+       if (!strcasecmp(s, "vertical"))
+               st = SWM_V_STACK;
+       else if (!strcasecmp(s, "horizontal"))
+               st = SWM_H_STACK;
+       else if (!strcasecmp(s, "fullscreen"))
+               st = SWM_MAX_STACK;
+       else
+               errx(1, "invalid layout entry, should be 'ws[<idx>]:"
+                   "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
+                   "<type>'\n");
+
+       for (i = 0; i < ScreenCount(display); i++) {
+               ws = (struct workspace *)&screens[i].ws;
+               ws[ws_id].cur_layout = &layouts[st];
+
+               ws[ws_id].always_raise = raise;
+               if (st == SWM_MAX_STACK)
+                       continue;
+
+               /* master grow */
+               for (x = 0; x < abs(mg); x++) {
+                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
+                           mg >= 0 ?  SWM_ARG_ID_MASTERGROW :
+                           SWM_ARG_ID_MASTERSHRINK);
+                       stack();
+               }
+               /* master add */
+               for (x = 0; x < abs(ma); x++) {
+                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
+                           ma >= 0 ?  SWM_ARG_ID_MASTERADD :
+                           SWM_ARG_ID_MASTERDEL);
+                       stack();
+               }
+               /* stack inc */
+               for (x = 0; x < abs(si); x++) {
+                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
+                           si >= 0 ?  SWM_ARG_ID_STACKINC :
+                           SWM_ARG_ID_STACKDEC);
+                       stack();
+               }
+       }
+
+       return (0);
+}
+
 /* config options */
 struct config_option {
        char                    *optname;
-       int (*func)(char*, char*, int);
-       int funcflags;
+       int                     (*func)(char*, char*, int);
+       int                     funcflags;
 };
 struct config_option configopt[] = {
        { "bar_enabled",                setconfvalue,   SWM_S_BAR_ENABLED },
@@ -4609,6 +4708,7 @@ struct config_option configopt[] = {
        { "disable_border",             setconfvalue,   SWM_S_DISABLE_BORDER },
        { "border_width",               setconfvalue,   SWM_S_BORDER_WIDTH },
        { "autorun",                    setautorun,     0 },
+       { "layout",                     setlayout,      0 },
 };