JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Fix a crash when mvws_n is used in an empty workspace.
authorLawrence Teo <lteo@lteo.net>
Tue, 10 Jan 2012 01:30:00 +0000 (20:30 -0500)
committerLawrence Teo <lteo@lteo.net>
Tue, 10 Jan 2012 01:45:49 +0000 (20:45 -0500)
mvws_n invokes send_to_ws(), which in turn calls focus() to focus on
the previous window before sending the current window to the desired
workspace. The TAILQ_PREV() call in focus() will fail if there are no
windows in the current workspace.

This commit adds a safeguard to focus() by ensuring that the list of
windows in the current workspace is not empty and that there is at
least one uniconified window to focus on before proceeding.

This commit also modifies send_to_ws() to set r->ws->focus to NULL if
there are no more windows in the workspace after sending the current
window to another workspace. This fixes an odd behavior where you can
"summon" a window that you have previously moved to another workspace,
even though you are in an empty workspace.

Closes FS#191

ok marco

scrotwm.c

index c2aece7..37cdf48 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -2446,6 +2446,7 @@ focus(struct swm_region *r, union arg *args)
        struct ws_win           *cur_focus = NULL;
        struct ws_win_list      *wl = NULL;
        struct workspace        *ws = NULL;
        struct ws_win           *cur_focus = NULL;
        struct ws_win_list      *wl = NULL;
        struct workspace        *ws = NULL;
+       int                     all_iconics;
 
        if (!(r && r->ws))
                return;
 
        if (!(r && r->ws))
                return;
@@ -2471,6 +2472,17 @@ focus(struct swm_region *r, union arg *args)
                return;
        ws = r->ws;
        wl = &ws->winlist;
                return;
        ws = r->ws;
        wl = &ws->winlist;
+       if (TAILQ_EMPTY(wl))
+               return;
+       /* make sure there is at least one uniconified window */
+       all_iconics = 1;
+       TAILQ_FOREACH(winfocus, wl, entry)
+               if (winfocus->iconic == 0) {
+                       all_iconics = 0;
+                       break;
+               }
+       if (all_iconics)
+               return;
 
        winlostfocus = cur_focus;
 
 
        winlostfocus = cur_focus;
 
@@ -3118,7 +3130,7 @@ send_to_ws(struct swm_region *r, union arg *args)
        unsigned char           ws_idx_str[SWM_PROPLEN];
        union arg               a;
 
        unsigned char           ws_idx_str[SWM_PROPLEN];
        union arg               a;
 
-       if (r && r->ws)
+       if (r && r->ws && r->ws->focus)
                win = r->ws->focus;
        else
                return;
                win = r->ws->focus;
        else
                return;
@@ -3146,6 +3158,8 @@ send_to_ws(struct swm_region *r, union arg *args)
        unmap_window(win);
        TAILQ_REMOVE(&ws->winlist, win, entry);
        TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
        unmap_window(win);
        TAILQ_REMOVE(&ws->winlist, win, entry);
        TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
+       if (TAILQ_EMPTY(&ws->winlist))
+               r->ws->focus = NULL;
        win->ws = nws;
 
        /* Try to update the window's workspace property */
        win->ws = nws;
 
        /* Try to update the window's workspace property */