]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/window.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / libdraw / window.c
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, 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
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, ulong val)
105 {
106         return _allocwindow(nil, s, r, ref, val);
107 }
108
109 Image*
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
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 }