JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
shuffle some stuff around to make more sense
[spectrwm.git] / scrotwm.c
index 5365ee0..edcd339 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -192,6 +192,7 @@ int                 bar_extra = 1;
 int                    bar_extra_running = 0;
 int                    bar_verbose = 1;
 int                    bar_height = 0;
+int                    stack_enabled = 1;
 int                    clock_enabled = 1;
 int                    title_name_enabled = 0;
 int                    title_class_enabled = 0;
@@ -324,12 +325,13 @@ struct layout {
        u_int32_t       flags;
 #define SWM_L_FOCUSPREV                (1<<0)
 #define SWM_L_MAPONFOCUS       (1<<1)
+       char            *name;
 } layouts[] =  {
        /* stack,               configure */
-       { vertical_stack,       vertical_config,        0},
-       { horizontal_stack,     horizontal_config,      0},
+       { vertical_stack,       vertical_config,        0,      "[|]" },
+       { horizontal_stack,     horizontal_config,      0,      "[-]" },
        { max_stack,            NULL,
-         SWM_L_FOCUSPREV | SWM_L_MAPONFOCUS},
+         SWM_L_FOCUSPREV | SWM_L_MAPONFOCUS,                   "[ ]"},
        { NULL,                 NULL,                   0},
 };
 
@@ -759,6 +761,7 @@ bar_update(void)
        char                    s[SWM_BAR_MAX];
        char                    loc[SWM_BAR_MAX];
        char                    *b;
+       char                    *stack = "";
 
        if (bar_enabled == 0)
                return;
@@ -791,8 +794,12 @@ bar_update(void)
                        if (r && r->ws)
                                bar_class_name(s, sizeof s, r->ws->focus);
 
-                       snprintf(loc, sizeof loc, "%d:%d    %s %s    %s",
-                           x++, r->ws->idx + 1, s, bar_ext, bar_vertext);
+                       if (stack_enabled)
+                               stack = r->ws->cur_layout->name;
+
+                       snprintf(loc, sizeof loc, "%d:%d %s   %s %s    %s",
+                           x++, r->ws->idx + 1, stack, s, bar_ext,
+                           bar_vertext);
                        bar_print(r, loc);
                }
        }
@@ -1186,14 +1193,14 @@ unfocus_win(struct ws_win *win)
        if (win->ws->r == NULL)
                return;
 
-       grabbuttons(win, 0);
-       XSetWindowBorder(display, win->id,
-           win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
-
        if (win->ws->focus == win) {
                win->ws->focus = NULL;
                win->ws->focus_prev = win;
        }
+
+       grabbuttons(win, 0);
+       XSetWindowBorder(display, win->id,
+           win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
 }
 
 void
@@ -1226,12 +1233,11 @@ focus_win(struct ws_win *win)
        if (win->ws->r != NULL) {
                XSetWindowBorder(display, win->id,
                    win->ws->r->s->c[SWM_S_COLOR_FOCUS].color);
-               grabbuttons(win, 1);
                if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS)
                        XMapRaised(display, win->id);
                XSetInputFocus(display, win->id,
                    RevertToPointerRoot, CurrentTime);
-               XSync(display, False);
+               grabbuttons(win, 1);
        }
 }
 
@@ -1240,7 +1246,7 @@ switchws(struct swm_region *r, union arg *args)
 {
        int                     wsid = args->id;
        struct swm_region       *this_r, *other_r;
-       struct ws_win           *win, *winfocus = NULL;
+       struct ws_win           *win, *winfocus = NULL, *parent = NULL;
        struct workspace        *new_ws, *old_ws;
 
        this_r = r;
@@ -1276,7 +1282,9 @@ switchws(struct swm_region *r, union arg *args)
                 */
                if (new_ws->old_r == this_r)
                        TAILQ_FOREACH(win, &new_ws->winlist, entry)
-                               XMapRaised(display, win->id);
+                               if (!(win->ws->cur_layout->flags &
+                                   SWM_L_MAPONFOCUS))
+                                       XMapRaised(display, win->id);
 
                TAILQ_FOREACH(win, &old_ws->winlist, entry)
                        unmap_window(win);
@@ -1289,7 +1297,17 @@ switchws(struct swm_region *r, union arg *args)
 
        ignore_enter = 1;
        stack();
-       focus_win(winfocus);
+       if (winfocus) {
+               /* make sure we see the parent window */
+               if (winfocus->transient) {
+                       parent = find_window(winfocus->transient);
+                       if (parent)
+                               focus_win(parent);
+               }
+
+               focus_win(winfocus);
+       }
+       ignore_enter = 0;
        bar_update();
 }
 
