1 /*
2    Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3    All rights reserved.
4 
5 This file is part of x11vnc.
6 
7 x11vnc is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at
10 your option) any later version.
11 
12 x11vnc is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with x11vnc; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20 or see <http://www.gnu.org/licenses/>.
21 
22 In addition, as a special exception, Karl J. Runge
23 gives permission to link the code of its release of x11vnc with the
24 OpenSSL project's "OpenSSL" library (or with modified versions of it
25 that use the same license as the "OpenSSL" library), and distribute
26 the linked executables.  You must obey the GNU General Public License
27 in all respects for all of the code used other than "OpenSSL".  If you
28 modify this file, you may extend this exception to your version of the
29 file, but you are not obligated to do so.  If you do not wish to do
30 so, delete this exception statement from your version.
31 */
32 
33 /* -- macosx.c -- */
34 
35 #include "config.h"
36 #if (defined(__MACH__) && defined(__APPLE__) && defined(HAVE_MACOSX_NATIVE_DISPLAY))
37 
38 #define DOMAC 1
39 
40 #else
41 
42 #define DOMAC 0
43 
44 #endif
45 
46 #include "x11vnc.h"
47 #include "cleanup.h"
48 #include "scan.h"
49 #include "screen.h"
50 #include "pointer.h"
51 #include "allowed_input_t.h"
52 #include "keyboard.h"
53 #include "cursor.h"
54 #include "connections.h"
55 #include "macosxCG.h"
56 #include "macosxCGP.h"
57 #include "macosxCGS.h"
58 
59 void macosx_log(char *);
60 char *macosx_console_guess(char *str, int *fd);
61 void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client);
62 void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client);
63 char *macosx_get_fb_addr(void);
64 int macosx_get_cursor(void);
65 int macosx_get_cursor_pos(int *, int *);
66 void macosx_send_sel(char *, int);
67 void macosx_set_sel(char *, int);
68 int macosx_valid_window(Window, XWindowAttributes*);
69 
70 Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
71     Window **children_return, unsigned int *nchildren_return);
72 int macosx_get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h,
73     Window *frame, Window *win);
74 
75 void macosx_add_mapnotify(Window win, int level, int map);
76 void macosx_add_create(Window win, int level);
77 void macosx_add_destroy(Window win, int level);
78 void macosx_add_visnotify(Window win, int level, int obscured);
79 int macosx_checkevent(XEvent *ev);
80 
macosx_log(char * str)81 void macosx_log(char *str) {
82 	rfbLog(str);
83 }
84 
85 #if (! DOMAC)
86 
macosx_event_loop(void)87 void macosx_event_loop(void) {
88 	return;
89 }
macosx_console_guess(char * str,int * fd)90 char *macosx_console_guess(char *str, int *fd) {
91 	if (!str || !fd) {}
92 	return NULL;
93 }
macosx_key_command(rfbBool down,rfbKeySym keysym,rfbClientPtr client)94 void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
95 	if (!down || !keysym || !client) {}
96 	return;
97 }
macosx_pointer_command(int mask,int x,int y,rfbClientPtr client)98 void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) {
99 	if (!mask || !x || !y || !client) {}
100 	return;
101 }
macosx_get_fb_addr(void)102 char *macosx_get_fb_addr(void) {
103 	return NULL;
104 }
macosx_get_cursor(void)105 int macosx_get_cursor(void) {
106 	return 0;
107 }
macosx_get_cursor_pos(int * x,int * y)108 int macosx_get_cursor_pos(int *x, int *y) {
109 	if (!x || !y) {}
110 	return 0;
111 }
macosx_send_sel(char * str,int len)112 void macosx_send_sel(char * str, int len) {
113 	if (!str || !len) {}
114 	return;
115 }
macosx_set_sel(char * str,int len)116 void macosx_set_sel(char * str, int len) {
117 	if (!str || !len) {}
118 	return;
119 }
macosx_valid_window(Window w,XWindowAttributes * a)120 int macosx_valid_window(Window w, XWindowAttributes* a) {
121 	if (!w || !a) {}
122 	return 0;
123 }
macosx_xquerytree(Window w,Window * root_return,Window * parent_return,Window ** children_return,unsigned int * nchildren_return)124 Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
125     Window **children_return, unsigned int *nchildren_return) {
126 	if (!w || !root_return || !parent_return || !children_return || !nchildren_return) {}
127 	return (Status) 0;
128 }
macosx_add_mapnotify(Window win,int level,int map)129 void macosx_add_mapnotify(Window win, int level, int map) {
130 	if (!win || !level || !map) {}
131 	return;
132 }
macosx_add_create(Window win,int level)133 void macosx_add_create(Window win, int level) {
134 	if (!win || !level) {}
135 	return;
136 }
macosx_add_destroy(Window win,int level)137 void macosx_add_destroy(Window win, int level) {
138 	if (!win || !level) {}
139 	return;
140 }
macosx_add_visnotify(Window win,int level,int obscured)141 void macosx_add_visnotify(Window win, int level, int obscured) {
142 	if (!win || !level || !obscured) {}
143 	return;
144 }
145 
macosx_checkevent(XEvent * ev)146 int macosx_checkevent(XEvent *ev) {
147 	if (!ev) {}
148 	return 0;
149 }
150 
151 
152 #else
153 
macosx_event_loop(void)154 void macosx_event_loop(void) {
155 	macosxCG_event_loop();
156 }
157 
macosx_get_fb_addr(void)158 char *macosx_get_fb_addr(void) {
159 	macosxCG_init();
160 	return macosxCG_get_fb_addr();
161 }
162 
163 int macosx_opengl_get_width(void);
164 int macosx_opengl_get_height(void);
165 int macosx_opengl_get_bpp(void);
166 int macosx_opengl_get_bps(void);
167 int macosx_opengl_get_spp(void);
168 
macosx_console_guess(char * str,int * fd)169 char *macosx_console_guess(char *str, int *fd) {
170 	char *q, *in = strdup(str);
171 	char *atparms = NULL, *file = NULL;
172 
173 	macosxCG_init();
174 
175 	if (strstr(in, "console") != in) {
176 		rfbLog("console_guess: unrecognized console/fb format: %s\n", str);
177 		free(in);
178 		return NULL;
179 	}
180 
181 	*fd = -1;
182 
183 	q = strrchr(in, '@');
184 	if (q) {
185 		atparms = strdup(q+1);
186 		*q = '\0';
187 	}
188 	q = strrchr(in, ':');
189 	if (q) {
190 		file = strdup(q+1);
191 		*q = '\0';
192 	}
193 	if (! file || file[0] == '\0')  {
194 		file = strdup("/dev/null");
195 	}
196 	rfbLog("console_guess: file is %s\n", file);
197 
198 	if (! pipeinput_str) {
199 		pipeinput_str = strdup("MACOSX");
200 		initialize_pipeinput();
201 	}
202 
203 	if (! atparms) {
204 		int w, h, b, bps, dep;
205 		unsigned long rm = 0, gm = 0, bm = 0;
206 
207 		if (macosx_read_opengl) {
208 			w = macosx_opengl_get_width();
209 			h = macosx_opengl_get_height();
210 			b = macosx_opengl_get_bpp();
211 
212 			bps = macosx_opengl_get_bps();
213 			dep = macosx_opengl_get_spp() * bps;
214 
215 		} else {
216 			w = macosxCG_CGDisplayPixelsWide();
217 			h = macosxCG_CGDisplayPixelsHigh();
218 			b = macosxCG_CGDisplayBitsPerPixel();
219 
220 			bps = macosxCG_CGDisplayBitsPerSample();
221 			dep = macosxCG_CGDisplaySamplesPerPixel() * bps;
222 		}
223 
224 		rm = (1 << bps) - 1;
225 		gm = (1 << bps) - 1;
226 		bm = (1 << bps) - 1;
227 		rm = rm << 2 * bps;
228 		gm = gm << 1 * bps;
229 		bm = bm << 0 * bps;
230 
231 		if (b == 8 && rm == 0xff && gm == 0xff && bm == 0xff) {
232 			/* I don't believe it... */
233 			rm = 0x07;
234 			gm = 0x38;
235 			bm = 0xc0;
236 		}
237 
238 		/* @66666x66666x32:0xffffffff:... */
239 		atparms = (char *) malloc(200);
240 		sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx", w, h, b, rm, gm, bm);
241 	}
242 	if (atparms) {
243 		int gw, gh, gb;
244 		if (sscanf(atparms, "%dx%dx%d", &gw, &gh, &gb) == 3)  {
245 			fb_x = gw;
246 			fb_y = gh;
247 			fb_b = gb;
248 		}
249 	}
250 	if (! atparms) {
251 		rfbLog("console_guess: could not get @ parameters.\n");
252 		return NULL;
253 	}
254 
255 	q = (char *) malloc(strlen("map:macosx:") + strlen(file) + 1 + strlen(atparms) + 1);
256 	sprintf(q, "map:macosx:%s@%s", file, atparms);
257 	free(atparms);
258 	return q;
259 }
260 
261 Window macosx_click_frame = None;
262 
macosx_pointer_command(int mask,int x,int y,rfbClientPtr client)263 void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) {
264 	allowed_input_t input;
265 	static int last_mask = 0;
266 	int rc;
267 
268 	if (0) fprintf(stderr, "macosx_pointer_command: %d %d - %d\n", x, y, mask);
269 
270 	if (mask >= 0) {
271 		got_pointer_calls++;
272 	}
273 
274 	if (view_only) {
275 		return;
276 	}
277 
278 	get_allowed_input(client, &input);
279 
280 	if (! input.motion || ! input.button) {
281 		/* XXX fix me with last_x, last_y, etc. */
282 		return;
283 	}
284 
285 	if (mask >= 0) {
286 		got_user_input++;
287 		got_pointer_input++;
288 		last_pointer_client = client;
289 		last_pointer_time = time(NULL);
290 	}
291 	if (last_mask != mask) {
292 		if (0) fprintf(stderr, "about to inject mask change %d -> %d: %.4f\n", last_mask, mask, dnowx());
293 		if (mask) {
294 			int px, py, x, y, w, h;
295 			macosx_click_frame = None;
296 			if (!macosx_get_wm_frame_pos(&px, &py, &x, &y, &w, &h, &macosx_click_frame, NULL)) {
297 				macosx_click_frame = None;
298 			}
299 		}
300 	}
301 
302 	macosxCG_pointer_inject(mask, x, y);
303 
304 	if (cursor_x != x || cursor_y != y) {
305 		last_pointer_motion_time = dnow();
306 	}
307 
308 	cursor_x = x;
309 	cursor_y = y;
310 
311 	if (last_mask != mask) {
312 		last_pointer_click_time = dnow();
313 		if (ncache > 0) {
314 			/* XXX Y */
315 			int i;
316 if (0) fprintf(stderr, "about to get all windows:           %.4f\n", dnowx());
317 			for (i=0; i < 2; i++) {
318 				macosxCGS_get_all_windows();
319 				if (0) fprintf(stderr, "!");
320 				if (macosx_checkevent(NULL)) {
321 					break;
322 				}
323 			}
324 if (0) fprintf(stderr, "\ndone:                               %.4f\n", dnowx());
325 		}
326 	}
327 	last_mask = mask;
328 
329 	/* record the x, y position for the rfb screen as well. */
330 	cursor_position(x, y, client);
331 
332 	/* change the cursor shape if necessary */
333 	rc = set_cursor(x, y, get_which_cursor());
334 	cursor_changes += rc;
335 
336 	last_event = last_input = last_pointer_input = time(NULL);
337 }
338 
init_key_table(void)339 void init_key_table(void) {
340 	macosxCG_init_key_table();
341 }
342 
macosx_key_command(rfbBool down,rfbKeySym keysym,rfbClientPtr client)343 void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
344 	allowed_input_t input;
345 	if (debug_keyboard) fprintf(stderr, "macosx_key_command: %d %s\n", (int) keysym, down ? "down" : "up");
346 
347 	if (view_only) {
348 		return;
349 	}
350 	get_allowed_input(client, &input);
351 	if (! input.keystroke) {
352 		return;
353 	}
354 
355 	init_key_table();
356 	macosxCG_keysym_inject((int) down, (unsigned int) keysym);
357 }
358 
359 extern void macosxGCS_poll_pb(void);
360 
macosx_get_cursor_pos(int * x,int * y)361 int macosx_get_cursor_pos(int *x, int *y) {
362 	macosxCG_get_cursor_pos(x, y);
363 	if (nofb) {
364 		/* good time to poll the pasteboard */
365 		macosxGCS_poll_pb();
366 	}
367 	return 1;
368 }
369 
370 static char *cuttext = NULL;
371 static int cutlen = 0;
372 
macosx_send_sel(char * str,int len)373 void macosx_send_sel(char *str, int len) {
374 	if (screen && all_clients_initialized()) {
375 		if (cuttext) {
376 			int n = cutlen;
377 			if (len < n) {
378 				n = len;
379 			}
380 			if (!memcmp(str, cuttext, (size_t) n)) {
381 				/* the same text we set pasteboard to ... */
382 				return;
383 			}
384 		}
385 		if (debug_sel) {
386 			rfbLog("macosx_send_sel: %d\n", len);
387 		}
388 		rfbSendServerCutText(screen, str, len);
389 	}
390 }
391 
macosx_set_sel(char * str,int len)392 void macosx_set_sel(char *str, int len) {
393 	if (screen && all_clients_initialized()) {
394 		if (cutlen <= len) {
395 			if (cuttext) {
396 				free(cuttext);
397 			}
398 			cutlen = 2*(len+1);
399 			cuttext = (char *) calloc(cutlen, 1);
400 		}
401 		memcpy(cuttext, str, (size_t) len);
402 		cuttext[len] = '\0';
403 		if (debug_sel) {
404 			rfbLog("macosx_set_sel: %d\n", len);
405 		}
406 		macosxGCS_set_pasteboard(str, len);
407 	}
408 }
409 
macosx_get_cursor(void)410 int macosx_get_cursor(void) {
411 	return macosxCG_get_cursor();
412 }
413 
414 typedef struct evdat {
415 	int win;
416 	int map;
417 	int level;
418 	int vis;
419 	int type;
420 } evdat_t;
421 
422 #define MAX_EVENTS 1024
423 evdat_t mac_events[MAX_EVENTS];
424 int mac_events_ptr = 0;
425 int mac_events_last = 0;
426 
macosx_add_mapnotify(Window win,int level,int map)427 void macosx_add_mapnotify(Window win, int level, int map) {
428 	int i = mac_events_last++;
429 	mac_events[i].win = win;
430 	mac_events[i].level = level;
431 
432 	if (map) {
433 		mac_events[i].type = MapNotify;
434 	} else {
435 		mac_events[i].type = UnmapNotify;
436 	}
437 	mac_events[i].map = map;
438 	mac_events[i].vis = -1;
439 
440 	mac_events_last = mac_events_last % MAX_EVENTS;
441 
442 	return;
443 }
444 
macosx_add_create(Window win,int level)445 void macosx_add_create(Window win, int level) {
446 	int i = mac_events_last++;
447 	mac_events[i].win = win;
448 	mac_events[i].level = level;
449 
450 	mac_events[i].type = CreateNotify;
451 	mac_events[i].map = -1;
452 	mac_events[i].vis = -1;
453 
454 	mac_events_last = mac_events_last % MAX_EVENTS;
455 
456 	return;
457 }
458 
macosx_add_destroy(Window win,int level)459 void macosx_add_destroy(Window win, int level) {
460 	int i = mac_events_last++;
461 	mac_events[i].win = win;
462 	mac_events[i].level = level;
463 
464 	mac_events[i].type = DestroyNotify;
465 	mac_events[i].map = -1;
466 	mac_events[i].vis = -1;
467 
468 	mac_events_last = mac_events_last % MAX_EVENTS;
469 
470 	return;
471 }
472 
macosx_add_visnotify(Window win,int level,int obscured)473 void macosx_add_visnotify(Window win, int level, int obscured) {
474 	int i = mac_events_last++;
475 	mac_events[i].win = win;
476 	mac_events[i].level = level;
477 
478 	mac_events[i].type = VisibilityNotify;
479 	mac_events[i].map = -1;
480 
481 	mac_events[i].vis = 1;
482 	if (obscured == 0) {
483 		mac_events[i].vis = VisibilityUnobscured;
484 	} else if (obscured == 1) {
485 		mac_events[i].vis = VisibilityPartiallyObscured;
486 	} else if (obscured == 2) {
487 		mac_events[i].vis = VisibilityFullyObscured; 	/* NI */
488 	}
489 
490 	mac_events_last = mac_events_last % MAX_EVENTS;
491 
492 	return;
493 }
494 
macosx_checkevent(XEvent * ev)495 int macosx_checkevent(XEvent *ev) {
496 	int i = mac_events_ptr;
497 
498 	if (mac_events_ptr == mac_events_last) {
499 		return 0;
500 	}
501 	if (ev == NULL) {
502 		return mac_events[i].type;
503 	}
504 
505 	ev->xany.window = mac_events[i].win;
506 
507 	if (mac_events[i].type == CreateNotify) {
508 		ev->type = CreateNotify;
509 		ev->xany.window = rootwin;
510 		ev->xcreatewindow.window = mac_events[i].win;
511 	} else if (mac_events[i].type == DestroyNotify) {
512 		ev->type = DestroyNotify;
513 		ev->xdestroywindow.window = mac_events[i].win;
514 	} else if (mac_events[i].type == VisibilityNotify) {
515 		ev->type = VisibilityNotify;
516 		ev->xvisibility.state = mac_events[i].vis;
517 	} else if (mac_events[i].type == MapNotify) {
518 		ev->type = MapNotify;
519 	} else if (mac_events[i].type == UnmapNotify) {
520 		ev->type = UnmapNotify;
521 	} else {
522 		fprintf(stderr, "unknown macosx_checkevent: %d\n", mac_events[i].type);
523 	}
524 	mac_events_ptr++;
525 	mac_events_ptr = mac_events_ptr % MAX_EVENTS;
526 
527 	return mac_events[i].type;
528 }
529 
530 typedef struct windat {
531 	int win;
532 	int x, y;
533 	int width, height;
534 	int level;
535 	int mapped;
536 	int clipped;
537 	int ncache_only;
538 } windat_t;
539 
540 extern int macwinmax;
541 extern windat_t macwins[];
542 
macosx_get_wm_frame_pos(int * px,int * py,int * x,int * y,int * w,int * h,Window * frame,Window * win)543 int macosx_get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h,
544     Window *frame, Window *win) {
545 	static int last_idx = -1;
546 	int x1, x2, y1, y2;
547 	int idx = -1, k;
548 	macosxCGS_get_all_windows();
549 	macosxCG_get_cursor_pos(px, py);
550 
551 	for (k = 0; k<macwinmax; k++) {
552 		if (! macwins[k].mapped) {
553 			continue;
554 		}
555 		x1 = macwins[k].x;
556 		x2 = macwins[k].x + macwins[k].width;
557 		y1 = macwins[k].y;
558 		y2 = macwins[k].y + macwins[k].height;
559 if (debug_wireframe) fprintf(stderr, "%d/%d:	%d %d %d  - %d %d %d\n", k, macwins[k].win, x1, *px, x2, y1, *py, y2);
560 		if (x1 <= *px && *px < x2) {
561 			if (y1 <= *py && *py < y2) {
562 				idx = k;
563 				break;
564 			}
565 		}
566 	}
567 	if (idx < 0) {
568 		return 0;
569 	}
570 
571 	*x = macwins[idx].x;
572 	*y = macwins[idx].y;
573 	*w = macwins[idx].width;
574 	*h = macwins[idx].height;
575 	*frame = (Window) macwins[idx].win;
576 	if (win != NULL) {
577 		*win = *frame;
578 	}
579 
580 	last_idx = idx;
581 
582 	return 1;
583 }
584 
macosx_valid_window(Window w,XWindowAttributes * a)585 int macosx_valid_window(Window w, XWindowAttributes* a) {
586 	static int last_idx = -1;
587 	int win = (int) w;
588 	int i, k, idx = -1;
589 
590 	if (last_idx >= 0 && last_idx < macwinmax) {
591 		if (macwins[last_idx].win == win) {
592 			idx = last_idx;
593 		}
594 	}
595 
596 	if (idx < 0) {
597 		idx = macosxCGS_get_qlook(w);
598 		if (idx >= 0 && idx < macwinmax) {
599 			if (macwins[idx].win != win) {
600 				idx = -1;
601 			}
602 		} else {
603 			idx = -1;
604 		}
605 	}
606 
607 	if (idx < 0) {
608 		for (i = 0; i<macwinmax; i++) {
609 			k = i;
610 			if (i == -1)  {
611 				if (last_idx >= 0 && last_idx < macwinmax) {
612 					k = last_idx;
613 				} else {
614 					last_idx = -1;
615 					continue;
616 				}
617 			}
618 			if (macwins[k].win == win) {
619 				idx = k;
620 				break;
621 			}
622 		}
623 	}
624 	if (idx < 0) {
625 		return 0;
626 	}
627 
628 	a->x = macwins[idx].x;
629 	a->y = macwins[idx].y;
630 	a->width  = macwins[idx].width;
631 	a->height = macwins[idx].height;
632 	a->depth = depth;
633 	a->border_width = 0;
634 	a->backing_store = 0;
635 	if (macwins[idx].mapped) {
636 		a->map_state = IsViewable;
637 	} else {
638 		a->map_state = IsUnmapped;
639 	}
640 
641 	last_idx = idx;
642 
643 	return 1;
644 }
645 
646 #define QTMAX 2048
647 static Window cret[QTMAX];
648 
649 extern int CGS_levelmax;
650 extern int CGS_levels[];
651 
macosx_xquerytree(Window w,Window * root_return,Window * parent_return,Window ** children_return,unsigned int * nchildren_return)652 Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
653     Window **children_return, unsigned int *nchildren_return) {
654 
655 	int i, n, k;
656 
657 	*root_return = (Window) 0;
658 	*parent_return = (Window) 0;
659 	if (!w) {}
660 
661 	macosxCGS_get_all_windows();
662 
663 	n = 0;
664 	for (k = CGS_levelmax - 1; k >= 0; k--) {
665 		for (i = macwinmax - 1; i >= 0; i--) {
666 			if (n >= QTMAX) break;
667 			if (macwins[i].level == CGS_levels[k]) {
668 if (0) fprintf(stderr, "k=%d i=%d n=%d\n", k, i, n);
669 				cret[n++] = (Window) macwins[i].win;
670 			}
671 		}
672 	}
673 	*children_return = cret;
674 	*nchildren_return = (unsigned int) macwinmax;
675 
676 	return (Status) 1;
677 }
678 
macosx_check_offscreen(int win)679 int macosx_check_offscreen(int win) {
680 	sraRegionPtr r0, r1;
681 	int x1, y1, x2, y2;
682 	int ret;
683 	int i = macosxCGS_find_index(win);
684 
685 	if (i < 0) {
686 		return 0;
687 	}
688 
689 	x1 = macwins[i].x;
690 	y1 = macwins[i].y;
691 	x2 = macwins[i].x + macwins[i].width;
692 	y2 = macwins[i].y + macwins[i].height;
693 
694 	r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
695 	r1 = sraRgnCreateRect(x1, y1, x2, y2);
696 
697 	if (sraRgnAnd(r1, r0)) {
698 		ret = 0;
699 	} else {
700 		ret = 1;
701 	}
702 	sraRgnDestroy(r0);
703 	sraRgnDestroy(r1);
704 
705 	return ret;
706 }
707 
macosx_check_clipped(int win,int * list,int n)708 int macosx_check_clipped(int win, int *list, int n) {
709 	sraRegionPtr r0, r1, r2;
710 	int x1, y1, x2, y2;
711 	int ret = 0;
712 	int k, j, i = macosxCGS_find_index(win);
713 
714 	if (i < 0) {
715 		return 0;
716 	}
717 
718 	x1 = macwins[i].x;
719 	y1 = macwins[i].y;
720 	x2 = macwins[i].x + macwins[i].width;
721 	y2 = macwins[i].y + macwins[i].height;
722 
723 	r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
724 	r1 = sraRgnCreateRect(x1, y1, x2, y2);
725 	sraRgnAnd(r1, r0);
726 
727 	for (k = 0; k < n; k++) {
728 		j = macosxCGS_find_index(list[k]);	/* XXX slow? */
729 		if (j < 0) {
730 			continue;
731 		}
732 		x1 = macwins[j].x;
733 		y1 = macwins[j].y;
734 		x2 = macwins[j].x + macwins[j].width;
735 		y2 = macwins[j].y + macwins[j].height;
736 		r2 = sraRgnCreateRect(x1, y1, x2, y2);
737 		if (sraRgnAnd(r2, r1)) {
738 			ret = 1;
739 			sraRgnDestroy(r2);
740 			break;
741 		}
742 		sraRgnDestroy(r2);
743 	}
744 	sraRgnDestroy(r0);
745 	sraRgnDestroy(r1);
746 
747 	return ret;
748 }
749 
750 
751 #endif 	/* HAVE_MACOSX_NATIVE_DISPLAY */
752 
753