devmouse.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #define Image IMAGE
  16. #include <draw.h>
  17. #include <memdraw.h>
  18. #include <cursor.h>
  19. #include "screen.h"
  20. enum {
  21. ScrollUp = 0x08,
  22. ScrollDown = 0x10,
  23. ScrollLeft = 0x20,
  24. ScrollRight = 0x40,
  25. };
  26. typedef struct Mouseinfo Mouseinfo;
  27. typedef struct Mousestate Mousestate;
  28. struct Mousestate
  29. {
  30. Point xy; /* mouse.xy */
  31. int buttons; /* mouse.buttons */
  32. uint32_t counter; /* increments every update */
  33. uint32_t msec; /* time of last event */
  34. };
  35. struct Mouseinfo
  36. {
  37. Lock _lock;
  38. Mousestate Mousestate;
  39. int dx;
  40. int dy;
  41. int track; /* dx & dy updated */
  42. int redraw; /* update cursor on screen */
  43. uint32_t lastcounter; /* value when /dev/mouse read */
  44. uint32_t lastresize;
  45. uint32_t resize;
  46. Rendez rend;
  47. Ref r;
  48. QLock ql;
  49. int open;
  50. int acceleration;
  51. int maxacc;
  52. Mousestate queue[16]; /* circular buffer of click events */
  53. int ri; /* read index into queue */
  54. int wi; /* write index into queue */
  55. unsigned char qfull; /* queue is full */
  56. };
  57. enum
  58. {
  59. CMbuttonmap,
  60. CMscrollswap,
  61. CMswap,
  62. CMwildcard,
  63. };
  64. static Cmdtab mousectlmsg[] =
  65. {
  66. {CMbuttonmap, "buttonmap", 0},
  67. {CMscrollswap, "scrollswap", 0},
  68. {CMswap, "swap", 1},
  69. {CMwildcard, "*", 0},
  70. };
  71. Mouseinfo mouse;
  72. Cursorinfo cursor;
  73. int mouseshifted;
  74. int kbdbuttons;
  75. void (*kbdmouse)(int);
  76. Cursor curs;
  77. void Cursortocursor(Cursor*);
  78. int mousechanged(void*);
  79. static void mouseclock(void);
  80. enum{
  81. Qdir,
  82. Qcursor,
  83. Qmouse,
  84. Qmousein,
  85. Qmousectl,
  86. };
  87. static Dirtab mousedir[]={
  88. {".", {Qdir, 0, QTDIR}, 0, DMDIR|0555},
  89. {"cursor", {Qcursor}, 0, 0666},
  90. {"mouse", {Qmouse}, 0, 0666},
  91. {"mousein", {Qmousein}, 0, 0220},
  92. {"mousectl", {Qmousectl}, 0, 0220},
  93. };
  94. static unsigned char buttonmap[8] = {
  95. 0, 1, 2, 3, 4, 5, 6, 7,
  96. };
  97. static int mouseswap;
  98. static int scrollswap;
  99. static uint32_t mousetime;
  100. extern Memimage* gscreen;
  101. extern uint32_t kerndate;
  102. static void
  103. mousereset(void)
  104. {
  105. curs = arrow;
  106. Cursortocursor(&arrow);
  107. /* redraw cursor about 30 times per second */
  108. addclock0link(mouseclock, 33);
  109. }
  110. static void
  111. mousefromkbd(int buttons)
  112. {
  113. kbdbuttons = buttons;
  114. mousetrack(0, 0, 0, TK2MS(machp()->ticks));
  115. }
  116. static int
  117. mousedevgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
  118. {
  119. int rc;
  120. rc = devgen(c, name, tab, ntab, i, dp);
  121. if(rc != -1)
  122. dp->atime = mousetime;
  123. return rc;
  124. }
  125. static void
  126. mouseinit(void)
  127. {
  128. curs = arrow;
  129. Cursortocursor(&arrow);
  130. cursoron(1);
  131. kbdmouse = mousefromkbd;
  132. mousetime = seconds();
  133. }
  134. static Chan*
  135. mouseattach(char *spec)
  136. {
  137. return devattach('m', spec);
  138. }
  139. static Walkqid*
  140. mousewalk(Chan *c, Chan *nc, char **name, int nname)
  141. {
  142. Walkqid *wq;
  143. /*
  144. * We use devgen() and not mousedevgen() here
  145. * see "Ugly problem" in dev.c/devwalk()
  146. */
  147. wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
  148. if(wq != nil && wq->clone != c && wq->clone != nil && (wq->clone->qid.type&QTDIR)==0)
  149. incref(&mouse.r);
  150. return wq;
  151. }
  152. static int
  153. mousestat(Chan *c, unsigned char *db, int n)
  154. {
  155. return devstat(c, db, n, mousedir, nelem(mousedir), mousedevgen);
  156. }
  157. static Chan*
  158. mouseopen(Chan *c, int omode)
  159. {
  160. switch((uint32_t)c->qid.path){
  161. case Qdir:
  162. if(omode != OREAD)
  163. error(Eperm);
  164. break;
  165. case Qmouse:
  166. lock(&mouse.r.l);
  167. if(mouse.open){
  168. unlock(&mouse.r.l);
  169. error(Einuse);
  170. }
  171. mouse.open = 1;
  172. mouse.r.ref++;
  173. mouse.lastresize = mouse.resize;
  174. unlock(&mouse.r.l);
  175. break;
  176. case Qmousein:
  177. if(!iseve())
  178. error(Eperm);
  179. break;
  180. default:
  181. incref(&mouse.r);
  182. }
  183. c->mode = openmode(omode);
  184. c->flag |= COPEN;
  185. c->offset = 0;
  186. return c;
  187. }
  188. static void
  189. mousecreate(Chan *c, char *j, int i, int u)
  190. {
  191. error(Eperm);
  192. }
  193. static void
  194. mouseclose(Chan *c)
  195. {
  196. if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
  197. if(c->qid.path == Qmousein)
  198. return;
  199. lock(&mouse.r.l);
  200. if(c->qid.path == Qmouse)
  201. mouse.open = 0;
  202. if(--mouse.r.ref == 0){
  203. cursoroff(1);
  204. curs = arrow;
  205. Cursortocursor(&arrow);
  206. cursoron(1);
  207. }
  208. unlock(&mouse.r.l);
  209. }
  210. }
  211. static int32_t
  212. mouseread(Chan *c, void *va, int32_t n, int64_t off)
  213. {
  214. Proc *up = externup();
  215. char buf[1+4*12+1];
  216. unsigned char *p;
  217. uint32_t offset = off;
  218. Mousestate m;
  219. int b;
  220. p = va;
  221. switch((uint32_t)c->qid.path){
  222. case Qdir:
  223. return devdirread(c, va, n, mousedir, nelem(mousedir), mousedevgen);
  224. case Qcursor:
  225. if(offset != 0)
  226. return 0;
  227. if(n < 2*4+2*2*16)
  228. error(Eshort);
  229. n = 2*4+2*2*16;
  230. lock(&cursor.l);
  231. BPLONG(p+0, curs.offset.x);
  232. BPLONG(p+4, curs.offset.y);
  233. memmove(p+8, curs.clr, 2*16);
  234. memmove(p+40, curs.set, 2*16);
  235. unlock(&cursor.l);
  236. return n;
  237. case Qmouse:
  238. while(mousechanged(0) == 0)
  239. sleep(&mouse.rend, mousechanged, 0);
  240. mouse.qfull = 0;
  241. mousetime = seconds();
  242. /*
  243. * No lock of the indices is necessary here, because ri is only
  244. * updated by us, and there is only one mouse reader
  245. * at a time. I suppose that more than one process
  246. * could try to read the fd at one time, but such behavior
  247. * is degenerate and already violates the calling
  248. * conventions for sleep above.
  249. */
  250. if(mouse.ri != mouse.wi) {
  251. m = mouse.queue[mouse.ri];
  252. if(++mouse.ri == nelem(mouse.queue))
  253. mouse.ri = 0;
  254. } else {
  255. while(!canlock(&cursor.l))
  256. tsleep(&up->sleep, return0, 0, TK2MS(1));
  257. m = mouse.Mousestate;
  258. unlock(&cursor.l);
  259. }
  260. b = buttonmap[m.buttons&7];
  261. /* put buttons 4 and 5 back in */
  262. b |= m.buttons & (3<<3);
  263. if(scrollswap){
  264. if (b == 8)
  265. b = 16;
  266. else if (b == 16)
  267. b = 8;
  268. }
  269. snprint(buf, sizeof buf, "m%11d %11d %11d %11lu ",
  270. m.xy.x, m.xy.y,
  271. b,
  272. m.msec);
  273. mouse.lastcounter = m.counter;
  274. if(n > 1+4*12)
  275. n = 1+4*12;
  276. if(mouse.lastresize != mouse.resize){
  277. mouse.lastresize = mouse.resize;
  278. buf[0] = 'r';
  279. }
  280. memmove(va, buf, n);
  281. return n;
  282. }
  283. return 0;
  284. }
  285. static void
  286. setbuttonmap(char* map)
  287. {
  288. int i, x, one, two, three;
  289. one = two = three = 0;
  290. for(i = 0; i < 3; i++){
  291. if(map[i] == 0)
  292. error(Ebadarg);
  293. if(map[i] == '1'){
  294. if(one)
  295. error(Ebadarg);
  296. one = 1<<i;
  297. }
  298. else if(map[i] == '2'){
  299. if(two)
  300. error(Ebadarg);
  301. two = 1<<i;
  302. }
  303. else if(map[i] == '3'){
  304. if(three)
  305. error(Ebadarg);
  306. three = 1<<i;
  307. }
  308. else
  309. error(Ebadarg);
  310. }
  311. if(map[i])
  312. error(Ebadarg);
  313. memset(buttonmap, 0, 8);
  314. for(i = 0; i < 8; i++){
  315. x = 0;
  316. if(i & 1)
  317. x |= one;
  318. if(i & 2)
  319. x |= two;
  320. if(i & 4)
  321. x |= three;
  322. buttonmap[x] = i;
  323. }
  324. }
  325. static int32_t
  326. mousewrite(Chan *c, void *va, int32_t n, int64_t r)
  327. {
  328. Proc *up = externup();
  329. char *p;
  330. Point pt;
  331. Cmdbuf *cb;
  332. Cmdtab *ct;
  333. char buf[64];
  334. int b, msec;
  335. p = va;
  336. switch((uint32_t)c->qid.path){
  337. case Qdir:
  338. error(Eisdir);
  339. case Qcursor:
  340. cursoroff(1);
  341. if(n < 2*4+2*2*16){
  342. curs = arrow;
  343. Cursortocursor(&arrow);
  344. }else{
  345. n = 2*4+2*2*16;
  346. curs.offset.x = BGLONG(p+0);
  347. curs.offset.y = BGLONG(p+4);
  348. memmove(curs.clr, p+8, 2*16);
  349. memmove(curs.set, p+40, 2*16);
  350. Cursortocursor(&curs);
  351. }
  352. qlock(&mouse.ql);
  353. mouse.redraw = 1;
  354. mouseclock();
  355. qunlock(&mouse.ql);
  356. cursoron(1);
  357. return n;
  358. case Qmousectl:
  359. cb = parsecmd(va, n);
  360. if(waserror()){
  361. free(cb);
  362. nexterror();
  363. }
  364. ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
  365. switch(ct->index){
  366. case CMswap:
  367. if(mouseswap)
  368. setbuttonmap("123");
  369. else
  370. setbuttonmap("321");
  371. mouseswap ^= 1;
  372. break;
  373. case CMscrollswap:
  374. scrollswap ^= 1;
  375. break;
  376. case CMbuttonmap:
  377. if(cb->nf == 1)
  378. setbuttonmap("123");
  379. else
  380. setbuttonmap(cb->f[1]);
  381. break;
  382. case CMwildcard:
  383. mousectl(cb);
  384. break;
  385. }
  386. free(cb);
  387. poperror();
  388. return n;
  389. case Qmousein:
  390. if(n > sizeof buf-1)
  391. n = sizeof buf -1;
  392. memmove(buf, va, n);
  393. buf[n] = 0;
  394. p = 0;
  395. pt.x = strtol(buf+1, &p, 0);
  396. if(p == 0)
  397. error(Eshort);
  398. pt.y = strtol(p, &p, 0);
  399. if(p == 0)
  400. error(Eshort);
  401. b = strtol(p, &p, 0);
  402. msec = strtol(p, &p, 0);
  403. if(msec == 0)
  404. msec = TK2MS(machp()->ticks);
  405. mousetrack(pt.x, pt.y, b, msec);
  406. return n;
  407. case Qmouse:
  408. if(n > sizeof buf-1)
  409. n = sizeof buf -1;
  410. memmove(buf, va, n);
  411. buf[n] = 0;
  412. p = 0;
  413. pt.x = strtoul(buf+1, &p, 0);
  414. if(p == 0)
  415. error(Eshort);
  416. pt.y = strtoul(p, 0, 0);
  417. qlock(&mouse.ql);
  418. if(ptinrect(pt, gscreen->r)){
  419. mouse.Mousestate.xy = pt;
  420. mouse.redraw = 1;
  421. mouse.track = 1;
  422. mouseclock();
  423. }
  424. qunlock(&mouse.ql);
  425. return n;
  426. }
  427. error(Egreg);
  428. return -1;
  429. }
  430. Dev mousedevtab = {
  431. .dc = 'm',
  432. .name = "mouse",
  433. .reset = mousereset,
  434. .init = mouseinit,
  435. .shutdown = devshutdown,
  436. .attach = mouseattach,
  437. .walk = mousewalk,
  438. .stat = mousestat,
  439. .open = mouseopen,
  440. .create = mousecreate,
  441. .close = mouseclose,
  442. .read = mouseread,
  443. .bread = devbread,
  444. .write = mousewrite,
  445. .bwrite = devbwrite,
  446. .remove = devremove,
  447. .wstat = devwstat,
  448. };
  449. void
  450. Cursortocursor(Cursor *c)
  451. {
  452. lock(&cursor.l);
  453. memmove(&cursor.c, c, sizeof(Cursor));
  454. setcursor(c);
  455. unlock(&cursor.l);
  456. }
  457. /*
  458. * called by the clock routine to redraw the cursor
  459. */
  460. static void
  461. mouseclock(void)
  462. {
  463. if(mouse.track){
  464. mousetrack(mouse.dx, mouse.dy, mouse.Mousestate.buttons, TK2MS(machp()->ticks));
  465. mouse.track = 0;
  466. mouse.dx = 0;
  467. mouse.dy = 0;
  468. }
  469. if(mouse.redraw && canlock(&cursor.l)){
  470. mouse.redraw = 0;
  471. cursoroff(0);
  472. mouse.redraw = cursoron(0);
  473. unlock(&cursor.l);
  474. }
  475. drawactive(0);
  476. }
  477. static int
  478. scale(int x)
  479. {
  480. int sign = 1;
  481. if(x < 0){
  482. sign = -1;
  483. x = -x;
  484. }
  485. switch(x){
  486. case 0:
  487. case 1:
  488. case 2:
  489. case 3:
  490. break;
  491. case 4:
  492. x = 6 + (mouse.acceleration>>2);
  493. break;
  494. case 5:
  495. x = 9 + (mouse.acceleration>>1);
  496. break;
  497. default:
  498. x *= mouse.maxacc;
  499. break;
  500. }
  501. return sign*x;
  502. }
  503. /*
  504. * called at interrupt level to update the structure and
  505. * awaken any waiting procs.
  506. */
  507. void
  508. mousetrack(int dx, int dy, int b, int msec)
  509. {
  510. int x, y, lastb;
  511. if(gscreen==nil)
  512. return;
  513. if(mouse.acceleration){
  514. dx = scale(dx);
  515. dy = scale(dy);
  516. }
  517. x = mouse.Mousestate.xy.x + dx;
  518. if(x < gscreen->clipr.min.x)
  519. x = gscreen->clipr.min.x;
  520. if(x >= gscreen->clipr.max.x)
  521. x = gscreen->clipr.max.x;
  522. y = mouse.Mousestate.xy.y + dy;
  523. if(y < gscreen->clipr.min.y)
  524. y = gscreen->clipr.min.y;
  525. if(y >= gscreen->clipr.max.y)
  526. y = gscreen->clipr.max.y;
  527. lastb = mouse.Mousestate.buttons;
  528. mouse.Mousestate.xy = Pt(x, y);
  529. mouse.Mousestate.buttons = b|kbdbuttons;
  530. mouse.redraw = 1;
  531. mouse.Mousestate.counter++;
  532. mouse.Mousestate.msec = msec;
  533. /*
  534. * if the queue fills, we discard the entire queue and don't
  535. * queue any more events until a reader polls the mouse.
  536. */
  537. if(!mouse.qfull && lastb != b) { /* add to ring */
  538. mouse.queue[mouse.wi] = mouse.Mousestate;
  539. if(++mouse.wi == nelem(mouse.queue))
  540. mouse.wi = 0;
  541. if(mouse.wi == mouse.ri)
  542. mouse.qfull = 1;
  543. }
  544. wakeup(&mouse.rend);
  545. drawactive(1);
  546. }
  547. /*
  548. * microsoft 3 button, 7 bit bytes
  549. *
  550. * byte 0 - 1 L R Y7 Y6 X7 X6
  551. * byte 1 - 0 X5 X4 X3 X2 X1 X0
  552. * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0
  553. * byte 3 - 0 M x x x x x (optional)
  554. *
  555. * shift & right button is the same as middle button (for 2 button mice)
  556. */
  557. int
  558. m3mouseputc(Queue *queue, int c)
  559. {
  560. static unsigned char msg[3];
  561. static int nb;
  562. static int middle;
  563. static unsigned char b[] = { 0, 4, 1, 5, 0, 2, 1, 3 };
  564. short x;
  565. int dx, dy, newbuttons;
  566. static uint32_t lasttick;
  567. uint32_t m;
  568. /* Resynchronize in stream with timing. */
  569. m = machp()->ticks;
  570. if(TK2SEC(m - lasttick) > 2)
  571. nb = 0;
  572. lasttick = m;
  573. if(nb==0){
  574. /*
  575. * an extra byte comes for middle button motion.
  576. * only two possible values for the extra byte.
  577. */
  578. if(c == 0x00 || c == 0x20){
  579. /* an extra byte gets sent for the middle button */
  580. middle = (c&0x20) ? 2 : 0;
  581. newbuttons = (mouse.Mousestate.buttons & ~2) | middle;
  582. mousetrack(0, 0, newbuttons, TK2MS(machp()->ticks));
  583. return 0;
  584. }
  585. }
  586. msg[nb] = c;
  587. if(++nb == 3){
  588. nb = 0;
  589. newbuttons = middle | b[((msg[0]>>4)&3) | (mouseshifted?4:0)];
  590. x = (msg[0]&0x3)<<14;
  591. dx = (x>>8) | msg[1];
  592. x = (msg[0]&0xc)<<12;
  593. dy = (x>>8) | msg[2];
  594. mousetrack(dx, dy, newbuttons, TK2MS(machp()->ticks));
  595. }
  596. return 0;
  597. }
  598. /*
  599. * microsoft intellimouse 3 buttons + scroll
  600. * byte 0 - 1 L R Y7 Y6 X7 X6
  601. * byte 1 - 0 X5 X4 X3 X2 X1 X0
  602. * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0
  603. * byte 3 - 0 0 M % % % %
  604. *
  605. * %: 0xf => U , 0x1 => D
  606. *
  607. * L: left
  608. * R: right
  609. * U: up
  610. * D: down
  611. */
  612. int
  613. m5mouseputc(Queue *queue, int c)
  614. {
  615. static unsigned char msg[8];
  616. static int nb;
  617. static uint32_t lasttick;
  618. uint32_t m;
  619. /* Resynchronize in stream with timing. */
  620. m = machp()->ticks;
  621. if(TK2SEC(m - lasttick) > 2)
  622. nb = 0;
  623. lasttick = m;
  624. msg[nb++] = c & 0x7f;
  625. if (nb == 4) {
  626. char dx,dy,newbuttons;
  627. dx = msg[1] | (msg[0] & 0x3) << 6;
  628. dy = msg[2] | (msg[0] & 0xc) << 4;
  629. newbuttons =
  630. (msg[0] & 0x10) >> (mouseshifted ? 3 : 2)
  631. | (msg[0] & 0x20) >> 5
  632. | ( msg[3] == 0x10 ? 0x02 :
  633. msg[3] == 0x0f ? ScrollUp :
  634. msg[3] == 0x01 ? ScrollDown : 0 );
  635. mousetrack(dx, dy, newbuttons, TK2MS(machp()->ticks));
  636. nb = 0;
  637. }
  638. return 0;
  639. }
  640. /*
  641. * Logitech 5 byte packed binary mouse format, 8 bit bytes
  642. *
  643. * shift & right button is the same as middle button (for 2 button mice)
  644. */
  645. int
  646. mouseputc(Queue *queue, int c)
  647. {
  648. static short msg[5];
  649. static int nb;
  650. static unsigned char b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 3, 3, 7};
  651. int dx, dy, newbuttons;
  652. static uint32_t lasttick;
  653. uint32_t m;
  654. /* Resynchronize in stream with timing. */
  655. m = machp()->ticks;
  656. if(TK2SEC(m - lasttick) > 2)
  657. nb = 0;
  658. lasttick = m;
  659. if((c&0xF0) == 0x80)
  660. nb=0;
  661. msg[nb] = c;
  662. if(c & 0x80)
  663. msg[nb] |= ~0xFF; /* sign extend */
  664. if(++nb == 5){
  665. newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)];
  666. dx = msg[1]+msg[3];
  667. dy = -(msg[2]+msg[4]);
  668. mousetrack(dx, dy, newbuttons, TK2MS(machp()->ticks));
  669. nb = 0;
  670. }
  671. return 0;
  672. }
  673. int
  674. mousechanged(void *v)
  675. {
  676. return mouse.lastcounter != mouse.Mousestate.counter ||
  677. mouse.lastresize != mouse.resize;
  678. }
  679. Point
  680. mousexy(void)
  681. {
  682. return mouse.Mousestate.xy;
  683. }
  684. void
  685. mouseaccelerate(int x)
  686. {
  687. mouse.acceleration = x;
  688. if(mouse.acceleration < 3)
  689. mouse.maxacc = 2;
  690. else
  691. mouse.maxacc = mouse.acceleration;
  692. }
  693. /*
  694. * notify reader that screen has been resized
  695. */
  696. void
  697. mouseresize(void)
  698. {
  699. mouse.resize++;
  700. wakeup(&mouse.rend);
  701. }