shithub: lola

Download patch

ref: abb04b10b904fc3937ac0b790f0dc850ae7acde1
parent: dafdfcb12496bfc27cdc863996172a7409dffd11
author: aap <[email protected]>
date: Mon Jan 30 14:14:41 EST 2023

border resize/move; fixes; cleanup

--- a/TODO
+++ b/TODO
@@ -1,10 +1,10 @@
 rethink resizing and repainting
 rethink hiding/unhiding
 snarfversion
-check for bad rects
-border resize/move
+check for bad rects (what's left here?)
 top/bottom/current seems to work a bit different in rio
 release keys and buttons when unfocused
+make sure there are no deadlocks
 ...
 
 ideas:
--- a/inc.h
+++ b/inc.h
@@ -94,7 +94,16 @@
 	NumColors
 };
 
+extern Image *background;
 extern Image *colors[NumColors];
+extern Cursor whitearrow;
+extern Cursor query;
+extern Cursor crosscursor;
+extern Cursor boxcursor;
+extern Cursor sightcursor;
+extern Cursor *corners[9];
+void initdata(void);
+
 extern Screen *wscreen;
 extern Mousectl *mctl;
 extern int scrolling;
@@ -103,12 +112,14 @@
 extern int gotscreen;
 extern int servekbd;
 
-extern Cursor whitearrow;
 extern Cursor *cursor;
 void setcursoroverride(Cursor *c, int ov);
 void setcursornormal(Cursor *c);
 
+Rectangle newrect(void);
+int goodrect(Rectangle r);
 
+
 typedef struct RuneConvBuf RuneConvBuf;
 struct RuneConvBuf
 {
@@ -215,6 +226,8 @@
 	Channel *mouseread;
 	Channel *wctlread;
 	Channel *complete;
+
+	char *threadname;	/* for debugging */
 };
 
 extern Window *bottomwin, *topwin;
@@ -235,10 +248,12 @@
 void wsetlabel(Window *w, char *label);
 void wsetname(Window *w);
 void wsetpid(Window *w, int pid, int dolabel);
+void wdelete(Window *w);
 void wmove(Window *w, Point pos);
 void wraise(Window *w);
 void wlower(Window *w);
 void wfocus(Window *w);
+void wunfocus(Window *w);
 int whide(Window *w);
 int wunhide(Window *w);
 void wsethold(Window *w, int hold);
@@ -274,8 +289,6 @@
 extern Channel *totap;		/* our keyboard input to tap program */
 extern Channel *wintap;	/* tell the tapthread which Window to send to */
 
-
-Rectangle newrect(void);
 
 extern Srv fsys;
 void fs(void);
--- a/main.c
+++ b/main.c
@@ -1,65 +1,5 @@
 #include "inc.h"
 
