summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/9/port/devmouse.c225
1 files changed, 85 insertions, 140 deletions
diff --git a/sys/src/9/port/devmouse.c b/sys/src/9/port/devmouse.c
index 90b8e76c6..950aff4ce 100644
--- a/sys/src/9/port/devmouse.c
+++ b/sys/src/9/port/devmouse.c
@@ -33,20 +33,19 @@ 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 */
- ulong lastresize;
- ulong resize;
+ int resize; /* generate resize event */
Rendez r;
Ref;
int open;
int acceleration;
int maxacc;
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 */
+ ulong ri; /* read index into queue */
+ ulong wi; /* write index into queue */
};
enum
@@ -69,9 +68,7 @@ static Cmdtab mousectlmsg[] =
Mouseinfo mouse;
Cursorinfo cursor;
-int mouseshifted;
Cursor curs;
-int mouseinbuttons;
void Cursortocursor(Cursor*);
int mousechanged(void*);
@@ -164,16 +161,11 @@ mouseattach(char *spec)
static Walkqid*
mousewalk(Chan *c, Chan *nc, char **name, int nname)
{
- Walkqid *wq;
-
/*
* We use devgen() and not mousedevgen() here
* see "Ugly problem" in dev.c/devwalk()
*/
- wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
- if(wq != nil && wq->clone != c && wq->clone != nil && (wq->clone->qid.type&QTDIR)==0)
- incref(&mouse);
- return wq;
+ return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
}
static int
@@ -193,17 +185,6 @@ mouseopen(Chan *c, int omode)
if(omode != OREAD)
error(Eperm);
break;
- case Qmouse:
- lock(&mouse);
- if(mouse.open){
- unlock(&mouse);
- error(Einuse);
- }
- mouse.open = 1;
- mouse.ref++;
- mouse.lastresize = mouse.resize;
- unlock(&mouse);
- break;
case Qmousein:
if(!iseve())
error(Eperm);
@@ -211,7 +192,13 @@ mouseopen(Chan *c, int omode)
if(c->aux == nil)
error(Enomem);
break;
- default:
+ case Qmouse:
+ if(tas(&mouse.open) != 0)
+ error(Einuse);
+ mouse.lastcounter = mouse.counter;
+ mouse.resize = 0;
+ /* wet floor */
+ case Qcursor:
incref(&mouse);
}
c->mode = mode;
@@ -220,34 +207,23 @@ mouseopen(Chan *c, int omode)
return c;
}
-static Chan*
-mousecreate(Chan*, char*, int, ulong)
-{
- if(!conf.monitor)
- error(Egreg);
- error(Eperm);
- return 0;
-}
-
static void
mouseclose(Chan *c)
{
- if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
- lock(&mouse);
- if(c->qid.path == Qmouse)
- mouse.open = 0;
- else if(c->qid.path == Qmousein){
- unlock(&mouse);
- mouseinbuttons &= ~((Mousestate*)c->aux)->buttons;
- free(c->aux); /* Mousestate */
- c->aux = nil;
- return;
- }
- if(--mouse.ref != 0){
- unlock(&mouse);
+ if((c->qid.type&QTDIR)!=0 || (c->flag&COPEN)==0)
+ return;
+ switch((ulong)c->qid.path){
+ case Qmousein:
+ mouse.inbuttons &= ~((Mousestate*)c->aux)->buttons;
+ free(c->aux); /* Mousestate */
+ c->aux = nil;
+ return;
+ case Qmouse:
+ mouse.open = 0;
+ /* wet floor */
+ case Qcursor:
+ if(decref(&mouse) != 0)
return;
- }
- unlock(&mouse);
cursoroff();
curs = arrow;
Cursortocursor(&arrow);
@@ -277,40 +253,23 @@ mouseread(Chan *c, void *va, long n, vlong off)
if(n < 2*4+2*2*16)
error(Eshort);
n = 2*4+2*2*16;
- lock(&cursor);
BPLONG(p+0, curs.offset.x);
BPLONG(p+4, curs.offset.y);
memmove(p+8, curs.clr, 2*16);
memmove(p+40, curs.set, 2*16);
- unlock(&cursor);
return n;
case Qmouse:
while(mousechanged(0) == 0)
sleep(&mouse.r, mousechanged, 0);
-
- mouse.qfull = 0;
mousetime = seconds();
- /*
- * No lock of the indices 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 {
- while(!canlock(&cursor))
- tsleep(&up->sleep, return0, 0, TK2MS(1));
-
+ ilock(&mouse);
+ if(mouse.ri != mouse.wi)
+ m = mouse.queue[mouse.ri++ % nelem(mouse.queue)];
+ else
m = mouse.Mousestate;
- unlock(&cursor);
- }
+ iunlock(&mouse);
b = buttonmap[m.buttons&7];
/* put buttons 4 and 5 back in */
@@ -321,16 +280,16 @@ mouseread(Chan *c, void *va, long n, vlong off)
else if (b == 16)
b = 8;
sprint(buf, "m%11d %11d %11d %11lud ",
- m.xy.x, m.xy.y,
- b,
- m.msec);
+ m.xy.x, m.xy.y, b, m.msec);
+
mouse.lastcounter = m.counter;
- if(n > 1+4*12)
- n = 1+4*12;
- if(mouse.lastresize != mouse.resize){
- mouse.lastresize = mouse.resize;
+ if(mouse.resize){
+ mouse.resize = 0;
buf[0] = 'r';
}
+
+ if(n > 1+4*12)
+ n = 1+4*12;
memmove(va, buf, n);
return n;
}
@@ -459,7 +418,7 @@ mousewrite(Chan *c, void *va, long n, vlong)
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);
@@ -467,7 +426,7 @@ mousewrite(Chan *c, void *va, long n, vlong)
if(*p == 0)
error(Eshort);
b = strtol(p, &p, 0);
- msec = strtol(p, &p, 0);
+ msec = strtol(p, 0, 0);
if(msec == 0)
msec = TK2MS(MACHP(0)->ticks);
@@ -480,7 +439,7 @@ mousewrite(Chan *c, void *va, long n, vlong)
m->msec = msec;
b ^= m->buttons;
m->buttons ^= b;
- mouseinbuttons = (m->buttons & b) | (mouseinbuttons & ~b);
+ mouse.inbuttons = (m->buttons & b) | (mouse.inbuttons & ~b);
b = mouse.buttons & ~b;
/* include wheel */
@@ -498,15 +457,12 @@ mousewrite(Chan *c, void *va, long n, vlong)
n = sizeof buf -1;
memmove(buf, va, n);
buf[n] = 0;
- p = 0;
- pt.x = strtoul(buf+1, &p, 0);
- if(p == 0)
+
+ pt.x = strtol(buf+1, &p, 0);
+ if(*p == 0)
error(Eshort);
- pt.y = strtoul(p, 0, 0);
- if(gscreen != nil && ptinrect(pt, gscreen->r)){
- mouse.xy = pt;
- mousetrack(0, 0, mouse.buttons, TK2MS(MACHP(0)->ticks));
- }
+ pt.y = strtol(p, 0, 0);
+ absmousetrack(pt.x, pt.y, mouse.buttons, TK2MS(MACHP(0)->ticks));
return n;
}
@@ -525,7 +481,7 @@ Dev mousedevtab = {
mousewalk,
mousestat,
mouseopen,
- mousecreate,
+ devcreate,
mouseclose,
mouseread,
devbread,
@@ -631,36 +587,46 @@ absmousetrack(int x, int y, int b, int msec)
if(x < gscreen->clipr.min.x)
x = gscreen->clipr.min.x;
if(x >= gscreen->clipr.max.x)
- 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;
+ y = gscreen->clipr.max.y-1;
- b |= mouseinbuttons;
- lastb = mouse.buttons;
+ ilock(&mouse);
mouse.xy = Pt(x, y);
+ lastb = mouse.buttons;
+ b |= mouse.inbuttons;
mouse.buttons = b;
- mouse.counter++;
mouse.msec = msec;
+ mouse.counter++;
/*
- * if the queue fills, we discard the entire queue and don't
- * queue any more events until a reader polls the mouse.
+ * if the queue fills, 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;
- }
+ 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();
}
+static ulong
+lastms(void)
+{
+ static ulong lasttick;
+ ulong t, d;
+
+ t = MACHP(0)->ticks;
+ d = t - lasttick;
+ lasttick = t;
+ return TK2MS(d);
+}
+
/*
* microsoft 3 button, 7 bit bytes
*
@@ -680,16 +646,11 @@ m3mouseputc(Queue*, int c)
static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 3 };
short x;
int dx, dy, newbuttons;
- static ulong lasttick;
- ulong m;
- /* Resynchronize in stream with timing. */
- m = MACHP(0)->ticks;
- if(TK2SEC(m - lasttick) > 2)
+ if(lastms() > 500)
+ nb = 0;
+ if(nb == 3){
nb = 0;
- lasttick = m;
-
- if(nb==0){
/*
* an extra byte comes for middle button motion.
* only two possible values for the extra byte.
@@ -704,8 +665,7 @@ m3mouseputc(Queue*, int c)
}
msg[nb] = c;
if(++nb == 3){
- nb = 0;
- newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)];
+ newbuttons = middle | b[(msg[0]>>4)&3];
x = (msg[0]&0x3)<<14;
dx = (x>>8) | msg[1];
x = (msg[0]&0xc)<<12;
@@ -732,30 +692,24 @@ m3mouseputc(Queue*, int c)
int
m5mouseputc(Queue*, int c)
{
- static uchar msg[3];
+ static uchar msg[4];
static int nb;
- static ulong lasttick;
- ulong m;
- /* Resynchronize in stream with timing. */
- m = MACHP(0)->ticks;
- if(TK2SEC(m - lasttick) > 2)
+ if(lastms() > 500)
+ nb = 0;
+ msg[nb] = c & 0x7f;
+ if(++nb == 4){
nb = 0;
- lasttick = m;
-
- msg[nb++] = c & 0x7f;
- if (nb == 4) {
schar dx,dy,newbuttons;
dx = msg[1] | (msg[0] & 0x3) << 6;
dy = msg[2] | (msg[0] & 0xc) << 4;
newbuttons =
- (msg[0] & 0x10) >> (mouseshifted ? 3 : 2)
+ (msg[0] & 0x10) >> 2
| (msg[0] & 0x20) >> 5
| ( msg[3] == 0x10 ? 0x02 :
msg[3] == 0x0f ? ScrollUp :
msg[3] == 0x01 ? ScrollDown : 0 );
mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
- nb = 0;
}
return 0;
}
@@ -772,26 +726,18 @@ mouseputc(Queue*, int c)
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;
- static ulong lasttick;
- ulong m;
- /* Resynchronize in stream with timing. */
- m = MACHP(0)->ticks;
- if(TK2SEC(m - lasttick) > 2)
+ if(lastms() > 500 || (c&0xF0) == 0x80)
nb = 0;
- lasttick = m;
-
- if((c&0xF0) == 0x80)
- nb=0;
msg[nb] = c;
if(c & 0x80)
msg[nb] |= ~0xFF; /* sign extend */
if(++nb == 5){
- newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)];
+ nb = 0;
+ newbuttons = b[((msg[0]&7)^7)];
dx = msg[1]+msg[3];
dy = -(msg[2]+msg[4]);
mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
- nb = 0;
}
return 0;
}
@@ -799,8 +745,7 @@ mouseputc(Queue*, int c)
int
mousechanged(void*)
{
- return mouse.lastcounter != mouse.counter ||
- mouse.lastresize != mouse.resize;
+ return mouse.lastcounter != mouse.counter || mouse.resize != 0;
}
Point
@@ -825,7 +770,7 @@ mouseaccelerate(int x)
void
mouseresize(void)
{
- mouse.resize++;
+ mouse.resize = 1;
wakeup(&mouse.r);
}