xref: /plan9/sys/src/libdraw/window.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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