ref: 9942eb201a657640cf244b261008b850352a29f3
dir: /musw.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include <mouse.h>
#include <keyboard.h>
#include "dat.h"
#include "fns.h"
typedef struct Keymap Keymap;
struct Keymap
{
Rune key;
KeyOp op;
};
Keymap kmap[] = {
{.key = Kup, .op = K↑},
{.key = Kleft, .op = K↺},
{.key = Kright, .op = K↻},
{.key = 'w', .op = K↑},
{.key = 'a', .op = K↺},
{.key = 'd', .op = K↻},
{.key = ' ', .op = Kfire},
{.key = 'h', .op = Khyper},
{.key = 'y', .op = Ksay},
{.key = 'q', .op = Kquit}
};
ulong kup, kdown;
typedef struct Ball Ball;
struct Ball
{
double x, v;
};
Ball bouncer;
int debug;
void
kbdproc(void *)
{
Rune r;
Keymap *k;
char buf[128], *s;
int fd, n;
threadsetname("kbdproc");
if((fd = open("/dev/kbd", OREAD)) < 0)
sysfatal("kbdproc: %r");
memset(buf, 0, sizeof buf);
for(;;){
if(buf[0] != 0){
n = strlen(buf)+1;
memmove(buf, buf+n, sizeof(buf)-n);
}
if(buf[0] == 0){
if((n = read(fd, buf, sizeof(buf)-1)) <= 0)
break;
buf[n-1] = 0;
buf[n] = 0;
}
if(buf[0] == 'c'){
if(utfrune(buf, Kdel)){
close(fd);
threadexitsall(nil);
}
}
if(buf[0] != 'k' && buf[0] != 'K')
continue;
s = buf+1;
kdown = 0;
while(*s){
s += chartorune(&r, s);
for(k = kmap; k < kmap+nelem(kmap); k++)
if(r == k->key){
kdown |= 1 << k->op;
break;
}
}
kup = ~kdown;
if(debug)
fprint(2, "kup %.*lub\nkdown %.*lub\n",
sizeof(kup)*8, kup, sizeof(kdown)*8, kdown);
}
}
void
threadnetrecv(void *arg)
{
uchar buf[256];
int fd, n;
Ioproc *io;
fd = *((int*)arg);
io = ioproc();
while((n = ioread(io, fd, buf, sizeof buf)) > 0){
unpack(buf, n, "dd", &bouncer.x, &bouncer.v);
if(debug)
fprint(2, "bouncer [%g %g]\n", bouncer.x, bouncer.v);
}
closeioproc(io);
}
void resize(void);
void
threadresize(void *arg)
{
Mousectl *mc;
Alt a[3];
mc = arg;
a[0].op = CHANRCV; a[0].c = mc->c; a[0].v = &mc->Mouse;
a[1].op = CHANRCV; a[1].c = mc->resizec; a[1].v = nil;
a[2].op = CHANEND;
for(;;)
if(alt(a) == 1)
resize();
}
void
redraw(void)
{
lockdisplay(display);
draw(screen, screen->r, display->black, nil, ZP);
fillellipse(screen, addpt(screen->r.min,Pt(Dx(screen->r)/2,Dy(screen->r)/2+bouncer.x)), 2, 2, display->white, ZP);
flushimage(display, 1);
unlockdisplay(display);
}
void
resize(void)
{
if(debug)
fprint(2, "resizing\n");
lockdisplay(display);
if(getwindow(display, Refnone) < 0)
sysfatal("resize failed");
unlockdisplay(display);
redraw();
}
void
usage(void)
{
fprint(2, "usage: %s [-d] server\n", argv0);
threadexitsall("usage");
}
void
threadmain(int argc, char *argv[])
{
char *server;
int fd;
Mousectl *mc;
Ioproc *io;
ARGBEGIN{
case 'd':
debug++;
break;
default:
usage();
}ARGEND;
if(argc != 1)
usage();
server = argv[0];
if(newwindow("-dx 640 -dy 480") < 0)
sysfatal("newwindow: %r");
if(initdraw(nil, nil, nil) < 0)
sysfatal("initdraw: %r");
if((mc = initmouse(nil, screen)) == nil)
sysfatal("initmouse: %r");
display->locking = 1;
unlockdisplay(display);
proccreate(kbdproc, nil, 4096);
fd = dial(server, nil, nil, nil);
if(fd < 0)
sysfatal("dial: %r");
threadcreate(threadnetrecv, &fd, 4096);
threadcreate(threadresize, mc, 4096);
io = ioproc();
for(;;){
redraw();
iosleep(io, FPS2MS(30));
}
}