Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/bitsy/devpenmouse.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname bitsy/devpenmouse.c 2000/1021
## diff -e /dev/null /n/emeliedump/2000/1021/sys/src/9/bitsy/devpenmouse.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

#define	Image	IMAGE
#include	<draw.h>
#include	<memdraw.h>
#include	<cursor.h>
#include	"screen.h"

typedef struct Mouseinfo	Mouseinfo;
typedef struct Mousestate	Mousestate;
typedef struct Calibration	Calibration;

struct Calibration
{
	long	scalex;
	long	scaley;
	long	transx;
	long	transy;
} calibration = {
	-0x10000*0x400/320,
	-0x10000*0x400/240,
	320,
	240
};

struct Mousestate
{
	Point	xy;			/* mouse.xy */
	int		buttons;	/* mouse.buttons */
	ulong	counter;	/* increments every update */
	ulong	msec;		/* time of last event */
};

struct Mouseinfo
{
	Mousestate;
	ulong	lastcounter;	/* value when /dev/mouse read */
	Rendez	r;
	Ref;
	QLock;
	int	open;
	int	inopen;
	Mousestate 	queue[16];	/* circular buffer of click events */
	int	ri;	/* read index into queue */
	int	wi;	/* write index into queue */
	uchar	qfull;	/* queue is full */
};

Mouseinfo	mouse;
int		mouseshifted;

int	penmousechanged(void*);
static void	penmousetrack(int b, int x, int y);

enum{
	Qdir,
	Qmouse,
	Qmousein,
	Qmousectl,
};

static Dirtab mousedir[]={
	"mouse",	{Qmouse},		0,			0666,
	"mousein",	{Qmousein},		0,			0220,
	"mousectl",	{Qmousectl},	0,			0220,
};

static uchar buttonmap[8] = {
	0, 1, 2, 3, 4, 5, 6, 7,
};
static int mouseswap;

extern	Memimage*	gscreen;

void
penbutton(int up, int b) {
	if (up)
		mouse.buttons &= ~ (1 << b);
	else
		mouse.buttons |= 1 << b;
	penmousetrack(mouse.buttons, -1, -1);
}

void
pentrackxy(int x, int y) {
	if (x == -1) {
		/* pen up. associate with button 1, 2, 3 up */
		if (mouse.buttons & 0x7)
			mouse.buttons &= ~0x7;
	} else {
		x = (x<<16)/calibration.scalex + calibration.transx;
		y = (y<<16)/calibration.scaley + calibration.transy;
	}
	penmousetrack(mouse.buttons, x, y);
}

static void
penmousereset(void)
{
	if(!conf.monitor)
		return;
}

static void
penmouseinit(void)
{
	if(!conf.monitor)
		return;
}

static Chan*
penmouseattach(char *spec)
{
	if(!conf.monitor)
		error(Egreg);
	return devattach('m', spec);
}

static Chan*
penmouseclone(Chan *c, Chan *nc)
{
	nc = devclone(c, nc);
	if(c->qid.path != CHDIR)
		incref(&mouse);
	return nc;
}

static int
penmousewalk(Chan *c, char *name)
{
	return devwalk(c, name, mousedir, nelem(mousedir), devgen);
}

static void
penmousestat(Chan *c, char *db)
{
	devstat(c, db, mousedir, nelem(mousedir), devgen);
}

