shithub: lola

Download patch

ref: 0d4390b3430bd8dd9e2ed21a3ed977856ea5505c
parent: 3ca0009a7450e86fed00995d8e296c41619160ba
author: aap <aap@papnet.eu>
date: Mon Aug 26 13:37:39 EDT 2024

implemented tabs for all themes. fixed crash in kbd thread.

--- a/README
+++ b/README
@@ -38,7 +38,6 @@
 		click new window or background
 	- TODO:
 		- no fs interface yet
-		- only implemented for simple theme so far
 - misc
 	- 1-3 chord on desktop opens secondary menu
 
@@ -47,4 +46,3 @@
 The window decoration style is set by linking in the relevant file,
 so edit the `mkfile' to try different styles.
 The options are: flat.c, simple.c, win3.c, win95.c
-	BUG: only simple.c currently working because of tabs
--- a/data.c
+++ b/data.c
@@ -177,6 +177,9 @@
 {
 	Image *img;
 
+	if(name == nil)
+		return mkcolor(col);
+
 	name = smprint("th_%s", name);
 
 	img = namedimage(display, name);
--- a/flat.c
+++ b/flat.c
@@ -2,6 +2,7 @@
 
 int bordersz = 4;
 int titlesz = 18;
+int tabsz = 18;
 
 enum {
 	TITLE,
@@ -17,34 +18,59 @@
 };
 
 Image *wincolors[NumWinColors];
+Image *shadecol;
 
 void
-wdecor(WinTab *w)
+wdecor(Window *w)
 {
 	if(w->frame == nil)
 		return;
-	int c = w->holdmode ?
-		w == focused ? TITLEHOLD : LTITLEHOLD :
-		w == focused ? TITLE : LTITLE;
+	int c = wcolsel(w);
+	int tc = TITLE + wcolsel(w);
 
-	Rectangle r = w->frame->r;
+	Rectangle r;
+	int margin;
 
 	if(!w->noborder){
-		border(w->frame, r, bordersz, wincolors[c], ZP);
-		r = insetrect(r, bordersz);
+		r = w->rect;
+		border(w->frame, r, bordersz, wincolors[tc], ZP);
 	}
 
 	if(!w->notitle){
+		r = w->titlerect;
 		r.max.y = r.min.y + titlesz;
-		draw(w->frame, r, wincolors[c], nil, ZP);
+		draw(w->frame, r, wincolors[tc], nil, ZP);
 
-		Point pt = Pt(r.min.x, r.min.y);
-		string(w->frame, pt, wincolors[c+4], pt, font, w->label);
+		margin = w->noborder ? titlesz : titlesz + bordersz;
+		margin = (margin - font->height)/2;
+		Point pt = Pt(r.min.x, w->rect.min.y + margin + 1);
+		if(w->cur)
+			string(w->frame, pt, wincolors[TITLETEXT+c], pt, font, w->cur->label);
 	}
+
+	r = rectsubpt(w->tabrect, Pt(0,1));
+	draw(w->frame, r, wincolors[c], nil, ZP);
+
+	int n = w->ref;
+	if(n > 1){
+		int wd = Dx(r)/n;
+		int xxx = r.max.x;
+		r.max.x = r.min.x + wd;
+		for(WinTab *t = w->tab; t; t = t->next){
+			if(t->next == nil)
+				r.max.x = xxx;
+			if(t != w->cur)
+				draw(w->frame, r, shadecol, nil, ZP);
+			margin = (tabsz - font->height)/2;
+			Point pt = Pt(r.min.x+bordersz/2, r.min.y + margin);
+			string(w->frame, pt, wincolors[TITLETEXT+c], pt, font, t->label);
+			r = rectaddpt(r, Pt(wd,0));
+		}
+	}
 }
 
 void
-wtitlectl(WinTab *w)
+wtitlectl(Window *w)
 {
 	if(mctl->buttons & 7){
 		wraise(w);
@@ -53,8 +79,14 @@
 			if(!w->maximized)
 				grab(w, 1);
 		}
-		if(mctl->buttons & 4)
-			btn3menu();
+		if(mctl->buttons & 4){
+			Window *ww = pick();
+			if(ww){
+				tmigrate(w->cur, ww);
+				wraise(ww);
+				wfocus(ww);
+			}
+		}
 	}
 }
 
@@ -74,4 +106,6 @@
 	wincolors[LTITLETEXT] = getcolor("ltitletext", 0x808080FF);
 	wincolors[TITLEHOLDTEXT] = getcolor("titleholdtext", 0xFFFFFFFF);
 	wincolors[LTITLEHOLDTEXT] = getcolor("ltitleholdtext", 0xC0C0C0FF);
+
+	shadecol = getcolor(nil, 0x00000020);
 }
--- a/inc.h
+++ b/inc.h
@@ -185,6 +185,7 @@
 
 extern int bordersz;
 extern int titlesz;
+extern int tabsz;
 
 typedef struct Window Window;
 typedef struct WinTab WinTab;
@@ -268,6 +269,7 @@
 extern Window *focused, *cursorwin;
 extern Point screenoff;
 
+int wcolsel(Window *w);
 void wtitlectl(Window *w);
 void wdecor(Window *w);
 void wmaximize(Window *w);
@@ -300,6 +302,9 @@
 WinTab *tcreate(Window *w, bool scrolling);
 void tfocus(WinTab *t);
 void tdelete(WinTab *t);
+void tmigrate(WinTab *t, Window *w);
+void tmoveleft(WinTab *t);
+void tmoveright(WinTab *t);
 
 void screenoffset(int offx, int offy);
 
@@ -335,6 +340,7 @@
 void refresh(void);
 Point dmenuhit(int but, Mousectl *mc, int nx, int ny, Point last);
 void drainmouse(Mousectl *mc, WinTab *w);
+Window *pick(void);
 void grab(Window *w, int btn);
 void btn3menu(void);
 
--- a/main.c
+++ b/main.c
@@ -47,7 +47,6 @@
 			threadexitsall(msg);
 	fprint(2, "lola %d: abort: %s\n", getpid(), msg);
 	abort();
-	return 0;
 }
 
 /*
@@ -648,6 +647,70 @@
 		screenoffset(ssel.x*dx, ssel.y*dy);
 }
 
+// TODO: header
+Window *wcreate_(Rectangle r, bool hidden);
+
+static void
+wtabctl(Window *w)
+{
+	Rectangle r;
+
+	if(mctl->buttons & 7){
+		wraise(w);
+		wfocus(w);
+		r = w->tabrect;
+		int n = w->ref;
+		if(n > 1){
+			int wd = Dx(r)/n;
+			r.max.x = r.min.x + wd;
+			for(WinTab *t = w->tab; t; t = t->next){
+				if(ptinrect(mctl->xy, r)){
+					if(mctl->buttons & 1){
+						tfocus(t);
+						/* chording */
+						while(mctl->buttons){
+							int b = mctl->buttons;
+							if(b & 6){
+								if(b & 2)
+									tmoveleft(t);
+								else
+									tmoveright(t);
+							}
+							while(mctl->buttons == b)
+								readmouse(mctl);
+						}
+					}else if(mctl->buttons & 2){
+						tdelete(t);
+						while(mctl->buttons)
+							readmouse(mctl);
+					}else if(mctl->buttons & 4){
+						Point pt = mctl->xy;
+						Window *ww = pick();
+						if(ww){
+							/* move tab into clicked window */
+							tmigrate(t, ww);
+							wraise(ww);
+							wfocus(ww);
+						}else{
+							/* HACK: pick doesn't say whether we cancelled
+							 * or clicked background */
+							ww = wpointto(mctl->xy);
+							if(ww == nil){
+								r = rectaddpt(w->rect, subpt(mctl->xy, pt));
+								ww = wcreate_(r, 0);
+								tmigrate(t, ww);
+							}
+						}
+						return;
+					}
+					break;
+				}
+				r = rectaddpt(r, Pt(wd,0));
+			}
+		}
+	}
+}
+
 void
 mthread(void*)
 {
@@ -703,7 +766,10 @@
 				}else{
 					/* title bar */
 					setcursornormal(nil);
-					wtitlectl(w);
+					if(ptinrect(mctl->xy, w->titlerect))
+						wtitlectl(w);
+					else
+						wtabctl(w);
 				}
 			}else if(w->cur == nil){
 				/* no tab in window */
@@ -835,7 +901,6 @@
 			alts[Atotap].op = CHANSND;
 		else
 			alts[Atotap].op = CHANNOP;
-WinTab *ftab = focused ? focused->cur : nil;
 		switch(alt(alts)){
 		case Akbd:
 			/* from keyboard to tap or to window */
@@ -844,7 +909,7 @@
 				ctldown = utfrune(s+1, Kctl) != nil;
 			}
 			prev = cur;
-			cur = ftab;
+			cur = focused ? focused->cur : nil;
 			if(totap){
 				if(cur != prev && cur){
 					/* notify tap of focus change */
@@ -865,7 +930,7 @@
 
 		case Afromtap:
 			/* from tap to window */
-			if(cur && cur == ftab)
+			if(cur && focused && cur == focused->cur)
 				sendp(cur->kbd, s);
 			else
 				free(s);
--- a/simple.c
+++ b/simple.c
@@ -2,6 +2,7 @@
 
 int bordersz = 4;
 int titlesz = 17;//19;
+int tabsz = 18;
 
 enum {
 	TITLE,
@@ -21,7 +22,7 @@
 Image *wincolors[NumWinColors];
 Image *icons[4];
 
-Image *testcol;
+Image *shadecol;
 
 void
 btn(Image *img, Rectangle r, Image *col, Image *icon, int down)
@@ -28,7 +29,6 @@
 {
 	USED(down);
 
-//	border(img, r, 1, col, ZP);
 	r = centerrect(r, icon->r);
 	draw(img, r, col, icon, ZP);
 }
@@ -52,26 +52,21 @@
 	return ptinrect(mctl->xy, r);
 }
 
-int
-colsel(Window *w)
-{
-	return w->cur && w->cur->holdmode ?
-		w == focused ? 2 : 3 :
-		w == focused ? 0 : 1;
-}
-
 void
 wdecor(Window *w)
 {
 	if(w->frame == nil)
 		return;
-	int c = TITLE + colsel(w);
-	int c2 = w == focused ? FRAME : LFRAME;
+	int sel = wcolsel(w);
+	int c = TITLE + sel;
+	int c1 = TITLETEXT + sel;
+	int c2 = FRAME + (sel&1);
 
 	Rectangle r, b1, b2, b3;
+	int margin;
 
 	if(!w->noborder){
-		r = w->frame->r;
+		r = w->rect;
 		border(w->frame, r, bordersz, wincolors[c], ZP);
 		border(w->frame, r, 1, wincolors[c2], ZP);
 		border(w->frame, insetrect(w->contrect,-1), 1, wincolors[c2], ZP);
@@ -83,26 +78,23 @@
 		draw(w->frame, r, wincolors[c], nil, ZP);
 
 		b1 = r;
-b1.max.x -= bordersz/2;
+		b1.max.x -= bordersz/2;
 		b1.min.x = b1.max.x - titlesz + bordersz;
 		b1.max.y = b1.min.y + Dx(b1);
 		b2 = rectsubpt(b1, Pt(titlesz, 0));
 		b3 = rectsubpt(b2, Pt(titlesz, 0));
-		btn(w->frame, b1, wincolors[c+4], icons[3], 0);
-		btn(w->frame, b2, wincolors[c+4], icons[1+w->maximized], 0);
-		btn(w->frame, b3, wincolors[c+4], icons[0], 0);
+		btn(w->frame, b1, wincolors[c1], icons[3], 0);
+		btn(w->frame, b2, wincolors[c1], icons[1+w->maximized], 0);
+		btn(w->frame, b3, wincolors[c1], icons[0], 0);
 
-r.min.x += bordersz/2;
-r.min.y -= 2;
-		Point pt = Pt(r.min.x, r.min.y);
-//if(w->cur && w->ref == 1)
-if(w->cur)
-		string(w->frame, pt, wincolors[c+4], pt, font, w->cur->label);
+		margin = w->noborder ? titlesz : titlesz + bordersz;
+		margin = (margin - font->height)/2;
+		Point pt = Pt(r.min.x, w->rect.min.y + margin + 1);
+		if(w->cur)
+			string(w->frame, pt, wincolors[c1], pt, font, w->cur->label);
 	}
 
 	r = rectsubpt(w->tabrect, Pt(0,1));
-//	r.min.x--;
-//	r.max.x++;
 	draw(w->frame, r, wincolors[c], nil, ZP);
 
 	int n = w->ref;
@@ -113,99 +105,37 @@
 		for(WinTab *t = w->tab; t; t = t->next){
 			if(t->next == nil)
 				r.max.x = xxx;
-	if(t != w->cur)
-	draw(w->frame, r, testcol, nil, ZP);
-			Point pt = Pt(r.min.x+bordersz/2, r.min.y);
-			string(w->frame, pt, wincolors[c+4], pt, font, t->label);
+			if(t != w->cur)
+				draw(w->frame, r, shadecol, nil, ZP);
+			margin = (tabsz - font->height)/2;
+			Point pt = Pt(r.min.x+bordersz/2, r.min.y + margin);
+			string(w->frame, pt, wincolors[c1], pt, font, t->label);
 			r = rectaddpt(r, Pt(wd,0));
 		}
 	}
 }
 
-Window *pick(void);
-Window *wcreate_(Rectangle r, bool hidden);
-void tmigrate(WinTab *t, Window *w);
-void tmoveleft(WinTab *t);
-void tmoveright(WinTab *t);
-
-static void
-tabctl(Window *w)
+void
+wtitlectl(Window *w)
 {
-	Rectangle r;
-
 	if(mctl->buttons & 7){
 		wraise(w);
 		wfocus(w);
-		r = rectsubpt(w->tabrect, Pt(0,1));
-		int n = w->ref;
-		if(n > 1){
-			int wd = Dx(r)/n;
-			r.max.x = r.min.x + wd;
-			for(WinTab *t = w->tab; t; t = t->next){
-				if(ptinrect(mctl->xy, r)){
-					if(mctl->buttons & 1){
-						tfocus(t);
-						/* chording */
-						while(mctl->buttons){
-							int b = mctl->buttons;
-							if(b & 6){
-								if(b & 2)
-									tmoveleft(t);
-								else
-									tmoveright(t);
-							}
-							while(mctl->buttons == b)
-								readmouse(mctl);
-						}
-					}else if(mctl->buttons & 2)
-						tdelete(t);
-					else if(mctl->buttons & 4){
-Point pt = mctl->xy;
-						Window *ww = pick();
-						if(ww){
-							tmigrate(t, ww);
-							wraise(ww);
-							wfocus(ww);
-							return;
-						}else{
-							ww = wpointto(mctl->xy);
-							if(ww == nil){
-	tmigrate(t, wcreate_(rectaddpt(w->rect, subpt(mctl->xy, pt)), 0));
-							}
-						}
-					}
-					break;
-				}
-				r = rectaddpt(r, Pt(wd,0));
-			}
-		}
-	}
-}
-
-static void
-titlectl(Window *w)
-{
-	if(mctl->buttons & 7){
-		wraise(w);
-		wfocus(w);
 		if(mctl->buttons & 1) {
-			int c = TITLE + colsel(w);
+			int c = TITLETEXT + wcolsel(w);
 
 			Rectangle r = w->titlerect;
+			r.max.x -= bordersz/2;
 			Rectangle br = Rect(0,0,titlesz-bordersz,titlesz-bordersz);
-r.max.x -= bordersz/2;
 			Rectangle br1 = rectaddpt(br, Pt(r.max.x-titlesz+bordersz, r.min.y));
 			Rectangle br2 = rectsubpt(br1, Pt(titlesz, 0));
 			Rectangle br3 = rectsubpt(br2, Pt(titlesz, 0));
-			// hack...
-			if(w->notitle)
-				br1 = br2 = br3 = Rect(0,0,0,0);
 
 			if(ptinrect(mctl->xy, br1)){
-				if(btnctl(w->frame, br1, wincolors[c+4], icons[3]))
+				if(btnctl(w->frame, br1, wincolors[c], icons[3]))
 					wdelete(w);
 			}else if(ptinrect(mctl->xy, br2)){
-				if(btnctl(w->frame, br2, wincolors[c+4], icons[1+w->maximized])){
+				if(btnctl(w->frame, br2, wincolors[c], icons[1+w->maximized])){
 					if(w->maximized)
 						wrestore(w);
 					else
@@ -212,34 +142,22 @@
 						wmaximize(w);
 				}
 			}else if(ptinrect(mctl->xy, br3)){
-				if(btnctl(w->frame, br3, wincolors[c+4], icons[0]))
+				if(btnctl(w->frame, br3, wincolors[c], icons[0]))
 					whide(w);
 			}else if(!w->maximized)
 				grab(w, 1);
 		}
 		if(mctl->buttons & 4){
-//			btn3menu();
 			Window *ww = pick();
 			if(ww){
 				tmigrate(w->cur, ww);
 				wraise(ww);
 				wfocus(ww);
-				return;
 			}
 		}
 	}
 }
 
-void
-wtitlectl(Window *w)
-{
-	if(ptinrect(mctl->xy, w->titlerect))
-		titlectl(w);
-	else
-		tabctl(w);
-}
-
-
 static char minbtn[] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -336,5 +254,5 @@
 	icons[2] = mkicon(rstbtn, 16, 13);
 	icons[3] = mkicon(closebtn, 16, 13);
 
-	testcol = getcolor("asdfasdfasdf", 0x00000020);
+	shadecol = getcolor(nil, 0x00000020);
 }
--- a/win3.c
+++ b/win3.c
@@ -2,6 +2,7 @@
 
 int bordersz = 4;
 int titlesz = 19;
+int tabsz = 23;
 
 enum {
 	ColDefault,
@@ -97,15 +98,17 @@
 
 
 void
-wdecor(WinTab *w)
+wdecor(Window *w)
 {
 	if(w->frame == nil)
 		return;
 
-	Rectangle r = w->frame->r;
+	int inact = w != focused;
+	Rectangle r;
 
 	if(!w->noborder){
-		border(w->frame, r, bordersz, wincolors[w == focused ? ColBorder : ColBorderInact], ZP);
+		r = w->rect;
+		border(w->frame, r, bordersz, wincolors[ColBorder + inact], ZP);
 		border(w->frame, r, 1, wincolors[ColFrame], ZP);
 		border(w->frame, insetrect(r,3), 1, wincolors[ColFrame], ZP);
 
@@ -128,8 +131,9 @@
 	}
 
 	if(!w->notitle){
-		r.max.y = r.min.y + titlesz-1;
-		draw(w->frame, r, wincolors[w == focused ? ColTitle : ColTitleInact], nil, ZP);
+		r = w->titlerect;
+		r.max.y -= 1;
+		draw(w->frame, r, wincolors[ColTitle + inact], nil, ZP);
 		draw(w->frame, Rect(r.min.x,r.max.y,r.max.x,r.max.y+1), wincolors[ColFrame], nil, ZP);
 
 		// menu
@@ -148,20 +152,44 @@
 		winbtn(w->frame, br, icons[0], 0);
 		border(w->frame, insetrect(br,-1), 1, display->black, ZP);
 
-		int sp = (Dx(r)-stringwidth(font, w->label))/2;
-		Point pt = Pt(r.min.x+sp, r.min.y);
-		string(w->frame, pt, wincolors[w == focused ? ColTitleText : ColTitleTextInact], pt, font, w->label);
+		if(w->cur){
+			int sp = (Dx(r)-stringwidth(font, w->cur->label))/2;
+			Point pt = Pt(r.min.x+sp, r.min.y);
+			string(w->frame, pt, wincolors[ColTitleText + inact], pt, font, w->cur->label);
+		}
 	}
+
+	r = w->tabrect;
+	draw(w->frame, r, wincolors[ColDefault], nil, ZP);
+	draw(w->frame, Rect(r.min.x,r.max.y-1,r.max.x,r.max.y), display->black, nil, ZP);
+
+	int n = w->ref;
+	if(n > 1){
+		int wd = Dx(r)/n;
+		r.max.y -= 1;
+		int xxx = r.max.x;
+		r.max.x = r.min.x + wd;
+		for(WinTab *t = w->tab; t; t = t->next){
+			if(t->next == nil)
+				r.max.x = xxx;
+			if(t == w->cur)
+				border(w->frame, insetrect(r,1), 1, display->black, ZP);
+			int margin = (tabsz - font->height)/2;
+			Point pt = Pt(r.min.x+bordersz/2, r.min.y + margin);
+			string(w->frame, pt, display->black, pt, font, t->label);
+			r = rectaddpt(r, Pt(wd,0));
+		}
+	}
 }
 
 void
-wtitlectl(WinTab *w)
+wtitlectl(Window *w)
 {
 	if(mctl->buttons & 7){
 		wraise(w);
 		wfocus(w);
 		if(mctl->buttons & 1) {
-			Rectangle r = w->frame->r;
+			Rectangle r = w->rect;
 			if(!w->noborder)
 				r = insetrect(r, bordersz);
 			Rectangle br = Rect(0,0,titlesz-1,titlesz-1);
@@ -168,9 +196,6 @@
 			Rectangle br1 = rectaddpt(br, r.min);
 			Rectangle br2 = rectaddpt(br1, Pt(Dx(r)-titlesz-1, 0));
 			Rectangle br3 = rectaddpt(br2, Pt(-titlesz-2, 0));
-			// hack...
-			if(w->notitle)
-				br1 = br2 = br3 = Rect(0,0,0,0);
 
 			if(ptinrect(mctl->xy, br1)){
 				if(winbtnctlflat(w->frame, br1, icons[3], icons[4]))
--- a/win95.c
+++ b/win95.c
@@ -2,6 +2,7 @@
 
 int bordersz = 4;
 int titlesz = 19;
+int tabsz = 20;
 
 enum {
 	ColDefault,
@@ -69,22 +70,24 @@
 }
 
 void
-wdecor(WinTab *w)
+wdecor(Window *w)
 {
 	if(w->frame == nil)
 		return;
 
-	Rectangle r = w->frame->r;
+	int inact = w != focused;
+	Rectangle r;
 
 	if(!w->noborder){
+		r = w->rect;
 		border(w->frame, r, bordersz, wincolors[ColDefault], ZP);
 		winframe(w->frame, r);
-		r = insetrect(r, bordersz);
 	}
 
 	if(!w->notitle){
-		r.max.y = r.min.y + titlesz-1;
-		draw(w->frame, r, wincolors[w == focused ? ColTitle : ColTitleInact], nil, ZP);
+		r = w->titlerect;
+		r.max.y -= 1;
+		draw(w->frame, r, wincolors[ColTitle + inact], nil, ZP);
 		draw(w->frame, Rect(r.min.x,r.max.y,r.max.x,r.max.y+1), wincolors[ColDefault], nil, ZP);
 
 		// draw buttons
@@ -100,28 +103,47 @@
 		draw(w->frame, br, icons[4], icons[4], ZP);
 
 		Point pt = Pt(r.min.x + 2 + titlesz-1, r.min.y);
-		string(w->frame, pt, wincolors[w == focused ? ColTitleText : ColTitleTextInact], pt, font, w->label);
+		if(w->cur)
+			string(w->frame, pt, wincolors[ColTitleText + inact], pt, font, w->cur->label);
 	}
+
+
+	r = w->tabrect;
+	draw(w->frame, r, wincolors[ColDefault], nil, ZP);
+	draw(w->frame, Rect(r.min.x,r.max.y-1,r.max.x,r.max.y), display->black, nil, ZP);
+
+	int n = w->ref;
+	if(n > 1){
+		int wd = Dx(r)/n;
+		r.max.y -= 1;
+		int xxx = r.max.x;
+		r.max.x = r.min.x + wd;
+		for(WinTab *t = w->tab; t; t = t->next){
+			if(t->next == nil)
+				r.max.x = xxx;
+			if(t == w->cur)
+				border(w->frame, insetrect(r,1), 1, display->black, ZP);
+			int margin = (tabsz - font->height)/2;
+			Point pt = Pt(r.min.x+bordersz/2, r.min.y + margin);
+			string(w->frame, pt, display->black, pt, font, t->label);
+			r = rectaddpt(r, Pt(wd,0));
+		}
+	}
 }
 
 void
-wtitlectl(WinTab *w)
+wtitlectl(Window *w)
 {
 	if(mctl->buttons & 7){
 		wraise(w);
 		wfocus(w);
 		if(mctl->buttons & 1) {
-			Rectangle r = w->frame->r;
-			if(!w->noborder)
-				r = insetrect(r, bordersz);
-			r.max.y = r.min.y + titlesz-1;
+			Rectangle r = w->titlerect;
+			r.max.y -= 1;
 			Rectangle br1 = insetrect(r, 2);
 			br1.min.x = br1.max.x - Dy(br1) - 2;
 			Rectangle br2 = rectaddpt(br1, Pt(-Dx(br1)-2, 0));
 			Rectangle br3 = rectaddpt(br1, Pt(-2*Dx(br1)-2, 0));
-			// hack...
-			if(w->notitle)
-				br1 = br2 = br3 = Rect(0,0,0,0);
 
 			if(ptinrect(mctl->xy, br1)){
 				if(winbtnctl(w->frame, br1, icons[3]))
--- a/wind.c
+++ b/wind.c
@@ -82,8 +82,8 @@
 	w->tabrect = ZR;
 	if(w->ref > 1){
 		w->tabrect = w->contrect;
-		w->tabrect.max.y = w->tabrect.min.y + 18;
-		w->contrect.min.y += 18;
+		w->tabrect.max.y = w->tabrect.min.y + tabsz;
+		w->contrect.min.y += tabsz;
 	}
 
 	r = insetrect(w->contrect, 1);
@@ -93,9 +93,16 @@
 	w->textr.min.x = w->scrollr.max.x + 4;
 }
 
+int
+wcolsel(Window *w)
+{
+	return (w != focused) + (w->cur && w->cur->holdmode)*2;
+}
+
 static void
 wsetcolors(WinTab *w)
 {
+// TODO: this should use wcolsel
 	int c = w->holdmode ?
 		w->w == focused ? HOLDTEXT : PALEHOLDTEXT :
 		w->w == focused ? TEXT : PALETEXT;