diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f913c1b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+dwm
+config.h
diff --git a/config.def.h b/config.def.h
index 81f2d32..fa14f40 100644
--- a/config.def.h
+++ b/config.def.h
@@ -92,6 +92,7 @@ static const Key keys[] = {
 	{ MODKEY,                       XK_equal,  setgaps,        {.i = +5 } },
 	{ MODKEY|ShiftMask,             XK_minus,  setgaps,        {.i = 0 } },
 	{ MODKEY,                       XK_F5,     togglerainbow,  {0} },
+	{ MODKEY|ShiftMask,             XK_F5,     togglerainbowbar,  {0} },
 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
 	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
 	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
@@ -131,4 +132,3 @@ static const Button buttons[] = {
 	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} },
 	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },
 };
-
diff --git a/drw.c b/drw.c
index 9fdd1a4..98298a4 100644
--- a/drw.c
+++ b/drw.c
@@ -79,6 +79,8 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
 void
 drw_free(Drw *drw)
 {
+	if (!drw)
+		return;
 	XFreePixmap(drw->dpy, drw->drawable);
 	XFreeGC(drw->dpy, drw->gc);
 	drw_fontset_free(drw->fonts);
@@ -160,9 +162,12 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
 void
 drw_fontset_free(Fnt *font)
 {
-	if (font) {
-		drw_fontset_free(font->next);
+	Fnt *next;
+
+	while (font) {
+		next = font->next;
 		xfont_free(font);
+		font = next;
 	}
 }
 
@@ -200,7 +205,6 @@ drw_clr_free(Drw *drw, Clr *c)
 	if (!drw || !c)
 		return;
 
-	/* c is typedef XftColor Clr */
 	XftColorFree(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
 	             DefaultColormap(drw->dpy, drw->screen), c);
 }
@@ -269,13 +273,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
 	if (!render) {
 		w = invert ? invert : ~invert;
 	} else {
-		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
-		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+		if (!drw->nobg) {
+			XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
+			XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+		}
 		if (w < lpad)
 			return x + w;
 		d = XftDrawCreate(drw->dpy, drw->drawable,
 		                  DefaultVisual(drw->dpy, drw->screen),
 		                  DefaultColormap(drw->dpy, drw->screen));
+		if (!d)
+			return x + w;
 		x += lpad;
 		w -= lpad;
 	}
@@ -331,17 +339,29 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
 		if (utf8strlen) {
 			if (render) {
 				ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
-				XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
-				                  usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
+				if (drw->nobg) {
+					static XftColor nobg_fg;
+					static int nobg_fg_init = 0;
+					if (!nobg_fg_init) {
+						if (XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
+							DefaultColormap(drw->dpy, drw->screen), "#000000", &nobg_fg))
+							nobg_fg_init = 1;
+					}
+					XftDrawStringUtf8(d, nobg_fg_init ? &nobg_fg : &drw->scheme[invert ? ColBg : ColFg],
+					                  usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
+				} else {
+					XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
+					                  usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
+				}
 			}
 			x += ew;
-			w -= ew;
+			w = ew < w ? w - ew : 0;
 		}
 		if (utf8err && (!render || invalid_width < w)) {
 			if (render)
 				drw_text(drw, x, y, w, h, 0, invalid, invert);
 			x += invalid_width;
-			w -= invalid_width;
+			w = invalid_width < w ? w - invalid_width : 0;
 		}
 		if (render && overflow)
 			drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
@@ -365,6 +385,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
 			if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint)
 				goto no_match;
 
+			/* cap fallback fonts to prevent unbounded growth */
+			{
+				int nfonts = 0;
+				for (curfont = drw->fonts; curfont; curfont = curfont->next)
+					nfonts++;
+				if (nfonts >= 64)
+					goto no_match;
+			}
+
 			fccharset = FcCharSetCreate();
 			FcCharSetAddChar(fccharset, utf8codepoint);
 
@@ -412,7 +441,7 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
 		return;
 
 	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
-	XSync(drw->dpy, False);
+	XFlush(drw->dpy);
 }
 
 unsigned int
diff --git a/drw.h b/drw.h
index bda06f9..975d158 100644
--- a/drw.h
+++ b/drw.h
@@ -24,6 +24,7 @@ typedef struct {
 	GC gc;
 	Clr *scheme;
 	Fnt *fonts;
+	int nobg;
 } Drw;
 
 /* Drawable abstraction */
diff --git a/dwm.c b/dwm.c
index 34fe9a5..71bd8b9 100644
--- a/dwm.c
+++ b/dwm.c
@@ -170,6 +170,7 @@ static void detachstack(Client *c);
 static Monitor *dirtomon(int dir);
 static void drawbar(Monitor *m);
 static void drawbars(void);
+static void drawrainbowbar(Monitor *m);
 static void drawrainbowborder(Client *c);
 static unsigned long hsvtorgb(float h, float s, float v);
 static void enternotify(XEvent *e);
@@ -224,6 +225,7 @@ static void tile(Monitor *m);
 static void togglebar(const Arg *arg);
 static void togglefloating(const Arg *arg);
 static void togglerainbow(const Arg *arg);
+static void togglerainbowbar(const Arg *arg);
 static void toggletag(const Arg *arg);
 static void toggleview(const Arg *arg);
 static void unfocus(Client *c, int setfocus);
@@ -286,7 +288,10 @@ static Window root, wmcheckwin;
 
 /* rainbow border state */
 static float rainbow_hue = 0;