static Chan*
penmouseopen(Chan *c, int omode)
{
	switch(c->qid.path){
	case CHDIR:
		if(omode != OREAD)
			error(Eperm);
		break;
	case Qmouse:
		lock(&mouse);
		if(mouse.open){
			unlock(&mouse);
			error(Einuse);
		}
		mouse.open = 1;
		mouse.ref++;
		unlock(&mouse);
		break;
	case Qmousein:
	/*	error("disabled");	*/
		lock(&mouse);
		if(mouse.inopen){
			unlock(&mouse);
			error(Einuse);
		}
		mouse.inopen = 1;
		unlock(&mouse);
		break;
	default:
		incref(&mouse);
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

static void
penmousecreate(Chan*, char*, int, ulong)
{
	if(!conf.monitor)
		error(Egreg);
	error(Eperm);
}

static void
penmouseclose(Chan *c)
{
	if(c->qid.path!=CHDIR && (c->flag&COPEN)){
		lock(&mouse);
		if(c->qid.path == Qmouse)
			mouse.open = 0;
		else if(c->qid.path == Qmousein){
			mouse.inopen = 0;
			unlock(&mouse);
			return;
		}
		--mouse.ref;
		unlock(&mouse);
	}
}


static long
penmouseread(Chan *c, void *va, long n, vlong)
{
	char buf[4*12+1];
	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
	Mousestate m;
	int b;

	switch(c->qid.path){
	case CHDIR:
		return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);

	case Qmouse:
		while(penmousechanged(0) == 0)
			sleep(&mouse.r, penmousechanged, 0);

		mouse.qfull = 0;

		/*
		 * No lock of the indicies is necessary here, because ri is only
		 * updated by us, and there is only one mouse reader
		 * at a time.  I suppose that more than one process
		 * could try to read the fd at one time, but such behavior
		 * is degenerate and already violates the calling
		 * conventions for sleep above.
		 */
		if(mouse.ri != mouse.wi) {
			m = mouse.queue[mouse.ri];
			if(++mouse.ri == nelem(mouse.queue))
				mouse.ri = 0;
		} else {
			m = mouse.Mousestate;
		}

		b = buttonmap[m.buttons&7];
		/* put buttons 4 and 5 back in */
		b |= m.buttons & (3<<3);
		sprint(buf, "m%11d %11d %11d %11lud",
			m.xy.x, m.xy.y,
			b,
			m.msec);
		mouse.lastcounter = m.counter;
		if(n > 1+4*12)
			n = 1+4*12;
		memmove(va, buf, n);
		return n;
	}
	return 0;
}

static void
setbuttonmap(char* map)
{
	int i, x, one, two, three;

	one = two = three = 0;
	for(i = 0; i < 3; i++){
		if(map[i] == 0)
			error(Ebadarg);
		if(map[i] == '1'){
			if(one)
				error(Ebadarg);
			one = 1<<i;
		}
		else if(map[i] == '2'){
			if(two)
				error(Ebadarg);
			two = 1<<i;
		}
		else if(map[i] == '3'){
			if(three)
				error(Ebadarg);
			three = 1<<i;
		}
		else
			error(Ebadarg);
	}
	if(map[i])
		error(Ebadarg);

	memset(buttonmap, 0, 8);
	for(i = 0; i < 8; i++){
		x = 0;
		if(i & 1)
			x |= one;
		if(i & 2)
			x |= two;
		if(i & 4)
			x |= three;
		buttonmap[x] = i;
	}
}

static long
penmousewrite(Chan *c, void *va, long n, vlong)
{
	char *p;
	Point pt;
	char buf[64], *field[3];
	int nf, b;

	p = va;
	switch(c->qid.path){
	case CHDIR:
		error(Eisdir);

	case Qmousectl:
		if(n >= sizeof(buf))
			n = sizeof(buf)-1;
		strncpy(buf, va, n);
		if(buf[n - 1] == '\n')
			buf[n-1] = 0;
		else
			buf[n] = 0;
		nf = getfields(buf, field, 3, 1, " ");
		if(strcmp(field[0], "swap") == 0){
			if(mouseswap)
				setbuttonmap("123");
			else
				setbuttonmap("321");
			mouseswap ^= 1;
		}
		else if(strcmp(field[0], "calibrate") == 0){
			if (nf == 1) {
				calibration.scalex = 1;
				calibration.scaley = 1;
				calibration.transx = 0;
				calibration.transy = 0;
			} else if (nf == 5) {
				calibration.scalex = strtol(field[1], nil, 0);
				calibration.scaley = strtol(field[2], nil, 0);
				calibration.transx = strtol(field[3], nil, 0);
				calibration.transy = strtol(field[4], nil, 0);
			}
		}
		return n;

	case Qmousein:
		if(n > sizeof buf-1)
			n = sizeof buf -1;
		memmove(buf, va, n);
		buf[n] = 0;
		p = 0;
		pt.x = strtol(buf+1, &p, 0);
		if(p == 0)
			error(Eshort);
		pt.y = strtol(p, &p, 0);
		if(p == 0)
			error(Eshort);
		b = strtol(p, &p, 0);
		penmousetrack(b, pt.x, pt.y);
		return n;
		
	case Qmouse:
		if(n > sizeof buf-1)
			n = sizeof buf -1;
		memmove(buf, va, n);
		buf[n] = 0;
		p = 0;
		pt.x = strtoul(buf+1, &p, 0);
		if(p == 0)
			error(Eshort);
		pt.y = strtoul(p, 0, 0);
		qlock(&mouse);
		if(ptinrect(pt, gscreen->r))
			penmousetrack(mouse.buttons, pt.x, pt.y);
		qunlock(&mouse);
		return n;
	}

	error(Egreg);
	return -1;
}

Dev penmousedevtab = {
	'm',
	"penmouse",

	penmousereset,
	penmouseinit,
	penmouseattach,
	penmouseclone,
	penmousewalk,
	penmousestat,
	penmouseopen,
	penmousecreate,
	penmouseclose,
	penmouseread,
	devbread,
	penmousewrite,
	devbwrite,
	devremove,
	devwstat,
};

/*
 *  called at interrupt level to update the structure and
 *  awaken any waiting procs.
 */
static void
penmousetrack(int b, int x, int y)
{
	int lastb;

	if(gscreen==nil)
		return;

	if (x >= 0) {
		mouse.xy = Pt(x, y);
	}
	lastb = mouse.buttons;
	mouse.buttons = b;
	mouse.counter++;
	mouse.msec = TK2MS(MACHP(0)->ticks);

	/*
	 * if the queue fills, we discard the entire queue and don't
	 * queue any more events until a reader polls the mouse.
	 */
	if(!mouse.qfull && lastb != b) {	/* add to ring */
		mouse.queue[mouse.wi] = mouse.Mousestate;
		if(++mouse.wi == nelem(mouse.queue))
			mouse.wi = 0;
		if(mouse.wi == mouse.ri)
			mouse.qfull = 1;
	}
	wakeup(&mouse.r);
}

int
penmousechanged(void*)
{
	return mouse.lastcounter != mouse.counter;
}

Point
penmousexy(void)
{
	return mouse.xy;
}
.
## diffname bitsy/devpenmouse.c 2000/1024
## diff -e /n/emeliedump/2000/1021/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1024/sys/src/9/bitsy/devpenmouse.c
341c
			} else
				print("calibrate %d fields\n", nf);