-Cursor whitearrow = {
-	{0, 0},
-	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 
-	 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 
-	 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 
-	 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
-	{0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, 
-	 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, 
-	 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, 
-	 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
-};
-
-Cursor query = {
-	{-7,-7},
-	{0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 
-	 0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8, 
-	 0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0, 
-	 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },
-	{0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c, 
-	 0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0, 
-	 0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80, 
-	 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
-};
-
-Cursor crosscursor = {
-	{-7, -7},
-	{0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
-	 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
-	 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0,
-	 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, },
-	{0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
-	 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE,
-	 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
-	 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, }
-};
-
-Cursor boxcursor = {
-	{-7, -7},
-	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
-	 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
-	 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
-	{0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
-	 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
-	 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
-	 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, }
-};
-
-Cursor sightcursor = {
-	{-7, -7},
-	{0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
-	 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
-	 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
-	 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, },
-	{0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
-	 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
-	 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
-	 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00, }
-};
-
 typedef struct RKeyboardctl RKeyboardctl;
 struct RKeyboardctl
 {
@@ -75,8 +15,6 @@
 int gotscreen;
 int servekbd;
 
-Image *background;
-Image *colors[NumColors];
 Screen *wscreen;
 
 void
@@ -284,6 +222,78 @@
 	return rc;
 }
 
+int
+whichside(int x, int lo, int hi)
+{
+	return	x < lo+20 ? 0 :
+		x > hi-20 ? 2 :
+		1;
+}
+
+/* 0 1 2
+ * 3   5
+ * 6 7 8 */
+int
+whichcorner(Rectangle r, Point p)
+{
+	int i, j;
+	
+	i = whichside(p.x, r.min.x, r.max.x);
+	j = whichside(p.y, r.min.y, r.max.y);
+	return 3*j+i;
+}
+
+/* replace corner or edge of rect with point */
+Rectangle
+changerect(Rectangle r, int corner, Point p)
+{
+	switch(corner){
+	case 0: return Rect(p.x, p.y, r.max.x, r.max.y);
+	case 1: return Rect(r.min.x, p.y, r.max.x, r.max.y);
+	case 2: return Rect(r.min.x, p.y, p.x+1, r.max.y);
+	case 3: return Rect(p.x, r.min.y, r.max.x, r.max.y);
+	case 5: return Rect(r.min.x, r.min.y, p.x+1, r.max.y);
+	case 6: return Rect(p.x, r.min.y, r.max.x, p.y+1);
+	case 7: return Rect(r.min.x, r.min.y, r.max.x, p.y+1);
+	case 8: return Rect(r.min.x, r.min.y, p.x+1, p.y+1);
+	}
+	return r;
+}
+
+Rectangle
+bandrect(Rectangle r, int but, Mousectl *mc)
+{
+	Rectangle or, nr;
+	int corner, ncorner;
+
+	or = r;
+	corner = whichcorner(r, mc->xy);
+	setcursornormal(corners[corner]);
+
+	do{
+		drawgetrect(r, 1);
+		readmouse(mc);
+		drawgetrect(r, 0);
+		nr = canonrect(changerect(r, corner, mc->xy));
+		if(goodrect(nr))
+			r = nr;
+		ncorner = whichcorner(r, mc->xy);
+		/* can switch from edge to corner, but not vice versa */
+		if(ncorner != corner && ncorner != 4 && (corner|~ncorner) & 1){
+			corner = ncorner;
+			setcursornormal(corners[corner]);
+		}
+	}while(mc->buttons == but);
+
+	if(mc->buttons){
+		drainmouse(mctl, nil);
+		return or;
+	}
+
+	setcursornormal(nil);
+	return r;
+}
+
 Window*
 pick(void)
 {
@@ -299,10 +309,11 @@
 }
 
 void
-grab(void)
+grab(Window *w)
 {
-	Window *w = clickwindow(3, mctl);
 	if(w == nil)
+		w = clickwindow(3, mctl);
+	if(w == nil)
 		setcursoroverride(nil, FALSE);
 	else{
 		Rectangle r = dragrect(3, w->img->r, mctl);
@@ -330,6 +341,17 @@
 	}
 }
 
+void
+bandresize(Window *w)
+{
+	Rectangle r;
+	r = bandrect(w->img->r, mctl->buttons, mctl);
+	if(!eqrect(r, w->img->r)){
+		wresize(w, r);
+		flushimage(display, 1);
+	}
+}
+
 int
 obscured(Window *w, Rectangle r, Window *t)
 {
@@ -357,6 +379,51 @@
 	return 0;
 }
 
+/* Check that newly created window will be of manageable size */
+int
+goodrect(Rectangle r)
+{
+	if(badrect(r) || !eqrect(canonrect(r), r))
+		return 0;
+	/* reasonable sizes only please */
+	if(Dx(r) > BIG*Dx(screen->r))
+		return 0;
+	if(Dy(r) > BIG*Dy(screen->r))
+		return 0;
+	/*
+	 * the height has to be big enough to fit one line of text.
+	 * that includes the border on each side with an extra pixel
+	 * so that the text is still drawn
+	 */
+	if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height)
+		return 0;
+	/* window must be on screen */
+	if(!rectXrect(screen->r, r))
+		return 0;
+	/* must have some screen and border visible so we can move it out of the way */
+	if(rectinrect(screen->r, insetrect(r, Borderwidth)))
+		return 0;
+	return 1;
+}
+
+/* Rectangle for new window */
+Rectangle
+newrect(void)
+{
+	static int i = 0;
+	int minx, miny, dx, dy;
+
+	dx = min(600, Dx(screen->r) - 2*Borderwidth);
+	dy = min(400, Dy(screen->r) - 2*Borderwidth);
+	minx = 32 + 16*i;
+	miny = 32 + 16*i;
+	i++;
+	i %= 10;
+
+	return Rect(minx, miny, minx+dx, miny+dy);
+}
+
+
 enum {
 	Cut,
 	Paste,
@@ -471,11 +538,11 @@
 		if(w) sweep(w);
 		break;
 	case Move:
-		grab();
+		grab(nil);
 		break;
 	case Delete:
 		w = pick();
-		if(w) wsendmsg(w, Deleted);
+		if(w) wdelete(w);
 		break;
 	case Hide:
 		w = pick();
@@ -502,51 +569,55 @@
 mthread(void*)
 {
 	Window *w;
-	int inside;
 
 	threadsetname("mousethread");
 	while(readmouse(mctl) != -1){
 		w = wpointto(mctl->xy);
+		cursorwin = w;
 again:
-		inside = w && w == focused && ptinrect(mctl->xy, w->contrect);
 
-		cursorwin = w;
-		if(w)
-			wsetcursor(w);
-		else
+		if(w == nil){
 			setcursornormal(nil);
-
-/* TODO: handle borders */
-		if(inside && w->mouseopen){
-			drainmouse(mctl, w->mc.c);
-		}else if(inside){
-// TODO: this can't happen with rio, but maybe we should support it
-if(mctl->buttons && topwin != w)
-wraise(w);
-			if(mctl->buttons & (1|8|16) || ptinrect(mctl->xy, w->text.scrollr))
-				drainmouse(mctl, w->mc.c);
-			if(mctl->buttons & 2){
-				incref(w);
-				btn2menu(w);
-				wrelease(w);
-			}
 			if(mctl->buttons & 4)
 				btn3menu();
-		}else if(w){
+		}else if(!ptinrect(mctl->xy, w->contrect)){
+			/* border */
+			setcursornormal(corners[whichcorner(w->img->r, mctl->xy)]);
+			if(mctl->buttons & 7){
+				wraise(w);
+				wfocus(w);
+				if(mctl->buttons & 4)
+					grab(w);
+				if(mctl->buttons & 3)
+					bandresize(w);
+			}
+		}else if(w != focused){
+			wsetcursor(w);
 			if(mctl->buttons & 7 ||
 			   mctl->buttons & (8|16) && focused->mouseopen){
 				wraise(w);
 				wfocus(w);
-				if(ptinrect(mctl->xy, w->contrect)){	// temp hack for borders
 				if(mctl->buttons & 1)
 					drainmouse(mctl, nil);
 				else
 					goto again;
-				}
 			}
-		}else{
+		}else if(!w->mouseopen){
+			wsetcursor(w);
+			if(mctl->buttons && topwin != w)
+				wraise(w);
+			if(mctl->buttons & (1|8|16) || ptinrect(mctl->xy, w->text.scrollr))
+				drainmouse(mctl, w->mc.c);
+			if(mctl->buttons & 2){
+				incref(w);
+				btn2menu(w);
+				wrelease(w);
+			}
 			if(mctl->buttons & 4)
 				btn3menu();
+		}else{
+			wsetcursor(w);
+			drainmouse(mctl, w->mc.c);
 		}
 	}
 }
@@ -737,7 +808,6 @@
 	return nil;
 }
 
-/* BUG: there's a deadlock somewhere sometimes when you delete a ktrans window */
 void
 keyboardtap(void*)
 {
@@ -874,21 +944,7 @@
 	snarffd = open("/dev/snarf", OREAD|OCEXEC);
 	gotscreen = access("/dev/screen", AEXIST)==0;
 
-	background = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
-	colors[BACK] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xFFFFFFFF);
-	colors[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCFF);
-	colors[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x999999FF);
-	colors[TEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF);
-	colors[HTEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF);
-
-	colors[TITLE] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreygreen);
-	colors[LTITLE] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen);
-	colors[TITLEHOLD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue);
-	colors[LTITLEHOLD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreyblue);
-
-	colors[PALETEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x666666FF);
-	colors[HOLDTEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue);
-	colors[PALEHOLDTEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreyblue);
+	initdata();
 
 	wscreen = allocscreen(screen, background, 0);
 	draw(screen, screen->r, background, nil, ZP);
