struct Mousestate
{
Point xy; /* mouse.xy */
int buttons; /* mouse.buttons */
ulong counter; /* increments every update */
ulong msec; /* time of last event */
};
struct Mouseinfo
{
Lock;
Mousestate;
int inbuttons; /* buttons from /dev/mousein */
int redraw; /* update cursor on screen */
Rendez redrawr; /* wait for cursor screen updates */
ulong lastcounter; /* value when /dev/mouse read */
int resize; /* generate resize event */
Rendez r;
Ref;
int open;
int acceleration;
int maxacc;
Mousestate queue[16]; /* circular buffer of click events */
ulong ri; /* read index into queue */
ulong wi; /* write index into queue */
};
static Walkqid*
mousewalk(Chan *c, Chan *nc, char **name, int nname)
{
/*
* We use devgen() and not mousedevgen() here
* see "Ugly problem" in dev.c/devwalk()
*/
return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
}
static int
mousestat(Chan *c, uchar *db, int n)
{
return devstat(c, db, n, mousedir, nelem(mousedir), mousedevgen);
}
static Chan*
mouseopen(Chan *c, int omode)
{
int mode;
ilock(&mouse);
if(mouse.ri != mouse.wi)
m = mouse.queue[mouse.ri++ % nelem(mouse.queue)];
else
m = mouse.Mousestate;
iunlock(&mouse);
b = buttonmap[m.buttons&7];
/* put buttons 4 and 5 back in */
b |= m.buttons & (3<<3);
if (scrollswap)
if (b == 8)
b = 16;
else if (b == 16)
b = 8;
sprint(buf, "m%11d %11d %11d %11ld ",
m.xy.x, m.xy.y, b, m.msec);
if(x < 0){
sign = -1;
x = -x;
}
switch(x){
case 0:
case 1:
case 2:
case 3:
break;
case 4:
x = 6 + (mouse.acceleration>>2);
break;
case 5:
x = 9 + (mouse.acceleration>>1);
break;
default:
x *= mouse.maxacc;
break;
}
return sign*x;
}
/*
* called at interrupt level to update the structure and
* awaken any waiting procs.
*/
void
mousetrack(int dx, int dy, int b, ulong msec)
{
if(mouse.acceleration){
dx = scale(dx);
dy = scale(dy);
}
absmousetrack(mouse.xy.x + dx, mouse.xy.y + dy, b, msec);
}
void
absmousetrack(int x, int y, int b, ulong msec)
{
int lastb;
if(gscreen==nil)
return;
if(x < gscreen->clipr.min.x)
x = gscreen->clipr.min.x;
if(x >= gscreen->clipr.max.x)
x = gscreen->clipr.max.x-1;
if(y < gscreen->clipr.min.y)
y = gscreen->clipr.min.y;
if(y >= gscreen->clipr.max.y)
y = gscreen->clipr.max.y-1;
/*
* if the queue fills, don't queue any more events until a
* reader polls the mouse.
*/
if(b != lastb && (mouse.wi-mouse.ri) < nelem(mouse.queue))
mouse.queue[mouse.wi++ % nelem(mouse.queue)] = mouse.Mousestate;
iunlock(&mouse);
wakeup(&mouse.r);
mouseredraw();
}
void
scmousetrack(int x, int y, int b, ulong msec)
{
vlong vx, vy;
t = MACHP(0)->ticks;
d = t - lasttick;
lasttick = t;
return TK2MS(d);
}
/*
* microsoft 3 button, 7 bit bytes
*
* byte 0 - 1 L R Y7 Y6 X7 X6
* byte 1 - 0 X5 X4 X3 X2 X1 X0
* byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0
* byte 3 - 0 M x x x x x (optional)
*
* shift & right button is the same as middle button (for 2 button mice)
*/
int
m3mouseputc(Queue*, int c)
{
static uchar msg[3];
static int nb;
static int middle;
static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 3 };
short x;
int dx, dy, newbuttons;
if(lastms() > 500)
nb = 0;
if(nb == 3){
nb = 0;
/*
* an extra byte comes for middle button motion.
* only two possible values for the extra byte.
*/
if(c == 0x00 || c == 0x20){
/* an extra byte gets sent for the middle button */
middle = (c&0x20) ? 2 : 0;
newbuttons = (mouse.buttons & ~2) | middle;
mousetrack(0, 0, newbuttons, TK2MS(MACHP(0)->ticks));
return 0;
}
}
msg[nb] = c;
if(++nb == 3){
newbuttons = middle | b[(msg[0]>>4)&3];
x = (msg[0]&0x3)<<14;
dx = (x>>8) | msg[1];
x = (msg[0]&0xc)<<12;
dy = (x>>8) | msg[2];
mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
}
return 0;
}
/*
* microsoft intellimouse 3 buttons + scroll
* byte 0 - 1 L R Y7 Y6 X7 X6
* byte 1 - 0 X5 X4 X3 X2 X1 X0
* byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0
* byte 3 - 0 0 M % % % %
*
* %: 0xf => U , 0x1 => D
*
* L: left
* R: right
* U: up
* D: down
*/
int
m5mouseputc(Queue*, int c)
{
static uchar msg[4];
static int nb;
/*
* Logitech 5 byte packed binary mouse format, 8 bit bytes
*
* shift & right button is the same as middle button (for 2 button mice)
*/
int
mouseputc(Queue*, int c)
{
static short msg[5];
static int nb;
static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 3, 3, 7};
int dx, dy, newbuttons;