.
322c
		nf = getfields(buf, field, 5, 1, " ");
.
306c
	char buf[64], *field[5];
.
247c
			m.buttons,
.
242,244d
214d
207d
97a
		if ((mouse.buttons & 0x7) == 0)
			mouse.buttons |= 0x1;
.
93,94c
		mouse.buttons &= ~0x7;
.
## diffname bitsy/devpenmouse.c 2000/1025
## diff -e /n/emeliedump/2000/1024/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1025/sys/src/9/bitsy/devpenmouse.c
414d
409,412c
	if (x >= 0)
.
85c
		mouse.buttons |= b;
.
83c
		mouse.buttons &= ~b;
.
## diffname bitsy/devpenmouse.c 2000/1101
## diff -e /n/emeliedump/2000/1025/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1101/sys/src/9/bitsy/devpenmouse.c
328,329c
				calibration.scalex = 1<<16;
				calibration.scaley = 1<<16;
.
95,96c
		x = ((x*calibration.scalex)>>16) + calibration.transx;
		y = ((y*calibration.scaley)>>16) + calibration.transy;
.
## diffname bitsy/devpenmouse.c 2000/1102
## diff -e /n/emeliedump/2000/1101/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1102/sys/src/9/bitsy/devpenmouse.c
25,28c
	-23540,
	-16858,
	342,
	252
