JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Reuse class hint in the status-bar.
[spectrwm.git] / spectrwm.c
index b1fc3f0..796153b 100644 (file)
@@ -241,8 +241,7 @@ struct search_window {
        Window                          indicator;
 };
 TAILQ_HEAD(search_winlist, search_window);
-
-struct search_winlist search_wl;
+struct search_winlist                  search_wl;
 
 /* search actions */
 enum {
@@ -253,6 +252,11 @@ enum {
        SWM_SEARCH_SEARCH_WINDOW
 };
 
+#define SWM_STACK_TOP          (0)
+#define SWM_STACK_BOTTOM       (1)
+#define        SWM_STACK_ABOVE         (2)
+#define        SWM_STACK_BELOW         (3)
+
 /* dialog windows */
 double                 dialog_ratio = 0.6;
 /* status bar */
@@ -296,6 +300,10 @@ int                        title_name_enabled = 0;
 int                    title_class_enabled = 0;
 int                    window_name_enabled = 0;
 int                    focus_mode = SWM_FOCUS_DEFAULT;
+int                    focus_close = SWM_STACK_BELOW;
+int                    focus_close_wrap = 1;
+int                    focus_default = SWM_STACK_TOP;
+int                    spawn_position = SWM_STACK_TOP;
 int                    disable_border = 0;
 int                    border_width = 1;
 int                    verbose_layout = 0;
@@ -467,7 +475,6 @@ struct swm_screen {
        GC                      bar_gc;
 };
 struct swm_screen      *screens;
-int                    num_screens;
 
 /* args to functions */
 union arg {
@@ -599,11 +606,11 @@ get_property(Window id, Atom atom, long count, Atom type, unsigned long *nitems,
            &real, &format, nitems_ret, nbytes_ret, data);
 
        if (status != Success)
-               return False;
+               return (False);
        if (real != type)
-               return False;
+               return (False);
 
-       return True;
+       return (True);
 }
 
 void
@@ -671,7 +678,7 @@ setup_ewmh(void)
                for (j = 0; j < LENGTH(ewmh); j++)
                        XChangeProperty(display, screens[i].root,
                            sup_list, XA_ATOM, 32,
-                           PropModeAppend, (unsigned char *)&ewmh[j].atom,1);
+                           PropModeAppend, (unsigned char *)&ewmh[j].atom, 1);
        }
 }
 
@@ -754,10 +761,10 @@ ewmh_set_win_fullscreen(struct ws_win *win, int fs)
        struct swm_geometry     rg;
 
        if (!win->ws->r)
-               return 0;
+               return (0);
 
        if (!win->floating)
-               return 0;
+               return (0);
 
        DNPRINTF(SWM_D_MISC, "ewmh_set_win_fullscreen: window: 0x%lx, "
            "fullscreen %s\n", win->id, YESNO(fs));
@@ -778,7 +785,7 @@ ewmh_set_win_fullscreen(struct ws_win *win, int fs)
                }
        }
 
-       return 1;
+       return (1);
 }
 
 void
@@ -1019,7 +1026,7 @@ geteventname(XEvent *e)
                name = "Unknown";
        }
 
-       return name;
+       return (name);
 }
 
 char *
@@ -1035,7 +1042,7 @@ xrandr_geteventname(XEvent *e)
                name = "Unknown";
        }
 
-       return name;
+       return (name);
 }
 
 void
