JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Mostly fix max_stack. Only known bug is that the focuses window doesn't
[spectrwm.git] / scrotwm.c
index 0dda010..2770962 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -198,7 +198,7 @@ GC                  bar_gc;
 XGCValues              bar_gcv;
 int                    bar_fidx = 0;
 XFontStruct            *bar_fs;
-char                   *bar_fonts[] = { NULL, NULL, NULL };    /* XXX Make fully dynamic */
+char                   *bar_fonts[] = { NULL, NULL, NULL, NULL };/* XXX Make fully dynamic */
 char                   *spawn_term[] = { NULL, NULL };         /* XXX Make fully dynamic */
 
 #define SWM_MENU_FN    (2)
@@ -1203,22 +1203,19 @@ switchws(struct swm_region *r, union arg *args)
            "%d -> %d\n", r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r),
            old_ws->idx, wsid);
 
-       /* get focus window */
-       if (new_ws->focus)
-               winfocus = new_ws->focus;
-       else if (new_ws->focus_prev)
-               winfocus = new_ws->focus_prev;
+       if (new_ws == old_ws)
+               return;
 
+       /* get focus window */
        if (new_ws->focus)
                winfocus = new_ws->focus;
        else if (new_ws->focus_prev)
                winfocus = new_ws->focus_prev;
-
-       if (new_ws == old_ws)
-               return;
+       else
+               winfocus = TAILQ_FIRST(&new_ws->winlist);
 
        other_r = new_ws->r;
-       if (!other_r) {
+       if (other_r == NULL) {
                /* if the other workspace is hidden, switch windows */
                /* map new window first to prevent ugly blinking */
                old_ws->r = NULL;
@@ -1422,14 +1419,19 @@ void
 cycle_layout(struct swm_region *r, union arg *args)
 {
        struct workspace        *ws = r->ws;
+       struct ws_win           *winfocus;
 
        DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx);
 
+       winfocus = ws->focus;
+
        ws->cur_layout++;
        if (ws->cur_layout->l_stack == NULL)
                ws->cur_layout = &layouts[0];
+
        ignore_enter = 1;
        stack();
+       focus_win(winfocus);
 }
 
 void
@@ -1506,6 +1508,10 @@ stack_floater(struct ws_win *win, struct swm_region *r)
                wc.y = (HEIGHT(r) - win->g.h) / 2;
        }
 
+       /* adjust for region */
+       wc.x += r->g.x;
+       wc.y += r->g.y;
+
        DNPRINTF(SWM_D_STACK, "stack_floater: win %lu x %d y %d w %d h %d\n",
            win->id, wc.x, wc.y, wc.width, wc.height);
 
@@ -1809,7 +1815,7 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
 {
        XWindowChanges          wc;
        struct swm_geometry     gg = *g;
-       struct ws_win           *win, *winfocus;
+       struct ws_win           *win;
        unsigned int            mask;
        int                     winno;
 
@@ -1821,19 +1827,12 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
        if (winno == 0 && count_win(ws, 1) == 0)
                return;
 
-       if (ws->focus == NULL)
-               ws->focus = TAILQ_FIRST(&ws->winlist);
-       winfocus = ws->focus;
-
        TAILQ_FOREACH(win, &ws->winlist, entry) {
                if (win->transient != 0 || win->floating != 0) {
                        if (win == ws->focus) {
-                               /* XXX maximize? */
                                stack_floater(win, ws->r);
                                XMapRaised(display, win->id);
-                       } else {
-                               /* XXX this sucks */
-                               XUnmapWindow(display, win->id);
+                               focus_win(win); /* override */
                        }
                } else {
                        bzero(&wc, sizeof wc);
@@ -1844,23 +1843,15 @@ 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);
-
-                       if (win == ws->focus) {
-                               XMapRaised(display, win->id);
-                       } else
-                               XUnmapWindow(display, win->id);
                }
        }
-
-       if (winfocus)
-               focus_win(winfocus); /* has to be done outside of the loop */
 }
 
 void
 send_to_ws(struct swm_region *r, union arg *args)
 {
        int                     wsid = args->id;
-       struct ws_win           *win = r->ws->focus;
+       struct ws_win           *win = r->ws->focus, *winfocus = NULL;
        struct workspace        *ws, *nws;
        Atom                    ws_idx_atom = 0;
        unsigned char           ws_idx_str[SWM_PROPLEN];
@@ -1873,14 +1864,20 @@ send_to_ws(struct swm_region *r, union arg *args)
        ws = win->ws;
        nws = &win->s->ws[wsid];
 
-       XUnmapWindow(display, win->id);
-
        /* find a window to focus */
-       ws->focus = TAILQ_PREV(win, ws_win_list, entry);
-       if (ws->focus == NULL)
-               ws->focus = TAILQ_FIRST(&ws->winlist);
-       if (ws->focus == win)
-               ws->focus = NULL;
+       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);
+       }
+       /* out of windows in ws so focus on nws instead */
+       if (winfocus == NULL)
+               winfocus = win;
+
+       XUnmapWindow(display, win->id);
 
        TAILQ_REMOVE(&ws->winlist, win, entry);
 
