]> code.delx.au - spectrwm/blobdiff - spectrwm.c
layout option now applies on startup and reset
[spectrwm] / spectrwm.c
index d5dbe618c92c013db710c0b9d32ca630eea1e204..5a278d11d6562cb679180574b9d9771276dcce71 100644 (file)
@@ -396,6 +396,7 @@ int          region_padding = 0;
 int             tile_gap = 0;
 bool            java_workaround = true;
 bool            verbose_layout = false;
+bool            track_pid_ws = true;
 #ifdef SWM_DEBUG
 bool            debug_enabled;
 time_t          time_started;
@@ -498,6 +499,7 @@ void        vertical_stack(struct workspace *, struct swm_geometry *);
 void   horizontal_config(struct workspace *, int);
 void   horizontal_stack(struct workspace *, struct swm_geometry *);
 void   max_stack(struct workspace *, struct swm_geometry *);
+void   max_config(struct workspace *, int);
 void   plain_stacker(struct workspace *);
 void   fancy_stacker(struct workspace *);
 
@@ -512,7 +514,7 @@ struct layout {
        /* stack,               configure */
        { vertical_stack,       vertical_config,        0,      plain_stacker },
        { horizontal_stack,     horizontal_config,      0,      plain_stacker },
-       { max_stack,            NULL,
+       { max_stack,            max_config,
          SWM_L_MAPONFOCUS | SWM_L_FOCUSPREV,                   plain_stacker },
        { NULL,                 NULL,                   0,      NULL  },
 };
@@ -599,6 +601,16 @@ struct swm_screen {
 };
 struct swm_screen      *screens;
 
+struct layout_config {
+       bool configured;
+       int layout;
+       int master_grow;
+       int master_add;
+       int stack_inc;
+       int always_raise;
+       bool apply_flip;
+} initial_layouts[SWM_WS_MAX];
+
 /* args to functions */
 union arg {
        int                     id;
@@ -615,7 +627,6 @@ union arg {
 #define SWM_ARG_ID_MASTERADD   (22)
 #define SWM_ARG_ID_MASTERDEL   (23)
 #define SWM_ARG_ID_FLIPLAYOUT  (24)
-#define SWM_ARG_ID_STACKRESET  (30)
 #define SWM_ARG_ID_STACKINIT   (31)
 #define SWM_ARG_ID_STACKBALANCE        (32)
 #define SWM_ARG_ID_CYCLEWS_UP  (40)
@@ -902,7 +913,7 @@ enum actionid {
        FN_STACK_BALANCE,
        FN_STACK_INC,
        FN_STACK_DEC,
-       FN_STACK_RESET,
+       FN_STACK_INIT,
        FN_SWAP_MAIN,
        FN_SWAP_NEXT,
        FN_SWAP_PREV,
@@ -1100,6 +1111,7 @@ void       grab_windows(void);
 void    grabbuttons(void);
 void    grabkeys(void);
 void    iconify(struct binding *, struct swm_region *, union arg *);
+void    initlayout(struct workspace *);
 bool    isxlfd(char *);
 bool    keybindreleased(struct binding *, xcb_key_release_event_t *);
 void    keypress(xcb_key_press_event_t *);
@@ -1588,6 +1600,25 @@ ewmh_autoquirk(struct ws_win *win)
                }
        }
        free(r);
+
+
+       c = xcb_get_property(conn, 0, win->id,
+           ewmh[_NET_WM_STATE].atom, XCB_ATOM_ATOM, 0, UINT32_MAX);
+       r = xcb_get_property_reply(conn, c, NULL);
+       if (r == NULL)
+               return;
+
+       type = xcb_get_property_value(r);
+       n = xcb_get_property_value_length(r) / sizeof(xcb_atom_t);
+
+       for (i = 0; i < n; i++) {
+               if (type[i] == ewmh[_NET_WM_STATE_SKIP_PAGER].atom ||
+                   type[i] == ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom) {
+                       win->quirks = SWM_Q_FLOAT | SWM_Q_ANYWHERE;
+                       break;
+               }
+       }
+       free(r);
 }
 
 void
@@ -3761,32 +3792,34 @@ spawn(int ws_idx, union arg *args, bool close_fd)
 
        close(xcb_get_file_descriptor(conn));
 
-       if ((ret = getenv("LD_PRELOAD"))) {
-               if (asprintf(&ret, "%s:%s", SWM_LIB, ret) == -1) {
-                       warn("spawn: asprintf LD_PRELOAD");
+       if (track_pid_ws) {
+               if ((ret = getenv("LD_PRELOAD"))) {
+                       if (asprintf(&ret, "%s:%s", SWM_LIB, ret) == -1) {
+                               warn("spawn: asprintf LD_PRELOAD");
+                               _exit(1);
+                       }
+                       setenv("LD_PRELOAD", ret, 1);
+                       free(ret);
+               } else {
+                       setenv("LD_PRELOAD", SWM_LIB, 1);
+               }
+
+               if (asprintf(&ret, "%d", ws_idx) == -1) {
+                       warn("spawn: asprintf SWM_WS");
                        _exit(1);
                }
-               setenv("LD_PRELOAD", ret, 1);
+               setenv("_SWM_WS", ret, 1);
                free(ret);
-       } else {
-               setenv("LD_PRELOAD", SWM_LIB, 1);
-       }
-
-       if (asprintf(&ret, "%d", ws_idx) == -1) {
-               warn("spawn: asprintf SWM_WS");
-               _exit(1);
-       }
-       setenv("_SWM_WS", ret, 1);
-       free(ret);
-       ret = NULL;
+               ret = NULL;
 
-       if (asprintf(&ret, "%d", getpid()) == -1) {
-               warn("spawn: asprintf _SWM_PID");
-               _exit(1);
+               if (asprintf(&ret, "%d", getpid()) == -1) {
+                       warn("spawn: asprintf _SWM_PID");
+                       _exit(1);
+               }
+               setenv("_SWM_PID", ret, 1);
+               free(ret);
+               ret = NULL;
        }
-       setenv("_SWM_PID", ret, 1);
-       free(ret);
-       ret = NULL;
 
        if (setsid() == -1) {
                warn("spawn: setsid");
@@ -4939,14 +4972,15 @@ stack_config(struct binding *bp, struct swm_region *r, union arg *args)
        DNPRINTF(SWM_D_STACK, "stack_config: id: %d workspace: %d\n",
            args->id, ws->idx);
 
-       if (clear_maximized(ws) > 0)
-               stack(r);
-
-       if (ws->cur_layout->l_config != NULL)
+       if (args->id == SWM_ARG_ID_STACKINIT) {
+               initlayout(ws);
+       } else {
                ws->cur_layout->l_config(ws, args->id);
+       }
+
+       clear_maximized(ws);
+       stack(r);
 
-       if (args->id != SWM_ARG_ID_STACKINIT)
-               stack(r);
        bar_draw(r->bar);
 
        center_pointer(r);
@@ -5392,7 +5426,6 @@ vertical_config(struct workspace *ws, int id)
            id, ws->idx);
 
        switch (id) {
-       case SWM_ARG_ID_STACKRESET:
        case SWM_ARG_ID_STACKINIT:
                ws->l_state.vertical_msize = SWM_V_SLICE / 2;
                ws->l_state.vertical_mwin = 1;
@@ -5445,7 +5478,6 @@ horizontal_config(struct workspace *ws, int id)
        DNPRINTF(SWM_D_STACK, "horizontal_config: workspace: %d\n", ws->idx);
 
        switch (id) {
-       case SWM_ARG_ID_STACKRESET:
        case SWM_ARG_ID_STACKINIT:
                ws->l_state.horizontal_mwin = 1;
                ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
@@ -5536,10 +5568,6 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
 
                /* Set maximized flag for all maxed windows. */
                if (!MAXIMIZED(w)) {
-                       /* Preserve floating geometry. */
-                       if (ABOVE(w))
-                               store_float_geom(w);
-
                        ewmh_apply_flags(w, w->ewmh_flags | EWMH_F_MAXIMIZED);
                        ewmh_update_wm_state(w);
                }
@@ -5586,6 +5614,16 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                        map_window(w);
 }
 
+void
+max_config(struct workspace *ws, int id)
+{
+       /* suppress unused warning since vars are needed */
+       (void)ws;
+       (void)id;
+
+       DNPRINTF(SWM_D_STACK, "max_config: workspace: %d (noop)\n", ws->idx);
+}
+
 void
 send_to_rg(struct binding *bp, struct swm_region *r, union arg *args)
 {
@@ -7503,7 +7541,7 @@ struct action {
        { "stack_balance",      stack_config,   0, {.id = SWM_ARG_ID_STACKBALANCE} },
        { "stack_inc",          stack_config,   0, {.id = SWM_ARG_ID_STACKINC} },
        { "stack_dec",          stack_config,   0, {.id = SWM_ARG_ID_STACKDEC} },
-       { "stack_reset",        stack_config,   0, {.id = SWM_ARG_ID_STACKRESET} },
+       { "stack_reset",        stack_config,   0, {.id = SWM_ARG_ID_STACKINIT} },
        { "swap_main",          swapwin,        0, {.id = SWM_ARG_ID_SWAPMAIN} },
        { "swap_next",          swapwin,        0, {.id = SWM_ARG_ID_SWAPNEXT} },
        { "swap_prev",          swapwin,        0, {.id = SWM_ARG_ID_SWAPPREV} },
@@ -8285,7 +8323,7 @@ setup_keybindings(void)
        BINDKEYSPAWN(MODSHIFT,  XK_Return,              "term");
        BINDKEY(MODSHIFT,       XK_comma,               FN_STACK_INC);
        BINDKEY(MODSHIFT,       XK_period,              FN_STACK_DEC);
-       BINDKEY(MODSHIFT,       XK_space,               FN_STACK_RESET);
+       BINDKEY(MODSHIFT,       XK_space,               FN_STACK_INIT);
        BINDKEY(MODKEY,         XK_Return,              FN_SWAP_MAIN);
        BINDKEY(MODSHIFT,       XK_j,                   FN_SWAP_NEXT);
        BINDKEY(MODSHIFT,       XK_k,                   FN_SWAP_PREV);
@@ -8910,6 +8948,7 @@ enum {
        SWM_S_STACK_ENABLED,
        SWM_S_TERM_WIDTH,
        SWM_S_TILE_GAP,
+       SWM_S_TRACK_PID_WS,
        SWM_S_URGENT_COLLAPSE,
        SWM_S_URGENT_ENABLED,
        SWM_S_VERBOSE_LAYOUT,
@@ -9118,6 +9157,9 @@ setconfvalue(const char *selector, const char *value, int flags)
        case SWM_S_TILE_GAP:
                tile_gap = atoi(value);
                break;
+       case SWM_S_TRACK_PID_WS:
+               track_pid_ws = atoi(value);
+               break;
        case SWM_S_URGENT_COLLAPSE:
                urgent_collapse = (atoi(value) != 0);
                break;
@@ -9343,7 +9385,7 @@ int
 setlayout(const char *selector, const char *value, int flags)
 {
        struct workspace        *ws;
-       int                     ws_id, i, x, mg, ma, si, ar;
+       int                     ws_id, i, mg, ma, si, ar;
        int                     st = SWM_V_STACK, num_screens;
        char                    s[1024];
        bool                    f = false;
@@ -9352,9 +9394,6 @@ setlayout(const char *selector, const char *value, int flags)
        (void)selector;
        (void)flags;
 
-       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, &ar, s) != 6)
@@ -9377,46 +9416,69 @@ setlayout(const char *selector, const char *value, int flags)
                f = true;
        } else if (strcasecmp(s, "fullscreen") == 0)
                st = SWM_MAX_STACK;
-       else
+       else {
                errx(1, "invalid layout entry, should be 'ws[<idx>]:"
                    "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
                    "<type>'");
+               return 0;
+       }
+
+       initial_layouts[ws_id].configured = true;
+       initial_layouts[ws_id].layout = st;
+       initial_layouts[ws_id].master_grow = mg;
+       initial_layouts[ws_id].master_add = ma;
+       initial_layouts[ws_id].stack_inc = si;
+       initial_layouts[ws_id].always_raise = ar;
+       initial_layouts[ws_id].apply_flip = f;
 
        num_screens = get_screen_count();
-       for (i = 0; i < num_screens; i++) {
-               ws = (struct workspace *)&screens[i].ws;
-               ws[ws_id].cur_layout = &layouts[st];
+       for (i = 0; i < num_screens; ++i) {
+               ws = &screens[i].ws[ws_id];
+               initlayout(ws);
+       }
 
-               ws[ws_id].always_raise = (ar != 0);
-               if (st == SWM_MAX_STACK)
-                       continue;
+       return 0;
+}
 
-               /* 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);
-               }
-               /* 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 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);
-               }
-               /* Apply flip */
-               if (f) {
-                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
-                           SWM_ARG_ID_FLIPLAYOUT);
-               }
-       }
+void
+initlayout(struct workspace *ws)
+{
+       int                     i, ws_id;
 
-       return (0);
+       ws_id = ws->idx;
+
+       if (!initial_layouts[ws_id].configured)
+               return;
+
+       ws->cur_layout = &layouts[initial_layouts[ws_id].layout];
+
+       ws->cur_layout->l_config(ws, SWM_ARG_ID_STACKINIT);
+
+       ws->always_raise = (initial_layouts[ws_id].always_raise != 0);
+
+       /* master grow */
+       for (i = 0; i < abs(initial_layouts[ws_id].master_grow); i++) {
+               ws->cur_layout->l_config(ws,
+                   initial_layouts[ws_id].master_grow >= 0 ?  SWM_ARG_ID_MASTERGROW :
+                   SWM_ARG_ID_MASTERSHRINK);
+       }
+       /* master add */
+       for (i = 0; i < abs(initial_layouts[ws_id].master_add); i++) {
+               ws->cur_layout->l_config(ws,
+                   initial_layouts[ws_id].master_add >= 0 ?  SWM_ARG_ID_MASTERADD :
+                   SWM_ARG_ID_MASTERDEL);
+       }
+       /* stack inc */
+       for (i = 0; i < abs(initial_layouts[ws_id].stack_inc); i++) {
+               ws->cur_layout->l_config(ws,
+                   initial_layouts[ws_id].stack_inc >= 0 ?  SWM_ARG_ID_STACKINC :
+                   SWM_ARG_ID_STACKDEC);
+       }
+       /* Apply flip */
+       if (initial_layouts[ws_id].apply_flip) {
+               ws->cur_layout->l_config(ws,
+                   SWM_ARG_ID_FLIPLAYOUT);
+       }
 }
 
 /* config options */
@@ -9476,6 +9538,7 @@ struct config_option configopt[] = {
        { "tile_gap",                   setconfvalue,   SWM_S_TILE_GAP },
        { "title_class_enabled",        setconfvalue,   SWM_S_WINDOW_CLASS_ENABLED }, /* For backwards compat. */
        { "title_name_enabled",         setconfvalue,   SWM_S_WINDOW_INSTANCE_ENABLED }, /* For backwards compat. */
+       { "track_pid_ws",               setconfvalue,   SWM_S_TRACK_PID_WS },
        { "urgent_collapse",            setconfvalue,   SWM_S_URGENT_COLLAPSE },
        { "urgent_enabled",             setconfvalue,   SWM_S_URGENT_ENABLED },
        { "verbose_layout",             setconfvalue,   SWM_S_VERBOSE_LAYOUT },
@@ -11888,9 +11951,7 @@ setup_screens(void)
                        TAILQ_INIT(&ws->unmanagedlist);
 
                        for (k = 0; layouts[k].l_stack != NULL; k++)
-                               if (layouts[k].l_config != NULL)
-                                       layouts[k].l_config(ws,
-                                           SWM_ARG_ID_STACKINIT);
+                               layouts[k].l_config(ws, SWM_ARG_ID_STACKINIT);
                        ws->cur_layout = &layouts[0];
                        ws->cur_layout->l_string(ws);
                }