JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
add border width for bar too
[spectrwm.git] / scrotwm.c
index b7f37fd..01cbd38 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -52,7 +52,7 @@
 
 static const char      *cvstag = "$scrotwm$";
 
-#define        SWM_VERSION     "0.9.26"
+#define        SWM_VERSION     "0.9.29"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -198,6 +198,7 @@ int                 bar_version = 0;
 sig_atomic_t           bar_alarm = 0;
 int                    bar_delay = 30;
 int                    bar_enabled = 1;
+int                    bar_border_width = 1;
 int                    bar_at_bottom = 0;
 int                    bar_extra = 1;
 int                    bar_extra_running = 0;
@@ -208,8 +209,10 @@ int                        clock_enabled = 1;
 char                   *clock_format = NULL;
 int                    title_name_enabled = 0;
 int                    title_class_enabled = 0;
+int                    window_name_enabled = 0;
 int                    focus_mode = SWM_FOCUS_DEFAULT;
 int                    disable_border = 0;
+int                    border_width = 1;
 pid_t                  bar_pid;
 GC                     bar_gc;
 XGCValues              bar_gcv;
@@ -1040,10 +1043,12 @@ custom_region(char *val)
        if (x  < 0 || x > DisplayWidth(display, sidx) ||
            y < 0 || y > DisplayHeight(display, sidx) ||
            w + x > DisplayWidth(display, sidx) ||
-           h + y > DisplayHeight(display, sidx))
-               errx(1, "region %ux%u+%u+%u not within screen boundaries "
+           h + y > DisplayHeight(display, sidx)) {
+               fprintf(stderr, "ignoring region %ux%u+%u+%u - not within screen boundaries "
                    "(%ux%u)\n", w, h, x, y,
                    DisplayWidth(display, sidx), DisplayHeight(display, sidx));
+               return;
+       }
 
        new_region(&screens[sidx], x, y, w, h);
 }
@@ -1114,6 +1119,23 @@ out:
 }
 
 void
+bar_window_name(char *s, ssize_t sz, struct ws_win *cur_focus)
+{
+       char                    *title;
+
+       if (window_name_enabled && cur_focus != NULL) {
+               XFetchName(display, cur_focus->id, &title);
+               if (title) {
+                       if (cur_focus->floating)
+                               strlcat(s, "(f) ", sz);
+                       strlcat(s, title, sz);
+                       strlcat(s, " ", sz);
+                       XFree(title);
+               }
+       }
+}
+
+void
 bar_update(void)
 {
        time_t                  tmt;
@@ -1157,8 +1179,10 @@ bar_update(void)
                x = 1;
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
                        strlcpy(cn, "", sizeof cn);
-                       if (r && r->ws)
+                       if (r && r->ws) {
                                bar_class_name(cn, sizeof cn, r->ws->focus);
+                               bar_window_name(cn, sizeof cn, r->ws->focus);
+                       }
 
                        if (stack_enabled)
                                stack = r->ws->cur_layout->name;
@@ -1273,13 +1297,13 @@ bar_setup(struct swm_region *r)
        if (bar_fs == NULL)
                errx(1, "couldn't create font structure");
 
-       bar_height = bar_fs->ascent + bar_fs->descent + 3;
+       bar_height = bar_fs->ascent + bar_fs->descent + 1 + 2 * bar_border_width;
        x = X(r);
        y = bar_at_bottom ? (Y(r) + HEIGHT(r) - bar_height) : Y(r);
 
        r->bar_window = XCreateSimpleWindow(display,
-           r->s->root, x, y, WIDTH(r) - 2, bar_height - 2,
-           1, r->s->c[SWM_S_COLOR_BAR_BORDER].color,
+           r->s->root, x, y, WIDTH(r) - 2 * bar_border_width, bar_height - 2 * bar_border_width,
+           bar_border_width, r->s->c[SWM_S_COLOR_BAR_BORDER].color,
            r->s->c[SWM_S_COLOR_BAR].color);
        bar_gc = XCreateGC(display, r->bar_window, 0, &bar_gcv);
        XSetFont(display, bar_gc, bar_fs->fid);
@@ -1369,7 +1393,7 @@ configreq_win(struct ws_win *win)
        cr.y = win->g.y;
        cr.width = win->g.w;
        cr.height = win->g.h;
-       cr.border_width = 1;
+       cr.border_width = border_width;
 
        XSendEvent(display, win->id, False, StructureNotifyMask, (XEvent *)&cr);
 }
