mouse.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <cursor.h>
  6. #include <mouse.h>
  7. void
  8. moveto(Mousectl *m, Point pt)
  9. {
  10. fprint(m->mfd, "m%d %d", pt.x, pt.y);
  11. m->xy = pt;
  12. }
  13. void
  14. closemouse(Mousectl *mc)
  15. {
  16. if(mc == nil)
  17. return;
  18. postnote(PNPROC, mc->pid, "kill");
  19. do; while(nbrecv(mc->c, &mc->Mouse) > 0);
  20. close(mc->mfd);
  21. close(mc->cfd);
  22. free(mc->file);
  23. free(mc->c);
  24. free(mc->resizec);
  25. free(mc);
  26. }
  27. int
  28. readmouse(Mousectl *mc)
  29. {
  30. if(mc->image)
  31. flushimage(mc->image->display, 1);
  32. if(recv(mc->c, &mc->Mouse) < 0){
  33. fprint(2, "readmouse: %r\n");
  34. return -1;
  35. }
  36. return 0;
  37. }
  38. static
  39. void
  40. _ioproc(void *arg)
  41. {
  42. int n, nerr, one;
  43. char buf[1+5*12];
  44. Mouse m;
  45. Mousectl *mc;
  46. mc = arg;
  47. threadsetname("mouseproc");
  48. one = 1;
  49. memset(&m, 0, sizeof m);
  50. mc->pid = getpid();
  51. nerr = 0;
  52. for(;;){
  53. n = read(mc->mfd, buf, sizeof buf);
  54. if(n != 1+4*12){
  55. yield(); /* if error is due to exiting, we'll exit here */
  56. fprint(2, "mouse: bad count %d not 49: %r\n", n);
  57. if(n<0 || ++nerr>10)
  58. threadexits("read error");
  59. continue;
  60. }
  61. nerr = 0;
  62. switch(buf[0]){
  63. case 'r':
  64. send(mc->resizec, &one);
  65. /* fall through */
  66. case 'm':
  67. m.xy.x = atoi(buf+1+0*12);
  68. m.xy.y = atoi(buf+1+1*12);
  69. m.buttons = atoi(buf+1+2*12);
  70. m.msec = atoi(buf+1+3*12);
  71. send(mc->c, &m);
  72. /*
  73. * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
  74. * This means that programs should receive into mc->Mouse (see readmouse() above) if
  75. * they want full synchrony.
  76. */
  77. mc->Mouse = m;
  78. break;
  79. }
  80. }
  81. }
  82. Mousectl*
  83. initmouse(char *file, Image *i)
  84. {
  85. Mousectl *mc;
  86. char *t, *sl;
  87. mc = mallocz(sizeof(Mousectl), 1);
  88. if(file == nil)
  89. file = "/dev/mouse";
  90. mc->file = strdup(file);
  91. mc->mfd = open(file, ORDWR|OCEXEC);
  92. if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){
  93. bind("#m", "/dev", MAFTER);
  94. mc->mfd = open(file, ORDWR|OCEXEC);
  95. }
  96. if(mc->mfd < 0){
  97. free(mc);
  98. return nil;
  99. }
  100. t = malloc(strlen(file)+16);
  101. strcpy(t, file);
  102. sl = utfrrune(t, '/');
  103. if(sl)
  104. strcpy(sl, "/cursor");
  105. else
  106. strcpy(t, "/dev/cursor");
  107. mc->cfd = open(t, ORDWR|OCEXEC);
  108. free(t);
  109. mc->image = i;
  110. mc->c = chancreate(sizeof(Mouse), 0);
  111. mc->resizec = chancreate(sizeof(int), 2);
  112. proccreate(_ioproc, mc, 4096);
  113. return mc;
  114. }
  115. void
  116. setcursor(Mousectl *mc, Cursor *c)
  117. {
  118. char curs[2*4+2*2*16];
  119. if(c == nil)
  120. write(mc->cfd, curs, 0);
  121. else{
  122. BPLONG(curs+0*4, c->offset.x);
  123. BPLONG(curs+1*4, c->offset.y);
  124. memmove(curs+2*4, c->clr, 2*2*16);
  125. write(mc->cfd, curs, sizeof curs);
  126. }
  127. }