window.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. typedef struct Memimage Memimage;
  13. static int screenid;
  14. Screen*
  15. allocscreen(Image *image, Image *fill, int public)
  16. {
  17. uint8_t *a;
  18. Screen *s;
  19. int id, try;
  20. Display *d;
  21. d = image->display;
  22. if(d != fill->display){
  23. werrstr("allocscreen: image and fill on different displays");
  24. return 0;
  25. }
  26. s = malloc(sizeof(Screen));
  27. if(s == 0)
  28. return 0;
  29. SET(id);
  30. for(try=0; try<25; try++){
  31. /* loop until find a free id */
  32. a = bufimage(d, 1+4+4+4+1);
  33. if(a == 0){
  34. free(s);
  35. return 0;
  36. }
  37. id = ++screenid;
  38. a[0] = 'A';
  39. BPLONG(a+1, id);
  40. BPLONG(a+5, image->id);
  41. BPLONG(a+9, fill->id);
  42. a[13] = public;
  43. if(flushimage(d, 0) != -1)
  44. break;
  45. }
  46. s->display = d;
  47. s->id = id;
  48. s->image = image;
  49. assert(s->image && s->image->chan != 0);
  50. s->fill = fill;
  51. return s;
  52. }
  53. Screen*
  54. publicscreen(Display *d, int id, uint32_t chan)
  55. {
  56. uint8_t *a;
  57. Screen *s;
  58. s = malloc(sizeof(Screen));
  59. if(s == 0)
  60. return 0;
  61. a = bufimage(d, 1+4+4);
  62. if(a == 0){
  63. Error:
  64. free(s);
  65. return 0;
  66. }
  67. a[0] = 'S';
  68. BPLONG(a+1, id);
  69. BPLONG(a+5, chan);
  70. if(flushimage(d, 0) < 0)
  71. goto Error;
  72. s->display = d;
  73. s->id = id;
  74. s->image = 0;
  75. s->fill = 0;
  76. return s;
  77. }
  78. int
  79. freescreen(Screen *s)
  80. {
  81. uint8_t *a;
  82. Display *d;
  83. if(s == 0)
  84. return 0;
  85. d = s->display;
  86. a = bufimage(d, 1+4);
  87. if(a == 0)
  88. return -1;
  89. a[0] = 'F';
  90. BPLONG(a+1, s->id);
  91. /*
  92. * flush(1) because screen is likely holding last reference to
  93. * window, and want it to disappear visually.
  94. */
  95. if(flushimage(d, 1) < 0)
  96. return -1;
  97. free(s);
  98. return 1;
  99. }
  100. Image*
  101. allocwindow(Screen *s, Rectangle r, int ref, uint32_t val)
  102. {
  103. return _allocwindow(nil, s, r, ref, val);
  104. }
  105. Image*
  106. _allocwindow(Image *i, Screen *s, Rectangle r, int ref, uint32_t val)
  107. {
  108. Display *d;
  109. d = s->display;
  110. i = _allocimage(i, d, r, d->screenimage->chan, 0, val, s->id, ref);
  111. if(i == 0)
  112. return 0;
  113. i->screen = s;
  114. i->next = s->display->windows;
  115. s->display->windows = i;
  116. return i;
  117. }
  118. static
  119. void
  120. topbottom(Image **w, int n, int top)
  121. {
  122. int i;
  123. uint8_t *b;
  124. Display *d;
  125. if(n < 0){
  126. Ridiculous:
  127. fprint(2, "top/bottom: ridiculous number of windows\n");
  128. return;
  129. }
  130. if(n == 0)
  131. return;
  132. if(n > (w[0]->display->bufsize-100)/4)
  133. goto Ridiculous;
  134. /*
  135. * this used to check that all images were on the same screen.
  136. * we don't know the screen associated with images we acquired
  137. * by name. instead, check that all images are on the same display.
  138. * the display will check that they are all on the same screen.
  139. */
  140. d = w[0]->display;
  141. for(i=1; i<n; i++)
  142. if(w[i]->display != d){
  143. fprint(2, "top/bottom: windows not on same screen\n");
  144. return;
  145. }
  146. if(n==0)
  147. return;
  148. b = bufimage(d, 1+1+2+4*n);
  149. b[0] = 't';
  150. b[1] = top;
  151. BPSHORT(b+2, n);
  152. for(i=0; i<n; i++)
  153. BPLONG(b+4+4*i, w[i]->id);
  154. }
  155. void
  156. bottomwindow(Image *w)
  157. {
  158. if(w->screen == 0)
  159. return;
  160. topbottom(&w, 1, 0);
  161. }
  162. void
  163. topwindow(Image *w)
  164. {
  165. if(w->screen == 0)
  166. return;
  167. topbottom(&w, 1, 1);
  168. }
  169. void
  170. bottomnwindows(Image **w, int n)
  171. {
  172. topbottom(w, n, 0);
  173. }
  174. void
  175. topnwindows(Image **w, int n)
  176. {
  177. topbottom(w, n, 1);
  178. }
  179. int
  180. originwindow(Image *w, Point log, Point scr)
  181. {
  182. uint8_t *b;
  183. Point delta;
  184. flushimage(w->display, 0);
  185. b = bufimage(w->display, 1+4+2*4+2*4);
  186. if(b == nil)
  187. return 0;
  188. b[0] = 'o';
  189. BPLONG(b+1, w->id);
  190. BPLONG(b+5, log.x);
  191. BPLONG(b+9, log.y);
  192. BPLONG(b+13, scr.x);
  193. BPLONG(b+17, scr.y);
  194. if(flushimage(w->display, 1) < 0)
  195. return -1;
  196. delta = subpt(log, w->r.min);
  197. w->r = rectaddpt(w->r, delta);
  198. w->clipr = rectaddpt(w->clipr, delta);
  199. return 1;
  200. }