@@ -1334,8 +1352,10 @@ cyclews(struct swm_region *r, union arg *args)
 void
 cyclescr(struct swm_region *r, union arg *args)
 {
-       struct swm_region       *rr;
-       int                     i;
+       struct swm_region       *rr = NULL;
+       struct workspace        *ws = NULL;
+       struct ws_win           *winfocus = NULL;
+       int                     i, x, y;
 
        /* do nothing if we don't have more than one screen */
        if (!(ScreenCount(display) > 1 || outputs > 1))
@@ -1356,10 +1376,28 @@ cyclescr(struct swm_region *r, union arg *args)
        default:
                return;
        };
+       if (rr == NULL)
+               return;
+
+       ws = rr->ws;
+       winfocus = ws->focus;
+       if (winfocus == NULL)
+               winfocus = ws->focus_prev;
+       if (winfocus) {
+               /* use window coordinates */
+               x = winfocus->g.x + 1;
+               y = winfocus->g.y + 1;
+       } else {
+               /* use region coordinates */
+               x = rr->g.x + 1;
+               y = rr->g.y + 1 + bar_enabled ? bar_height : 0;
+       }
+
        unfocus_all();
        XSetInputFocus(display, PointerRoot, RevertToPointerRoot, CurrentTime);
-       XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, rr->g.x,
-           rr->g.y + bar_enabled ? bar_height : 0);
+       XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, x, y);
+
+       focus_win(winfocus);
 }
 
 void
@@ -1475,7 +1513,7 @@ void
 cycle_layout(struct swm_region *r, union arg *args)
 {
        struct workspace        *ws = r->ws;
-       struct ws_win           *winfocus;
+       struct ws_win           *winfocus, *parent = NULL;
 
        DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx);
 
@@ -1487,7 +1525,14 @@ cycle_layout(struct swm_region *r, union arg *args)
 
        ignore_enter = 1;
        stack();
-       focus_win(winfocus);
+       /* make sure we see the parent window */
+       if (winfocus) {
+               if (winfocus->transient)
+                       parent = find_window(winfocus->transient);
+               if (parent)
+                       focus_win(parent);
+               focus_win(winfocus);
+       }
        ignore_enter = 0;
 }
 
@@ -1535,7 +1580,6 @@ stack(void) {
        }
        if (font_adjusted)
                font_adjusted--;
-       XSync(display, False);
 }
 
 void
@@ -1900,8 +1944,11 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                        win->g.h = wc.height = gg.h;
                        mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
                        XConfigureWindow(display, win->id, mask, &wc);
+
+                       /* unmap only if we don't have multi screen */
                        if (win != ws->focus)
-                               unmap_window(win);
+                               if (!(ScreenCount(display) > 1 || outputs > 1))
+                                       unmap_window(win);
                }
        }
 
@@ -1947,7 +1994,6 @@ send_to_ws(struct swm_region *r, union arg *args)
                if (ScreenCount(display) > 1 || outputs > 1)
                        winfocus = win;
 
-
        unmap_window(win);
        TAILQ_REMOVE(&ws->winlist, win, entry);
        TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
@@ -2969,11 +3015,11 @@ setup_quirks(void)
 /* conf file stuff */
 #define SWM_CONF_FILE  "scrotwm.conf"
 
-enum   { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_CLOCK_ENABLED,
-         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 };
+enum   { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_STACK_ENABLED,
+         SWM_S_CLOCK_ENABLED, 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 };
 
 int
 setconfvalue(char *selector, char *value, int flags)
@@ -2985,6 +3031,9 @@ setconfvalue(char *selector, char *value, int flags)
        case SWM_S_BAR_ENABLED:
                bar_enabled = atoi(value);
                break;
+       case SWM_S_STACK_ENABLED:
+               stack_enabled = atoi(value);
+               break;
        case SWM_S_CLOCK_ENABLED:
                clock_enabled = atoi(value);
                break;