+static XImage *rainbow_bar_img = NULL;
+static int rainbow_bar_img_w = 0, rainbow_bar_img_h = 0;
 static int rainbow_enabled;
+static int rainbow_bar_enabled;
 
 /* configuration, allows nested code to access above variables */
 #include "config.h"
@@ -532,6 +537,8 @@ cleanup(void)
 		while (m->stack)
 			unmanage(m->stack, 0);
 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
+	if (rainbow_bar_img)
+		XDestroyImage(rainbow_bar_img);
 	while (mons)
 		cleanupmon(mons);
 	for (i = 0; i < CurLast; i++)
@@ -774,6 +781,12 @@ drawbar(Monitor *m)
 	if (!m->showbar)
 		return;
 
+	/* paint rainbow gradient background when enabled */
+	if (rainbow_bar_enabled) {
+		drawrainbowbar(m);
+		drw->nobg = 1;
+	}
+
 	/* draw status first so it can be overdrawn by tags later */
 	if (m == selmon) { /* status is only drawn on selected monitor */
 		char *text, *s, ch;
@@ -803,9 +816,14 @@ drawbar(Monitor *m)
 	}
 	x = 0;
 	for (i = 0; i < LENGTH(tags); i++) {
+		int sel = m->tagset[m->seltags] & 1 << i;
 		w = TEXTW(tags[i]);
-		drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
+		drw_setscheme(drw, scheme[sel ? SchemeSel : SchemeNorm]);
+		if (sel && drw->nobg)
+			drw->nobg = 0;
 		drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
+		if (sel && rainbow_bar_enabled)
+			drw->nobg = 1;
 		if (occ & 1 << i)
 			drw_rect(drw, x + boxs, boxs, boxw, boxw,
 				m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
@@ -822,11 +840,12 @@ drawbar(Monitor *m)
 			drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
 			if (m->sel->isfloating)
 				drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
-		} else {
+		} else if (!rainbow_bar_enabled) {
 			drw_setscheme(drw, scheme[SchemeNorm]);
 			drw_rect(drw, x, 0, w, bh, 1, 1);
 		}
 	}
+	drw->nobg = 0;
 	drw_map(drw, m->barwin, 0, 0, m->ww, bh);
 }
 
@@ -861,6 +880,40 @@ hsvtorgb(float h, float s, float v)
 	return (R << 16) | (G << 8) | B;
 }
 
+void
+drawrainbowbar(Monitor *m)
+{
+	int w = m->ww;
+
+	if (!m->showbar)
+		return;
+
+	if (!rainbow_bar_img || rainbow_bar_img_w != w || rainbow_bar_img_h != bh) {
+		if (rainbow_bar_img)
+			XDestroyImage(rainbow_bar_img);
+		char *data = calloc((size_t)w * bh, 4);
+		if (!data)
+			return;
+		rainbow_bar_img = XCreateImage(dpy, DefaultVisual(dpy, screen),
+			DefaultDepth(dpy, screen), ZPixmap, 0, data, w, bh, 32, 0);
+		if (!rainbow_bar_img) {
+			free(data);
+			return;
+		}
+		rainbow_bar_img_w = w;
+		rainbow_bar_img_h = bh;
+	}
+
+	for (int x = 0; x < w; x++) {
+		float hue = fmodf(rainbow_hue + 360.0f * x / w, 360.0f);
+		unsigned long color = hsvtorgb(hue, 0.7f, 1.0f);
+		for (int y = 0; y < bh; y++)
+			XPutPixel(rainbow_bar_img, x, y, color);
+	}
+
+	XPutImage(dpy, drw->drawable, drw->gc, rainbow_bar_img, 0, 0, 0, 0, w, bh);
+}
+
 void
 drawrainbowborder(Client *c)
 {
@@ -1570,7 +1623,7 @@ run(void)
 		FD_ZERO(&rfds);
 		FD_SET(xfd, &rfds);
 		tv.tv_sec = 0;
-		tv.tv_usec = rainbow_enabled ? (rainbow_interval * 1000L) : 200000L;
+		tv.tv_usec = (rainbow_enabled || rainbow_bar_enabled) ? (rainbow_interval * 1000L) : 200000L;
 
 		if (select(xfd + 1, &rfds, NULL, NULL, &tv) > 0) {
 			while (XPending(dpy)) {
@@ -1580,14 +1633,17 @@ run(void)
 			}
 		}
 
-		if (rainbow_enabled) {
+		/* rainbow animation: only tick at fixed interval */
+		if (rainbow_enabled || rainbow_bar_enabled) {
 			gettimeofday(&now, NULL);
 			now_ms = now.tv_sec * 1000LL + now.tv_usec / 1000;
 			if (now_ms - last_rainbow_ms >= rainbow_interval) {
 				last_rainbow_ms = now_ms;
 				rainbow_hue = fmodf(rainbow_hue + rainbow_step, 360.0f);
-				if (selmon && selmon->sel)
+				if (rainbow_enabled && selmon && selmon->sel)
 					drawrainbowborder(selmon->sel);
+				if (rainbow_bar_enabled)
+					drawbars();
 				XFlush(dpy);
 			}
 		}
@@ -1976,6 +2032,13 @@ togglerainbow(const Arg *arg)
 		XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel][ColBorder].pixel);
 }
 
+void
+togglerainbowbar(const Arg *arg)
+{
+	rainbow_bar_enabled = !rainbow_bar_enabled;
+	drawbars();
+}
+
 void
 toggletag(const Arg *arg)
 {