--- a/mkfile
+++ b/mkfile
@@ -8,7 +8,8 @@
 	wctl.$O \
 	fs.$O \
 	util.$O \
-	time.$O
+	time.$O \
+	data.$O
 
 HFILES=inc.h
 
--- a/wind.c
+++ b/wind.c
@@ -165,8 +165,7 @@
 	if(w->deleted)
 		return;
 	w->deleted = TRUE;
-	if(focused == w)
-		wfocus(nil);
+	assert(w != focused);	/* this must be done elsewhere */
 	wlistremove(w);
 	for(i = 0; i < nwindows; i++)
 		if(windows[i] == w){
@@ -174,7 +173,6 @@
 			memmove(&windows[i], &windows[i+1], (nwindows-i)*sizeof(Window*));
 			break;
 		}
-
 	if(w->img){
 		/* rio does this, not sure if useful */
 		originwindow(w->img, w->img->r.min, screen->r.max);
@@ -194,6 +192,7 @@
 		return 0;
 	if(i < 0)
 		panic("negative ref count");
+	wunfocus(w);
 	wclose(w);
 	wsendmsg(w, Closed);
 	return 1;
@@ -202,6 +201,7 @@
 void
 wsendmsg(Window *w, int type)
 {
+	assert(w->threadname != threadgetname());
 	sendul(w->ctl, type);
 }
 
@@ -283,6 +283,13 @@
 }
 
 void
