vncs: update devmouse code
This commit is contained in:
parent
5cc1cb1820
commit
6cbc226351
4 changed files with 100 additions and 248 deletions
|
@ -14,40 +14,31 @@ typedef struct Mousestate Mousestate;
|
|||
|
||||
struct Mousestate
|
||||
{
|
||||
Point xy; /* mouse.xy */
|
||||
int buttons; /* mouse.buttons */
|
||||
Point xy; /* mouse.xy */
|
||||
int buttons; /* mouse.buttons */
|
||||
ulong counter; /* increments every update */
|
||||
ulong msec; /* time of last event */
|
||||
ulong msec; /* time of last event */
|
||||
};
|
||||
|
||||
struct Mouseinfo
|
||||
{
|
||||
Lock;
|
||||
Mousestate;
|
||||
int dx;
|
||||
int dy;
|
||||
int track; /* dx & dy updated */
|
||||
int redraw; /* update cursor on screen */
|
||||
ulong lastcounter; /* value when /dev/mouse read */
|
||||
Rendez r;
|
||||
Ref;
|
||||
QLock;
|
||||
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 */
|
||||
Mousestate queue[16]; /* circular buffer of click events */
|
||||
ulong ri; /* read index into queue */
|
||||
ulong wi; /* write index into queue */
|
||||
};
|
||||
|
||||
Mouseinfo mouse;
|
||||
Cursorinfo cursor;
|
||||
int mouseshifted;
|
||||
Cursor curs;
|
||||
|
||||
void Cursortocursor(Cursor*);
|
||||
int mousechanged(void*);
|
||||
static void mouseclock(void);
|
||||
|
||||
enum{
|
||||
Qdir,
|
||||
|
@ -65,13 +56,22 @@ static Dirtab mousedir[]={
|
|||
"mousectl", {Qmousectl}, 0, 0222,
|
||||
};
|
||||
|
||||
static uchar buttonmap[8] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
Cursor arrow = {
|
||||
{ -1, -1 },
|
||||
{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
|
||||
0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
|
||||
0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
|
||||
0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
|
||||
},
|
||||
{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
|
||||
0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
|
||||
0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
|
||||
0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
|
||||
},
|
||||
};
|
||||
static int mouseswap;
|
||||
|
||||
extern Memimage* gscreen;
|
||||
extern void mousewarpnote(Point);
|
||||
extern Memimage* gscreen;
|
||||
extern void mousewarpnote(Point);
|
||||
|
||||
static void
|
||||
mousereset(void)
|
||||
|
@ -83,7 +83,9 @@ mousereset(void)
|
|||
static void
|
||||
mouseinit(void)
|
||||
{
|
||||
cursoron(1);
|
||||
curs = arrow;
|
||||
Cursortocursor(&arrow);
|
||||
cursoron();
|
||||
}
|
||||
|
||||
static Chan*
|
||||
|
@ -95,12 +97,7 @@ mouseattach(char *spec)
|
|||
static Walkqid*
|
||||
mousewalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
Walkqid *wq;
|
||||
|
||||
wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
|
||||
if(wq != nil && wq->clone != c && (wq->clone->qid.type&QTDIR)==0)
|
||||
incref(&mouse);
|
||||
return wq;
|
||||
return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -112,54 +109,48 @@ mousestat(Chan *c, uchar *db, int n)
|
|||
static Chan*
|
||||
mouseopen(Chan *c, int omode)
|
||||
{
|
||||
int mode;
|
||||
|
||||
mode = openmode(omode);
|
||||
switch((ulong)c->qid.path){
|
||||
case Qdir:
|
||||
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:
|
||||
case Qmousectl:
|
||||
error(Egreg); /* dummy */
|
||||
error(Egreg);
|
||||
break;
|
||||
default:
|
||||
case Qmouse:
|
||||
if(_tas(&mouse.open) != 0)
|
||||
error(Einuse);
|
||||
mouse.lastcounter = mouse.counter;
|
||||
/* wet floor */
|
||||
case Qcursor:
|
||||
incref(&mouse);
|
||||
}
|
||||
c->mode = openmode(omode);
|
||||
c->mode = mode;
|
||||
c->flag |= COPEN;
|
||||
c->offset = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
mousecreate(Chan*, char*, int, ulong)
|
||||
{
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
static void
|
||||
mouseclose(Chan *c)
|
||||
{
|
||||
if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
|
||||
lock(&mouse);
|
||||
if(c->qid.path == Qmouse)
|
||||
mouse.open = 0;
|
||||
if(--mouse.ref == 0){
|
||||
cursoroff(1);
|
||||
curs = arrow;
|
||||
Cursortocursor(&arrow);
|
||||
cursoron(1);
|
||||
}
|
||||
unlock(&mouse);
|
||||
if((c->qid.type&QTDIR)!=0 || (c->flag&COPEN)==0)
|
||||
return;
|
||||
switch((ulong)c->qid.path){
|
||||
case Qmouse:
|
||||
mouse.open = 0;
|
||||
/* wet floor */
|
||||
case Qcursor:
|
||||
if(decref(&mouse) != 0)
|
||||
return;
|
||||
cursoroff();
|
||||
curs = arrow;
|
||||
Cursortocursor(&arrow);
|
||||
cursoron();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,12 +158,10 @@ mouseclose(Chan *c)
|
|||
static long
|
||||
mouseread(Chan *c, void *va, long n, vlong off)
|
||||
{
|
||||
char buf[4*12+1];
|
||||
char buf[1+4*12+1];
|
||||
uchar *p;
|
||||
static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
|
||||
ulong offset = off;
|
||||
Mousestate m;
|
||||
int b;
|
||||
|
||||
p = va;
|
||||
switch((ulong)c->qid.path){
|
||||
|
@ -185,47 +174,28 @@ 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)
|
||||
rendsleep(&mouse.r, mousechanged, 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 {
|
||||
lock(&cursor);
|
||||
|
||||
lock(&mouse);
|
||||
if(mouse.ri != mouse.wi)
|
||||
m = mouse.queue[mouse.ri++ % nelem(mouse.queue)];
|
||||
else
|
||||
m = mouse.Mousestate;
|
||||
unlock(&cursor);
|
||||
}
|
||||
unlock(&mouse);
|
||||
|
||||
sprint(buf, "m%11d %11d %11d %11lud ",
|
||||
m.xy.x, m.xy.y, m.buttons, m.msec);
|
||||
|
||||
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);
|
||||
|
@ -234,49 +204,6 @@ mouseread(Chan *c, void *va, long n, vlong off)
|
|||
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
|
||||
mousewrite(Chan *c, void *va, long n, vlong)
|
||||
{
|
||||
|
@ -290,7 +217,7 @@ mousewrite(Chan *c, void *va, long n, vlong)
|
|||
error(Eisdir);
|
||||
|
||||
case Qcursor:
|
||||
cursoroff(1);
|
||||
cursoroff();
|
||||
if(n < 2*4+2*2*16){
|
||||
curs = arrow;
|
||||
Cursortocursor(&arrow);
|
||||
|
@ -302,11 +229,7 @@ mousewrite(Chan *c, void *va, long n, vlong)
|
|||
memmove(curs.set, p+40, 2*16);
|
||||
Cursortocursor(&curs);
|
||||
}
|
||||
qlock(&mouse);
|
||||
mouse.redraw = 1;
|
||||
mouseclock();
|
||||
qunlock(&mouse);
|
||||
cursoron(1);
|
||||
cursoron();
|
||||
return n;
|
||||
|
||||
case Qmouse:
|
||||
|
@ -314,17 +237,13 @@ 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);
|
||||
qlock(&mouse);
|
||||
if(ptinrect(pt, gscreen->r)){
|
||||
mousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
|
||||
mousewarpnote(pt);
|
||||
}
|
||||
qunlock(&mouse);
|
||||
pt.y = strtol(p, 0, 0);
|
||||
absmousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
|
||||
mousewarpnote(pt);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -342,7 +261,7 @@ Dev mousedevtab = {
|
|||
mousewalk,
|
||||
mousestat,
|
||||
mouseopen,
|
||||
mousecreate,
|
||||
devcreate,
|
||||
mouseclose,
|
||||
mouseread,
|
||||
devbread,
|
||||
|
@ -361,75 +280,42 @@ Cursortocursor(Cursor *c)
|
|||
unlock(&cursor);
|
||||
}
|
||||
|
||||
static int
|
||||
scale(int x)
|
||||
{
|
||||
int sign = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
mouseclock(void)
|
||||
{
|
||||
lock(&cursor);
|
||||
if(mouse.redraw){
|
||||
mouse.redraw = 0;
|
||||
cursoroff(0);
|
||||
mouse.redraw = cursoron(0);
|
||||
}
|
||||
unlock(&cursor);
|
||||
}
|
||||
|
||||
/*
|
||||
* called at interrupt level to update the structure and
|
||||
* awaken any waiting procs.
|
||||
*/
|
||||
void
|
||||
mousetrack(int x, int y, int b, int msec)
|
||||
absmousetrack(int x, int y, int b, ulong msec)
|
||||
{
|
||||
int lastb;
|
||||
|
||||
lastb = mouse.buttons;
|
||||
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;
|
||||
|
||||
|
||||
lock(&mouse);
|
||||
mouse.xy = Pt(x, y);
|
||||
lastb = mouse.buttons;
|
||||
mouse.buttons = b;
|
||||
mouse.redraw = 1;
|
||||
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;
|
||||
unlock(&mouse);
|
||||
|
||||
rendwakeup(&mouse.r);
|
||||
mouseclock();
|
||||
|
||||
cursoron();
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -443,13 +329,3 @@ mousexy(void)
|
|||
{
|
||||
return mouse.xy;
|
||||
}
|
||||
|
||||
void
|
||||
mouseaccelerate(int x)
|
||||
{
|
||||
mouse.acceleration = x;
|
||||
if(mouse.acceleration < 3)
|
||||
mouse.maxacc = 2;
|
||||
else
|
||||
mouse.maxacc = mouse.acceleration;
|
||||
}
|
||||
|
|
|
@ -39,20 +39,6 @@ static Memimage *cursorset;
|
|||
static Memimage *cursorclear;
|
||||
static Cursor screencursor;
|
||||
|
||||
Cursor arrow = {
|
||||
{ -1, -1 },
|
||||
{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
|
||||
0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
|
||||
0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
|
||||
0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
|
||||
},
|
||||
{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
|
||||
0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
|
||||
0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
|
||||
0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
screeninit(int x, int y, char *chanstr)
|
||||
{
|
||||
|
@ -230,26 +216,16 @@ setcursor(Cursor* curs)
|
|||
memmove(cursclr, curs->clr, CURSORDIM*CURSORDIM/8);
|
||||
}
|
||||
|
||||
int
|
||||
cursoron(int dolock)
|
||||
void
|
||||
cursoron(void)
|
||||
{
|
||||
if(dolock)
|
||||
lock(&cursor);
|
||||
cursorpos = mousexy();
|
||||
if(dolock)
|
||||
unlock(&cursor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cursoroff(int dolock)
|
||||
cursoroff(void)
|
||||
{
|
||||
if(dolock)
|
||||
lock(&cursor);
|
||||
cursorpos = offscreen;
|
||||
if(dolock)
|
||||
unlock(&cursor);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -12,8 +12,8 @@ extern int cursorver;
|
|||
extern Point cursorpos;
|
||||
|
||||
Point mousexy(void);
|
||||
int cursoron(int);
|
||||
void cursoroff(int);
|
||||
void cursoron(void);
|
||||
void cursoroff(void);
|
||||
void setcursor(Cursor*);
|
||||
void flushmemscreen(Rectangle r);
|
||||
Rectangle cursorrect(void);
|
||||
|
@ -28,7 +28,7 @@ int setcolor(ulong, ulong, ulong, ulong);
|
|||
#define TK2SEC(x) 0
|
||||
extern void blankscreen(int);
|
||||
void screeninit(int x, int y, char *chanstr);
|
||||
void mousetrack(int x, int y, int b, int msec);
|
||||
void absmousetrack(int x, int y, int b, ulong msec);
|
||||
uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*);
|
||||
|
||||
void fsinit(char *mntpt, int x, int y, char *chanstr);
|
||||
|
|
|
@ -802,7 +802,7 @@ clientreadproc(Vncs *v)
|
|||
buttons = vncrdchar(v);
|
||||
x = vncrdshort(v);
|
||||
y = vncrdshort(v);
|
||||
mousetrack(x, y, buttons, nsec()/(1000*1000LL));
|
||||
absmousetrack(x, y, buttons, nsec()/(1000*1000LL));
|
||||
break;
|
||||
|
||||
/* send cut text */
|
||||
|
|
Loading…
Reference in a new issue