wsys.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include "vnc.h"
  2. #include "vncv.h"
  3. #include <cursor.h>
  4. typedef struct Cursor Cursor;
  5. typedef struct Mouse Mouse;
  6. struct Mouse {
  7. int buttons;
  8. Point xy;
  9. };
  10. static void
  11. resize(Vnc *v, int first)
  12. {
  13. int fd;
  14. Point d;
  15. d = addpt(v->dim, Pt(2*Borderwidth, 2*Borderwidth));
  16. lockdisplay(display);
  17. if(getwindow(display, Refnone) < 0)
  18. sysfatal("internal error: can't get the window image");
  19. /*
  20. * limit the window to at most the vnc server's size
  21. */
  22. if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)){
  23. fd = open("/dev/wctl", OWRITE);
  24. if(fd >= 0){
  25. fprint(fd, "resize -dx %d -dy %d", d.x, d.y);
  26. close(fd);
  27. }
  28. }
  29. unlockdisplay(display);
  30. }
  31. static void
  32. eresized(void)
  33. {
  34. resize(vnc, 0);
  35. requestupdate(vnc, 0);
  36. }
  37. static Cursor dotcursor = {
  38. {-7, -7},
  39. {0x00, 0x00,
  40. 0x00, 0x00,
  41. 0x00, 0x00,
  42. 0x00, 0x00,
  43. 0x03, 0xc0,
  44. 0x07, 0xe0,
  45. 0x0f, 0xf0,
  46. 0x0f, 0xf0,
  47. 0x0f, 0xf0,
  48. 0x07, 0xe0,
  49. 0x03, 0xc0,
  50. 0x00, 0x00,
  51. 0x00, 0x00,
  52. 0x00, 0x00,
  53. 0x00, 0x00,
  54. 0x00, 0x00, },
  55. {0x00, 0x00,
  56. 0x00, 0x00,
  57. 0x00, 0x00,
  58. 0x00, 0x00,
  59. 0x00, 0x00,
  60. 0x03, 0xc0,
  61. 0x07, 0xe0,
  62. 0x07, 0xe0,
  63. 0x07, 0xe0,
  64. 0x03, 0xc0,
  65. 0x00, 0x00,
  66. 0x00, 0x00,
  67. 0x00, 0x00,
  68. 0x00, 0x00,
  69. 0x00, 0x00,
  70. 0x00, 0x00, }
  71. };
  72. static void
  73. mouseevent(Vnc *v, Mouse m)
  74. {
  75. vnclock(v);
  76. vncwrchar(v, MMouse);
  77. vncwrchar(v, m.buttons);
  78. vncwrpoint(v, m.xy);
  79. vncflush(v);
  80. vncunlock(v);
  81. }
  82. void
  83. mousewarp(Point pt)
  84. {
  85. pt = addpt(pt, screen->r.min);
  86. if(fprint(mousefd, "m%d %d", pt.x, pt.y) < 0)
  87. fprint(2, "mousefd write: %r\n");
  88. }
  89. void
  90. initmouse(void)
  91. {
  92. char buf[1024];
  93. snprint(buf, sizeof buf, "%s/mouse", display->devdir);
  94. if((mousefd = open(buf, ORDWR)) < 0)
  95. sysfatal("open %s: %r", buf);
  96. }
  97. enum {
  98. EventSize = 1+4*12
  99. };
  100. void
  101. readmouse(Vnc *v)
  102. {
  103. int cursorfd, len, n;
  104. char buf[10*EventSize], *start, *end;
  105. uchar curs[2*4+2*2*16];
  106. Cursor *cs;
  107. Mouse m;
  108. cs = &dotcursor;
  109. snprint(buf, sizeof buf, "%s/cursor", display->devdir);
  110. if((cursorfd = open(buf, OWRITE)) < 0)
  111. sysfatal("open %s: %r", buf);
  112. BPLONG(curs+0*4, cs->offset.x);
  113. BPLONG(curs+1*4, cs->offset.y);
  114. memmove(curs+2*4, cs->clr, 2*2*16);
  115. write(cursorfd, curs, sizeof curs);
  116. resize(v, 1);
  117. requestupdate(vnc, 0);
  118. start = end = buf;
  119. len = 0;
  120. for(;;){
  121. if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0)
  122. sysfatal("read mouse failed");
  123. len += n;
  124. end += n;
  125. while(len >= EventSize){
  126. if(*start == 'm'){
  127. m.xy.x = atoi(start+1);
  128. m.xy.y = atoi(start+1+12);
  129. m.buttons = atoi(start+1+2*12) & 0x1F;
  130. m.xy = subpt(m.xy, screen->r.min);
  131. if(ptinrect(m.xy, Rpt(ZP, v->dim))){
  132. mouseevent(v, m);
  133. /* send wheel button *release* */
  134. if ((m.buttons & 0x7) != m.buttons) {
  135. m.buttons &= 0x7;
  136. mouseevent(v, m);
  137. }
  138. }
  139. } else
  140. eresized();
  141. start += EventSize;
  142. len -= EventSize;
  143. }
  144. if(start - buf > sizeof(buf) - EventSize){
  145. memmove(buf, start, len);
  146. start = buf;
  147. end = start+len;
  148. }
  149. }
  150. }
  151. static int snarffd = -1;
  152. static ulong snarfvers;
  153. void
  154. writesnarf(Vnc *v, long n)
  155. {
  156. uchar buf[8192];
  157. long m;
  158. Biobuf *b;
  159. if((b = Bopen("/dev/snarf", OWRITE)) == nil){
  160. vncgobble(v, n);
  161. return;
  162. }
  163. while(n > 0){
  164. m = n;
  165. if(m > sizeof(buf))
  166. m = sizeof(buf);
  167. vncrdbytes(v, buf, m);
  168. n -= m;
  169. Bwrite(b, buf, m);
  170. }
  171. Bterm(b);
  172. snarfvers++;
  173. }
  174. char *
  175. getsnarf(int *sz)
  176. {
  177. char *snarf, *p;
  178. int n, c;
  179. *sz =0;
  180. n = 8192;
  181. p = snarf = malloc(n);
  182. seek(snarffd, 0, 0);
  183. while ((c = read(snarffd, p, n)) > 0){
  184. p += c;
  185. n -= c;
  186. *sz += c;
  187. if (n == 0){
  188. snarf = realloc(snarf, *sz + 8192);
  189. n = 8192;
  190. }
  191. }
  192. return snarf;
  193. }
  194. void
  195. checksnarf(Vnc *v)
  196. {
  197. Dir *dir;
  198. char *snarf;
  199. int len;
  200. if(snarffd < 0){
  201. snarffd = open("/dev/snarf", OREAD);
  202. if(snarffd < 0)
  203. sysfatal("can't open /dev/snarf: %r");
  204. }
  205. for(;;){
  206. sleep(1000);
  207. dir = dirstat("/dev/snarf");
  208. if(dir == nil) /* this happens under old drawterm */
  209. continue;
  210. if(dir->qid.vers > snarfvers){
  211. snarf = getsnarf(&len);
  212. vnclock(v);
  213. vncwrchar(v, MCCut);
  214. vncwrbytes(v, "pad", 3);
  215. vncwrlong(v, len);
  216. vncwrbytes(v, snarf, len);
  217. vncflush(v);
  218. vncunlock(v);
  219. free(snarf);
  220. snarfvers = dir->qid.vers;
  221. }
  222. free(dir);
  223. }
  224. }