blob: e7158cfb80275af8534078ee61915e63188ad1e7 [file] [log] [blame]
San Mehata430b2b2014-09-23 08:30:51 -07001/*
2 Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3 All rights reserved.
4
5This file is part of x11vnc.
6
7x11vnc is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or (at
10your option) any later version.
11
12x11vnc is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with x11vnc; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20or see <http://www.gnu.org/licenses/>.
21
22In addition, as a special exception, Karl J. Runge
23gives permission to link the code of its release of x11vnc with the
24OpenSSL project's "OpenSSL" library (or with modified versions of it
25that use the same license as the "OpenSSL" library), and distribute
26the linked executables. You must obey the GNU General Public License
27in all respects for all of the code used other than "OpenSSL". If you
28modify this file, you may extend this exception to your version of the
29file, but you are not obligated to do so. If you do not wish to do
30so, delete this exception statement from your version.
31*/
32
33/* -- xwrappers.c -- */
34
35#include "x11vnc.h"
36#include "xrecord.h"
37#include "keyboard.h"
38#include "xevents.h"
39#include "connections.h"
40#include "cleanup.h"
41#include "macosx.h"
42
43int xshm_present = 0;
44int xshm_opcode = 0;
45int xtest_present = 0;
46int xtrap_present = 0;
47int xrecord_present = 0;
48int xkb_present = 0;
49int xinerama_present = 0;
50
51int keycode_state[256];
52int rootshift = 0;
53int clipshift = 0;
54
55
56int guess_bits_per_color(int bits_per_pixel);
57
58int XFlush_wr(Display *disp);
59
60Status XShmGetImage_wr(Display *disp, Drawable d, XImage *image, int x, int y,
61 unsigned long mask);
62XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth,
63 int format, char* data, XShmSegmentInfo* shminfo, unsigned int width,
64 unsigned int height);
65Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo);
66Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo);
67Bool XShmQueryExtension_wr(Display *disp);
68int XShmGetEventBase_wr(Display *disp);
69
70XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
71 unsigned int width, unsigned int height, Bool show_cursor);
72XImage *XGetSubImage_wr(Display *disp, Drawable d, int x, int y,
73 unsigned int width, unsigned int height, unsigned long plane_mask,
74 int format, XImage *dest_image, int dest_x, int dest_y);
75XImage *XGetImage_wr(Display *disp, Drawable d, int x, int y,
76 unsigned int width, unsigned int height, unsigned long plane_mask,
77 int format);
78XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth,
79 int format, int offset, char *data, unsigned int width,
80 unsigned int height, int bitmap_pad, int bytes_per_line);
81void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h);
82void init_track_keycode_state(void);
83
84void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
85 unsigned long delay);
86void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
87 unsigned long delay);
88void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
89 unsigned long delay);
90void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
91 unsigned long delay);
92void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
93 unsigned long delay);
94void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
95 unsigned long delay);
96
97Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w);
98Bool XTestCompareCursorWithWindow_wr(Display* dpy, Window w, Cursor cursor);
99Bool XTestQueryExtension_wr(Display *dpy, int *ev, int *er, int *maj,
100 int *min);
101void XTestDiscard_wr(Display *dpy);
102Bool XETrapQueryExtension_wr(Display *dpy, int *ev, int *er, int *op);
103int XTestGrabControl_wr(Display *dpy, Bool impervious);
104int XTRAP_GrabControl_wr(Display *dpy, Bool impervious);
105void disable_grabserver(Display *in_dpy, int change);
106
107Bool XRecordQueryVersion_wr(Display *dpy, int *maj, int *min);
108
109int xauth_raw(int on);
110Display *XOpenDisplay_wr(char *display_name);
111int XCloseDisplay_wr(Display *display);
112
113Bool XQueryPointer_wr(Display *display, Window w, Window *root_return,
114 Window *child_return, int *root_x_return, int *root_y_return,
115 int *win_x_return, int *win_y_return, unsigned int *mask_return);
116
117Status XQueryTree_wr(Display *display, Window w, Window *root_return,
118 Window *parent_return, Window **children_return,
119 unsigned int *nchildren_return);
120
121int XFree_wr(void *data);
122int XSelectInput_wr(Display *display, Window w, long event_mask);
123
124void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h);
125static void upup_downdown_warning(KeyCode key, Bool down);
126
127/*
128 * used in rfbGetScreen and rfbNewFramebuffer: and estimate to the number
129 * of bits per color, of course for some visuals, e.g. 565, the number
130 * is not the same for each color. This is just a sane default.
131 */
132int guess_bits_per_color(int bits_per_pixel) {
133 int bits_per_color;
134
135 /* first guess, spread them "evenly" over R, G, and B */
136 bits_per_color = bits_per_pixel/3;
137 if (bits_per_color < 1) {
138 bits_per_color = 1; /* 1bpp, 2bpp... */
139 }
140
141 /* choose safe values for usual cases: */
142 if (bits_per_pixel == 8) {
143 bits_per_color = 2;
144 } else if (bits_per_pixel == 15 || bits_per_pixel == 16) {
145 bits_per_color = 5;
146 } else if (bits_per_pixel == 24 || bits_per_pixel == 32) {
147 bits_per_color = 8;
148 }
149 return bits_per_color;
150}
151
152int XFlush_wr(Display *disp) {
153#if NO_X11
154 if (!disp) {}
155 return 1;
156#else
157 if (disp) {
158 return XFlush(disp);
159 } else {
160 return 1;
161 }
162#endif /* NO_X11 */
163}
164
165/*
166 * Kludge to interpose image gets and limit to a subset rectangle of
167 * the rootwin. This is the -sid option trying to work around invisible
168 * saveUnders menu, etc, windows. Also -clip option.
169 */
170
171#define ADJUST_ROOTSHIFT \
172 if (rootshift && subwin) { \
173 d = rootwin; \
174 x += off_x; \
175 y += off_y; \
176 } \
177 if (clipshift) { \
178 x += coff_x; \
179 y += coff_y; \
180 }
181
182/*
183 * Wrappers for Image related X calls
184 */
185Status XShmGetImage_wr(Display *disp, Drawable d, XImage *image, int x, int y,
186 unsigned long mask) {
187
188 ADJUST_ROOTSHIFT
189
190 /* Note: the Solaris overlay stuff is all non-shm (using_shm = 0) */
191
192#if LIBVNCSERVER_HAVE_XSHM
193 return XShmGetImage(disp, d, image, x, y, mask);
194#else
195 if (!disp || !d || !image || !x || !y || !mask) {}
196 return (Status) 0;
197#endif
198}
199
200XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth,
201 int format, char* data, XShmSegmentInfo* shminfo, unsigned int width,
202 unsigned int height) {
203
204#if LIBVNCSERVER_HAVE_XSHM
205 return XShmCreateImage(disp, vis, depth, format, data, shminfo,
206 width, height);
207#else
208 if (!disp || !vis || !depth || !format || !data || !shminfo || !width || !height) {}
209 return (XImage *) 0;
210#endif
211}
212
213Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo) {
214#if LIBVNCSERVER_HAVE_XSHM
215 return XShmAttach(disp, shminfo);
216#else
217 if (!disp || !shminfo) {}
218 return (Status) 0;
219#endif
220}
221
222Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo) {
223#if LIBVNCSERVER_HAVE_XSHM
224 if (getenv("X11VNC_SHM_DEBUG")) fprintf(stderr, "XShmDetach_wr: %p disp: %p\n", (void *)shminfo, (void *)disp);
225 return XShmDetach(disp, shminfo);
226#else
227 if (!disp || !shminfo) {}
228 return (Status) 0;
229#endif
230}
231
232Bool XShmQueryExtension_wr(Display *disp) {
233#if LIBVNCSERVER_HAVE_XSHM
234 return XShmQueryExtension(disp);
235#else
236 if (!disp) {}
237 return False;
238#endif
239}
240
241int XShmGetEventBase_wr(Display *disp) {
242#if LIBVNCSERVER_HAVE_XSHM
243 return XShmGetEventBase(disp);
244#else
245 if (!disp) {}
246 return 0;
247#endif
248}
249
250/* wrapper for overlay screen reading: */
251
252XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
253 unsigned int width, unsigned int height, Bool show_cursor) {
254#if NO_X11
255 if (!disp || !d || !x || !y || !width || !height || !show_cursor) {}
256 return NULL;
257#else
258
259#ifdef SOLARIS_OVERLAY
260 return XReadScreen(disp, d, x, y, width, height,
261 show_cursor);
262#else
263# ifdef IRIX_OVERLAY
264 { unsigned long hints = 0, hints_ret;
265 if (show_cursor) hints |= XRD_READ_POINTER;
266 return XReadDisplay(disp, d, x, y, width, height,
267 hints, &hints_ret);
268 }
269# else
270 /* unused vars warning: */
271 if (disp || d || x || y || width || height || show_cursor) {}
272
273 return NULL;
274# endif
275#endif
276
277#endif /* NO_X11 */
278}
279
280XImage *XGetSubImage_wr(Display *disp, Drawable d, int x, int y,
281 unsigned int width, unsigned int height, unsigned long plane_mask,
282 int format, XImage *dest_image, int dest_x, int dest_y) {
283#if NO_X11
284 nox11_exit(1);
285 if (!disp || !d || !x || !y || !width || !height || !plane_mask || !format || !dest_image || !dest_x || !dest_y) {}
286 return NULL;
287#else
288 ADJUST_ROOTSHIFT
289
290 if (overlay && dest_x == 0 && dest_y == 0) {
291 size_t size = dest_image->height * dest_image->bytes_per_line;
292 XImage *xi;
293
294 xi = xreadscreen(disp, d, x, y, width, height,
295 (Bool) overlay_cursor);
296
297 if (! xi) return NULL;
298
299 /*
300 * There is extra overhead from memcpy and free...
301 * this is not like the real XGetSubImage(). We hope
302 * this significant overhead is still small compared to
303 * the time to retrieve the fb data.
304 */
305 memcpy(dest_image->data, xi->data, size);
306
307 XDestroyImage(xi);
308 return (dest_image);
309 }
310 return XGetSubImage(disp, d, x, y, width, height, plane_mask,
311 format, dest_image, dest_x, dest_y);
312#endif /* NO_X11 */
313}
314
315XImage *XGetImage_wr(Display *disp, Drawable d, int x, int y,
316 unsigned int width, unsigned int height, unsigned long plane_mask,
317 int format) {
318#if NO_X11
319 if (!disp || !d || !x || !y || !width || !height || !plane_mask || !format) {}
320 nox11_exit(1);
321 return NULL;
322#else
323
324 ADJUST_ROOTSHIFT
325
326 if (overlay) {
327 return xreadscreen(disp, d, x, y, width, height,
328 (Bool) overlay_cursor);
329 }
330 return XGetImage(disp, d, x, y, width, height, plane_mask, format);
331#endif /* NO_X11 */
332}
333
334XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth,
335 int format, int offset, char *data, unsigned int width,
336 unsigned int height, int bitmap_pad, int bytes_per_line) {
337 /*
338 * This is a kludge to get a created XImage to exactly match what
339 * XReadScreen returns: we noticed the rgb masks are different
340 * from XCreateImage with the high color visual (red mask <->
341 * blue mask). Note we read from the root window(!) then free
342 * the data.
343 */
344
345 if (raw_fb) { /* raw_fb hack */
346 XImage *xi;
347 xi = (XImage *) malloc(sizeof(XImage));
348 memset(xi, 0, sizeof(XImage));
349 xi->depth = depth;
350 if (depth >= 24) {
351 xi->bits_per_pixel = 32;
352 } else if (depth > 16) {
353 xi->bits_per_pixel = 24;
354 } else if (depth > 8) {
355 xi->bits_per_pixel = 16;
356 } else {
357 xi->bits_per_pixel = 8;
358 }
359 xi->format = format;
360 xi->xoffset = offset;
361 xi->data = data;
362 xi->width = width;
363 xi->height = height;
364 xi->bitmap_pad = bitmap_pad;
365 xi->bytes_per_line = bytes_per_line ? bytes_per_line :
366 xi->width * xi->bits_per_pixel / 8;
367 xi->bitmap_unit = -1; /* hint to not call XDestroyImage */
368 return xi;
369 }
370
371#if NO_X11
372 nox11_exit(1);
373 if (!disp || !visual || !depth || !format || !offset || !data || !width
374 || !height || !width || !bitmap_pad || !bytes_per_line) {}
375 return NULL;
376#else
377 if (overlay) {
378 XImage *xi;
379 xi = xreadscreen(disp, window, 0, 0, width, height, False);
380 if (xi == NULL) {
381 return xi;
382 }
383 if (xi->data != NULL) {
384 free(xi->data);
385 }
386 xi->data = data;
387 return xi;
388 }
389
390 return XCreateImage(disp, visual, depth, format, offset, data,
391 width, height, bitmap_pad, bytes_per_line);
392#endif /* NO_X11 */
393}
394
395static void copy_raw_fb_low_bpp(XImage *dest, int x, int y, unsigned int w,
396 unsigned int h) {
397 char *src, *dst;
398 unsigned int line;
399 static char *buf = NULL;
400 static int buflen = -1;
401 int bpl = wdpy_x * raw_fb_native_bpp / 8;
402 int n, ix, len, del, sz = wdpy_x * raw_fb_expand_bytes;
403
404 unsigned int rm_n = raw_fb_native_red_mask;
405 unsigned int gm_n = raw_fb_native_green_mask;
406 unsigned int bm_n = raw_fb_native_blue_mask;
407 unsigned int rm_f = main_red_mask;
408 unsigned int gm_f = main_green_mask;
409 unsigned int bm_f = main_blue_mask;
410
411 unsigned int rs_n = raw_fb_native_red_shift;
412 unsigned int gs_n = raw_fb_native_green_shift;
413 unsigned int bs_n = raw_fb_native_blue_shift;
414 unsigned int rs_f = main_red_shift;
415 unsigned int gs_f = main_green_shift;
416 unsigned int bs_f = main_blue_shift;
417
418 unsigned int rx_n = raw_fb_native_red_max;
419 unsigned int gx_n = raw_fb_native_green_max;
420 unsigned int bx_n = raw_fb_native_blue_max;
421 unsigned int rx_f = main_red_max;
422 unsigned int gx_f = main_green_max;
423 unsigned int bx_f = main_blue_max;
424
425 static unsigned int msk[8];
426 static int last_bpp = -1;
427 static int cga = -1;
428
429 if (rm_f | gm_f | bm_f) {}
430
431 if (cga < 0) {
432 if (getenv("RAWFB_CGA")) {
433 cga = 1;
434 } else {
435 cga = 0;
436 }
437 }
438
439 if (sz > buflen || buf == NULL) {
440 if (buf) {
441 free(buf);
442 }
443 buflen = sz + 1000;
444 buf = (char *) malloc(buflen);
445 }
446
447 if (clipshift && ! use_snapfb) {
448 x += coff_x;
449 y += coff_y;
450 }
451
452 if (last_bpp != raw_fb_native_bpp) {
453 int br;
454 for (br = 0; br < 8; br++) {
455 unsigned int pbit, k, m = 0;
456
457 for (k=0; k < (unsigned int) raw_fb_native_bpp; k++) {
458 pbit = 1 << (br+k);
459 m |= pbit;
460 }
461 msk[br] = m;
462 }
463 last_bpp = raw_fb_native_bpp;
464 }
465
466 dst = dest->data;
467if (0) fprintf(stderr, "x=%d y=%d w=%d h=%d bpl=%d d_bpl=%d-%dx%dx%d/%d %p\n",
468 x, y, w, h, bpl, dest->bytes_per_line, dest->width, dest->height, dest->bits_per_pixel, dest->depth, dst);
469
470 for (line = 0; line < h; line++) {
471
472 if (! raw_fb_seek) {
473 /* mmap */
474 src = raw_fb_addr + raw_fb_offset + bpl*(y+line);
475
476 memcpy(buf, src, bpl);
477 } else {
478 /* lseek */
479 off_t off;
480 off = (off_t) (raw_fb_offset + bpl*(y+line));
481
482 lseek(raw_fb_fd, off, SEEK_SET);
483
484 len = bpl;
485 del = 0;
486 while (len > 0) {
487 n = read(raw_fb_fd, buf + del, len);
488
489 if (n > 0) {
490 del += n;
491 len -= n;
492 } else if (n == 0) {
493 break;
494 } else if (errno != EINTR && errno != EAGAIN) {
495 break;
496 }
497 }
498 }
499 for (ix = 0; ix < (int) w; ix++) {
500 int bx = (x + ix) * raw_fb_native_bpp;
501 int ib = bx / 8;
502 int br = bx - ib * 8;
503 unsigned char val;
504
505 val = *((unsigned char*) (buf + ib));
506
507 val = msk[br] & val;
508 val = val >> br;
509
510 if (cga) {
511 /* this is expt for CGA */
512 double r, g, b;
513 int ir, ig, ib;
514 r = (2./3)*(val & 4) + (1./3)*(val & 8);
515 g = (2./3)*(val & 2) + (1./3)*(val & 8);
516 b = (2./3)*(val & 1) + (1./3)*(val & 8);
517 if (val == 6) {
518 g = g/2.;
519 }
520 ir = rx_f * r;
521 ig = gx_f * g;
522 ib = bx_f * b;
523 val = (ib << bs_f) | (ig << gs_f) | (ir << rs_f);
524 } else {
525 unsigned char rval, gval, bval;
526
527 rval = (val & rm_n) >> rs_n;
528 gval = (val & gm_n) >> gs_n;
529 bval = (val & bm_n) >> bs_n;
530
531 rval = (rx_f * rval) / rx_n;
532 gval = (gx_f * gval) / gx_n;
533 bval = (bx_f * bval) / bx_n;
534
535 rval = rval << rs_f;
536 gval = gval << gs_f;
537 bval = bval << bs_f;
538
539 val = rval | gval | bval;
540 }
541
542 *(dst+ix) = (char) val;
543 }
544
545 dst += dest->bytes_per_line;
546 }
547}
548
549static void copy_raw_fb_24_to_32(XImage *dest, int x, int y, unsigned int w,
550 unsigned int h) {
551 /*
552 * kludge to read 1 byte at a time and dynamically transform
553 * 24bpp -> 32bpp by inserting a extra 0 byte into dst.
554 */
555 char *src, *dst;
556 unsigned int line;
557 static char *buf = NULL;
558 static int buflen = -1;
559 int bpl = wdpy_x * 3; /* pixelsize == 3 */
560 int LE, n, stp, len, del, sz = w * 3;
561 int insert_zeroes = 1;
562
563#define INSERT_ZEROES \
564 len = sz; \
565 del = 0; \
566 stp = 0; \
567 while (len > 0) { \
568 if (insert_zeroes && (del - LE) % 4 == 0) { \
569 *(dst + del) = 0; \
570 del++; \
571 } \
572 *(dst + del) = *(buf + stp); \
573 del++; \
574 len--; \
575 stp++; \
576 }
577
578 if (rfbEndianTest) {
579 LE = 3; /* little endian */
580 } else {
581 LE = 0; /* big endian */
582 }
583
584 if (sz > buflen || buf == NULL) {
585 if (buf) {
586 free(buf);
587 }
588 buf = (char *) malloc(4*(sz + 1000));
589 }
590
591 if (clipshift && ! use_snapfb) {
592 x += coff_x;
593 y += coff_y;
594 }
595
596 if (use_snapfb && dest != snap) {
597 /* snapfb src */
598 src = snap->data + snap->bytes_per_line*y + 3*x;
599 dst = dest->data;
600 for (line = 0; line < h; line++) {
601 memcpy(buf, src, sz);
602
603 INSERT_ZEROES
604
605 src += snap->bytes_per_line;
606 dst += dest->bytes_per_line;
607 }
608
609 } else if (! raw_fb_seek) {
610 /* mmap */
611 bpl = raw_fb_bytes_per_line;
612 if (clipshift && wdpy_x != cdpy_x) {
613 bpl = wdpy_x * 3;
614 }
615 src = raw_fb_addr + raw_fb_offset + bpl*y + 3*x;
616 dst = dest->data;
617
618 if (use_snapfb && dest == snap) {
619 /*
620 * writing *to* snap_fb: need the x,y offset,
621 * and also do not do inserts.
622 */
623 dst += bpl*y + 3*x;
624 insert_zeroes = 0;
625 }
626
627 for (line = 0; line < h; line++) {
628 memcpy(buf, src, sz);
629
630 INSERT_ZEROES
631
632 src += bpl;
633 dst += dest->bytes_per_line;
634 }
635
636 } else {
637 /* lseek */
638 off_t off;
639 bpl = raw_fb_bytes_per_line;
640 if (clipshift && wdpy_x != cdpy_x) {
641 bpl = wdpy_x * 3;
642 }
643 off = (off_t) (raw_fb_offset + bpl*y + 3*x);
644
645 lseek(raw_fb_fd, off, SEEK_SET);
646 dst = dest->data;
647
648 if (use_snapfb && dest == snap) {
649 /*
650 * writing *to* snap_fb: need the x,y offset,
651 * and also do not do inserts.
652 */
653 dst += bpl*y + 3*x;
654 insert_zeroes = 0;
655 }
656
657 for (line = 0; line < h; line++) {
658 len = sz;
659 del = 0;
660 while (len > 0) {
661 n = read(raw_fb_fd, buf + del, len);
662
663 if (n > 0) {
664 del += n;
665 len -= n;
666 } else if (n == 0) {
667 break;
668 } else if (errno != EINTR && errno != EAGAIN) {
669 break;
670 }
671 }
672
673 INSERT_ZEROES
674
675 if (bpl > sz) {
676 off = (off_t) (bpl - sz);
677 lseek(raw_fb_fd, off, SEEK_CUR);
678 }
679 dst += dest->bytes_per_line;
680 }
681 }
682}
683
684#ifdef MACOSX
685void macosx_copy_opengl(char *, int, int, unsigned int, unsigned int);
686#endif
687
688void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h) {
689 char *src, *dst;
690 unsigned int line;
691 int pixelsize = bpp/8;
692 static int db = -1;
693
694#ifdef MACOSX
695 if (macosx_console && macosx_read_opengl) {
696 macosx_copy_opengl(dest->data, x, y, w, h);
697 return;
698 }
699#endif
700
701 if (xform24to32) {
702 copy_raw_fb_24_to_32(dest, x, y, w, h);
703 return;
704 }
705 if (raw_fb_native_bpp < 8) {
706 copy_raw_fb_low_bpp(dest, x, y, w, h);
707 return;
708 }
709 if (db < 0) {
710 if (getenv("DEBUG_COPY_RAW_FB")) {
711 db = atoi(getenv("DEBUG_COPY_RAW_FB"));
712 } else {
713 db = 0;
714 }
715 }
716
717 if (clipshift && ! use_snapfb) {
718 x += coff_x;
719 y += coff_y;
720 }
721
722
723 if (use_snapfb && dest != snap) {
724 /* snapfb src */
725 src = snap->data + snap->bytes_per_line*y + pixelsize*x;
726 dst = dest->data;
727
728if (db) fprintf(stderr, "snap->bytes_per_line: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d bpp: %d pixelsize: %d\n", snap->bytes_per_line, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x, bpp, pixelsize);
729
730 for (line = 0; line < h; line++) {
731 memcpy(dst, src, w * pixelsize);
732 src += snap->bytes_per_line;
733 dst += dest->bytes_per_line;
734 }
735
736 } else if (! raw_fb_seek) {
737 /* mmap */
738 int bpl = raw_fb_bytes_per_line;
739
740 if (clipshift && wdpy_x != cdpy_x) {
741 bpl = wdpy_x * pixelsize;
742 }
743
744 src = raw_fb_addr + raw_fb_offset + bpl*y + pixelsize*x;
745 dst = dest->data;
746
747if (db) fprintf(stderr, "bpl: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d bpp: %d pixelsize: %d\n", bpl, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x, bpp, pixelsize);
748
749 for (line = 0; line < h; line++) {
750 memcpy(dst, src, w * pixelsize);
751 src += bpl;
752 dst += dest->bytes_per_line;
753 }
754
755 } else {
756 /* lseek */
757 int n, len, del, sz = w * pixelsize;
758 off_t off;
759 int bpl = raw_fb_bytes_per_line;
760
761 if (clipshift && wdpy_x != cdpy_x) {
762 bpl = wdpy_x * pixelsize;
763 }
764
765 off = (off_t) (raw_fb_offset + bpl*y + pixelsize*x);
766
767 lseek(raw_fb_fd, off, SEEK_SET);
768 dst = dest->data;
769
770if (db) fprintf(stderr, "lseek 0 ps: %d sz: %d off: %d bpl: %d\n", pixelsize, sz, (int) off, bpl);
771
772 for (line = 0; line < h; line++) {
773 len = sz;
774 del = 0;
775 while (len > 0) {
776 n = read(raw_fb_fd, dst + del, len);
777
778 if (n > 0) {
779 del += n;
780 len -= n;
781 } else if (n == 0) {
782 break;
783 } else if (errno != EINTR && errno != EAGAIN) {
784 break;
785 }
786 }
787 if (bpl > sz) {
788 off = (off_t) (bpl - sz);
789 lseek(raw_fb_fd, off, SEEK_CUR);
790 }
791 dst += dest->bytes_per_line;
792 }
793 }
794}
795
796void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h) {
797 /* default (w=0, h=0) is the fill the entire XImage */
798 if (dest == NULL) {
799 return;
800 }
801 if (w < 1) {
802 w = dest->width;
803 }
804 if (h < 1) {
805 h = dest->height;
806 }
807
808 if (raw_fb) {
809 copy_raw_fb(dest, x, y, w, h);
810
811 } else if (use_snapfb && snap_fb && dest != snaprect) {
812 char *src, *dst;
813 unsigned int line;
814 int pixelsize = bpp/8;
815
816 src = snap->data + snap->bytes_per_line*y + pixelsize*x;
817 dst = dest->data;
818 for (line = 0; line < h; line++) {
819 memcpy(dst, src, w * pixelsize);
820 src += snap->bytes_per_line;
821 dst += dest->bytes_per_line;
822 }
823
824 } else if ((using_shm && ! xform24to32) && (int) w == dest->width &&
825 (int) h == dest->height) {
826 XShmGetImage_wr(dpy, window, dest, x, y, AllPlanes);
827
828 } else {
829 XGetSubImage_wr(dpy, window, x, y, w, h, AllPlanes,
830 ZPixmap, dest, 0, 0);
831 }
832}
833
834#define DEBUG_SKIPPED_INPUT(dbg, str) \
835 if (dbg) { \
836 rfbLog("skipped input: %s\n", str); \
837 }
838
839void init_track_keycode_state(void) {
840 int i;
841 for (i=0; i<256; i++) {
842 keycode_state[i] = 0;
843 }
844 get_keystate(keycode_state);
845}
846
847static void upup_downdown_warning(KeyCode key, Bool down) {
848 RAWFB_RET_VOID
849#if NO_X11
850 if (!key || !down) {}
851 return;
852#else
853 if ((down ? 1:0) == keycode_state[(int) key]) {
854 char *str = XKeysymToString(XKeycodeToKeysym(dpy, key, 0));
855 rfbLog("XTestFakeKeyEvent: keycode=0x%x \"%s\" is *already* "
856 "%s\n", key, str ? str : "null", down ? "down":"up");
857 }
858#endif /* NO_X11 */
859}
860
861/*
862 * wrappers for XTestFakeKeyEvent, etc..
863 * also for XTrap equivalents XESimulateXEventRequest
864 */
865
866void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
867 unsigned long delay) {
868
869 RAWFB_RET_VOID
870#if NO_X11
871 nox11_exit(1);
872 if (!dpy || !key || !down || !delay) {}
873 return;
874#else
875
876 if (! xtrap_present) {
877 DEBUG_SKIPPED_INPUT(debug_keyboard, "keyboard: no-XTRAP");
878 return;
879 }
880 /* unused vars warning: */
881 if (key || down || delay) {}
882
883# if LIBVNCSERVER_HAVE_LIBXTRAP
884 XESimulateXEventRequest(trap_ctx, down ? KeyPress : KeyRelease,
885 key, 0, 0, 0);
886 if (debug_keyboard) {
887 upup_downdown_warning(key, down);
888 }
889 keycode_state[(int) key] = down ? 1 : 0;
890# else
891 DEBUG_SKIPPED_INPUT(debug_keyboard, "keyboard: no-XTRAP-build");
892# endif
893
894#endif /* NO_X11 */
895}
896
897void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
898 unsigned long delay) {
899 static int first = 1;
900 int regrab = 0;
901
902 RAWFB_RET_VOID
903
904#if NO_X11
905 nox11_exit(1);
906 if (!dpy || !key || !down || !delay || !first) {}
907 return;
908#else
909 if (debug_keyboard) {
910 char *str = XKeysymToString(XKeycodeToKeysym(dpy, key, 0));
911 rfbLog("XTestFakeKeyEvent(dpy, keycode=0x%x \"%s\", %s)\n",
912 key, str ? str : "null", down ? "down":"up");
913 }
914 if (first) {
915 init_track_keycode_state();
916 first = 0;
917 }
918 if (down) {
919 last_keyboard_keycode = -key;
920 } else {
921 last_keyboard_keycode = key;
922 }
923
924 if (grab_kbd) {
925 XUngrabKeyboard(dpy, CurrentTime);
926 regrab = 1;
927 }
928 if (grab_ptr && ungrab_both) {
929 XUngrabPointer(dpy, CurrentTime);
930 regrab = 1;
931 }
932
933 if (xtrap_input) {
934 XTRAP_FakeKeyEvent_wr(dpy, key, down, delay);
935 if (regrab) {
936 adjust_grabs(1, 1);
937 }
938 return;
939 }
940
941 if (! xtest_present) {
942 DEBUG_SKIPPED_INPUT(debug_keyboard, "keyboard: no-XTEST");
943 return;
944 }
945 if (debug_keyboard) {
946 rfbLog("calling XTestFakeKeyEvent(%d, %d) %.4f\n",
947 key, down, dnowx());
948 }
949#if LIBVNCSERVER_HAVE_XTEST
950 XTestFakeKeyEvent(dpy, key, down, delay);
951 if (regrab) {
952 adjust_grabs(1, 1);
953 }
954 if (debug_keyboard) {
955 upup_downdown_warning(key, down);
956 }
957 keycode_state[(int) key] = down ? 1 : 0;
958#endif
959
960#endif /* NO_X11 */
961}
962
963void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
964 unsigned long delay) {
965
966 RAWFB_RET_VOID
967#if NO_X11
968 nox11_exit(1);
969 if (!dpy || !button || !is_press || !delay) {}
970 return;
971#else
972
973 if (! xtrap_present) {
974 DEBUG_SKIPPED_INPUT(debug_keyboard, "button: no-XTRAP");
975 return;
976 }
977 /* unused vars warning: */
978 if (button || is_press || delay) {}
979
980#if LIBVNCSERVER_HAVE_LIBXTRAP
981 XESimulateXEventRequest(trap_ctx,
982 is_press ? ButtonPress : ButtonRelease, button, 0, 0, 0);
983#else
984 DEBUG_SKIPPED_INPUT(debug_keyboard, "button: no-XTRAP-build");
985#endif
986
987#endif /* NO_X11 */
988}
989
990void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
991 unsigned long delay) {
992 int regrab = 0;
993
994 RAWFB_RET_VOID
995#if NO_X11
996 nox11_exit(1);
997 if (!dpy || !button || !is_press || !delay) {}
998 return;
999#else
1000
1001 if (grab_ptr) {
1002 XUngrabPointer(dpy, CurrentTime);
1003 regrab = 1;
1004 }
1005 if (grab_kbd && ungrab_both) {
1006 XUngrabKeyboard(dpy, CurrentTime);
1007 regrab = 1;
1008 }
1009
1010 if (xtrap_input) {
1011 XTRAP_FakeButtonEvent_wr(dpy, button, is_press, delay);
1012 if (regrab) {
1013 adjust_grabs(1, 1);
1014 }
1015 return;
1016 }
1017
1018 if (! xtest_present) {
1019 DEBUG_SKIPPED_INPUT(debug_keyboard, "button: no-XTEST");
1020 return;
1021 }
1022 if (debug_pointer) {
1023 rfbLog("calling XTestFakeButtonEvent(%d, %d) %.4f\n",
1024 button, is_press, dnowx());
1025 }
1026#if LIBVNCSERVER_HAVE_XTEST
1027 XTestFakeButtonEvent(dpy, button, is_press, delay);
1028#endif
1029 if (regrab) {
1030 adjust_grabs(1, 1);
1031 }
1032#endif /* NO_X11 */
1033}
1034
1035void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
1036 unsigned long delay) {
1037
1038 RAWFB_RET_VOID
1039
1040#if NO_X11
1041 nox11_exit(1);
1042 if (!dpy || !screen || !x || !y || !delay) {}
1043 return;
1044#else
1045 if (! xtrap_present) {
1046 DEBUG_SKIPPED_INPUT(debug_keyboard, "motion: no-XTRAP");
1047 return;
1048 }
1049 /* unused vars warning: */
1050 if (dpy || screen || x || y || delay) {}
1051
1052#if LIBVNCSERVER_HAVE_LIBXTRAP
1053 XESimulateXEventRequest(trap_ctx, MotionNotify, 0, x, y, 0);
1054#else
1055 DEBUG_SKIPPED_INPUT(debug_keyboard, "motion: no-XTRAP-build");
1056#endif
1057
1058#endif /* NO_X11 */
1059}
1060
1061void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
1062 unsigned long delay) {
1063 int regrab = 0;
1064
1065 RAWFB_RET_VOID
1066#if NO_X11
1067 nox11_exit(1);
1068 if (!dpy || !screen || !x || !y || !delay) {}
1069 return;
1070#else
1071
1072 if (grab_ptr) {
1073 XUngrabPointer(dpy, CurrentTime);
1074 regrab = 1;
1075 }
1076 if (grab_kbd && ungrab_both) {
1077 XUngrabKeyboard(dpy, CurrentTime);
1078 regrab = 1;
1079 }
1080
1081 if (xtrap_input) {
1082 XTRAP_FakeMotionEvent_wr(dpy, screen, x, y, delay);
1083 if (regrab) {
1084 adjust_grabs(1, 1);
1085 }
1086 return;
1087 }
1088
1089 if (debug_pointer) {
1090 rfbLog("calling XTestFakeMotionEvent(%d, %d) %.4f\n",
1091 x, y, dnowx());
1092 }
1093#if LIBVNCSERVER_HAVE_XTEST
1094 XTestFakeMotionEvent(dpy, screen, x, y, delay);
1095#endif
1096 if (regrab) {
1097 adjust_grabs(1, 1);
1098 }
1099#endif /* NO_X11 */
1100}
1101
1102Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w) {
1103 if (! xtest_present) {
1104 return False;
1105 }
1106 RAWFB_RET(False)
1107
1108#if LIBVNCSERVER_HAVE_XTEST
1109 return XTestCompareCurrentCursorWithWindow(dpy, w);
1110#else
1111 if (!w) {}
1112 return False;
1113#endif
1114}
1115
1116Bool XTestCompareCursorWithWindow_wr(Display* dpy, Window w, Cursor cursor) {
1117 if (! xtest_present) {
1118 return False;
1119 }
1120 RAWFB_RET(False)
1121#if LIBVNCSERVER_HAVE_XTEST
1122 return XTestCompareCursorWithWindow(dpy, w, cursor);
1123#else
1124 if (!dpy || !w || !cursor) {}
1125 return False;
1126#endif
1127}
1128
1129Bool XTestQueryExtension_wr(Display *dpy, int *ev, int *er, int *maj,
1130 int *min) {
1131 RAWFB_RET(False)
1132#if LIBVNCSERVER_HAVE_XTEST
1133 return XTestQueryExtension(dpy, ev, er, maj, min);
1134#else
1135 if (!dpy || !ev || !er || !maj || !min) {}
1136 return False;
1137#endif
1138}
1139
1140void XTestDiscard_wr(Display *dpy) {
1141 if (! xtest_present) {
1142 return;
1143 }
1144 RAWFB_RET_VOID
1145#if LIBVNCSERVER_HAVE_XTEST
1146 XTestDiscard(dpy);
1147#else
1148 if (!dpy) {}
1149#endif
1150}
1151
1152Bool XETrapQueryExtension_wr(Display *dpy, int *ev, int *er, int *op) {
1153 RAWFB_RET(False)
1154#if LIBVNCSERVER_HAVE_LIBXTRAP
1155 return XETrapQueryExtension(dpy, (INT32 *)ev, (INT32 *)er,
1156 (INT32 *)op);
1157#else
1158 /* unused vars warning: */
1159 if (ev || er || op) {}
1160 return False;
1161#endif
1162}
1163
1164int XTestGrabControl_wr(Display *dpy, Bool impervious) {
1165 if (! xtest_present) {
1166 return 0;
1167 }
1168 RAWFB_RET(0)
1169#if LIBVNCSERVER_HAVE_XTEST && LIBVNCSERVER_HAVE_XTESTGRABCONTROL
1170 XTestGrabControl(dpy, impervious);
1171 return 1;
1172#else
1173 if (!dpy || !impervious) {}
1174 return 0;
1175#endif
1176}
1177
1178int XTRAP_GrabControl_wr(Display *dpy, Bool impervious) {
1179 if (! xtrap_present) {
1180 /* unused vars warning: */
1181 if (dpy || impervious) {}
1182 return 0;
1183 }
1184 RAWFB_RET(0)
1185#if LIBVNCSERVER_HAVE_LIBXTRAP
1186 else {
1187 ReqFlags requests;
1188
1189 if (! impervious) {
1190 if (trap_ctx) {
1191 XEFreeTC(trap_ctx);
1192 }
1193 trap_ctx = NULL;
1194 return 1;
1195 }
1196
1197 if (! trap_ctx) {
1198 trap_ctx = XECreateTC(dpy, 0, NULL);
1199 if (! trap_ctx) {
1200 rfbLog("DEC-XTRAP XECreateTC failed. Watch "
1201 "out for XGrabServer from wm's\n");
1202 return 0;
1203 }
1204 XEStartTrapRequest(trap_ctx);
1205 memset(requests, 0, sizeof(requests));
1206 BitTrue(requests, X_GrabServer);
1207 BitTrue(requests, X_UngrabServer);
1208 XETrapSetRequests(trap_ctx, True, requests);
1209 XETrapSetGrabServer(trap_ctx, True);
1210 }
1211 return 1;
1212 }
1213#endif
1214 return 0;
1215}
1216
1217void disable_grabserver(Display *in_dpy, int change) {
1218 int ok = 0;
1219 static int didmsg = 0;
1220
1221 if (debug_grabs) {
1222 fprintf(stderr, "disable_grabserver/%d %.5f\n",
1223 xserver_grabbed, dnowx());
1224 didmsg = 0;
1225 }
1226
1227 if (! xtrap_input) {
1228 if (XTestGrabControl_wr(in_dpy, True)) {
1229 if (change) {
1230 XTRAP_GrabControl_wr(in_dpy, False);
1231 }
1232 if (! didmsg && ! raw_fb_str) {
1233 rfbLog("GrabServer control via XTEST.\n");
1234 didmsg = 1;
1235 }
1236 ok = 1;
1237 } else {
1238 if (XTRAP_GrabControl_wr(in_dpy, True)) {
1239 ok = 1;
1240 if (! didmsg && ! raw_fb_str) {
1241 rfbLog("Using DEC-XTRAP for protection"
1242 " from XGrabServer.\n");
1243 didmsg = 1;
1244 }
1245 }
1246 }
1247 } else {
1248 if (XTRAP_GrabControl_wr(in_dpy, True)) {
1249 if (change) {
1250 XTestGrabControl_wr(in_dpy, False);
1251 }
1252 if (! didmsg && ! raw_fb_str) {
1253 rfbLog("GrabServer control via DEC-XTRAP.\n");
1254 didmsg = 1;
1255 }
1256 ok = 1;
1257 } else {
1258 if (XTestGrabControl_wr(in_dpy, True)) {
1259 ok = 1;
1260 if (! didmsg && ! raw_fb_str) {
1261 rfbLog("DEC-XTRAP XGrabServer "
1262 "protection not available, "
1263 "using XTEST.\n");
1264 didmsg = 1;
1265 }
1266 }
1267 }
1268 }
1269 if (! ok && ! didmsg) {
1270 rfbLog("*********************************************************\n");
1271 rfbLog("* No XTEST or DEC-XTRAP protection from XGrabServer !!! *\n");
1272 rfbLog("* DEADLOCK if your window manager calls XGrabServer !!! *\n");
1273 rfbLog("*********************************************************\n");
1274 }
1275 XFlush_wr(in_dpy);
1276}
1277
1278Bool XRecordQueryVersion_wr(Display *dpy, int *maj, int *min) {
1279 RAWFB_RET(False)
1280#if LIBVNCSERVER_HAVE_RECORD
1281 return XRecordQueryVersion(dpy, maj, min);
1282#else
1283 if (!dpy || !maj || !min) {}
1284 return False;
1285#endif
1286}
1287
1288int xauth_raw(int on) {
1289 char tmp[] = "/tmp/x11vnc-xauth.XXXXXX";
1290 int tmp_fd = -1;
1291 static char *old_xauthority = NULL;
1292 static char *old_tmp = NULL;
1293 int db = 0;
1294
1295 if (on) {
1296 if (old_xauthority) {
1297 free(old_xauthority);
1298 old_xauthority = NULL;
1299 }
1300 if (old_tmp) {
1301 free(old_tmp);
1302 old_tmp = NULL;
1303 }
1304 if (xauth_raw_data) {
1305 tmp_fd = mkstemp(tmp);
1306 if (tmp_fd < 0) {
1307 rfbLog("could not create tmp xauth file: %s\n", tmp);
1308 return 0;
1309 }
1310 if (db) fprintf(stderr, "XAUTHORITY tmp: %s\n", tmp);
1311 write(tmp_fd, xauth_raw_data, xauth_raw_len);
1312 close(tmp_fd);
1313 if (getenv("XAUTHORITY")) {
1314 old_xauthority = strdup(getenv("XAUTHORITY"));
1315 } else {
1316 old_xauthority = strdup("");
1317 }
1318 set_env("XAUTHORITY", tmp);
1319 old_tmp = strdup(tmp);
1320 }
1321 return 1;
1322 } else {
1323 if (old_xauthority) {
1324 if (!strcmp(old_xauthority, "")) {
1325 char *xauth = getenv("XAUTHORITY");
1326 if (xauth) {
1327 *(xauth-2) = '_'; /* yow */
1328 }
1329 } else {
1330 set_env("XAUTHORITY", old_xauthority);
1331 }
1332 free(old_xauthority);
1333 old_xauthority = NULL;
1334 }
1335 if (old_tmp) {
1336 unlink(old_tmp);
1337 free(old_tmp);
1338 old_tmp = NULL;
1339 }
1340 return 1;
1341 }
1342}
1343
1344Display *XOpenDisplay_wr(char *display_name) {
1345 Display *d = NULL;
1346 int db = 0;
1347
1348 if (! xauth_raw(1)) {
1349 return NULL;
1350 }
1351#if NO_X11
1352 rfbLog("This x11vnc was built without X11 support (-rawfb only).\n");
1353 if (!display_name || !d || !db) {}
1354 return NULL;
1355#else
1356
1357 d = XOpenDisplay(display_name);
1358 if (db) fprintf(stderr, "XOpenDisplay_wr: %s %p\n", display_name, (void *)d);
1359
1360 if (d == NULL && !getenv("NO_XAUTHLOCALHOSTNAME")) {
1361 char *xalhn = getenv("XAUTHLOCALHOSTNAME");
1362 if (1 || !xalhn) {
1363 rfbLog("XOpenDisplay(\"%s\") failed.\n",
1364 display_name ? display_name : "");
1365 rfbLog("Trying again with XAUTHLOCALHOSTNAME=localhost ...\n");
1366 set_env("XAUTHLOCALHOSTNAME", "localhost");
1367 d = XOpenDisplay(display_name);
1368 if (d == NULL && xalhn) {
1369 char *ptr = getenv("XAUTHLOCALHOSTNAME");
1370 if (ptr) {
1371 *(ptr-2) = '_'; /* yow */
1372 rfbLog("XOpenDisplay(\"%s\") failed.\n",
1373 display_name ? display_name : "");
1374 rfbLog("Trying again with unset XAUTHLOCALHOSTNAME ...\n");
1375 d = XOpenDisplay(display_name);
1376 }
1377 }
1378 }
1379 }
1380
1381 xauth_raw(0);
1382
1383 return d;
1384#endif /* NO_X11 */
1385}
1386
1387int XCloseDisplay_wr(Display *display) {
1388 int db = 0;
1389 if (db) fprintf(stderr, "XCloseDisplay_wr: %p\n", (void *)display);
1390#if NO_X11
1391 return 0;
1392#else
1393 return XCloseDisplay(display);
1394#endif /* NO_X11 */
1395}
1396
1397static unsigned int Bmask = (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
1398static unsigned int Mmask = (ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask);
1399
1400static unsigned int last_local_button_mask = 0;
1401static unsigned int last_local_mod_mask = 0;
1402static int last_local_x = 0;
1403static int last_local_y = 0;
1404
1405Bool XQueryPointer_wr(Display *display, Window w, Window *root_return,
1406 Window *child_return, int *root_x_return, int *root_y_return,
1407 int *win_x_return, int *win_y_return, unsigned int *mask_return) {
1408#if NO_X11
1409 if (!display || !w || !root_return || !child_return || !root_x_return
1410 || !root_y_return || !win_x_return || !win_y_return || !mask_return) {}
1411 return False;
1412#else
1413 Bool rc;
1414 XErrorHandler old_handler;
1415
1416
1417 if (! display) {
1418 return False;
1419 }
1420 old_handler = XSetErrorHandler(trap_xerror);
1421 trapped_xerror = 0;
1422
1423 rc = XQueryPointer(display, w, root_return, child_return,
1424 root_x_return, root_y_return, win_x_return, win_y_return,
1425 mask_return);
1426
1427 XSetErrorHandler(old_handler);
1428 if (trapped_xerror) {
1429 rc = 0;
1430 }
1431 if (rc) {
1432 display_button_mask = (*mask_return) & Bmask;
1433 display_mod_mask = (*mask_return) & Mmask;
1434 if (last_local_button_mask != display_button_mask) {
1435 got_local_pointer_input++;
1436 } else if (*root_x_return != last_local_x ||
1437 *root_y_return != last_local_y) {
1438 got_local_pointer_input++;
1439 }
1440 last_local_button_mask = display_button_mask;
1441 last_local_mod_mask = display_mod_mask;
1442 last_local_x = *root_x_return;
1443 last_local_y = *root_y_return;
1444 }
1445 return rc;
1446#endif /* NO_X11 */
1447}
1448
1449
1450Status XQueryTree_wr(Display *display, Window w, Window *root_return,
1451 Window *parent_return, Window **children_return,
1452 unsigned int *nchildren_return) {
1453
1454#ifdef MACOSX
1455 if (macosx_console) {
1456 return macosx_xquerytree(w, root_return, parent_return,
1457 children_return, nchildren_return);
1458 }
1459#endif
1460#if NO_X11
1461 if (!display || !w || !root_return || !parent_return
1462 || !children_return || !nchildren_return) {}
1463 return (Status) 0;
1464#else
1465 if (! display) {
1466 return (Status) 0;
1467 }
1468 return XQueryTree(display, w, root_return, parent_return,
1469 children_return, nchildren_return);
1470#endif /* NO_X11 */
1471
1472}
1473
1474int XFree_wr(void *data) {
1475 if (data == NULL) {
1476 return 1;
1477 }
1478 if (! dpy) {
1479 return 1;
1480 }
1481#if NO_X11
1482 return 1;
1483#else
1484 return XFree(data);
1485#endif
1486}
1487
1488int XSelectInput_wr(Display *display, Window w, long event_mask) {
1489#if NO_X11
1490 if (!display || !w || !event_mask) {}
1491 return 0;
1492#else
1493 int rc;
1494 XErrorHandler old_handler;
1495 if (display == NULL || w == None) {
1496 return 0;
1497 }
1498 old_handler = XSetErrorHandler(trap_xerror);
1499 trapped_xerror = 0;
1500 rc = XSelectInput(display, w, event_mask);
1501 XSetErrorHandler(old_handler);
1502 if (trapped_xerror) {
1503 rc = 0;
1504 }
1505 return rc;
1506#endif
1507}
1508
1509void nox11_exit(int rc) {
1510#if NO_X11
1511 rfbLog("This x11vnc was not built with X11 support.\n");
1512 clean_up_exit(rc);
1513#else
1514 if (0) {rc = 0;}
1515#endif
1516}
1517
1518
1519#if NO_X11
1520#include "nox11_funcs.h"
1521#endif
1522