#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <draw.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>
#include <frame.h>
#include <9p.h>
#include "cook.h"
#include "gui.h"
typedef struct Cooker Cooker;
enum {
Tquiet = 3000, // timeout for quiet.
Ttick = 500, // tick interval.
Tdouble = 500, // timeout for double.
};
struct Cooker{
Channel* m; // raw.
Channel* c; // cooked.
};
int
Mfmt(Fmt* f)
{
Cmouse *m;
char* s;
m = va_arg(f->args, Cmouse*);
switch(m->flag){
case CMdouble:
s = "d";
break;
default:
s = " ";
}
return fmtprint(f," %s %x %P %uld", s, m->buttons, m->xy, m->msec);
}
static void
cookerthread(void* ca)
{
Cooker* cm = ca;
Mouse m, lm, m2;
Cmouse c;
ulong pressmsec;
int dclick, pressb;
pressmsec = time(nil);
memset(&m, 0, sizeof(m));
memset(&lm, 0, sizeof(lm));
dclick = pressb = 0;
while(recv(cm->m, &m) >= 0){
Sendnext:
/* Insert no-button events between
* click-a/rlse-a/click-b
*/
if (lm.buttons && m.buttons && !(lm.buttons&m.buttons)){
c.Mouse = lm;
c.buttons = 0;
c.flag = 0;
if (eventdebug > 2) edprint("sent1 %M\n", &c);
send(cm->c, &c);
}
/* Flag double clicks.
*/
if (!lm.buttons && m.buttons){
if (m.buttons == pressb){
if (m.msec - pressmsec < Tdouble)
dclick = 1;
}
pressb = m.buttons;
pressmsec = m.msec;
}
c.flag = dclick ? CMdouble : 0;
c.Mouse= m;
if (!m.buttons && dclick){
c.flag = CMdouble;
dclick = 0;
}
/* Drop just-more-move events that are ready even
* before delivering the one we are processing.
* Deliver just the last position.
*/
while(nbrecv(cm->m, &m2) > 0){
if (m2.buttons == m.buttons){
c.Mouse = m2; // ignored old.
m = m2;
} else {
send(cm->c, &c);
lm = m;
m = m2;
goto Sendnext;
}
}
send(cm->c, &c);
lm = m;
}
postnote(PNGROUP, getpid(), "mouse");
sysfatal("mouse");
}
Channel*
cookmouse(Channel* mc)
{
Cooker* cm;
cm = malloc(sizeof(Cooker));
cm->m = mc;
cm->c = chancreate(sizeof(Cmouse), 32);
threadcreate(cookerthread, cm, 8*1024);
return cm->c;
}
int
cookclick(Cmouse* m, Channel* mc)
{
int b;
b = m->buttons;
do {
recv(mc, m);
} while(m->buttons == b);
if (m->buttons == 0)
return 1;
do {
recv(mc, m);
} while(m->buttons != 0);
return 0;
}
int
cookslide(Cmouse* m, Channel* mc)
{
int b;
b = m->buttons;
while(m->buttons == b){
recv(mc, m);
}
if (m->buttons == 0)
return 1;
do {
recv(mc, m);
} while(m->buttons != 0);
return 0;
}
|