@@ -1393,7 +1417,7 @@ config_win(struct ws_win *win)
        ce.y = win->g.y;
        ce.width = win->g.w;
        ce.height = win->g.h;
-       ce.border_width = 1; /* XXX store this! */
+       ce.border_width = border_width; /* XXX store this! */
        ce.above = None;
        ce.override_redirect = False;
        XSendEvent(display, win->id, False, StructureNotifyMask, (XEvent *)&ce);
@@ -1711,7 +1735,7 @@ void
 unfocus_win(struct ws_win *win)
 {
        XEvent                  cne;
-       Window                  none = None;
+       Window                  none = None;
 
        DNPRINTF(SWM_D_FOCUS, "unfocus_win: id: %lu\n", WINID(win));
 
@@ -1721,7 +1745,7 @@ unfocus_win(struct ws_win *win)
                return;
 
        if (validate_ws(win->ws))
-               abort(); /* XXX replace with return at some point */
+               return; /* XXX this gets hit with thunderbird, needs fixing */
 
        if (win->ws->r == NULL)
                return;
@@ -1789,7 +1813,7 @@ focus_win(struct ws_win *win)
                return;
 
        if (validate_ws(win->ws))
-               abort(); /* XXX replace with return at some point */
+               return; /* XXX this gets hit with thunderbird, needs fixing */
 
        if (validate_win(win)) {
                kill_refs(win);
@@ -1825,6 +1849,9 @@ focus_win(struct ws_win *win)
                    ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
                    PropModeReplace, (unsigned char *)&win->id,1);
        }
+
+       if (window_name_enabled)
+               bar_update();
 }
 
 void
@@ -2217,8 +2244,8 @@ stack(void) {
 
                        /* start with screen geometry, adjust for bar */
                        g = r->g;
-                       g.w -= 2;
-                       g.h -= 2;
+                       g.w -= 2 * border_width;
+                       g.h -= 2 * border_width;
                        if (bar_enabled) {
                                if (!bar_at_bottom)
                                        g.y += bar_height;
@@ -2284,7 +2311,7 @@ stack_floater(struct ws_win *win, struct swm_region *r)
            (win->g.h >= HEIGHT(r)))
                wc.border_width = 0;
        else
-               wc.border_width = 1;
+               wc.border_width = border_width;
        if (win->transient && (win->quirks & SWM_Q_TRANSSZ)) {
                win->g.w = (double)WIDTH(r) * dialog_ratio;
                win->g.h = (double)HEIGHT(r) * dialog_ratio;
@@ -2295,22 +2322,22 @@ stack_floater(struct ws_win *win, struct swm_region *r)
                 * floaters and transients are auto-centred unless moved
                 * or resized
                 */
-               win->g.x = r->g.x + (WIDTH(r) - win->g.w) / 2;
-               win->g.y = r->g.y + (HEIGHT(r) - win->g.h) / 2;
+               win->g.x = r->g.x + (WIDTH(r) - win->g.w) / 2 - border_width;
+               win->g.y = r->g.y + (HEIGHT(r) - win->g.h) / 2 - border_width;
        }
 
        /* win can be outside r if new r smaller than old r */
        /* Ensure top left corner inside r (move probs otherwise) */
-       if (win->g.x < r->g.x )
-               win->g.x = r->g.x;
+       if (win->g.x < r->g.x - border_width)
+               win->g.x = r->g.x - border_width;
        if (win->g.x > r->g.x + r->g.w - 1)
                win->g.x = (win->g.w > r->g.w) ? r->g.x :
-                   (r->g.x + r->g.w - win->g.w - 2);
-       if (win->g.y < r->g.y )
-               win->g.y = r->g.y;
+                   (r->g.x + r->g.w - win->g.w - 2 * border_width);
+       if (win->g.y < r->g.y - border_width)
+               win->g.y = r->g.y - border_width;
        if (win->g.y > r->g.y + r->g.h - 1)
                win->g.y = (win->g.h > r->g.h) ? r->g.y :
-                   (r->g.y + r->g.h - win->g.h - 2);
+                   (r->g.y + r->g.h - win->g.h - 2 * border_width);
 
        wc.x = win->g.x;
        wc.y = win->g.y;
@@ -2436,11 +2463,11 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
        } else {
                msize = -2;
                colno = split = winno / stacks;
-               win_g.w = ((r_g.w - (stacks * 2) + 2) / stacks);
+               win_g.w = ((r_g.w - (stacks * 2 * border_width) + 2 * border_width) / stacks);
        }
        hrh = r_g.h / colno;
        extra = r_g.h - (colno * hrh);