@@ -1346,32 +1353,24 @@ void
 bar_class_name(char *s, ssize_t sz, struct ws_win *cur_focus)
 {
        int                     do_class, do_name;
-       Status                  status;
-       XClassHint              *xch = NULL;
+       XClassHint              *ch;
 
-       if ((title_name_enabled == 1 || title_class_enabled == 1) &&
-           cur_focus != NULL) {
-               if ((xch = XAllocClassHint()) == NULL)
-                       goto out;
-               status = XGetClassHint(display, cur_focus->id, xch);
-               if (status == BadWindow || status == BadAlloc)
-                       goto out;
-               do_class = (title_class_enabled && xch->res_class != NULL);
-               do_name = (title_name_enabled && xch->res_name != NULL);
-               if (do_class)
-                       strlcat(s, xch->res_class, sz);
-               if (do_class && do_name)
-                       strlcat(s, ":", sz);
-               if (do_name)
-                       strlcat(s, xch->res_name, sz);
-               strlcat(s, "    ", sz);
-       }
-out:
-       if (xch) {
-               XFree(xch->res_name);
-               XFree(xch->res_class);
-               XFree(xch);
-       }
+       if (title_name_enabled == 0 && title_class_enabled == 0)
+               return;
+       if (cur_focus == NULL)
+               return;
+
+       ch = &cur_focus->ch;
+       do_class = (title_class_enabled && ch->res_class != NULL);
+       do_name = (title_name_enabled && ch->res_name != NULL);
+
+       if (do_class)
+               strlcat(s, ch->res_class, sz);
+       if (do_class && do_name)
+               strlcat(s, ":", sz);
+       if (do_name)
+               strlcat(s, ch->res_name, sz);
+       strlcat(s, "    ", sz);
 }
 
 void
@@ -2159,7 +2158,7 @@ unfocus_win(struct ws_win *win)
 
        XChangeProperty(display, win->s->root,
            ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
-           PropModeReplace, (unsigned char *)&none,1);
+           PropModeReplace, (unsigned char *)&none, 1);
 }
 
 void
@@ -2235,7 +2234,7 @@ focus_win(struct ws_win *win)
 
                XChangeProperty(display, win->s->root,
                    ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
-                   PropModeReplace, (unsigned char *)&win->id,1);
+                   PropModeReplace, (unsigned char *)&win->id, 1);
        }
 
        bar_check_opts();
@@ -2476,7 +2475,6 @@ swapwin(struct swm_region *r, union arg *args)
                if (target == source) {
                        if (source->ws->focus_prev != NULL &&
                            source->ws->focus_prev != target)
-
                                source = source->ws->focus_prev;
                        else
                                return;
@@ -2511,8 +2509,6 @@ focus_prev(struct ws_win *win)
        struct ws_win_list      *wl = NULL;
        struct workspace        *ws = NULL;
 
-       DNPRINTF(SWM_D_FOCUS, "focus_prev: window: 0x%lx\n", WINID(win));
-
        if (!(win && win->ws))
                return;
 
@@ -2520,14 +2516,15 @@ focus_prev(struct ws_win *win)
        wl = &ws->winlist;
        cur_focus = ws->focus;
 
+       DNPRINTF(SWM_D_FOCUS, "focus_prev: window: 0x%lx, cur_focus: 0x%lx\n",
+           WINID(win), WINID(cur_focus));
+
        /* pickle, just focus on whatever */
        if (cur_focus == NULL) {
                /* use prev_focus if valid */
                if (ws->focus_prev && ws->focus_prev != cur_focus &&
                    find_window(WINID(ws->focus_prev)))
                        winfocus = ws->focus_prev;
-               if (winfocus == NULL)
-                       winfocus = TAILQ_FIRST(wl);
                goto done;
        }
 
@@ -2548,14 +2545,44 @@ focus_prev(struct ws_win *win)
                        goto done;
        }
 
-       if (cur_focus == win)
-               winfocus = TAILQ_PREV(win, ws_win_list, entry);
-       if (winfocus == NULL)
-               winfocus = TAILQ_LAST(wl, ws_win_list);
-       if (winfocus == NULL || winfocus == win)
-               winfocus = TAILQ_NEXT(cur_focus, entry);
+       DNPRINTF(SWM_D_FOCUS, "focus_prev: focus_close: %d\n", focus_close);
 
+       if (winfocus == NULL || winfocus == win) {
+               switch (focus_close) {
+               case SWM_STACK_BOTTOM:
+                       winfocus = TAILQ_FIRST(wl);
+                       break;
+               case SWM_STACK_TOP:
+                       winfocus = TAILQ_LAST(wl, ws_win_list);
+                       break;
+               case SWM_STACK_ABOVE:
+                       if ((winfocus = TAILQ_NEXT(cur_focus, entry)) == NULL) {
+                               if (focus_close_wrap)
+                                       winfocus = TAILQ_FIRST(wl);
+                               else
+                                       winfocus = TAILQ_PREV(cur_focus,
+                                           ws_win_list, entry);
+                       }
+                       break;
+               case SWM_STACK_BELOW:
+                       if ((winfocus = TAILQ_PREV(cur_focus, ws_win_list,
+                           entry)) == NULL) {
+                               if (focus_close_wrap)
+                                       winfocus = TAILQ_LAST(wl, ws_win_list);
+                               else
+                                       winfocus = TAILQ_NEXT(cur_focus, entry);
+                       }
+                       break;
+               }
+       }
 done:
