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*
allocscreen(Image * image,Image * fill,int public)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*
publicscreen(Display * d,int id,ulong chan)52 publicscreen(Display *d, int id, ulong 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
freescreen(Screen * s)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*
allocwindow(Screen * s,Rectangle r,int ref,ulong val)104 allocwindow(Screen *s, Rectangle r, int ref, ulong val)
105 {
106 return _allocwindow(nil, s, r, ref, val);
107 }
108
109 Image*
_allocwindow(Image * i,Screen * s,Rectangle r,int ref,ulong val)110 _allocwindow(Image *i, Screen *s, Rectangle r, int ref, ulong 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
topbottom(Image ** w,int n,int top)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
bottomwindow(Image * w)165 bottomwindow(Image *w)
166 {
167 if(w->screen == 0)
168 return;
169 topbottom(&w, 1, 0);
170 }
171
172 void
topwindow(Image * w)173 topwindow(Image *w)
174 {
175 if(w->screen == 0)
176 return;
177 topbottom(&w, 1, 1);
178 }
179
180 void
bottomnwindows(Image ** w,int n)181 bottomnwindows(Image **w, int n)
182 {
183 topbottom(w, n, 0);
184 }
185
186 void
topnwindows(Image ** w,int n)187 topnwindows(Image **w, int n)
188 {
189 topbottom(w, n, 1);
190 }
191
192 int
originwindow(Image * w,Point log,Point scr)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 }
215