-       win_g.h = hrh - 2;
+       win_g.h = hrh - 2 * border_width;
 
        /*  stack all the tiled windows */
        i = j = 0, s = stacks;
@@ -2463,15 +2490,15 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
                        if (flip)
                                win_g.x = r_g.x;
                        else
-                               win_g.x += win_g.w + 2;
-                       win_g.w = (r_g.w - msize - (stacks * 2)) / stacks;
+                               win_g.x += win_g.w + 2 * border_width;
+                       win_g.w = (r_g.w - msize - (stacks * 2 * border_width)) / stacks;
                        if (s == 1)
-                               win_g.w += (r_g.w - msize - (stacks * 2)) %
+                               win_g.w += (r_g.w - msize - (stacks * 2 * border_width)) %
                                    stacks;
                        s--;
                        j = 0;
                }
-               win_g.h = hrh - 2;
+               win_g.h = hrh - 2 * border_width;
                if (rot) {
                        h_inc = win->sh.width_inc;
                        h_base = win->sh.base_width;
@@ -2498,15 +2525,15 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
                if (j == 0)
                        win_g.y = r_g.y;
                else
-                       win_g.y += last_h + 2;
+                       win_g.y += last_h + 2 * border_width;
 
                bzero(&wc, sizeof wc);
                if (disable_border && bar_enabled == 0 && winno == 1){
                        wc.border_width = 0;
-                       win_g.w += 2;
-                       win_g.h += 2;
+                       win_g.w += 2 * border_width;
+                       win_g.h += 2 * border_width;
                } else
-                       wc.border_width = 1;
+                       wc.border_width = border_width;
                reconfigure = 0;
                if (rot) {
                        if (win->g.x != win_g.y || win->g.y != win_g.x ||
@@ -2700,13 +2727,13 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                        win->g.x = wc.x = gg.x;
                        win->g.y = wc.y = gg.y;
                        if (bar_enabled){
-                               wc.border_width = 1;
+                               wc.border_width = border_width;
                                win->g.w = wc.width = gg.w;
                                win->g.h = wc.height = gg.h;
                        } else {
                                wc.border_width = 0;
-                               win->g.w = wc.width = gg.w + 2;
-                               win->g.h = wc.height = gg.h + 2;
+                               win->g.w = wc.width = gg.w + 2 * border_width;
+                               win->g.h = wc.height = gg.h + 2 * border_width;
                        }
                        mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
                        XConfigureWindow(display, win->id, mask, &wc);
@@ -2832,6 +2859,9 @@ floating_toggle(struct swm_region *r, union arg *args)
        struct ws_win           *win = r->ws->focus;
        union arg               a;
 
+       if (win == NULL)
+               return;
+
        ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
            _NET_WM_STATE_TOGGLE);
 
@@ -2853,12 +2883,12 @@ resize_window(struct ws_win *win, int center)
        r = root_to_region(win->wa.root);
        bzero(&wc, sizeof wc);
        mask = CWBorderWidth | CWWidth | CWHeight;
-       wc.border_width = 1;
+       wc.border_width = border_width;
        wc.width = win->g.w;
        wc.height = win->g.h;
        if (center == SWM_ARG_ID_CENTER) {
-               wc.x = (WIDTH(r) - win->g.w) / 2;
-               wc.y = (HEIGHT(r) - win->g.h) / 2;
+               wc.x = (WIDTH(r) - win->g.w) / 2 - border_width;
+               wc.y = (HEIGHT(r) - win->g.h) / 2 - border_width;
                mask |= CWX | CWY;
        }
 
@@ -2903,14 +2933,14 @@ resize(struct ws_win *win, union arg *args)
 
        /* place pointer at bottom left corner or nearest point inside r */
        if ( win->g.x + win->g.w < r->g.x + r->g.w - 1)
-               relx = win->g.w;
+               relx = win->g.w - 1;
        else
-               relx = r->g.x + r->g.w - win->g.x - 2;
+               relx = r->g.x + r->g.w - win->g.x - 1;
 
        if ( win->g.y + win->g.h < r->g.y + r->g.h - 1)
-               rely = win->g.h;
+               rely = win->g.h - 1;
        else
-               rely = r->g.y + r->g.h - win->g.y - 2;
+               rely = r->g.y + r->g.h - win->g.y - 1;
 
        XWarpPointer(display, None, win->id, 0, 0, 0, 0, relx, rely);
        do {
@@ -2934,11 +2964,11 @@ resize(struct ws_win *win, union arg *args)
                                ev.xmotion.x = 1;
                        if (ev.xmotion.y <= 1)
                                ev.xmotion.y = 1;
-                       win->g.w = ev.xmotion.x;
-                       win->g.h = ev.xmotion.y;
+                       win->g.w = ev.xmotion.x + 1;
+                       win->g.h = ev.xmotion.y + 1;
 
-                       /* not free, don't sync more than 60 times / second */
-                       if ((ev.xmotion.time - time) > (1000 / 60) ) {
+                       /* not free, don't sync more than 120 times / second */
+                       if ((ev.xmotion.time - time) > (1000 / 120) ) {
                                time = ev.xmotion.time;
                                XSync(display, False);
                                resize_window(win, args->id);
@@ -3012,7 +3042,7 @@ move(struct ws_win *win, union arg *args)
        if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
            GrabModeAsync, None, None /* cursor */, CurrentTime) != GrabSuccess)
                return;
-       XWarpPointer(display, None, win->id, 0, 0, 0, 0, -1, -1);
+       XWarpPointer(display, None, win->id, 0, 0, 0, 0, 0, 0);
        do {
                XMaskEvent(display, MOUSEMASK | ExposureMask |
                    SubstructureRedirectMask, &ev);
@@ -3030,11 +3060,11 @@ move(struct ws_win *win, union arg *args)
                                ev.xmotion.y_root > r->g.y + r->g.h - 1)
                                continue;
 
-                       win->g.x = ev.xmotion.x_root;
-                       win->g.y = ev.xmotion.y_root;
+                       win->g.x = ev.xmotion.x_root - border_width;
+                       win->g.y = ev.xmotion.y_root - border_width;
 
-                       /* not free, don't sync more than 60 times / second */
-                       if ((ev.xmotion.time - time) > (1000 / 60) ) {
+                       /* not free, don't sync more than 120 times / second */
+                       if ((ev.xmotion.time - time) > (1000 / 120) ) {
                                time = ev.xmotion.time;
                                XSync(display, False);
                                move_window(win);
@@ -3937,11 +3967,11 @@ setup_quirks(void)
 /* conf file stuff */
 #define SWM_CONF_FILE  "scrotwm.conf"
 
-enum   { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_STACK_ENABLED,
+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_SS_ENABLED, SWM_S_TERM_WIDTH,
-         SWM_S_TITLE_CLASS_ENABLED, SWM_S_TITLE_NAME_ENABLED,
-         SWM_S_FOCUS_MODE, SWM_S_DISABLE_BORDER, SWM_S_BAR_FONT,
+         SWM_S_TITLE_CLASS_ENABLED, SWM_S_TITLE_NAME_ENABLED, SWM_S_WINDOW_NAME_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
        };
@@ -3956,6 +3986,9 @@ setconfvalue(char *selector, char *value, int flags)
        case SWM_S_BAR_ENABLED:
                bar_enabled = atoi(value);
                break;
+       case SWM_S_BAR_BORDER_WIDTH:
+               bar_border_width = atoi(value);
+               break;
        case SWM_S_BAR_AT_BOTTOM:
                bar_at_bottom = atoi(value);
                break;
@@ -3987,6 +4020,9 @@ setconfvalue(char *selector, char *value, int flags)
        case SWM_S_TITLE_CLASS_ENABLED:
                title_class_enabled = atoi(value);
                break;
+       case SWM_S_WINDOW_NAME_ENABLED:
+               window_name_enabled = atoi(value);
+               break;
        case SWM_S_TITLE_NAME_ENABLED:
                title_name_enabled = atoi(value);
                break;
@@ -4003,6 +4039,9 @@ setconfvalue(char *selector, char *value, int flags)
        case SWM_S_DISABLE_BORDER:
                disable_border = atoi(value);
                break;
+       case SWM_S_BORDER_WIDTH:
+               border_width = atoi(value);
+               break;
        case SWM_S_BAR_FONT:
                free(bar_fonts[0]);
                if ((bar_fonts[0] = strdup(value)) == NULL)
@@ -4071,6 +4110,7 @@ struct config_option configopt[] = {
        { "bar_enabled",                setconfvalue,   SWM_S_BAR_ENABLED },
        { "bar_at_bottom",              setconfvalue,   SWM_S_BAR_AT_BOTTOM },
        { "bar_border",                 setconfcolor,   SWM_S_COLOR_BAR_BORDER },
+       { "bar_border_width",                   setconfvalue,   SWM_S_BAR_BORDER_WIDTH },
        { "bar_color",                  setconfcolor,   SWM_S_COLOR_BAR },
        { "bar_font_color",             setconfcolor,   SWM_S_COLOR_BAR_FONT },
        { "bar_font",                   setconfvalue,   SWM_S_BAR_FONT },
@@ -4092,11 +4132,13 @@ struct config_option configopt[] = {
        { "spawn_term",                 setconfvalue,   SWM_S_SPAWN_TERM },
        { "screenshot_enabled",         setconfvalue,   SWM_S_SS_ENABLED },
        { "screenshot_app",             setconfvalue,   SWM_S_SS_APP },
+       { "window_name_enabled",        setconfvalue,   SWM_S_WINDOW_NAME_ENABLED },
        { "term_width",                 setconfvalue,   SWM_S_TERM_WIDTH },
        { "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 },
        { "disable_border",             setconfvalue,   SWM_S_DISABLE_BORDER },
+       { "border_width",               setconfvalue,   SWM_S_BORDER_WIDTH },
 };
 
 
@@ -4379,7 +4421,7 @@ manage_window(Window id)
        /* border me */
        if (border_me) {
                bzero(&wc, sizeof wc);
-               wc.border_width = 1;
+               wc.border_width = border_width;
                mask = CWBorderWidth;
                XConfigureWindow(display, win->id, mask, &wc);
                configreq_win(win);
@@ -4439,7 +4481,9 @@ unmanage_window(struct ws_win *win)
                        parent->child_trans = NULL;
        }
 
-       /* work around for mplayer going full screen */
+       /* focus on root just in case */
+       XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
+
        if (!win->floating)
                focus_prev(win);
 
@@ -4866,6 +4910,8 @@ propertynotify(XEvent *e)
                XMoveResizeWindow(display, win->id,
                    win->g.x, win->g.y, win->g.w, win->g.h);
 #endif
+               if (window_name_enabled)
+                       bar_update();
                break;
        default:
                break;