.
## diffname bitsy/devpenmouse.c 2000/1104
## diff -e /n/emeliedump/2000/1102/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1104/sys/src/9/bitsy/devpenmouse.c
27,28c
	23540,
	252,
	342
.
25d
## diffname bitsy/devpenmouse.c 2000/1120
## diff -e /n/emeliedump/2000/1104/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1120/sys/src/9/bitsy/devpenmouse.c
25,28c
	-16435,
	23275,
	253,
	-23
.
## diffname bitsy/devpenmouse.c 2000/1130
## diff -e /n/emeliedump/2000/1120/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1130/sys/src/9/bitsy/devpenmouse.c
427a
	drawactive(1);
.
## diffname bitsy/devpenmouse.c 2000/1206
## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1206/sys/src/9/bitsy/devpenmouse.c
226c
		 * No lock of the indices is necessary here, because ri is only
.
## diffname bitsy/devpenmouse.c 2000/1207
## diff -e /n/emeliedump/2000/1206/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1207/sys/src/9/bitsy/devpenmouse.c
97,98c
		if ((mouse.buttons & 0x1f) == 0) {
			if (mouse.modifiers)
				mouse.buttons |= mouse.modifiers;
			else
				mouse.buttons |= 0x1;
		}
.
92,93c
		/* pen up. associate with button 1 through 5 up */
		mouse.buttons &= ~0x1f;
.
82,86c
	if (b & 0x20) {
		if (up)
			mouse.buttons &= ~b;
		else
			mouse.buttons |= b;
		penmousetrack(mouse.buttons, -1, -1);
	} else {
		if (up)
			mouse.modifiers &= ~b;
		else
			mouse.modifiers |= b;
	}
.
34a
	int		modifiers;	/* state of physical buttons 2, 3, 4, 5 */
.
30a
/* The pen goes down, tracks some and goes up again.  The pen alone can
 * only simulate a one-button mouse.
 * To simulate a more-button (five, in this case) mouse, we use the four
 * keys along the the bottom of the iPaq as modifiers.
 * When one (or more) of the modifier keys is (are) down, a pen-down event
 * causes the corresponding bottons to go down.  If no modifier key is
 * depressed, a pen-down event is translated into a button-one down event.
 * Releasing the modifier keys has no direct effect.  The pen-up event is
 * the one that triggers mouse-up events.
 */
.
## diffname bitsy/devpenmouse.c 2000/1214
## diff -e /n/emeliedump/2000/1207/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1214/sys/src/9/bitsy/devpenmouse.c
239a

	case Qmousectl:
		sprint(buf, "c%11ld %11ld %11ld %11ld",
				calibration.scalex, calibration.scaley,
				calibration.transx, calibration.transy);
		if(n > 1+4*12)
			n = 1+4*12;
		memmove(va, buf, n);
		return n;
.
81c
	"mousectl",	{Qmousectl},	0,			0660,
.
## diffname bitsy/devpenmouse.c 2000/1215
## diff -e /n/emeliedump/2000/1214/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1215/sys/src/9/bitsy/devpenmouse.c
363a
				if ((!isdigit(*field[1]) && *field[1] != '-')
				 || (!isdigit(*field[2]) && *field[2] != '-')
				 || (!isdigit(*field[3]) && *field[3] != '-')
				 || (!isdigit(*field[4]) && *field[4] != '-'))
					error(Ectlsyntax);
.
12a
#include	<ctype.h>
.
## diffname bitsy/devpenmouse.c 2000/1216
## diff -e /n/emeliedump/2000/1215/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1216/sys/src/9/bitsy/devpenmouse.c
272d
## diffname bitsy/devpenmouse.c 2001/0115
## diff -e /n/emeliedump/2000/1216/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/0115/sys/src/9/bitsy/devpenmouse.c
368c
					error("bad syntax in control file message");
