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;