shithub: drawfs

Download patch

ref: 403546812898220ca456dea0f559cb2221ec4fcf
parent: d831cb7c1deb4699a6465eb76cca5c5158233325
author: sirjofri <sirjofri@sirjofri.de>
date: Tue Jan 7 12:12:15 EST 2025

more work

--- a/Readme.md
+++ b/Readme.md
@@ -4,13 +4,26 @@
 
 ## Usage notes
 
+**Note:** Instead of running the programs manually, you can use the script
+`t.rc`. All `t.rc` scripts are built around amd64 architecture.
+
 ### Run drawfs
 
 - It's best to just use `cd drawfs && t.rc`, but you can do it manually:
 - `cd drawfs`
 - `X.out -n test`
-- `mount /srv/drawfs.test /dev`
-- run a graphical program, tested with `clock`
+
+### Run mousefs
+
+- It's best to just use `cd mousefs && t.rc`, but you can do it manually:
+- `cd mousefs`
+- `X.out -n test`
+
+### Run graphical program
+
+- `mount -b /srv/drawfs.test /dev`
+- `mount -b /srv/mousefs.test /dev`
+- just run any graphical program in that new environment
 
 ### Run drawmgr in a separate window
 
--- a/drawfs/fns.h
+++ b/drawfs/fns.h
@@ -1,3 +1,6 @@
 void initfs(char *srvname, Channel *chan);
 void initcmd(char *srvname, Channel *chan);
 void readscreenimage(Req *r, int full);
+int shouldrefresh(void);
+void setlive(int live);
+void resizescreen(int x, int y);
--- a/drawfs/fs.c
+++ b/drawfs/fs.c
@@ -11,6 +11,9 @@
 
 /* see: /sys/src/9/port/devdraw.c */
 
+#define min(A, B) ((A) < (B) ? (A) : (B))
+#define max(A, B) ((A) > (B) ? (A) : (B))
+
 jmp_buf errjmp;
 #define waserror() setjmp(errjmp)
 #define error(MSG) { fprint(2, MSG); longjmp(errjmp, 1); }
@@ -237,8 +240,16 @@
 static ulong fullimagelen = 0;
 static uchar *rectimage = nil;
 static ulong rectimagelen = 0;
+static int live = 0;
 
 void
+setlive(int l)
+{
+	live = l;
+	fprint(2, "set live status: %s\n", live ? "online" : "offline");
+}
+
+void
 prepscreenimage(int full)
 {
 	Rectangle r;
@@ -296,9 +307,17 @@
 	}
 	len = full ? fullimagelen : rectimagelen;
 	
+	fprint(2, "readscreenimage %s\n", full ? "full" : "refresh");
+	
 	readbuf(r, data, len);
 }
 
+int
+shouldrefresh(void)
+{
+	return !(fullimage || rectimage);
+}
+
 static int
 drawcmp(char *a, char *b, int n)
 {
@@ -395,9 +414,6 @@
 void
 flushmemscreen(Rectangle r)
 {
-	// stub
-	// TODO: send update message?
-	
 	if (fullimage)
 		free(fullimage);
 	if (rectimage)
@@ -407,7 +423,10 @@
 	fullimagelen = 0;
 	rectimagelen = 0;
 	
-	chanprint(fschannel, "r%R\n", r);
+	fprint(2, "flush!\n");
+	
+	if (live)
+		chanprint(fschannel, "r\n");
 }
 
 static void
@@ -488,6 +507,8 @@
 	Memimage *i;
 	Rectangle r;
 	
+	sdraw.softscreen = 1;
+	
 	r = Rect(0, 0, 300, 200);
 	chan = XRGB32;
 	
@@ -504,6 +525,33 @@
 	snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
 	drawaddname(nil, di, strlen(screenname), screenname);
 	return di;
+}
+
+void
+resizescreen(int x, int y)
+{
+	Memimage *i;
+	Rectangle r;
+	
+	if (x < 50)
+		x = 50;
+	if (y < 50)
+		y = 50;
+	r = Rect(0, 0, x, y);
+	i = allocmemimage(r, XRGB32);
+	if (!i)
+		sysfatal("allocmemimage: %r");
+	memfillcolor(i, 0x00ffeeff);
+	
+	fprint(2, "resize to %R\n", r);
+	
+	dlock();
+	
+	freememimage(screendimage->image);
+	screendimage->image = i;
+	screenimage = i;
+	
+	dunlock();
 }
 
 DName*
