]> code.delx.au - spectrwm/blobdiff - spectrwm.c
WIP floating fixes for max stack
[spectrwm] / spectrwm.c
index 5a278d11d6562cb679180574b9d9771276dcce71..a835d00ac98290db99336ec5e9d2dd15e6b46e7d 100644 (file)
@@ -248,7 +248,8 @@ uint32_t            swm_debug = 0
 #define MAXIMIZED(w)           (MAXIMIZED_VERT(w) || MAXIMIZED_HORZ(w))
 #define MANUAL(w)              ((w)->ewmh_flags & SWM_F_MANUAL)
 #define TRANS(w)               ((w)->transient != XCB_WINDOW_NONE)
-#define FLOATING(w)            (ABOVE(w) || TRANS(w) || FULLSCREEN(w) ||      \
+#define FLOATING(w)            (ABOVE(w) || TRANS(w))
+#define FLOATINGFULLMAX(w)     (ABOVE(w) || TRANS(w) || FULLSCREEN(w) ||      \
     MAXIMIZED(w))
 
 /* Constrain Window flags */
@@ -999,10 +1000,12 @@ void      bar_toggle(struct binding *, struct swm_region *, union arg *);
 void    bar_urgent(char *, size_t);
 void    bar_window_class(char *, size_t, struct swm_region *);
 void    bar_window_class_instance(char *, size_t, struct swm_region *);
+void    bar_window_index_count(char *, size_t, struct swm_region *);
 void    bar_window_instance(char *, size_t, struct swm_region *);
 void    bar_window_name(char *, size_t, struct swm_region *);
 void    bar_window_state(char *, size_t, struct swm_region *);
 void    bar_workspace_name(char *, size_t, struct swm_region *);
+void    bar_workspace_state(char *, size_t, struct swm_region *);
 int     binding_cmp(struct binding *, struct binding *);
 void    binding_insert(uint16_t, enum binding_type, uint32_t, enum actionid,
             uint32_t, const char *);
@@ -1737,19 +1740,14 @@ ewmh_apply_flags(struct ws_win *win, uint32_t pending)
        }
 
        if (changed & EWMH_F_ABOVE) {
-               if (ws->cur_layout != &layouts[SWM_MAX_STACK]) {
-                       if (ABOVE(win))
-                               load_float_geom(win);
-                       else if (!MAXIMIZED(win))
-                               store_float_geom(win);
+               if (ABOVE(win))
+                       load_float_geom(win);
+               else if (!MAXIMIZED(win))
+                       store_float_geom(win);
 
-                       win->ewmh_flags &= ~EWMH_F_MAXIMIZED;
-                       changed &= ~EWMH_F_MAXIMIZED;
-                       raise_window(win);
-               } else {
-                       /* Revert. */
-                       win->ewmh_flags ^= EWMH_F_ABOVE & pending;
-               }
+               win->ewmh_flags &= ~EWMH_F_MAXIMIZED;
+               changed &= ~EWMH_F_MAXIMIZED;
+               raise_window(win);
        }
 
        if (changed & EWMH_F_MAXIMIZED) {
@@ -2430,6 +2428,30 @@ bar_window_class_instance(char *s, size_t sz, struct swm_region *r)
        bar_window_instance(s, sz, r);
 }
 
+void
+bar_window_index_count(char *s, size_t sz, struct swm_region *r)
+{
+       struct ws_win           *w;
+       int                     count, index;
+
+       if (r == NULL || r->ws == NULL || r->ws->focus == NULL) {
+               strlcat(s, "0/0", sz);
+               return;
+       }
+
+       count = 0;
+       index = 0;
+
+       TAILQ_FOREACH(w, &r->ws->winlist, entry) {
+               ++count;
+               if (w->id == r->ws->focus->id) {
+                       index = count;
+               }
+       }
+
+       snprintf(s, sz, "%d/%d", index, count);
+}
+
 void
 bar_window_state(char *s, size_t sz, struct swm_region *r)
 {
@@ -2509,6 +2531,44 @@ bar_workspace_name(char *s, size_t sz, struct swm_region *r)
                strlcat(s, r->ws->name, sz);
 }
 
