devmouse.c 14 KB

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