+       if (winfocus == NULL) {
+               if (focus_default == SWM_STACK_TOP)
+                       winfocus = TAILQ_LAST(wl, ws_win_list);
+               else
+                       winfocus = TAILQ_FIRST(wl);
+       }
+
        focus_magic(winfocus);
 }
 
@@ -3739,16 +3766,16 @@ floating_toggle_win(struct ws_win *win)
        struct swm_region       *r;
 
        if (win == NULL)
-               return 0;
+               return (0);
 
        if (!win->ws->r)
-               return 0;
+               return (0);
 
        r = win->ws->r;
 
        /* reject floating toggles in max stack mode */
        if (win->ws->cur_layout == &layouts[SWM_MAX_STACK])
-               return 0;
+               return (0);
 
        if (win->floating) {
                if (!win->floatmaxed) {
@@ -3769,7 +3796,7 @@ floating_toggle_win(struct ws_win *win)
 
        ewmh_update_actions(win);
 
-       return 1;
+       return (1);
 }
 
 void
@@ -5281,11 +5308,12 @@ enum    { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_BAR_BORDER_WIDTH,
          SWM_S_STACK_ENABLED, SWM_S_CLOCK_ENABLED, SWM_S_CLOCK_FORMAT,
          SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, SWM_S_WORKSPACE_LIMIT,
          SWM_S_SS_ENABLED, SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED,
-         SWM_S_TITLE_NAME_ENABLED, SWM_S_WINDOW_NAME_ENABLED, SWM_S_URGENT_ENABLED,
-         SWM_S_FOCUS_MODE, SWM_S_DISABLE_BORDER, SWM_S_BORDER_WIDTH,
-         SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM,
-         SWM_S_SS_APP, SWM_S_DIALOG_RATIO, SWM_S_BAR_AT_BOTTOM,
-         SWM_S_VERBOSE_LAYOUT, SWM_S_BAR_JUSTIFY
+         SWM_S_TITLE_NAME_ENABLED, SWM_S_WINDOW_NAME_ENABLED,
+         SWM_S_URGENT_ENABLED, SWM_S_FOCUS_MODE, SWM_S_FOCUS_CLOSE,
+         SWM_S_FOCUS_CLOSE_WRAP, SWM_S_FOCUS_DEFAULT, SWM_S_SPAWN_ORDER,
+         SWM_S_DISABLE_BORDER, SWM_S_BORDER_WIDTH, SWM_S_BAR_FONT,
+         SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM, SWM_S_SS_APP, SWM_S_DIALOG_RATIO,
+         SWM_S_BAR_AT_BOTTOM, SWM_S_VERBOSE_LAYOUT, SWM_S_BAR_JUSTIFY
        };
 
 int
@@ -5371,6 +5399,41 @@ setconfvalue(char *selector, char *value, int flags)
                else
                        errx(1, "focus_mode");
                break;
+       case SWM_S_FOCUS_CLOSE:
+               if (!strcmp(value, "first"))
+                       focus_close = SWM_STACK_BOTTOM;
+               else if (!strcmp(value, "last"))
+                       focus_close = SWM_STACK_TOP;
+               else if (!strcmp(value, "next"))
+                       focus_close = SWM_STACK_ABOVE;
+               else if (!strcmp(value, "previous"))
+                       focus_close = SWM_STACK_BELOW;
+               else
+                       errx(1, "focus_close");
+               break;
+       case SWM_S_FOCUS_CLOSE_WRAP:
+               focus_close_wrap = atoi(value);
+               break;
+       case SWM_S_FOCUS_DEFAULT:
+               if (!strcmp(value, "last"))
+                       focus_default = SWM_STACK_TOP;
+               else if (!strcmp(value, "first"))
+                       focus_default = SWM_STACK_BOTTOM;
+               else
+                       errx(1, "focus_default");
+               break;
+       case SWM_S_SPAWN_ORDER:
+               if (!strcmp(value, "first"))
+                       spawn_position = SWM_STACK_BOTTOM;
+               else if (!strcmp(value, "last"))
+                       spawn_position = SWM_STACK_TOP;
+               else if (!strcmp(value, "next"))
+                       spawn_position = SWM_STACK_ABOVE;
+               else if (!strcmp(value, "previous"))
+                       spawn_position = SWM_STACK_BELOW;
+               else
+                       errx(1, "spawn_position");
+               break;
        case SWM_S_DISABLE_BORDER:
                disable_border = atoi(value);
                break;
@@ -5620,6 +5683,10 @@ struct config_option configopt[] = {
        { "title_class_enabled",        setconfvalue,   SWM_S_TITLE_CLASS_ENABLED },
        { "title_name_enabled",         setconfvalue,   SWM_S_TITLE_NAME_ENABLED },
        { "focus_mode",                 setconfvalue,   SWM_S_FOCUS_MODE },
+       { "focus_close",                setconfvalue,   SWM_S_FOCUS_CLOSE },
+       { "focus_close_wrap",           setconfvalue,   SWM_S_FOCUS_CLOSE_WRAP },
+       { "focus_default",              setconfvalue,   SWM_S_FOCUS_DEFAULT },
+       { "spawn_position",             setconfvalue,   SWM_S_SPAWN_ORDER },
        { "disable_border",             setconfvalue,   SWM_S_DISABLE_BORDER },
        { "border_width",               setconfvalue,   SWM_S_BORDER_WIDTH },
        { "autorun",                    setautorun,     0 },
@@ -5859,12 +5926,27 @@ manage_window(Window id)
                DNPRINTF(SWM_D_MISC, "manage_window: previously unmanaged "
                    "window: 0x%lx\n", win->id);
                TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
-               if (win->transient) {
+               if (win->transient)
                        set_child_transient(win, &trans);
-               } if (trans && (ww = find_window(trans)))
+
+               if (trans && (ww = find_window(trans)))
                        TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
-               else
+               else if ((ww = win->ws->focus) &&
+                   spawn_position == SWM_STACK_ABOVE)
+                       TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win, entry);
+               else if (ww && spawn_position == SWM_STACK_BELOW)
+                       TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win, entry);
+               else switch (spawn_position) {
+               default:
+               case SWM_STACK_TOP:
+               case SWM_STACK_ABOVE:
                        TAILQ_INSERT_TAIL(&win->ws->winlist, win, entry);
+                       break;
+               case SWM_STACK_BOTTOM:
+               case SWM_STACK_BELOW:
+                       TAILQ_INSERT_HEAD(&win->ws->winlist, win, entry);
+               }
+
                ewmh_update_actions(win);
                return (win);
        }
