winwatch.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <event.h>
  5. typedef struct Win Win;
  6. struct Win {
  7. int n;
  8. int dirty;
  9. char *label;
  10. Rectangle r;
  11. };
  12. Win *win;
  13. int nwin;
  14. int mwin;
  15. int onwin;
  16. int rows, cols;
  17. Font *font;
  18. Image *lightblue;
  19. enum {
  20. PAD = 3,
  21. MARGIN = 5
  22. };
  23. void*
  24. erealloc(void *v, ulong n)
  25. {
  26. v = realloc(v, n);
  27. if(v == nil)
  28. sysfatal("out of memory reallocating %lud", n);
  29. return v;
  30. }
  31. void*
  32. emalloc(ulong n)
  33. {
  34. void *v;
  35. v = malloc(n);
  36. if(v == nil)
  37. sysfatal("out of memory allocating %lud", n);
  38. memset(v, 0, n);
  39. return v;
  40. }
  41. char*
  42. estrdup(char *s)
  43. {
  44. int l;
  45. char *t;
  46. if (s == nil)
  47. return nil;
  48. l = strlen(s)+1;
  49. t = emalloc(l);
  50. memcpy(t, s, l);
  51. return t;
  52. }
  53. void
  54. refreshwin(void)
  55. {
  56. char label[128];
  57. int i, fd, lfd, n, nr, nw, m;
  58. Dir *pd;
  59. if((fd = open("/dev/wsys", OREAD)) < 0)
  60. return;
  61. nw = 0;
  62. /* i'd rather read one at a time but rio won't let me */
  63. while((nr=dirread(fd, &pd)) > 0){
  64. for(i=0; i<nr; i++){
  65. n = atoi(pd[i].name);
  66. sprint(label, "/dev/wsys/%d/label", n);
  67. if((lfd = open(label, OREAD)) < 0)
  68. continue;
  69. m = read(lfd, label, sizeof(label)-1);
  70. close(lfd);
  71. if(m < 0)
  72. continue;
  73. label[m] = '\0';
  74. if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){
  75. nw++;
  76. continue;
  77. }
  78. if(nw < nwin){
  79. free(win[nw].label);
  80. win[nw].label = nil;
  81. }
  82. if(nw >= mwin){
  83. mwin += 8;
  84. win = erealloc(win, mwin*sizeof(win[0]));
  85. }
  86. win[nw].n = n;
  87. win[nw].label = estrdup(label);
  88. win[nw].dirty = 1;
  89. win[nw].r = Rect(0,0,0,0);
  90. nw++;
  91. }
  92. free(pd);
  93. }
  94. while(nwin > nw)
  95. free(win[--nwin].label);
  96. nwin = nw;
  97. close(fd);
  98. }
  99. void
  100. drawnowin(int i)
  101. {
  102. Rectangle r;
  103. r = Rect(0,0,(Dx(screen->r)-2*MARGIN+PAD)/cols-PAD, font->height);
  104. r = rectaddpt(rectaddpt(r, Pt(MARGIN+(PAD+Dx(r))*(i/rows),
  105. MARGIN+(PAD+Dy(r))*(i%rows))), screen->r.min);
  106. draw(screen, insetrect(r, -1), lightblue, nil, ZP);
  107. }
  108. void
  109. drawwin(int i)
  110. {
  111. draw(screen, win[i].r, lightblue, nil, ZP);
  112. _string(screen, addpt(win[i].r.min, Pt(2,0)), display->black, ZP,
  113. font, win[i].label, nil, strlen(win[i].label),
  114. win[i].r, nil, ZP, SoverD);
  115. border(screen, win[i].r, 1, display->black, ZP);
  116. win[i].dirty = 0;
  117. }
  118. int
  119. geometry(void)
  120. {
  121. int i, ncols, z;
  122. Rectangle r;
  123. z = 0;
  124. rows = (Dy(screen->r)-2*MARGIN+PAD)/(font->height+PAD);
  125. if(rows*cols < nwin || rows*cols >= nwin*2){
  126. ncols = (nwin+rows-1)/rows;
  127. if(ncols != cols){
  128. cols = ncols;
  129. z = 1;
  130. }
  131. }
  132. r = Rect(0,0,(Dx(screen->r)-2*MARGIN+PAD)/cols-PAD, font->height);
  133. for(i=0; i<nwin; i++)
  134. win[i].r = rectaddpt(rectaddpt(r, Pt(MARGIN+(PAD+Dx(r))*(i/rows),
  135. MARGIN+(PAD+Dy(r))*(i%rows))), screen->r.min);
  136. return z;
  137. }
  138. void
  139. redraw(Image *screen, int all)
  140. {
  141. int i;
  142. all |= geometry();
  143. if(all)
  144. draw(screen, screen->r, lightblue, nil, ZP);
  145. for(i=0; i<nwin; i++)
  146. if(all || win[i].dirty)
  147. drawwin(i);
  148. if(!all)
  149. for(; i<onwin; i++)
  150. drawnowin(i);
  151. onwin = nwin;
  152. }
  153. void
  154. eresized(int new)
  155. {
  156. if(new && getwindow(display, Refmesg) < 0)
  157. fprint(2,"can't reattach to window");
  158. geometry();
  159. redraw(screen, 1);
  160. }
  161. void
  162. click(Mouse m)
  163. {
  164. int fd, i, j;
  165. char buf[128];
  166. if(m.buttons == 0 || (m.buttons & ~4))
  167. return;
  168. for(i=0; i<nwin; i++)
  169. if(ptinrect(m.xy, win[i].r))
  170. break;
  171. if(i == nwin)
  172. return;
  173. do
  174. m = emouse();
  175. while(m.buttons == 4);
  176. if(m.buttons != 0){
  177. do
  178. m = emouse();
  179. while(m.buttons);
  180. return;
  181. }
  182. for(j=0; j<nwin; j++)
  183. if(ptinrect(m.xy, win[j].r))
  184. break;
  185. if(j != i)
  186. return;
  187. sprint(buf, "/dev/wsys/%d/wctl", win[i].n);
  188. if((fd = open(buf, OWRITE)) < 0)
  189. return;
  190. write(fd, "unhide\n", 7);
  191. write(fd, "top\n", 4);
  192. write(fd, "current\n", 8);
  193. close(fd);
  194. }
  195. void
  196. usage(void)
  197. {
  198. fprint(2, "usage: winwatch [-f font]\n");
  199. exits("usage");
  200. }
  201. void
  202. main(int argc, char **argv)
  203. {
  204. char *fontname;
  205. int Etimer;
  206. Event e;
  207. fontname = "/lib/font/bit/lucidasans/unicode.8.font";
  208. ARGBEGIN{
  209. case 'f':
  210. fontname = EARGF(usage());
  211. break;
  212. }ARGEND
  213. if(argc)
  214. usage();
  215. initdraw(0, 0, "winwatch");
  216. lightblue = allocimagemix(display, DPalebluegreen, DWhite);
  217. if(lightblue == nil)
  218. sysfatal("allocimagemix: %r");
  219. if((font = openfont(display, fontname)) == nil)
  220. sysfatal("font '%s' not found", fontname);
  221. refreshwin();
  222. redraw(screen, 1);
  223. einit(Emouse|Ekeyboard);
  224. Etimer = etimer(0, 5000);
  225. for(;;){
  226. switch(eread(Emouse|Ekeyboard|Etimer, &e)){
  227. case Ekeyboard:
  228. if(e.kbdc==0x7F || e.kbdc=='q')
  229. exits(0);
  230. break;
  231. case Emouse:
  232. if(e.mouse.buttons)
  233. click(e.mouse);
  234. break;
  235. default: /* Etimer */
  236. refreshwin();
  237. redraw(screen, 0);
  238. break;
  239. }
  240. }
  241. }