+wdelete(Window *w)
+{
+	wunfocus(w);
+	wsendmsg(w, Deleted);
+}
+
+void
 wrepaint(Window *w)
 {
 	wsetcolors(w);
@@ -362,7 +369,7 @@
 	prev = focused;
 	focused = w;
 	sendp(wintap, w);
-	/* TODO a bit ugly the repitition,
+	/* TODO a bit ugly the repetition,
 	 * but this might not stay anyways */
 	if(prev){
 		prev->wctlready = TRUE;
@@ -376,6 +383,13 @@
 	}
 }
 
+void
+wunfocus(Window *w)
+{
+	if(w == focused)
+		wfocus(nil);
+}
+
 int
 whide(Window *w)
 {
@@ -382,8 +396,7 @@
 	if(w->hidden)
 		return -1;
 	incref(w);
-	if(w == focused)
-		wfocus(nil);
+	wunfocus(w);
 	w->hidden = TRUE;
 	w->wctlready = TRUE;
 	originwindow(w->img, w->img->r.min, screen->r.max);
@@ -777,6 +790,7 @@
 
 	w = arg;
 	threadsetname("winthread-%d", w->id);
+	w->threadname = threadgetname();
 	x = &w->text;
 	nr = 0;
 	memset(&cnv, 0, sizeof(cnv));
@@ -1030,7 +1044,7 @@
 		pid = recvul(cpid);
 		chanfree(cpid);
 		if(pid == 0){
-			wsendmsg(w, Deleted);
+			wdelete(w);
 			return 0;
 		}
 	}