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