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