+void
+bar_workspace_state(char *s, size_t sz, struct swm_region *r)
+{
+       struct ws_win           *win;
+       int                     i, j, num_screens;
+       bool                    used_workspaces[SWM_WS_MAX];
+       char                    tmp[8];
+       int                     first = 1;
+       char                    *fmt;
+
+       if (r == NULL || r->ws == NULL)
+               return;
+
+       for (i = 0; i < SWM_WS_MAX; ++i)
+               used_workspaces[i] = false;
+
+       num_screens = get_screen_count();
+       for (i = 0; i < num_screens; i++)
+               for (j = 0; j < workspace_limit; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               ++used_workspaces[win->ws->idx];
+
+       for (i = 0; i < SWM_WS_MAX; ++i) {
+               fmt = NULL;
+               if (i == r->ws->idx) {
+                       fmt = " [%d]";
+               } else if (used_workspaces[i]) {
+                       fmt = " %d";
+               }
+               if (fmt) {
+                       fmt = fmt + first;
+                       first = 0;
+                       snprintf(tmp, sizeof tmp, fmt, i + 1);
+                       strlcat(s, tmp, sz);
+               }
+       }
+}
+
 /* build the default bar format according to the defined enabled options */
 void
 bar_fmt(const char *fmtexp, char *fmtnew, struct swm_region *r, size_t sz)
@@ -2631,6 +2691,9 @@ bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep,
        case 'I':
                snprintf(tmp, sizeof tmp, "%d", r->ws->idx + 1);
                break;
+       case 'i':
+               bar_workspace_state(tmp, sizeof tmp, r);
+               break;
        case 'M':
                count = 0;
                TAILQ_FOREACH(w, &r->ws->winlist, entry)
@@ -2642,6 +2705,9 @@ bar_replace_seq(char *fmt, char *fmtrep, struct swm_region *r, size_t *offrep,
        case 'N':
                snprintf(tmp, sizeof tmp, "%d", r->s->idx + 1);
                break;
+       case 'p':
+               bar_window_index_count(tmp, sizeof tmp, r);
+               break;
        case 'P':
                bar_window_class_instance(tmp, sizeof tmp, r);
                break;
@@ -3287,13 +3353,13 @@ config_win(struct ws_win *win, xcb_configure_request_event_t *ev)
 }
 
 int
-count_win(struct workspace *ws, bool count_transient)
+count_win(struct workspace *ws, bool count_floating)
 {
        struct ws_win           *win;
        int                     count = 0;
 
        TAILQ_FOREACH(win, &ws->winlist, entry) {
-               if (!count_transient && FLOATING(win))
+               if (!count_floating && FLOATING(win))
                        continue;
                if (ICONIC(win))
                        continue;
@@ -3438,11 +3504,11 @@ raise_window(struct ws_win *win)
 void
 update_win_stacking(struct ws_win *win)
 {
-       struct ws_win           *sibling;
 #ifdef SWM_DEBUG
        struct ws_win           *w;
 #endif
        struct swm_region       *r;
+       uint16_t                configure_mask;
        uint32_t                val[2];
 
        if (win == NULL || (r = win->ws->r) == NULL)
@@ -3454,25 +3520,25 @@ update_win_stacking(struct ws_win *win)
                return;
        }
 
-       sibling = TAILQ_NEXT(win, stack_entry);
-       if (sibling != NULL && (FLOATING(win) == FLOATING(sibling) ||
-           (win->ws->always_raise && win->ws->focus == win))) {
-               val[0] = sibling->frame;
-               val[1] = XCB_STACK_MODE_ABOVE;
-       } else if (FLOATING(win) || (win->ws->always_raise &&
+        if (FLOATINGFULLMAX(win) || (win->ws->always_raise &&
            win->ws->focus == win)) {
-               val[0] = r->bar->id;
-               val[1] = XCB_STACK_MODE_ABOVE;
+               configure_mask = XCB_CONFIG_WINDOW_STACK_MODE;
+               val[0] = XCB_STACK_MODE_ABOVE;
+               val[1] = 0;
+
+               DNPRINTF(SWM_D_EVENT, "update_win_stacking: to very top "
+                   "win %#x (%#x), ", win->frame, win->id);
        } else {
+               configure_mask = XCB_CONFIG_WINDOW_STACK_MODE |
+                       XCB_CONFIG_WINDOW_SIBLING;
                val[0] = r->bar->id;
                val[1] = XCB_STACK_MODE_BELOW;
-       }
 
-       DNPRINTF(SWM_D_EVENT, "update_win_stacking: win %#x (%#x), "
-           "sibling %#x mode %#x\n", win->frame, win->id, val[0], val[1]);
+               DNPRINTF(SWM_D_EVENT, "update_win_stacking: to tile top "
+                   "win %#x (%#x), ", win->frame, win->id);
+       }
 
-       xcb_configure_window(conn, win->frame, XCB_CONFIG_WINDOW_SIBLING |
-           XCB_CONFIG_WINDOW_STACK_MODE, val);
+       xcb_configure_window(conn, win->frame, configure_mask, val);
 
 #ifdef SWM_DEBUG
        TAILQ_FOREACH(w, &win->ws->winlist, entry)
@@ -4595,9 +4661,6 @@ swapwin(struct binding *bp, struct swm_region *r, union arg *args)
                goto out;
        }
 
-       if (r->ws->cur_layout == &layouts[SWM_MAX_STACK])
-               return;
-
        clear_maximized(r->ws);
 
        source = cur_focus;
@@ -5292,7 +5355,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, bool flip)
                if (ICONIC(win))
                        continue;
 
-               if (FLOATING(win)) {
+               if (FLOATINGFULLMAX(win)) {
                        update_floater(win);
                        continue;
                }
@@ -5530,15 +5593,13 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
 {
        struct swm_geometry     gg = *g;
        struct ws_win           *w, *win = NULL, *parent = NULL, *tmpw;
-       int                     winno;
 
        DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
 
        if (ws == NULL)
                return;
 
-       winno = count_win(ws, false);
-       if (winno == 0 && count_win(ws, true) == 0)
+       if (count_win(ws, true) == 0)
                return;
 
        /* Figure out which top level window should be visible. */
@@ -5561,7 +5622,7 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                if (ICONIC(w))
                        continue;
 
-               if (TRANS(w)) {
+               if (TRANS(w) || ABOVE(w)) {
                        update_floater(w);
                        continue;
                }
@@ -6966,8 +7027,8 @@ resize_win(struct ws_win *win, struct binding *bp, int opt)
        if (FULLSCREEN(win))
                return;
 
-       /* In max_stack mode, should only resize transients. */
-       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK] && !TRANS(win))
+       /* In max_stack mode, should only resize transients/floating. */
+       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK] && !TRANS(win) && !ABOVE(win))
                return;
 
        DNPRINTF(SWM_D_EVENT, "resize: win %#x, floating: %s, "
@@ -7255,10 +7316,6 @@ move_win(struct ws_win *win, struct binding *bp, int opt)
        DNPRINTF(SWM_D_EVENT, "move: win %#x, floating: %s, transient: "
            "%#x\n", win->id, YESNO(ABOVE(win)), win->transient);
 
-       /* in max_stack mode should only move transients */
-       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK] && !TRANS(win))
-               return;
-
        if (!(ABOVE(win) || TRANS(win)) || MAXIMIZED(win)) {
                store_float_geom(win);
                restack = true;
@@ -9681,6 +9738,10 @@ conf_load(const char *filename, int keymapping)
                            configopt[optidx].optname);
                        continue;
                }
+               /* trim trailing spaces */
+               ce = optval + strlen(optval) - 1;
+               while (ce > optval && isspace(*ce)) --ce;
+               *(ce + 1) = '\0';
                /* call function to deal with it all */
                if (configopt[optidx].func(optsub, optval,
                    configopt[optidx].funcflags) != 0) {