shithub: lola

Download patch

ref: f42ae8d3b918c57f5c82d192aef0b9feccd7a313
parent: 1049552fb14efa811ca879b35244b8ea684995c1
author: aap <[email protected]>
date: Sat Jan 28 11:24:30 EST 2023

mouse fixes; Xreqs

--- a/TODO
+++ b/TODO
@@ -4,7 +4,6 @@
 	tap
 tap
 border resize/move
-move mouse
 write text
 wctl
 release keys and buttons when unfocused
--- a/fs.c
+++ b/fs.c
@@ -68,21 +68,29 @@
 char Enowindow[] = 	"window has no image";
 char Ebadmouse[] = 	"bad format on /dev/mouse";
 
+/* Extension of a Req, req->aux. also has a thread. */
+typedef struct Xreq Xreq;
+struct Xreq
+{
+	Req *req;
+	Channel *xc;
+	Channel *flush;		/* cancel read/write */
+	Xreq *next;
+};
+#define XR(req) ((Xreq*)(req)->aux)
+static Xreq *xreqfree;
+
 /* Extension of a Fid, fid->aux */
 typedef struct Xfid Xfid;
 struct Xfid
 {
-	Fid *fid;
-	Channel *xc;
-	Channel *flush;		// cancel read/write
 	Window *w;
 	RuneConvBuf cnv;
-	Xfid *next;
 };
-static Xfid *xfidfree;
+#define XF(fid) ((Xfid*)(fid)->aux)
 
-typedef struct XfidMsg XfidMsg;
-struct XfidMsg
+typedef struct XreqMsg XreqMsg;
+struct XreqMsg
 {
 	Req *r;
 	void (*f)(Req*);
@@ -89,61 +97,63 @@
 };
 
 static void
-xfidthread(void *a)
+xreqthread(void *a)
 {
-	Xfid *xf = a;
-	XfidMsg xm;
+	Xreq *xr = a;
+	XreqMsg xm;
 
 	for(;;){
-		recv(xf->xc, &xm);
+		recv(xr->xc, &xm);
+		xr->req = xm.r;
+		xm.r->aux = xr;
 		(*xm.f)(xm.r);
+		/* return to pool */
+		xr->req = nil;
+		xr->next = xreqfree;
+		xreqfree = xr;
 	}
 }
 
+static Xreq*
+getxreq(void)
+{
+	Xreq *xr;
+	if(xreqfree){
+		xr = xreqfree;
+		xreqfree = xr->next;
+	}else{
+		xr = emalloc(sizeof(Xreq));
+		xr->xc = chancreate(sizeof(XreqMsg), 0);
+		xr->flush = chancreate(sizeof(int), 0);
+		threadcreate(xreqthread, xr, mainstacksize);
+	}
+	xr->next = nil;
+	return xr;
+}
+
 static void
-toxfid(Req *r, void (*f)(Req*))
+toxreq(Req *r, void (*f)(Req*))
 {
-	Xfid *xf;
-	XfidMsg xm;
+	Xreq *xr;
+	XreqMsg xm;
 
-	xf = r->fid->aux;
+	xr = getxreq();
 	xm.r = r;
 	xm.f = f;
-	send(xf->xc, &xm);
+	send(xr->xc, &xm);
 }
 
 static Xfid*
-getxfid(Fid *fid, Window *w)
+getxfid(Window *w)
 {
 	Xfid *xf;
-	if(xfidfree){
-		xf = xfidfree;
-		xfidfree = xf->next;
-	}else{
-		xf = emalloc(sizeof(Xfid));
-		xf->xc = chancreate(sizeof(XfidMsg), 0);
-		xf->flush = chancreate(sizeof(int), 0);
-		threadcreate(xfidthread, xf, mainstacksize);
-	}
+	xf = emalloc(sizeof(Xfid));
 	memset(&xf->cnv, 0, sizeof(xf->cnv));
-	xf->fid = fid;
 	xf->w = w;
 	incref(w);
-	xf->next = nil;
 	return xf;
 }
 
-static void
-freexfid(Xfid *xf)
-{
-	wrelease(xf->w);
-	free(xf->cnv.buf);
-	xf->fid = nil;
-	xf->w = nil;
-	xf->next = xfidfree;
-	xfidfree = xf;
-}
-
 #define QID(w, q) ((w)<<8|(q))
 #define QWIN(q) ((q)>>8)
 #define QFILE(q) ((q)&0xFF)
@@ -170,7 +180,7 @@
 		return;
 	}
 