@@ -1903,6 +1900,7 @@ send_to_ws(struct swm_region *r, union arg *args)
        nws->restack = 1;
 
        stack();
+       focus_win(winfocus);
 }
 
 void
@@ -3192,7 +3190,7 @@ manage_window(Window id)
        Window                  trans;
        struct workspace        *ws;
        struct ws_win           *win, *ww;
-       int                     format, i, ws_idx, n;
+       int                     format, i, ws_idx, n, border_me = 0;
        unsigned long           nitems, bytes;
        Atom                    ws_idx_atom = 0, type;
        Atom                    *prot = NULL, *pp;
@@ -3248,14 +3246,19 @@ manage_window(Window id)
                ws = r->ws;
                /* this should launch transients in the same ws as parent */
                /* XXX doesn't work for intel xrandr */
-               if (id && trans) {
-                       if ((ww = find_window(trans)) != NULL) {
-                               ws = ww->ws;
-                               r = ws->r;
-                       }
-               }
+               if (id && trans)
+                       if ((ww = find_window(trans)) != NULL)
+                               if (ws->r) {
+                                       ws = ww->ws;
+                                       r = ww->ws->r;
+                                       border_me = 1;
+                               }
        }
 
+       /* shouldn't happen but does... */
+       if (ws->r == NULL)
+               ws->r = r; /* use found r since it isn't filled in */
+
        /* set up the window layout */
        win->id = id;
        win->ws = ws;
@@ -3305,9 +3308,7 @@ manage_window(Window id)
                        win->g.x = wc.x = WIDTH(win->ws->r) - win->g.w - 2;
                        mask |= CWX;
                }
-               wc.border_width = 1;
-               mask |= CWBorderWidth;
-               XConfigureWindow(display, win->id, mask, &wc);
+               border_me = 1;
        }
 
        /* Reset font sizes (the bruteforce way; no default keybinding). */
@@ -3318,13 +3319,21 @@ manage_window(Window id)
                        fake_keypress(win, XK_KP_Add, ShiftMask);
        }
 
+       /* border me */
+       if (border_me) {
+               bzero(&wc, sizeof wc);
+               wc.border_width = 1;
+               mask = CWBorderWidth;
+               XConfigureWindow(display, win->id, mask, &wc);
+       }
+
        XSelectInput(display, id, EnterWindowMask | FocusChangeMask |
            PropertyChangeMask | StructureNotifyMask);
 
        set_win_state(win, NormalState);
 
        /* floaters need to be mapped if they are in the current workspace */
-       if (win->floating && (ws->idx == r->ws->idx))
+       if ((win->floating || win->transient) && (ws->idx == r->ws->idx))
                XMapRaised(display, win->id);
 
        return (win);
@@ -3512,6 +3521,9 @@ mappingnotify(XEvent *e)
 void
 maprequest(XEvent *e)
 {
+       struct ws_win           *win;
+       struct swm_region       *r;
+
        XMapRequestEvent        *ev = &e->xmaprequest;
        XWindowAttributes       wa;
 
@@ -3528,9 +3540,10 @@ maprequest(XEvent *e)
        stack();
 
        /* make new win focused */
-       struct ws_win           *win;
        win = find_window(ev->window);
-       focus_win(win);
+       r = root_to_region(win->wa.root);
+       if (win->ws == r->ws)
+               focus_win(win);
 }
 
 void
@@ -3907,6 +3920,9 @@ setup_globals(void)
        if ((bar_fonts[1] = strdup("-*-times-medium-r-*-*-*-*-*-*-*-*-*-*"))
            == NULL)
                err(1, "setup_globals: strdup");
+       if ((bar_fonts[2] = strdup("-misc-fixed-medium-r-*-*-*-*-*-*-*-*-*-*"))
+           == NULL)
+               err(1, "setup_globals: strdup");
        if ((spawn_term[0] = strdup("xterm")) == NULL)
                err(1, "setup_globals: strdup");
 }
@@ -4009,6 +4025,8 @@ main(int argc, char *argv[])
        while (running) {
                while (XPending(display)) {
                        XNextEvent(display, &e);
+                       if (running == 0)
+                               goto done;
                        if (e.type < LASTEvent) {
                                dumpevent(&e);
                                if (handler[e.type])
@@ -4034,7 +4052,7 @@ main(int argc, char *argv[])
                /* if we are being restarted go focus on first window */
                if (winfocus) {
                        rr = TAILQ_FIRST(&screens[0].rl);
-                       /* move pointer to first screen */
+                       /* move pointer to first screen if multi screen */
                        if (ScreenCount(display) > 1 || outputs > 1)
                                XWarpPointer(display, None, rr->s[0].root,
                                    0, 0, 0, 0, rr->g.x,
@@ -4049,13 +4067,15 @@ main(int argc, char *argv[])
                FD_SET(xfd, &rd);
                if (select(xfd + 1, &rd, NULL, NULL, NULL) == -1)
                        if (errno != EINTR)
-                               errx(1, "select failed");
+                               DNPRINTF(SWM_D_MISC, "select failed");
+               if (running == 0)
+                       goto done;
                if (bar_alarm) {
                        bar_alarm = 0;
                        bar_update();
                }
        }
-
+done:
        bar_extra_stop();
 
        XCloseDisplay(display);