.
## diffname bitsy/devpenmouse.c 2001/0529
## diff -e /n/emeliedump/2001/0115/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devpenmouse.c
422d
337,338c
	switch((ulong)c->qid.path){
	case Qdir:
.
238,239c
	switch((ulong)c->qid.path){
	case Qdir:
.
217c
	if(c->qid.path != Qdir && (c->flag&COPEN)){
.
172,173c
	switch((ulong)c->qid.path){
	case Qdir:
.
163,168d
160c
	return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
.
158c
penmousestat(Chan *c, uchar *db, int n)
.
151,154c
	return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
.
148,149c
static Walkqid*
penmousewalk(Chan *c, Chan *nc, char **name, int nname)
.
80,82c
	".",			{Qdir, 0, QTDIR},	0,	DMDIR|0555,
	"mouse",		{Qmouse},		0,	0666,
	"mousein",	{Qmousein},		0,	0220,
	"mousectl",	{Qmousectl},		0,	0660,
.
## diffname bitsy/devpenmouse.c 2001/0822
## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/0822/sys/src/9/bitsy/devpenmouse.c
95c
	// button 5 (side button) immediately causes an event
	// when the pen is down (button 1), other buttons also
	// cause events, allowing chording with button 1
	if ((b & 0x20) || (mouse.buttons & 0x1)) {
.
## diffname bitsy/devpenmouse.c 2001/1117
## diff -e /n/emeliedump/2001/0822/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/1117/sys/src/9/bitsy/devpenmouse.c
344c
		nf = tokenize(buf, field, 5);
.
## diffname bitsy/devpenmouse.c 2001/1121
## diff -e /n/emeliedump/2001/1117/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/1121/sys/src/9/bitsy/devpenmouse.c
370a
		free(cb);
		poperror();
.
369c
				cmderror(cb, Ecmdargs);
			break;
.
358c
			} else if (cb->nf == 5) {
.
351,353c
			break;
		case CMcalibrate:
			if (cb->nf == 1) {
.
337,345c
		cb = parsecmd(va, n);
		if(waserror()){
			free(cb);
			nexterror();
		}
		ct = lookupcmd(cb, penmousecmd, nelem(penmousecmd));
		switch(ct->index){
		case CMswap:
.
327a
	Cmdbuf *cb;
	Cmdtab *ct;
.
85a
enum
{
	CMcalibrate,
	CMswap,
};

static Cmdtab penmousecmd[] =
{
	CMcalibrate,	"calibrate",	0,
	CMswap,		"swap",		1,
};

.
## diffname bitsy/devpenmouse.c 2001/1130
## diff -e /n/emeliedump/2001/1121/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/1130/sys/src/9/bitsy/devpenmouse.c
377,380c
				calibration.scalex = strtol(cb->f[1], nil, 0);
				calibration.scaley = strtol(cb->f[2], nil, 0);
				calibration.transx = strtol(cb->f[3], nil, 0);
				calibration.transy = strtol(cb->f[4], nil, 0);
.
372,375c
				if ((!isdigit(*cb->f[1]) && *cb->f[1] != '-')
				 || (!isdigit(*cb->f[2]) && *cb->f[2] != '-')
				 || (!isdigit(*cb->f[3]) && *cb->f[3] != '-')
				 || (!isdigit(*cb->f[4]) && *cb->f[4] != '-'))
.
342,343c
	char buf[64];
	int b;
.
125a

.
## diffname bitsy/devpenmouse.c 2002/0109
## diff -e /n/emeliedump/2001/1130/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2002/0109/sys/src/9/bitsy/devpenmouse.c
432a
	devshutdown,
.
## diffname bitsy/devpenmouse.c 2002/1112
## diff -e /n/emeliedump/2002/0109/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2002/1112/sys/src/9/bitsy/devpenmouse.c
476a
	resetsuspendtimer();
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.