devmouse.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #include "lib9.h"
  2. #include "sys.h"
  3. #include "error.h"
  4. #include "libdraw/draw.h"
  5. #include "libmemdraw/memdraw.h"
  6. #include "screen.h"
  7. Mouseinfo mouse;
  8. Cursorinfo cursor;
  9. static int mousechanged(void*);
  10. enum{
  11. Qdir,
  12. Qcursor,
  13. Qmouse
  14. };
  15. Dirtab mousedir[]={
  16. "cursor", {Qcursor}, 0, 0666,
  17. "mouse", {Qmouse}, 0, 0666,
  18. };
  19. #define NMOUSE (sizeof(mousedir)/sizeof(Dirtab))
  20. void
  21. mousereset(void)
  22. {
  23. }
  24. void
  25. mouseinit(void)
  26. {
  27. }
  28. Chan*
  29. mouseattach(void *spec)
  30. {
  31. return devattach('m', spec);
  32. }
  33. Chan*
  34. mouseclone(Chan *c, Chan *nc)
  35. {
  36. return devclone(c, nc);
  37. }
  38. int
  39. mousewalk(Chan *c, char *name)
  40. {
  41. return devwalk(c, name, mousedir, NMOUSE, devgen);
  42. }
  43. void
  44. mousestat(Chan *c, char *db)
  45. {
  46. devstat(c, db, mousedir, NMOUSE, devgen);
  47. }
  48. Chan*
  49. mouseopen(Chan *c, int omode)
  50. {
  51. switch(c->qid.path){
  52. case CHDIR:
  53. if(omode != OREAD)
  54. error(Eperm);
  55. break;
  56. case Qmouse:
  57. lock(&mouse.lk);
  58. if(mouse.open){
  59. unlock(&mouse.lk);
  60. error(Einuse);
  61. }
  62. mouse.open = 1;
  63. unlock(&mouse.lk);
  64. break;
  65. }
  66. c->mode = openmode(omode);
  67. c->flag |= COPEN;
  68. c->offset = 0;
  69. return c;
  70. }
  71. void
  72. mousecreate(Chan *c, char *name, int mode, ulong perm)
  73. {
  74. USED(c);
  75. USED(name);
  76. USED(mode);
  77. USED(perm);
  78. error(Eperm);
  79. }
  80. void
  81. mouseremove(Chan *c)
  82. {
  83. USED(c);
  84. error(Eperm);
  85. }
  86. void
  87. mousewstat(Chan *c, char *s)
  88. {
  89. USED(c);
  90. USED(s);
  91. error(Eperm);
  92. }
  93. void
  94. mouseclose(Chan *c)
  95. {
  96. if(c->qid.path==CHDIR || !(c->flag&COPEN))
  97. return;
  98. switch(c->qid.path) {
  99. case Qmouse:
  100. lock(&mouse.lk);
  101. mouse.open = 0;
  102. unlock(&mouse.lk);
  103. cursorarrow();
  104. }
  105. }
  106. long
  107. mouseread(Chan *c, void *va, long n, ulong offset)
  108. {
  109. char buf[4*12+1];
  110. uchar *p;
  111. int i, nn;
  112. ulong msec;
  113. /* static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; */
  114. p = va;
  115. switch(c->qid.path){
  116. case CHDIR:
  117. return devdirread(c, va, n, mousedir, NMOUSE, devgen);
  118. case Qcursor:
  119. if(offset != 0)
  120. return 0;
  121. if(n < 2*4+2*2*16)
  122. error(Eshort);
  123. n = 2*4+2*2*16;
  124. lock(&cursor.lk);
  125. BPLONG(p+0, cursor.offset.x);
  126. BPLONG(p+4, cursor.offset.y);
  127. memmove(p+8, cursor.clr, 2*16);
  128. memmove(p+40, cursor.set, 2*16);
  129. unlock(&cursor.lk);
  130. return n;
  131. case Qmouse:
  132. while(mousechanged(0) == 0)
  133. rendsleep(&mouse.r, mousechanged, 0);
  134. lock(&screen.lk);
  135. if(screen.reshaped) {
  136. screen.reshaped = 0;
  137. sprint(buf, "t%11d %11d", 0, ticks());
  138. if(n > 1+2*12)
  139. n = 1+2*12;
  140. memmove(va, buf, n);
  141. unlock(&screen.lk);
  142. return n;
  143. }
  144. unlock(&screen.lk);
  145. lock(&mouse.lk);
  146. i = mouse.ri;
  147. nn = (mouse.wi + Mousequeue - i) % Mousequeue;
  148. if(nn < 1)
  149. panic("empty mouse queue");
  150. msec = ticks();
  151. while(nn > 1) {
  152. if(mouse.queue[i].msec + Mousewindow > msec)
  153. break;
  154. i = (i+1)%Mousequeue;
  155. nn--;
  156. }
  157. sprint(buf, "m%11d %11d %11d %11d",
  158. mouse.queue[i].xy.x,
  159. mouse.queue[i].xy.y,
  160. mouse.queue[i].buttons,
  161. mouse.queue[i].msec);
  162. mouse.ri = (i+1)%Mousequeue;
  163. unlock(&mouse.lk);
  164. if(n > 1+4*12)
  165. n = 1+4*12;
  166. memmove(va, buf, n);
  167. return n;
  168. }
  169. return 0;
  170. }
  171. Block*
  172. mousebread(Chan *c, long n, ulong offset)
  173. {
  174. return devbread(c, n, offset);
  175. }
  176. long
  177. mousewrite(Chan *c, void *va, long n, ulong offset)
  178. {
  179. char *p;
  180. Point pt;
  181. char buf[64];
  182. USED(offset);
  183. p = va;
  184. switch(c->qid.path){
  185. case CHDIR:
  186. error(Eisdir);
  187. case Qcursor:
  188. if(n < 2*4+2*2*16){
  189. cursorarrow();
  190. }else{
  191. n = 2*4+2*2*16;
  192. lock(&cursor.lk);
  193. cursor.offset.x = BGLONG(p+0);
  194. cursor.offset.y = BGLONG(p+4);
  195. memmove(cursor.clr, p+8, 2*16);
  196. memmove(cursor.set, p+40, 2*16);
  197. unlock(&cursor.lk);
  198. setcursor();
  199. }
  200. return n;
  201. case Qmouse:
  202. if(n > sizeof buf-1)
  203. n = sizeof buf -1;
  204. memmove(buf, va, n);
  205. buf[n] = 0;
  206. p = 0;
  207. pt.x = strtoul(buf+1, &p, 0);
  208. if(p == 0)
  209. error(Eshort);
  210. pt.y = strtoul(p, 0, 0);
  211. if(ptinrect(pt, gscreen->r))
  212. mouseset(pt);
  213. return n;
  214. }
  215. error(Egreg);
  216. return -1;
  217. }
  218. long
  219. mousebwrite(Chan *c, Block *bp, ulong offset)
  220. {
  221. return devbwrite(c, bp, offset);
  222. }
  223. int
  224. mousechanged(void *a)
  225. {
  226. USED(a);
  227. return mouse.ri != mouse.wi || screen.reshaped;
  228. }