@@ -5951,6 +6033,8 @@ manage_window(Window id)
        win->s = r->s;  /* this never changes */
        if (trans && (ww = find_window(trans)))
                TAILQ_INSERT_AFTER(&ws->winlist, ww, win, entry);
+       else if (spawn_position == SWM_STACK_ABOVE && win->ws->focus)
+               TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win, entry);
        else
                TAILQ_INSERT_TAIL(&ws->winlist, win, entry);
 
@@ -6215,9 +6299,8 @@ configurerequest(XEvent *e)
                wc.sibling = ev->above;
                wc.stack_mode = ev->detail;
                XConfigureWindow(display, ev->window, ev->value_mask, &wc);
-       } else {
+       } else
                config_win(win, ev);
-       }
 }
 
 void
@@ -6993,9 +7076,9 @@ workaround(void)
                    screens[i].c[SWM_S_COLOR_UNFOCUS].color);
 
                XChangeProperty(display, root, netwmcheck, XA_WINDOW, 32,
-                   PropModeReplace, (unsigned char *)&win,1);
+                   PropModeReplace, (unsigned char *)&win, 1);
                XChangeProperty(display, win, netwmcheck, XA_WINDOW, 32,
-                   PropModeReplace, (unsigned char *)&win,1);
+                   PropModeReplace, (unsigned char *)&win, 1);
                XChangeProperty(display, win, netwmname, utf8_string, 8,
                    PropModeReplace, (unsigned char*)"LG3D", strlen("LG3D"));
        }