@@ -3079,6 +3128,7 @@ struct config_option configopt[] = {
        { "bar_action",                 setconfvalue,   SWM_S_BAR_ACTION },
        { "bar_delay",                  setconfvalue,   SWM_S_BAR_DELAY },
        { "bind",                       setconfbinding, 0 },
+       { "stack_enabled",              setconfvalue,   SWM_S_STACK_ENABLED },
        { "clock_enabled",              setconfvalue,   SWM_S_CLOCK_ENABLED },
        { "color_focus",                setconfcolor,   SWM_S_COLOR_FOCUS },
        { "color_unfocus",              setconfcolor,   SWM_S_COLOR_UNFOCUS },
@@ -3528,23 +3578,30 @@ destroynotify(XEvent *e)
                if (win->transient)
                        winfocus = find_window(win->transient);
                else if (ws->focus == win) {
-                       if ((ws->cur_layout->flags & SWM_L_FOCUSPREV) &&
-                           ws->focus_prev)
-                               winfocus = ws->focus_prev;
-                       else if (TAILQ_FIRST(wl) == win)
-                               winfocus = TAILQ_NEXT(win, entry);
-                       else {
-                               winfocus = TAILQ_PREV(ws->focus, ws_win_list,
-                                   entry);
-                               if (winfocus == NULL)
-                                       winfocus = TAILQ_LAST(wl, ws_win_list);
+                       /* if in max_stack try harder */
+                       if (ws->cur_layout->flags & SWM_L_FOCUSPREV)
+                               if (win != ws->focus && win != ws->focus_prev)
+                                       winfocus = ws->focus_prev;
+
+                       /* fallback and normal handling */
+                       if (winfocus == NULL) {
+                               if (TAILQ_FIRST(wl) == win)
+                                       winfocus = TAILQ_NEXT(win, entry);
+                               else {
+                                       winfocus = TAILQ_PREV(ws->focus,
+                                           ws_win_list, entry);
+                                       if (winfocus == NULL)
+                                               winfocus = TAILQ_LAST(wl,
+                                                   ws_win_list);
+                               }
                        }
                }
-
+               ignore_enter = 1;
                unmanage_window(win);
                stack();
                if (winfocus)
                        focus_win(winfocus);
+               ignore_enter = 0;
        }
 
        SWM_EV_EPILOGUE(display);
@@ -3570,8 +3627,11 @@ enternotify(XEvent *e)
        if (QLength(display))
                return;
 
-       if ((win = find_window(ev->window)) != NULL)
+       if ((win = find_window(ev->window)) != NULL) {
+               if (win->ws->focus == win)
+                       return;
                focus_win(win);
+       }
 }
 
 void
@@ -3679,7 +3739,7 @@ propertynotify(XEvent *e)
 void
 unmapnotify(XEvent *e)
 {
-       struct ws_win           *win, *winfocus;
+       struct ws_win           *win, *winfocus = NULL;
        struct workspace        *ws;
 
        DNPRINTF(SWM_D_EVENT, "unmapnotify: window: %lu\n", e->xunmap.window);
@@ -3690,8 +3750,6 @@ unmapnotify(XEvent *e)
        win = find_window(e->xunmap.window);
        if (win == NULL)
                goto done;
-       if (win->transient)
-               goto done;
 
        if (getstate(e->xunmap.window) == NormalState) {
                /*
@@ -3699,21 +3757,36 @@ unmapnotify(XEvent *e)
                 * longer visible due to the app unmapping it so unmanage it
                 */
 
-               /* find something to focus */
                ws = win->ws;
-               winfocus = TAILQ_PREV(win, ws_win_list, entry);
-               if (TAILQ_FIRST(&ws->winlist) == win)
-                       winfocus = TAILQ_NEXT(win, entry);
-               else {
-                       winfocus = TAILQ_PREV(ws->focus, ws_win_list, entry);
-                       if (winfocus == NULL)
-                               winfocus = TAILQ_LAST(&ws->winlist, ws_win_list);
+               /* if we are max_stack try harder to focus on something */
+               if (ws->cur_layout->flags & SWM_L_FOCUSPREV) {
+                       if (win->transient)
+                               winfocus = find_window(win->transient);
+                       else if (win != ws->focus && win != ws->focus_prev)
+                               winfocus = ws->focus_prev;
+               }
+
+               /* normal and fallback if haven't found anything to focus on */
+               if (winfocus == NULL) {
+                       winfocus = TAILQ_PREV(win, ws_win_list, entry);
+                       if (TAILQ_FIRST(&ws->winlist) == win)
+                               winfocus = TAILQ_NEXT(win, entry);
+                       else {
+                               if (ws->focus)
+                                       winfocus = TAILQ_PREV(ws->focus,
+                                           ws_win_list, entry);
+                               if (winfocus == NULL)
+                                       winfocus = TAILQ_LAST(&ws->winlist,
+                                           ws_win_list);
+                       }
                }
 
                /* trash window and refocus */
                unmanage_window(win);
+               ignore_enter = 1;
                stack();
                focus_win(winfocus);
+               ignore_enter = 0;
        }
 
 done: