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 "rfb/rfbconfig.h"
36 #if (defined(__MACH__) && defined(__APPLE__) && defined(LIBVNCSERVER_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);
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 /* LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY */
752
753