--- a/drawmgr/drawmgr.c
+++ b/drawmgr/drawmgr.c
@@ -1,7 +1,7 @@
 #include <u.h>
 #include <libc.h>
 #include <draw.h>
-#include <event.h>
+#include <thread.h>
 #include <keyboard.h>
 
 void
@@ -11,7 +11,18 @@
 	exits("usage");
 }
 
+enum {
+	Drefresh,
+};
+
+typedef struct Drawcmd Drawcmd;
+struct Drawcmd {
+	int cmd;
+};
+
 int drawdispfd;
+int drawctlfd;
+int mouseinfd;
 
 void
 refreshimage(void)
@@ -18,20 +29,27 @@
 {
 	Image *timg;
 	
+	fprint(2, "refreshimage\n");
+	
+	if (drawdispfd < 0)
+		drawdispfd = open("/mnt/drawcmd/display", OREAD);
+	if (drawdispfd < 0)
+		sysfatal("drawfs: display: %r");
 	seek(drawdispfd, 0, 0);
+	
 	timg = readimage(display, drawdispfd, 0);
 	if (!timg) {
-		fprint(2, "refreshimage: %r\n");
+		fprint(2, "readimage: %r\n");
 		return;
 	}
+	fprint(2, "img: %R\n", timg->r);
 	draw(screen, rectaddpt(timg->r, screen->r.min), timg, nil, ZP);
 	freeimage(timg);
 }
 
 void
-eresized(int new)
+resized(int new)
 {
-	Image *tmpimg;
 	Point size;
 	uchar buf[1+4+4];
 	
@@ -38,16 +56,23 @@
 	if (new && getwindow(display, Refnone) < 0)
 		sysfatal("can't reattach to window: %r");
 	
-	/*
+	draw(screen, screen->r, display->white, nil, ZP);
+	
 	size.x = Dx(screen->r);
 	size.y = Dy(screen->r);
 	
+	// TODO: filesystem needs to properly hook up the new image in resize.
+	// TODO: see: ../drawfs/fs.c:/^resizescreen
+	// TODO: then this can be re-enabled
+	/*
 	buf[0] = 'r';
 	BPLONG(buf+1, size.x);
 	BPLONG(buf+5, size.y);
-	write(drawcmdfd, buf, 1+4+4);
+	write(drawctlfd, buf, 1+4+4);
 	*/
 	
+	fprint(2, "resize %P\n", size);
+	
 	refreshimage();
 }
 
@@ -57,8 +82,8 @@
 	char file[256];
 	int drawfd;
 	
-	if (strlen(name) + strlen("/srv/drawfs..cmd") + 2 > 256)
-		sysfatal("error: name too long: %s\n", name);
+	if (strlen(name) + strlen("/srv/drawfs..cmd") + 2 > sizeof(file))
+		sysfatal("drawfs: name too long: %s", name);
 	
 	snprint(file, sizeof file, "/srv/drawfs.%s.cmd", name);
 	drawfd = open(file, ORDWR);
@@ -67,31 +92,116 @@
 	if (mount(drawfd, -1, "/mnt/drawcmd", MREPL, "") < 0)
 		sysfatal("mount drawfs: %r");
 	
-	drawdispfd = open("/mnt/drawcmd/display", OREAD);
-	if (drawdispfd < 0)
-		sysfatal("display file: %r");
+	drawctlfd = open("/mnt/drawcmd/ctl", ORDWR);
+	if (drawctlfd < 0)
+		sysfatal("drawfs: ctl: %r");
+	
+	drawdispfd = -1;
 }
 