-	r->fid->aux = getxfid(r->fid, w);
+	r->fid->aux = getxfid(w);
 	r->fid->qid = (Qid){QID(w->id,Qroot),0,QTDIR};
 	r->ofcall.qid = r->fid->qid;
 	respond(r, nil);
@@ -179,11 +189,8 @@
 static char*
 fsclone(Fid *fid, Fid *newfid)
 {
-	Xfid *xf;
-
-	xf = fid->aux;
-	if(xf)
-		newfid->aux = getxfid(newfid, xf->w);
+	if(XF(fid))
+		newfid->aux = getxfid(XF(fid)->w);
 	return nil;
 }
 
@@ -307,13 +314,11 @@
 static char *tsnarf;
 
 static void
-xfopen(Req *r)
+fsopen(Req *r)
 {
-	Xfid *xf;
 	Window *w;
 
-	xf = r->fid->aux;
-	w = xf->w;
+	w = XF(r->fid)->w;
 
 	if(w == nil || w->deleted){
 		respond(r, Edeleted);
@@ -320,7 +325,7 @@
 		return;
 	}
 
-	switch(QFILE(xf->fid->qid.path)){
+	switch(QFILE(r->fid->qid.path)){
 	case Qsnarf:
 		r->ifcall.mode &= ~OTRUNC;
 		if(r->ifcall.mode==ORDWR || r->ifcall.mode==OWRITE)
@@ -358,18 +363,22 @@
 }
 
 static void
-xfclose(Xfid *xf)
+fsclose(Fid *fid)
 {
+	Xfid *xf;
 	Window *w;
 	Text *x;
 
+	xf = XF(fid);
+	if(xf == nil)
+		return;
 	w = xf->w;
 	x = &w->text;
 
-	switch(QFILE(xf->fid->qid.path)){
+	switch(QFILE(fid->qid.path)){
 	/* replace snarf buffer when /dev/snarf is closed */
 	case Qsnarf:
-		if(xf->fid->omode==ORDWR || xf->fid->omode==OWRITE){
+		if(fid->omode==ORDWR || fid->omode==OWRITE){
 			setsnarf(tsnarf, ntsnarf);
 			ntsnarf = 0;
 		}
@@ -402,6 +411,11 @@
 		wsetcursor(w);
 		break;
 	}
+
+	wrelease(xf->w);
+	free(xf->cnv.buf);
+	free(xf);
+	fid->aux = nil;
 }
 
 static int
@@ -462,7 +476,6 @@
 static char*
 readblocking(Req *r, Channel *readchan)
 {
-	Xfid *xf;
 	Window *w;
 	Channel *chan;
 	Stringpair pair;
@@ -469,12 +482,11 @@
 	enum { Adata, Agone, Aflush, NALT };
 	Alt alts[NALT+1];
 
-	xf = r->fid->aux;
-	w = xf->w;
+	w = XF(r->fid)->w;
 
 	alts[Adata] = ALT(readchan, &chan, CHANRCV);
 	alts[Agone] = ALT(w->gone, nil, CHANRCV);
-	alts[Aflush] = ALT(xf->flush, nil, CHANRCV);
+	alts[Aflush] = ALT(XR(r)->flush, nil, CHANRCV);
 	alts[NALT].op = CHANEND;
 	switch(alt(alts)){
 	case Adata:
@@ -493,14 +505,12 @@
 }
 
 static void
-xfread(Req *r)
+xread(Req *r)
 {
-	Xfid *xf;
 	Window *w;
 	char *data;
 
-	xf = r->fid->aux;
-	w = xf->w;
+	w = XF(r->fid)->w;
 
 	if(w == nil || w->deleted){
 		respond(r, Edeleted);
@@ -507,7 +517,7 @@
 		return;
 	}
 
-	switch(QFILE(xf->fid->qid.path)){
+	switch(QFILE(r->fid->qid.path)){
 	case Qwinid:
 		data = smprint("%11d ", w->id);
 		readstr(r, data);
@@ -555,7 +565,7 @@
 }
 
 static void
-xfwrite(Req *r)
+xwrite(Req *r)
 {
 	Xfid *xf;
 	Window *w;
@@ -563,12 +573,13 @@
 	vlong offset;
 	u32int count;
 	char *data, *p;
+	Point pt;
 	Channel *kbd;
 	Stringpair pair;
 	enum { Adata, Agone, Aflush, NALT };
 	Alt alts[NALT+1];
 
-	xf = r->fid->aux;
+	xf = XF(r->fid);
 	w = xf->w;
 	x = &w->text;
 	offset = r->ifcall.offset;
@@ -584,7 +595,7 @@
 	case Qcons:
 		alts[Adata] = ALT(w->conswrite, &kbd, CHANRCV);
 		alts[Agone] = ALT(w->gone, nil, CHANRCV);
-		alts[Aflush] = ALT(xf->flush, nil, CHANRCV);
+		alts[Aflush] = ALT(XR(r)->flush, nil, CHANRCV);
 		alts[NALT].op = CHANEND;
 		switch(alt(alts)){
 		case Adata:
@@ -614,7 +625,10 @@
 			break;
 		}
 		if(strncmp(data, "rawon", 5) == 0){
-// TODO: apparently we turn of hold mode here
+			if(w->holdmode){
+				w->holdmode = 1;
+				wsendmsg(w, Holdoff, ZR, nil);
+			}
 			if(x->rawmode++ == 0)
 				wsendmsg(w, Rawon, ZR, nil);
 			break;
@@ -627,6 +641,21 @@
 		respond(r, "unknown control message");
 		return;
 
+	case Qmouse:
+		if(data[0] != 'm'){
+			respond(r, Ebadmouse);
+			return;
+		}
+		p = nil;
+		pt.x = strtoul(data+1, &p, 0);
+		if(p == nil){
+			respond(r, Eshort);
+			return;
+		}
+		pt.y = strtoul(p, nil, 0);
+		wmovemouse(w, pt);
+		break;
+
 	case Qcursor:
 		if(count < 2*4+2*2*16)
 			w->cursorp = nil;
@@ -694,38 +723,16 @@
 }
 
 static void
-fsopen(Req *r)
-{
-	toxfid(r, xfopen);
-}
-
-static void
-freefid(Fid *fid)
-{
-	Xfid *xf;
-
-	xf = fid->aux;
-	if(xf){
-		xfclose(xf);
-		freexfid(xf);
-	}
-	fid->aux = nil;
-}
-
-static void
 fsread(Req *r)
 {
-	Xfid *xf;
-
 	if((r->fid->qid.type & QTDIR) == 0){
-		toxfid(r, xfread);
+		toxreq(r, xread);
 		return;
 	}
 
 	switch(QFILE(r->fid->qid.path)){
 	case Qroot:
-		xf = r->fid->aux;
-		dirread9p(r, genrootdir, xf->w);
+		dirread9p(r, genrootdir, XF(r->fid)->w);
 		break;
 	case Qwsys:
 		dirread9p(r, genwsysdir, nil);
@@ -737,23 +744,21 @@
 static void
 fswrite(Req *r)
 {
-	toxfid(r, xfwrite);
+	toxreq(r, xwrite);
 }
 
 static void
 fsflush(Req *r)
 {
-	Req *or;
-	Xfid *xf;
+	Xreq *xr;
 	int dummy = 0;
 
-	or = r->oldreq;
-	xf = or->fid->aux;
-	assert(xf);
+	xr = XR(r->oldreq);
+	assert(xr);
 
 	/* TODO: not entirely sure this is right.
 	 * is it possible no-one is listening? */
-	send(xf->flush, &dummy);
+	send(xr->flush, &dummy);
 	respond(r, nil);
 }
 
@@ -760,12 +765,10 @@
 static void
 fsstat(Req *r)
 {
-	Xfid *xf;
 	int f;
 
-	xf = r->fid->aux;
 	f = QFILE(r->fid->qid.path);
-	genrootdir(f-1, &r->d, xf->w);
+	genrootdir(f-1, &r->d, XF(r->fid)->w);
 	respond(r, nil);
 }
 
@@ -778,7 +781,7 @@
 	.flush		fsflush,
 	.walk1		fswalk1,
 	.clone		fsclone,
-	.destroyfid	freefid,
+	.destroyfid	fsclose,
 	nil
 };
 
--- a/inc.h
+++ b/inc.h
@@ -11,6 +11,7 @@
 #include <complete.h>
 #include <plumb.h>
 
+typedef uchar bool;
 enum {
 	FALSE = 0,
 	TRUE = 1
@@ -43,7 +44,7 @@
 	uint qh;	/* host point, output here */
 
 	/* not entirely happy with this in here */
-	int rawmode;
+	bool rawmode;
 	Rune *raw;
 	int nraw;
 
@@ -137,7 +138,7 @@
 	ulong	counter;	/* serial no. of last mouse event we received */
 	ulong	lastcounter;	/* serial no. of last mouse event sent to client */
 	int	lastb;	/* last button state we received */
-	uchar	full;	/* filled the queue; no more recording until client comes back */	
+	bool	full;	/* filled the queue; no more recording until client comes back */	
 };
 
 typedef struct Kbdqueue Kbdqueue;
@@ -146,7 +147,7 @@
 	char *q[32];
 	int ri;
 	int wi;
-	uchar full;
+	bool full;
 };
 
 enum
@@ -174,8 +175,8 @@
 struct Window
 {
 	Ref;
-	int deleted;
-	int hidden;
+	bool deleted;
+	bool hidden;
 	Window *lower;
 	Window *higher;
 	Image *img;
@@ -183,6 +184,7 @@
 	char name[32];
 	int namecount;
 	char *label;
+	bool noborder;
 	Rectangle contrect;
 	int notefd;
 	char *dir;
@@ -190,7 +192,7 @@
 	Text text;
 	Rectangle scrollr;
 	Rectangle textr;
-	int scrolling;
+	bool scrolling;
 	int holdmode;
 
 	Mousectl mc;
@@ -203,8 +205,8 @@
 
 	Channel *kbd;
 	Kbdqueue kq;
-	int consctlopen;
-	int kbdopen;
+	bool consctlopen;
+	bool kbdopen;
 
 	Channel *gone;		// window gone
 	Channel *ctl;		// Wctlmesg
@@ -241,6 +243,7 @@
 void whide(Window *w);
 void wunhide(Window *w);
 void wsethold(Window *w, int hold);
+void wmovemouse(Window *w, Point pt);
 void wtype(Window *w, Rune r);
 void wsetname(Window *w);
 void wsetpid(Window *w, int pid, int dolabel);
--- a/wind.c
+++ b/wind.c
@@ -15,6 +15,7 @@
 	w->higher = bottomwin;
 	if(bottomwin) bottomwin->lower = w;
 	w->lower = nil;
+	if(topwin == nil) topwin = w;
 	bottomwin = w;
 }
 
@@ -24,6 +25,7 @@
 	w->lower = topwin;
 	if(topwin) topwin->higher = w;
 	w->higher = nil;
+	if(bottomwin == nil) bottomwin = w;
 	topwin = w;
 }
 
@@ -45,7 +47,10 @@
 void
 wcalcrects(Window *w)
 {
-	w->contrect = insetrect(w->img->r, Borderwidth);
+	if(w->noborder)
+		w->contrect = w->img->r;
+	else
+		w->contrect = insetrect(w->img->r, Borderwidth);
 	Rectangle r = insetrect(w->contrect, 1);
 	w->scrollr = r;
 	w->scrollr.max.x = w->scrollr.min.x + 12;
@@ -56,6 +61,8 @@
 void
 wdecor(Window *w)
 {
+	if(w->noborder)
+		return;
 	int c = w->holdmode ?
 		w == focused ? TITLEHOLD : LTITLEHOLD :
 		w == focused ? TITLE : LTITLE;
@@ -370,6 +377,15 @@
 	}
 }
 
+void
+wmovemouse(Window *w, Point pt)
+{
+	if(w != focused || wpointto(mctl->xy) != w)
+		return;
+	// TODO? rio also checks menuing and such
+	moveto(mctl, pt);
+}
+
 /*
  * Need to do this in a separate proc because if process we're interrupting
  * is dying and trying to print tombstone, kernel is blocked holding p->debug lock.
@@ -641,6 +657,7 @@
 	int i;
 
 	x = &w->text;
+/* TODO: this is kinda dumb right now. do we *really* need args? */
 (void)p;
 (void)r;
 	switch(type){
@@ -665,6 +682,8 @@
 
 	case Refresh:
 /* TODO: clean this up? */
+		if(w->deleted)
+			break;
 		draw(w->img, w->img->r, x->cols[BACK], nil, ZP);
 		wdecor(w);
 		xfill(x);
@@ -902,7 +921,7 @@
 	int i, n;
 	char err[ERRMAX];
 	
-	n = snprint(w->name, sizeof(w->name)-2, "window.%d.%d", w->id, w->namecount++);
+	n = snprint(w->name, sizeof(w->name)-2, "%s.%d.%d", w->noborder ? "noborder" : "window", w->id, w->namecount++);
 	for(i='A'; i<='Z'; i++){
 		if(nameimage(w->img, w->name, 1) > 0)
 			return;