devmouse.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. #include <u.h>
  2. #include <libc.h>
  3. #include "compat.h"
  4. #include "error.h"
  5. #define Image IMAGE
  6. #include <draw.h>
  7. #include <memdraw.h>
  8. #include <cursor.h>
  9. #include "screen.h"
  10. typedef struct Mouseinfo Mouseinfo;
  11. typedef struct Mousestate Mousestate;
  12. struct Mousestate
  13. {
  14. Point xy; /* mouse.xy */
  15. int buttons; /* mouse.buttons */
  16. ulong counter; /* increments every update */
  17. ulong msec; /* time of last event */
  18. };
  19. struct Mouseinfo
  20. {
  21. Mousestate;
  22. int dx;
  23. int dy;
  24. int track; /* dx & dy updated */
  25. int redraw; /* update cursor on screen */
  26. ulong lastcounter; /* value when /dev/mouse read */
  27. Rendez r;
  28. Ref;
  29. QLock;
  30. int open;
  31. int acceleration;
  32. int maxacc;
  33. Mousestate queue[16]; /* circular buffer of click events */
  34. int ri; /* read index into queue */
  35. int wi; /* write index into queue */
  36. uchar qfull; /* queue is full */
  37. };
  38. Mouseinfo mouse;
  39. Cursorinfo cursor;
  40. int mouseshifted;
  41. Cursor curs;
  42. void Cursortocursor(Cursor*);
  43. int mousechanged(void*);
  44. static void mouseclock(void);
  45. enum{
  46. Qdir,
  47. Qcursor,
  48. Qmouse,
  49. };
  50. static Dirtab mousedir[]={
  51. ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
  52. "cursor", {Qcursor}, 0, 0666,
  53. "mouse", {Qmouse}, 0, 0666,
  54. };
  55. static uchar buttonmap[8] = {
  56. 0, 1, 2, 3, 4, 5, 6, 7,
  57. };
  58. static int mouseswap;
  59. extern Memimage* gscreen;
  60. extern mousewarpnote(Point);
  61. static void
  62. mousereset(void)
  63. {
  64. curs = arrow;
  65. Cursortocursor(&arrow);
  66. }
  67. static void
  68. mouseinit(void)
  69. {
  70. cursoron(1);
  71. }
  72. static Chan*
  73. mouseattach(char *spec)
  74. {
  75. return devattach('m', spec);
  76. }
  77. static Walkqid*
  78. mousewalk(Chan *c, Chan *nc, char **name, int nname)
  79. {
  80. Walkqid *wq;
  81. wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
  82. if(wq != nil && wq->clone != c && (wq->clone->qid.type&QTDIR)==0)
  83. incref(&mouse);
  84. return wq;
  85. }
  86. static int
  87. mousestat(Chan *c, uchar *db, int n)
  88. {
  89. return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
  90. }
  91. static Chan*
  92. mouseopen(Chan *c, int omode)
  93. {
  94. switch((ulong)c->qid.path){
  95. case Qdir:
  96. if(omode != OREAD)
  97. error(Eperm);
  98. break;
  99. case Qmouse:
  100. lock(&mouse);
  101. if(mouse.open){
  102. unlock(&mouse);
  103. error(Einuse);
  104. }
  105. mouse.open = 1;
  106. mouse.ref++;
  107. unlock(&mouse);
  108. break;
  109. default:
  110. incref(&mouse);
  111. }
  112. c->mode = openmode(omode);
  113. c->flag |= COPEN;
  114. c->offset = 0;
  115. return c;
  116. }
  117. static void
  118. mousecreate(Chan*, char*, int, ulong)
  119. {
  120. error(Eperm);
  121. }
  122. static void
  123. mouseclose(Chan *c)
  124. {
  125. if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
  126. lock(&mouse);
  127. if(c->qid.path == Qmouse)
  128. mouse.open = 0;
  129. if(--mouse.ref == 0){
  130. cursoroff(1);
  131. curs = arrow;
  132. Cursortocursor(&arrow);
  133. cursoron(1);
  134. }
  135. unlock(&mouse);
  136. }
  137. }
  138. static long
  139. mouseread(Chan *c, void *va, long n, vlong off)
  140. {
  141. char buf[4*12+1];
  142. uchar *p;
  143. static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
  144. ulong offset = off;
  145. Mousestate m;
  146. int b;
  147. p = va;
  148. switch((ulong)c->qid.path){
  149. case Qdir:
  150. return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
  151. case Qcursor:
  152. if(offset != 0)
  153. return 0;
  154. if(n < 2*4+2*2*16)
  155. error(Eshort);
  156. n = 2*4+2*2*16;
  157. lock(&cursor);
  158. BPLONG(p+0, curs.offset.x);
  159. BPLONG(p+4, curs.offset.y);
  160. memmove(p+8, curs.clr, 2*16);
  161. memmove(p+40, curs.set, 2*16);
  162. unlock(&cursor);
  163. return n;
  164. case Qmouse:
  165. while(mousechanged(0) == 0)
  166. rendsleep(&mouse.r, mousechanged, 0);
  167. mouse.qfull = 0;
  168. /*
  169. * No lock of the indicies is necessary here, because ri is only
  170. * updated by us, and there is only one mouse reader
  171. * at a time. I suppose that more than one process
  172. * could try to read the fd at one time, but such behavior
  173. * is degenerate and already violates the calling
  174. * conventions for sleep above.
  175. */
  176. if(mouse.ri != mouse.wi){
  177. m = mouse.queue[mouse.ri];
  178. if(++mouse.ri == nelem(mouse.queue))
  179. mouse.ri = 0;
  180. } else {
  181. lock(&cursor);
  182. m = mouse.Mousestate;
  183. unlock(&cursor);
  184. }
  185. b = buttonmap[m.buttons&7];
  186. /* put buttons 4 and 5 back in */
  187. b |= m.buttons & (3<<3);
  188. sprint(buf, "m%11d %11d %11d %11lud",
  189. m.xy.x, m.xy.y,
  190. b,
  191. m.msec);
  192. mouse.lastcounter = m.counter;
  193. if(n > 1+4*12)
  194. n = 1+4*12;
  195. memmove(va, buf, n);
  196. return n;
  197. }
  198. return 0;
  199. }
  200. static void
  201. setbuttonmap(char* map)
  202. {
  203. int i, x, one, two, three;
  204. one = two = three = 0;
  205. for(i = 0; i < 3; i++){
  206. if(map[i] == 0)
  207. error(Ebadarg);
  208. if(map[i] == '1'){
  209. if(one)
  210. error(Ebadarg);
  211. one = 1<<i;
  212. }
  213. else if(map[i] == '2'){
  214. if(two)
  215. error(Ebadarg);
  216. two = 1<<i;
  217. }
  218. else if(map[i] == '3'){
  219. if(three)
  220. error(Ebadarg);
  221. three = 1<<i;
  222. }
  223. else
  224. error(Ebadarg);
  225. }
  226. if(map[i])
  227. error(Ebadarg);
  228. memset(buttonmap, 0, 8);
  229. for(i = 0; i < 8; i++){
  230. x = 0;
  231. if(i & 1)
  232. x |= one;
  233. if(i & 2)
  234. x |= two;
  235. if(i & 4)
  236. x |= three;
  237. buttonmap[x] = i;
  238. }
  239. }
  240. static long
  241. mousewrite(Chan *c, void *va, long n, vlong)
  242. {
  243. char *p;
  244. Point pt;
  245. char buf[64];
  246. p = va;
  247. switch((ulong)c->qid.path){
  248. case Qdir:
  249. error(Eisdir);
  250. case Qcursor:
  251. cursoroff(1);
  252. if(n < 2*4+2*2*16){
  253. curs = arrow;
  254. Cursortocursor(&arrow);
  255. }else{
  256. n = 2*4+2*2*16;
  257. curs.offset.x = BGLONG(p+0);
  258. curs.offset.y = BGLONG(p+4);
  259. memmove(curs.clr, p+8, 2*16);
  260. memmove(curs.set, p+40, 2*16);
  261. Cursortocursor(&curs);
  262. }
  263. qlock(&mouse);
  264. mouse.redraw = 1;
  265. mouseclock();
  266. qunlock(&mouse);
  267. cursoron(1);
  268. return n;
  269. case Qmouse:
  270. if(n > sizeof buf-1)
  271. n = sizeof buf -1;
  272. memmove(buf, va, n);
  273. buf[n] = 0;
  274. p = 0;
  275. pt.x = strtoul(buf+1, &p, 0);
  276. if(p == 0)
  277. error(Eshort);
  278. pt.y = strtoul(p, 0, 0);
  279. qlock(&mouse);
  280. if(ptinrect(pt, gscreen->r)){
  281. mousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
  282. mousewarpnote(pt);
  283. }
  284. qunlock(&mouse);
  285. return n;
  286. }
  287. error(Egreg);
  288. return -1;
  289. }
  290. Dev mousedevtab = {
  291. 'm',
  292. "mouse",
  293. mousereset,
  294. mouseinit,
  295. mouseattach,
  296. mousewalk,
  297. mousestat,
  298. mouseopen,
  299. mousecreate,
  300. mouseclose,
  301. mouseread,
  302. devbread,
  303. mousewrite,
  304. devbwrite,
  305. devremove,
  306. devwstat,
  307. };
  308. void
  309. Cursortocursor(Cursor *c)
  310. {
  311. lock(&cursor);
  312. memmove(&cursor.Cursor, c, sizeof(Cursor));
  313. setcursor(c);
  314. unlock(&cursor);
  315. }
  316. static int
  317. scale(int x)
  318. {
  319. int sign = 1;
  320. if(x < 0){
  321. sign = -1;
  322. x = -x;
  323. }
  324. switch(x){
  325. case 0:
  326. case 1:
  327. case 2:
  328. case 3:
  329. break;
  330. case 4:
  331. x = 6 + (mouse.acceleration>>2);
  332. break;
  333. case 5:
  334. x = 9 + (mouse.acceleration>>1);
  335. break;
  336. default:
  337. x *= mouse.maxacc;
  338. break;
  339. }
  340. return sign*x;
  341. }
  342. static void
  343. mouseclock(void)
  344. {
  345. lock(&cursor);
  346. if(mouse.redraw){
  347. mouse.redraw = 0;
  348. cursoroff(0);
  349. mouse.redraw = cursoron(0);
  350. }
  351. unlock(&cursor);
  352. }
  353. /*
  354. * called at interrupt level to update the structure and
  355. * awaken any waiting procs.
  356. */
  357. void
  358. mousetrack(int x, int y, int b, int msec)
  359. {
  360. int lastb;
  361. lastb = mouse.buttons;
  362. mouse.xy = Pt(x, y);
  363. mouse.buttons = b;
  364. mouse.redraw = 1;
  365. mouse.counter++;
  366. mouse.msec = msec;
  367. /*
  368. * if the queue fills, we discard the entire queue and don't
  369. * queue any more events until a reader polls the mouse.
  370. */
  371. if(!mouse.qfull && lastb != b){ /* add to ring */
  372. mouse.queue[mouse.wi] = mouse.Mousestate;
  373. if(++mouse.wi == nelem(mouse.queue))
  374. mouse.wi = 0;
  375. if(mouse.wi == mouse.ri)
  376. mouse.qfull = 1;
  377. }
  378. rendwakeup(&mouse.r);
  379. mouseclock();
  380. }
  381. int
  382. mousechanged(void*)
  383. {
  384. return mouse.lastcounter != mouse.counter;
  385. }
  386. Point
  387. mousexy(void)
  388. {
  389. return mouse.xy;
  390. }
  391. void
  392. mouseaccelerate(int x)
  393. {
  394. mouse.acceleration = x;
  395. if(mouse.acceleration < 3)
  396. mouse.maxacc = 2;
  397. else
  398. mouse.maxacc = mouse.acceleration;
  399. }