#include #include #include #include #include #include #include #include #include #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; }