-int
-keyinput(Event *ev)
+void
+initmousefs(char *name)
 {
-	switch (ev->kbdc) {
-	case Kdel:
-	case 'q':
-		return 1;
-	case 'r':
+	char file[256];
+	int fd;
+	
+	if (strlen(name) + strlen("/srv/mousefs..cmd") + 2 > sizeof(file))
+		sysfatal("mousefs: name too long: %s", name);
+	
+	snprint(file, sizeof file, "/srv/mousefs.%s.cmd", name);
+	fd = open(file, ORDWR);
+	if (fd < 0)
+		sysfatal("mousefs: %r");
+	if (mount(fd, -1, "/mnt/mousefs", MREPL, "") < 0)
+		sysfatal("mount mousefs: %r");
+	
+	mouseinfd = open("/mnt/mousefs/mouse", OWRITE);
+	if (mouseinfd < 0)
+		sysfatal("mousefs: mouse: %r");
+}
+
+void
+drawreadproc(void *arg)
+{
+	char buf[512];
+	int n;
+	Channel *c;
+	Drawcmd cmd;
+	
+	c = arg;
+	for (;;) {
+		if ((n = read(drawctlfd, buf, sizeof(buf) - 1)) <= 0)
+			sysfatal("drawreadproc eof: %r");
+		buf[n] = 0;
+		switch (buf[0]) {
+		case 'r':
+			cmd.cmd = Drefresh;
+			break;
+		}
+		send(c, &cmd);
+	}
+}
+
+void
+initdrawprocs(Alt *a)
+{
+	a->c = chancreate(sizeof(Drawcmd), 0);
+	proccreate(drawreadproc, a->c, 2048);
+}
+
+void
+mouseproc(void *arg)
+{
+	char m[50];
+	Point p;
+	int mfd;
+	Channel *c;
+	
+	c = arg;
+	mfd = open("/dev/mouse", OREAD);
+	if (mfd < 0)
+		sysfatal("open /dev/mouse: %r");
+	for (;;) {
+		if (read(mfd, m, 49) != 49)
+			sysfatal("mouse eof");
+		p.x = atoi(m+1);
+		p.y = atoi(m+1+12);
+		p.x -= screen->r.min.x;
+		p.y -= screen->r.min.y;
+		snprint(m+1, 11, "%11d %11d", p.x, p.y);
+		send(c, m);
+	}
+}
+
+void
+initmouseprocs(Alt *a)
+{
+	a->c = chancreate(sizeof(char)*50, 0);
+	proccreate(mouseproc, a->c, 2048);
+}
+
+void
+handledrawcmd(Drawcmd *d)
+{
+	switch (d->cmd) {
+	case Drefresh:
 		refreshimage();
 		break;
 	}
-	return 0;
 }
 
 void
-main(int argc, char **argv)
+threadmain(int argc, char **argv)
 {
-	Event ev;
-	int e;
+	char mdata[50];
+	Drawcmd dcmd;
 	
+	Alt a[] = {
+		{ nil, mdata, CHANRCV },
+		{ nil, &dcmd, CHANRCV },
+		{ nil, nil, CHANEND },
+	};
+	
 	char *name = nil;
 	
 	ARGBEGIN{
@@ -108,23 +218,32 @@
 	
 	rfork(RFNAMEG);
 	
+	initmousefs(name);
 	initdrawfs(name);
 	
 	if (initdraw(nil, nil, "drawmgr") < 0)
 		sysfatal("initdraw: %r");
 	
-	einit(Emouse|Ekeyboard);
+	initmouseprocs(&a[0]);
+	initdrawprocs(&a[1]);
 	
-	eresized(0);
+	resized(0);
 	
 	for (;;) {
-		e = event(&ev);
-		switch (e) {
-		case Ekeyboard:
-			if (keyinput(&ev))
-				exits(nil);
+		switch (alt(a)) {
+		case 0: /* mouse event */
+			if (mdata[0] == 'r') {
+				fprint(2, "resize\n");
+				resized(1);
+				break;
+			}
+			seek(mouseinfd, 0, 0);
+			if (write(mouseinfd, mdata, 49) != 49)
+				sysfatal("write mousein: %r");
 			break;
+		case 1: /* draw ctl event */
+			handledrawcmd(&dcmd);
+			break;
 		}
-		eresized(0);
 	}
 }
--- a/mkfile
+++ b/mkfile
@@ -1,4 +1,4 @@
-DIRS=drawfs consfs mousefs drawmgr
+DIRS=drawfs mousefs drawmgr
 
 all:V:
 	for (d in $DIRS)
--- /dev/null
+++ b/mousefs/cmd.c
@@ -1,0 +1,161 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <fcall.h>
+#include <9p.h>
+#include "fns.h"
+
+enum {
+	Qroot,
+	Qmouse,
+};
+
+static void
+mkqid(Qid* q, int p)
+{
+	q->path = p;
+	q->vers = 0;
+	q->type = p == Qroot ? QTDIR : QTFILE;
+}
+
+static void
+mkqdir(Dir *d, int p)
+{
+	mkqid(&d->qid, p);
+	d->mode = 0666;
+	if (d->qid.type & QTDIR)
+		d->mode |= DMDIR;
+	
+	d->atime = d->mtime = time(0);
+	d->length = 0;
+	d->uid = estrdup9p(getuser());
+	d->gid = estrdup9p(d->uid);
+	d->muid = estrdup9p(d->uid);
+	switch (p) {
+	case Qroot:
+		d->name = estrdup9p(".");
+		break;
+	case Qmouse:
+		d->name = estrdup9p("mouse");
+		break;
+	}
+}
+
+static void
+ctlattach(Req *r)
+{
+	mkqid(&r->fid->qid, Qroot);
+	r->ofcall.qid = r->fid->qid;
+	respond(r, nil);
+}
+
+static char*
+ctlwalk(Fid *fid, char *name, Qid *qid)
+{
+	switch (fid->qid.path) {
+	case Qroot:
+		if (strcmp(name, "..") == 0) {
+			*qid = fid->qid;
+			return nil;
+		}
+		if (strcmp(name, "mouse") == 0) {
+			mkqid(qid, Qmouse);
+			fid->qid = *qid;
+			return nil;
+		}
+	}
+	return "no file";
+}
+
+static void
+ctlstat(Req *r)
+{
+	if (r->fid->qid.path != Qroot && r->fid->qid.path != Qmouse) {
+		respond(r, "no file");
+		return;
+	}
+	mkqdir(&r->d, r->fid->qid.path);
+	respond(r, nil);
+}
+
+static int
+genroot(int n, Dir *d, void*)
+{
+	if (n != 0)
+		return -1;
+	mkqdir(d, Qmouse);
+	return 0;
+}
+
+static void
+ctlread(Req *r)
+{
+	switch (r->fid->qid.path) {
+	case Qroot:
+		dirread9p(r, genroot, nil);
+		respond(r, nil);
+		return;
+	case Qmouse:
+		respond(r, "no read");
+		return;
+	}
+	respond(r, "ctlread: no file");
+}
+
+typedef struct Mousedata Mousedata;
+struct Mousedata {
+	int x;
+	int y;
+	int b;
+	ulong msec;
+};
+Mousedata prev;
+
+static void
+ctlwrite(Req *r)
+{
+	Mousedata d;
+	
+	switch (r->fid->qid.path) {
+	case Qmouse:
+		break;
+	default:
+		respond(r, "no file");
+		return;
+	}
+	
+	if (r->ifcall.count != 49) {
+		respond(r, "invalid request size");
+		return;
+	}
+	
+	d.x = atoi(r->ifcall.data + 1+0*12);
+	d.y = atoi(r->ifcall.data + 1+1*12);
+	d.b = atoi(r->ifcall.data + 1+2*12);
+	d.msec = strtoll(r->ifcall.data + 1+3*12, 0, 0);
+	
+	absmousetrack(d.x, d.y, d.b, d.msec);
+	prev = d;
+	r->ofcall.count = r->ifcall.count;
+	respond(r, nil);
+	return;
+}
+
+Srv ctl = {
+	.attach = ctlattach,
+	.walk1 = ctlwalk,
+	.stat = ctlstat,
+	.read = ctlread,
+	.write = ctlwrite,
+};
+
+void
+initcmdfs(char *name)
+{
+	char *srvname;
+	
+	srvname = smprint("mousefs.%s.cmd", name);
+	if (!srvname)
+		sysfatal("%r");
+	postsrv(&ctl, srvname);
+}
--- a/mousefs/mkfile
+++ b/mousefs/mkfile
@@ -1,6 +1,7 @@
 </$objtype/mkfile
 
 TARG=mousefs
-OFILES=mousefs.$O
+OFILES=mousefs.$O\
+	cmd.$O\
 
 </sys/src/cmd/mkone
--- a/mousefs/mousefs.c
+++ b/mousefs/mousefs.c
@@ -6,6 +6,7 @@
 #include <thread.h>
 #include <fcall.h>
 #include <9p.h>
+#include "fns.h"
 
 void
 usage(void)
@@ -21,6 +22,7 @@
 #define min(A, B) ((A) < (B) ? (A) : (B))
 
 QLock drawlock;
+Rendez readrend;
 
 Cursor arrow = {
 	{ -1, -1 },
@@ -110,8 +112,8 @@
 	
 	if (b != lastb && (mouse.wi - mouse.ri) < nelem(mouse.queue))
 		mouse.queue[mouse.wi++ % nelem(mouse.queue)] = mouse.Mousestate;
+	rwakeup(&readrend);
 	qunlock(&mouse);
-	// TODO: wakeup?
 }
 
 void
@@ -304,6 +306,7 @@
 	
 	case Qmouse:
 		qlock(&mouse);
+		rsleep(&readrend);
 		if (mouse.ri != mouse.wi)
 			m = mouse.queue[mouse.ri++ % nelem(mouse.queue)];
 		else
@@ -502,6 +505,7 @@
 {
 	Cursortocursor(&arrow);
 	screenr = Rect(0, 0, 1024, 768);
+	readrend.l = &mouse;
 }
 
 void
@@ -533,6 +537,8 @@
 		sysfatal("%r");
 	
 	mouseinit();
+	
+	initcmdfs(name);
 	
 	postsrv(&fs, srvname);
 }
--- a/mousefs/t.rc
+++ b/mousefs/t.rc
@@ -2,10 +2,10 @@
 
 rfork en
 mk
-rm /srv/mousefs.test >[2]/dev/null
+rm /srv/mousefs.test /srv/mousefs.test.cmd >[2]/dev/null
 6.out -n test $*
 mount /srv/mousefs.test /mnt/mousetest
 cd /mnt/mousetest
 prompt=('mousefs; ' '	')
 rc
-rm /srv/mousefs.test >[2]/dev/null
+rm /srv/mousefs.test /srv/mousefs.test.cmd >[2]/dev/null
--- /dev/null
+++ b/t.rc
@@ -1,0 +1,16 @@
+#!/bin/rc
+
+rfork en
+
+srvfiles=(srv/drawfs.test /srv/drawfs.test.cmd /srv/mousefs.test /srv/mousefs.test.cmd)
+
+rm $srvfiles >[2]/dev/null
+
+drawfs/6.out -n test
+mousefs/6.out -n test $*
+
+mount -b /srv/drawfs.test /dev
+mount -b /srv/mousefs.test /dev
+prompt=('test; ' '	')
+rc
+rm $srvfiles >[2]/dev/null
--