event.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <cursor.h>
  5. #include <event.h>
  6. typedef struct Slave Slave;
  7. typedef struct Ebuf Ebuf;
  8. struct Slave
  9. {
  10. int pid;
  11. Ebuf *head; /* queue of messages for this descriptor */
  12. Ebuf *tail;
  13. int (*fn)(int, Event*, uchar*, int);
  14. };
  15. struct Ebuf
  16. {
  17. Ebuf *next;
  18. int n; /* number of bytes in buf */
  19. uchar buf[EMAXMSG];
  20. };
  21. static Slave eslave[MAXSLAVE];
  22. static int Skeyboard = -1;
  23. static int Smouse = -1;
  24. static int Stimer = -1;
  25. static int logfid;
  26. static int nslave;
  27. static int parentpid;
  28. static int epipe[2];
  29. static int eforkslave(ulong);
  30. static void extract(void);
  31. static void ekill(void);
  32. static int enote(void *, char *);
  33. static int mousefd;
  34. static int cursorfd;
  35. static
  36. Ebuf*
  37. ebread(Slave *s)
  38. {
  39. Ebuf *eb;
  40. Dir *d;
  41. ulong l;
  42. for(;;){
  43. d = dirfstat(epipe[0]);
  44. if(d == nil)
  45. drawerror(display, "events: eread stat error");
  46. l = d->length;
  47. free(d);
  48. if(s->head && l==0)
  49. break;
  50. extract();
  51. }
  52. eb = s->head;
  53. s->head = s->head->next;
  54. if(s->head == 0)
  55. s->tail = 0;
  56. return eb;
  57. }
  58. ulong
  59. event(Event *e)
  60. {
  61. return eread(~0UL, e);
  62. }
  63. ulong
  64. eread(ulong keys, Event *e)
  65. {
  66. Ebuf *eb;
  67. int i, id;
  68. if(keys == 0)
  69. return 0;
  70. for(;;){
  71. for(i=0; i<nslave; i++)
  72. if((keys & (1<<i)) && eslave[i].head){
  73. id = 1<<i;
  74. if(i == Smouse)
  75. e->mouse = emouse();
  76. else if(i == Skeyboard)
  77. e->kbdc = ekbd();
  78. else if(i == Stimer)
  79. eslave[i].head = 0;
  80. else{
  81. eb = ebread(&eslave[i]);
  82. e->n = eb->n;
  83. if(eslave[i].fn)
  84. id = (*eslave[i].fn)(id, e, eb->buf, eb->n);
  85. else
  86. memmove(e->data, eb->buf, eb->n);
  87. free(eb);
  88. }
  89. return id;
  90. }
  91. extract();
  92. }
  93. }
  94. int
  95. ecanmouse(void)
  96. {
  97. if(Smouse < 0)
  98. drawerror(display, "events: mouse not initialized");
  99. return ecanread(Emouse);
  100. }
  101. int
  102. ecankbd(void)
  103. {
  104. if(Skeyboard < 0)
  105. drawerror(display, "events: keyboard not initialzed");
  106. return ecanread(Ekeyboard);
  107. }
  108. int
  109. ecanread(ulong keys)
  110. {
  111. Dir *d;
  112. int i;
  113. ulong l;
  114. for(;;){
  115. for(i=0; i<nslave; i++)
  116. if((keys & (1<<i)) && eslave[i].head)
  117. return 1;
  118. d = dirfstat(epipe[0]);
  119. if(d == nil)
  120. drawerror(display, "events: ecanread stat error");
  121. l = d->length;
  122. free(d);
  123. if(l == 0)
  124. return 0;
  125. extract();
  126. }
  127. }
  128. ulong
  129. estartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int))
  130. {
  131. char buf[EMAXMSG+1];
  132. int i, r;
  133. if(fd < 0)
  134. drawerror(display, "events: bad file descriptor");
  135. if(n <= 0 || n > EMAXMSG)
  136. n = EMAXMSG;
  137. i = eforkslave(key);
  138. if(i < MAXSLAVE){
  139. eslave[i].fn = fn;
  140. return 1<<i;
  141. }
  142. buf[0] = i - MAXSLAVE;
  143. while((r = read(fd, buf+1, n))>0)
  144. if(write(epipe[1], buf, r+1)!=r+1)
  145. break;
  146. buf[0] = MAXSLAVE;
  147. write(epipe[1], buf, 1);
  148. _exits(0);
  149. return 0;
  150. }
  151. ulong
  152. estart(ulong key, int fd, int n)
  153. {
  154. return estartfn(key, fd, n, nil);
  155. }
  156. ulong
  157. etimer(ulong key, int n)
  158. {
  159. char t[2];
  160. if(Stimer != -1)
  161. drawerror(display, "events: timer started twice");
  162. Stimer = eforkslave(key);
  163. if(Stimer < MAXSLAVE)
  164. return 1<<Stimer;
  165. if(n <= 0)
  166. n = 1000;
  167. t[0] = t[1] = Stimer - MAXSLAVE;
  168. do
  169. sleep(n);
  170. while(write(epipe[1], t, 2) == 2);
  171. t[0] = MAXSLAVE;
  172. write(epipe[1], t, 1);
  173. _exits(0);
  174. return 0;
  175. }
  176. static void
  177. ekeyslave(int fd)
  178. {
  179. Rune r;
  180. char t[3], k[10];
  181. int kr, kn, w;
  182. if(eforkslave(Ekeyboard) < MAXSLAVE)
  183. return;
  184. kn = 0;
  185. t[0] = Skeyboard;
  186. for(;;){
  187. while(!fullrune(k, kn)){
  188. kr = read(fd, k+kn, sizeof k - kn);
  189. if(kr <= 0)
  190. goto breakout;
  191. kn += kr;
  192. }
  193. w = chartorune(&r, k);
  194. kn -= w;
  195. memmove(k, &k[w], kn);
  196. t[1] = r;
  197. t[2] = r>>8;
  198. if(write(epipe[1], t, 3) != 3)
  199. break;
  200. }
  201. breakout:;
  202. t[0] = MAXSLAVE;
  203. write(epipe[1], t, 1);
  204. _exits(0);
  205. }
  206. void
  207. einit(ulong keys)
  208. {
  209. int ctl, fd;
  210. char buf[256];
  211. parentpid = getpid();
  212. if(pipe(epipe) < 0)
  213. drawerror(display, "events: einit pipe");
  214. atexit(ekill);
  215. atnotify(enote, 1);
  216. snprint(buf, sizeof buf, "%s/mouse", display->devdir);
  217. mousefd = open(buf, ORDWR|OCEXEC);
  218. if(mousefd < 0)
  219. drawerror(display, "einit: can't open mouse\n");
  220. snprint(buf, sizeof buf, "%s/cursor", display->devdir);
  221. cursorfd = open(buf, ORDWR|OCEXEC);
  222. if(cursorfd < 0)
  223. drawerror(display, "einit: can't open cursor\n");
  224. if(keys&Ekeyboard){
  225. snprint(buf, sizeof buf, "%s/cons", display->devdir);
  226. fd = open(buf, OREAD);
  227. if(fd < 0)
  228. drawerror(display, "events: can't open console");
  229. snprint(buf, sizeof buf, "%s/consctl", display->devdir);
  230. ctl = open("/dev/consctl", OWRITE|OCEXEC);
  231. if(ctl < 0)
  232. drawerror(display, "events: can't open consctl");
  233. write(ctl, "rawon", 5);
  234. for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)
  235. ;
  236. ekeyslave(fd);
  237. }
  238. if(keys&Emouse){
  239. estart(Emouse, mousefd, 1+4*12);
  240. for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)
  241. ;
  242. }
  243. }
  244. static void
  245. extract(void)
  246. {
  247. Slave *s;
  248. Ebuf *eb;
  249. int i, n;
  250. uchar ebuf[EMAXMSG+1];
  251. /* avoid generating a message if there's nothing to show. */
  252. /* this test isn't perfect, though; could do flushimage(display, 0) then call extract */
  253. /* also: make sure we don't interfere if we're multiprocessing the display */
  254. if(display->locking){
  255. /* if locking is being done by program, this means it can't depend on automatic flush in emouse() etc. */
  256. if(canqlock(&display->qlock)){
  257. if(display->bufp > display->buf)
  258. flushimage(display, 1);
  259. unlockdisplay(display);
  260. }
  261. }else
  262. if(display->bufp > display->buf)
  263. flushimage(display, 1);
  264. loop:
  265. if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0
  266. || ebuf[0] >= MAXSLAVE)
  267. drawerror(display, "eof on event pipe");
  268. if(n == 0)
  269. goto loop;
  270. i = ebuf[0];
  271. if(i >= nslave || n <= 1)
  272. drawerror(display, "events: protocol error: short read");
  273. s = &eslave[i];
  274. if(i == Stimer){
  275. s->head = (Ebuf *)1;
  276. return;
  277. }
  278. if(i == Skeyboard && n != 3)
  279. drawerror(display, "events: protocol error: keyboard");
  280. if(i == Smouse){
  281. if(n < 1+1+2*12)
  282. drawerror(display, "events: protocol error: mouse");
  283. if(ebuf[1] == 'r')
  284. eresized(1);
  285. /* squash extraneous mouse events */
  286. if((eb=s->tail) && memcmp(eb->buf+1+2*12, ebuf+1+1+2*12, 12)==0){
  287. memmove(eb->buf, &ebuf[1], n - 1);
  288. return;
  289. }
  290. }
  291. /* try to save space by only allocating as much buffer as we need */
  292. eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1);
  293. if(eb == 0)
  294. drawerror(display, "events: protocol error 4");
  295. eb->n = n - 1;
  296. memmove(eb->buf, &ebuf[1], n - 1);
  297. eb->next = 0;
  298. if(s->head)
  299. s->tail = s->tail->next = eb;
  300. else
  301. s->head = s->tail = eb;
  302. }
  303. static int
  304. eforkslave(ulong key)
  305. {
  306. int i, pid;
  307. for(i=0; i<MAXSLAVE; i++)
  308. if((key & ~(1<<i)) == 0 && eslave[i].pid == 0){
  309. if(nslave <= i)
  310. nslave = i + 1;
  311. /*
  312. * share the file descriptors so the last child
  313. * out closes all connections to the window server.
  314. */
  315. switch(pid = rfork(RFPROC)){
  316. case 0:
  317. return MAXSLAVE+i;
  318. case -1:
  319. fprint(2, "events: fork error\n");
  320. exits("fork");
  321. }
  322. eslave[i].pid = pid;
  323. eslave[i].head = eslave[i].tail = 0;
  324. return i;
  325. }
  326. drawerror(display, "events: bad slave assignment");
  327. return 0;
  328. }
  329. static int
  330. enote(void *v, char *s)
  331. {
  332. char t[1];
  333. int i, pid;
  334. USED(v, s);
  335. pid = getpid();
  336. if(pid != parentpid){
  337. for(i=0; i<nslave; i++){
  338. if(pid == eslave[i].pid){
  339. t[0] = MAXSLAVE;
  340. write(epipe[1], t, 1);
  341. break;
  342. }
  343. }
  344. return 0;
  345. }
  346. close(epipe[0]);
  347. epipe[0] = -1;
  348. close(epipe[1]);
  349. epipe[1] = -1;
  350. for(i=0; i<nslave; i++){
  351. if(pid == eslave[i].pid)
  352. continue; /* don't kill myself */
  353. postnote(PNPROC, eslave[i].pid, "die");
  354. }
  355. return 0;
  356. }
  357. static void
  358. ekill(void)
  359. {
  360. enote(0, 0);
  361. }
  362. Mouse
  363. emouse(void)
  364. {
  365. Mouse m;
  366. Ebuf *eb;
  367. static but[2];
  368. int b;
  369. if(Smouse < 0)
  370. drawerror(display, "events: mouse not initialized");
  371. eb = ebread(&eslave[Smouse]);
  372. m.xy.x = atoi((char*)eb->buf+1+0*12);
  373. m.xy.y = atoi((char*)eb->buf+1+1*12);
  374. b = atoi((char*)eb->buf+1+2*12);
  375. m.buttons = b;
  376. m.msec = atoi((char*)eb->buf+1+3*12);
  377. if (logfid)
  378. fprint(logfid, "b: %d xy: %P\n", m.buttons, m.xy);
  379. free(eb);
  380. return m;
  381. }
  382. int
  383. ekbd(void)
  384. {
  385. Ebuf *eb;
  386. int c;
  387. if(Skeyboard < 0)
  388. drawerror(display, "events: keyboard not initialzed");
  389. eb = ebread(&eslave[Skeyboard]);
  390. c = eb->buf[0] + (eb->buf[1]<<8);
  391. free(eb);
  392. return c;
  393. }
  394. void
  395. emoveto(Point pt)
  396. {
  397. char buf[2*12+2];
  398. int n;
  399. n = sprint(buf, "m%d %d", pt.x, pt.y);
  400. write(mousefd, buf, n);
  401. }
  402. void
  403. esetcursor(Cursor *c)
  404. {
  405. uchar curs[2*4+2*2*16];
  406. if(c == 0)
  407. write(cursorfd, curs, 0);
  408. else{
  409. BPLONG(curs+0*4, c->offset.x);
  410. BPLONG(curs+1*4, c->offset.y);
  411. memmove(curs+2*4, c->clr, 2*2*16);
  412. write(cursorfd, curs, sizeof curs);
  413. }
  414. }
  415. int
  416. ereadmouse(Mouse *m)
  417. {
  418. int n;
  419. char buf[128];
  420. do{
  421. n = read(mousefd, buf, sizeof(buf));
  422. if(n < 0) /* probably interrupted */
  423. return -1;
  424. n = eatomouse(m, buf, n);
  425. }while(n == 0);
  426. return n;
  427. }
  428. int
  429. eatomouse(Mouse *m, char *buf, int n)
  430. {
  431. if(n != 1+4*12){
  432. werrstr("atomouse: bad count");
  433. return -1;
  434. }
  435. if(buf[0] == 'r')
  436. eresized(1);
  437. m->xy.x = atoi(buf+1+0*12);
  438. m->xy.y = atoi(buf+1+1*12);
  439. m->buttons = atoi(buf+1+2*12);
  440. m->msec = atoi(buf+1+3*12);
  441. return n;
  442. }