Blob


1 /*
2 * Window system protocol server.
3 */
5 #include <u.h>
6 #include <libc.h>
7 #include "cocoa-thread.h"
8 #include <draw.h>
9 #include <memdraw.h>
10 #include <keyboard.h>
11 #include <mouse.h>
12 #include <cursor.h>
13 #include <drawfcall.h>
14 #include "cocoa-screen.h"
15 #include "devdraw.h"
17 typedef struct Kbdbuf Kbdbuf;
18 typedef struct Mousebuf Mousebuf;
19 typedef struct Fdbuf Fdbuf;
20 typedef struct Tagbuf Tagbuf;
22 struct Kbdbuf
23 {
24 Rune r[32];
25 int ri;
26 int wi;
27 int stall;
28 };
30 struct Mousebuf
31 {
32 Mouse m[32];
33 Mouse last;
34 int ri;
35 int wi;
36 int stall;
37 };
39 struct Tagbuf
40 {
41 int t[32];
42 int ri;
43 int wi;
44 };
46 Kbdbuf kbd;
47 Mousebuf mouse;
48 Tagbuf kbdtags;
49 Tagbuf mousetags;
51 void runmsg(Wsysmsg*);
52 void replymsg(Wsysmsg*);
53 void matchkbd(void);
54 void matchmouse(void);
57 QLock lk;
58 void
59 zlock(void)
60 {
61 qlock(&lk);
62 }
64 void
65 zunlock(void)
66 {
67 qunlock(&lk);
68 }
70 int trace = 0;
72 void
73 servep9p(void)
74 {
75 uchar buf[4], *mbuf;
76 int nmbuf, n, nn;
77 Wsysmsg m;
79 fmtinstall('W', drawfcallfmt);
81 mbuf = nil;
82 nmbuf = 0;
83 while((n = read(3, buf, 4)) == 4){
84 GET(buf, n);
85 if(n > nmbuf){
86 free(mbuf);
87 mbuf = malloc(4+n);
88 if(mbuf == nil)
89 sysfatal("malloc: %r");
90 nmbuf = n;
91 }
92 memmove(mbuf, buf, 4);
93 nn = readn(3, mbuf+4, n-4);
94 if(nn != n-4)
95 sysfatal("eof during message");
97 /* pick off messages one by one */
98 if(convM2W(mbuf, nn+4, &m) <= 0)
99 sysfatal("cannot convert message");
100 if(trace) fprint(2, "<- %W\n", &m);
101 runmsg(&m);
105 void
106 replyerror(Wsysmsg *m)
108 char err[256];
110 rerrstr(err, sizeof err);
111 m->type = Rerror;
112 m->error = err;
113 replymsg(m);
116 /*
117 * Handle a single wsysmsg.
118 * Might queue for later (kbd, mouse read)
119 */
120 void
121 runmsg(Wsysmsg *m)
123 static uchar buf[65536];
124 int n;
125 Memimage *i;
127 switch(m->type){
128 case Tinit:
129 memimageinit();
130 i = attachscreen(m->label, m->winsize);
131 _initdisplaymemimage(i);
132 replymsg(m);
133 break;
135 case Trdmouse:
136 zlock();
137 mousetags.t[mousetags.wi++] = m->tag;
138 if(mousetags.wi == nelem(mousetags.t))
139 mousetags.wi = 0;
140 if(mousetags.wi == mousetags.ri)
141 sysfatal("too many queued mouse reads");
142 mouse.stall = 0;
143 matchmouse();
144 zunlock();
145 break;
147 case Trdkbd:
148 zlock();
149 kbdtags.t[kbdtags.wi++] = m->tag;
150 if(kbdtags.wi == nelem(kbdtags.t))
151 kbdtags.wi = 0;
152 if(kbdtags.wi == kbdtags.ri)
153 sysfatal("too many queued keyboard reads");
154 kbd.stall = 0;
155 matchkbd();
156 zunlock();
157 break;
159 case Tmoveto:
160 setmouse(m->mouse.xy);
161 replymsg(m);
162 break;
164 case Tcursor:
165 if(m->arrowcursor)
166 setcursor(nil);
167 else
168 setcursor(&m->cursor);
169 replymsg(m);
170 break;
172 case Tbouncemouse:
173 // _xbouncemouse(&m->mouse);
174 replymsg(m);
175 break;
177 case Tlabel:
178 kicklabel(m->label);
179 replymsg(m);
180 break;
182 case Trdsnarf:
183 m->snarf = getsnarf();
184 replymsg(m);
185 free(m->snarf);
186 break;
188 case Twrsnarf:
189 putsnarf(m->snarf);
190 replymsg(m);
191 break;
193 case Trddraw:
194 n = m->count;
195 if(n > sizeof buf)
196 n = sizeof buf;
197 n = _drawmsgread(buf, n);
198 if(n < 0)
199 replyerror(m);
200 else{
201 m->count = n;
202 m->data = buf;
203 replymsg(m);
205 break;
207 case Twrdraw:
208 if(_drawmsgwrite(m->data, m->count) < 0)
209 replyerror(m);
210 else
211 replymsg(m);
212 break;
214 case Ttop:
215 topwin();
216 replymsg(m);
217 break;
219 case Tresize:
220 // _xresizewindow(m->rect);
221 replymsg(m);
222 break;
226 /*
227 * Reply to m.
228 */
229 QLock replylock;
230 void
231 replymsg(Wsysmsg *m)
233 int n;
234 static uchar *mbuf;
235 static int nmbuf;
237 /* T -> R msg */
238 if(m->type%2 == 0)
239 m->type++;
241 if(trace) fprint(2, "-> %W\n", m);
242 /* copy to output buffer */
243 n = sizeW2M(m);
245 qlock(&replylock);
246 if(n > nmbuf){
247 free(mbuf);
248 mbuf = malloc(n);
249 if(mbuf == nil)
250 sysfatal("out of memory");
251 nmbuf = n;
253 convW2M(m, mbuf, n);
254 if(write(4, mbuf, n) != n)
255 sysfatal("write: %r");
256 qunlock(&replylock);
259 /*
260 * Match queued kbd reads with queued kbd characters.
261 */
262 void
263 matchkbd(void)
265 Wsysmsg m;
267 if(kbd.stall)
268 return;
269 while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){
270 m.type = Rrdkbd;
271 m.tag = kbdtags.t[kbdtags.ri++];
272 if(kbdtags.ri == nelem(kbdtags.t))
273 kbdtags.ri = 0;
274 m.rune = kbd.r[kbd.ri++];
275 if(kbd.ri == nelem(kbd.r))
276 kbd.ri = 0;
277 replymsg(&m);
281 /*
282 * Match queued mouse reads with queued mouse events.
283 */
284 void
285 matchmouse(void)
287 Wsysmsg m;
289 while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){
290 m.type = Rrdmouse;
291 m.tag = mousetags.t[mousetags.ri++];
292 if(mousetags.ri == nelem(mousetags.t))
293 mousetags.ri = 0;
294 m.mouse = mouse.m[mouse.ri];
295 m.resized = mouseresized;
296 /*
297 if(m.resized)
298 fprint(2, "sending resize\n");
299 */
300 mouseresized = 0;
301 mouse.ri++;
302 if(mouse.ri == nelem(mouse.m))
303 mouse.ri = 0;
304 replymsg(&m);
308 void
309 mousetrack(int x, int y, int b, uint ms)
311 Mouse *m;
313 if(x < mouserect.min.x)
314 x = mouserect.min.x;
315 if(x > mouserect.max.x)
316 x = mouserect.max.x;
317 if(y < mouserect.min.y)
318 y = mouserect.min.y;
319 if(y > mouserect.max.y)
320 y = mouserect.max.y;
322 zlock();
323 // If reader has stopped reading, don't bother.
324 // If reader is completely caught up, definitely queue.
325 // Otherwise, queue only button change events.
326 if(!mouse.stall)
327 if(mouse.wi == mouse.ri || mouse.last.buttons != b){
328 m = &mouse.last;
329 m->xy.x = x;
330 m->xy.y = y;
331 m->buttons = b;
332 m->msec = ms;
334 mouse.m[mouse.wi] = *m;
335 if(++mouse.wi == nelem(mouse.m))
336 mouse.wi = 0;
337 if(mouse.wi == mouse.ri){
338 mouse.stall = 1;
339 mouse.ri = 0;
340 mouse.wi = 1;
341 mouse.m[0] = *m;
343 matchmouse();
345 zunlock();
348 void
349 kputc(int c)
351 zlock();
352 kbd.r[kbd.wi++] = c;
353 if(kbd.wi == nelem(kbd.r))
354 kbd.wi = 0;
355 if(kbd.ri == kbd.wi)
356 kbd.stall = 1;
357 matchkbd();
358 zunlock();
361 static int alting;
363 void
364 abortcompose(void)
366 if(alting)
367 keystroke(Kalt);
370 void resizeimg(void);
372 void
373 keystroke(int c)
375 static Rune k[10];
376 static int nk;
377 int i;
379 if(c == Kalt){
380 alting = !alting;
381 nk = 0;
382 return;
384 if(c == Kcmd+'r') {
385 if(forcedpi)
386 forcedpi = 0;
387 else if(displaydpi >= 200)
388 forcedpi = 100;
389 else
390 forcedpi = 225;
391 resizeimg();
392 return;
394 if(!alting){
395 kputc(c);
396 return;
398 if(nk >= nelem(k)) // should not happen
399 nk = 0;
400 k[nk++] = c;
401 c = _latin1(k, nk);
402 if(c > 0){
403 alting = 0;
404 kputc(c);
405 nk = 0;
406 return;
408 if(c == -1){
409 alting = 0;
410 for(i=0; i<nk; i++)
411 kputc(k[i]);
412 nk = 0;
413 return;
415 // need more input
416 return;