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
--
⑨