Home | History | Annotate | Download | only in x11vnc
      1 /*
      2    Copyright (C) 2002-2010 Karl J. Runge <runge (at) 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 /* -- 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 
     43 int xshm_present = 0;
     44 int xshm_opcode = 0;
     45 int xtest_present = 0;
     46 int xtrap_present = 0;
     47 int xrecord_present = 0;
     48 int xkb_present = 0;
     49 int xinerama_present = 0;
     50 
     51 int keycode_state[256];
     52 int rootshift = 0;
     53 int clipshift = 0;
     54 
     55 
     56 int guess_bits_per_color(int bits_per_pixel);
     57 
     58 int XFlush_wr(Display *disp);
     59 
     60 Status XShmGetImage_wr(Display *disp, Drawable d, XImage *image, int x, int y,
     61     unsigned long mask);
     62 XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth,
     63     int format, char* data, XShmSegmentInfo* shminfo, unsigned int width,
     64     unsigned int height);
     65 Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo);
     66 Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo);
     67 Bool XShmQueryExtension_wr(Display *disp);
     68 int XShmGetEventBase_wr(Display *disp);
     69 
     70 XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
     71     unsigned int width, unsigned int height, Bool show_cursor);
     72 XImage *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);
     75 XImage *XGetImage_wr(Display *disp, Drawable d, int x, int y,
     76     unsigned int width, unsigned int height, unsigned long plane_mask,
     77     int format);
     78 XImage *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);
     81 void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h);
     82 void init_track_keycode_state(void);
     83 
     84 void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
     85     unsigned long delay);
     86 void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
     87     unsigned long delay);
     88 void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
     89     unsigned long delay);
     90 void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
     91     unsigned long delay);
     92 void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
     93     unsigned long delay);
     94 void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
     95     unsigned long delay);
     96 
     97 Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w);
     98 Bool XTestCompareCursorWithWindow_wr(Display* dpy, Window w, Cursor cursor);
     99 Bool XTestQueryExtension_wr(Display *dpy, int *ev, int *er, int *maj,
    100     int *min);
    101 void XTestDiscard_wr(Display *dpy);
    102 Bool XETrapQueryExtension_wr(Display *dpy, int *ev, int *er, int *op);
    103 int XTestGrabControl_wr(Display *dpy, Bool impervious);
    104 int XTRAP_GrabControl_wr(Display *dpy, Bool impervious);
    105 void disable_grabserver(Display *in_dpy, int change);
    106 
    107 Bool XRecordQueryVersion_wr(Display *dpy, int *maj, int *min);
    108 
    109 int xauth_raw(int on);
    110 Display *XOpenDisplay_wr(char *display_name);
    111 int XCloseDisplay_wr(Display *display);
    112 
    113 Bool 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 
    117 Status XQueryTree_wr(Display *display, Window w, Window *root_return,
    118     Window *parent_return, Window **children_return,
    119     unsigned int *nchildren_return);
    120 
    121 int XFree_wr(void *data);
    122 int XSelectInput_wr(Display *display, Window w, long event_mask);
    123 
    124 void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h);
    125 static 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  */
    132 int 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 
    152 int 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  */
    185 Status 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 
    200 XImage *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 
    213 Status 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 
    222 Status 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 
    232 Bool 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 
    241 int 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 
    252 XImage *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 
    280 XImage *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 
    315 XImage *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 
    334 XImage *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 
    395 static 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;
    467 if (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 
    549 static 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
    685 void macosx_copy_opengl(char *, int, int, unsigned int, unsigned int);
    686 #endif
    687 
    688 void 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 
    728 if (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 
    747 if (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 
    770 if (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 
    796 void 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 
    839 void 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 
    847 static 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 
    866 void 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 
    897 void 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 
    963 void 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 
    990 void 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 
   1035 void 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 
   1061 void 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 
   1102 Bool 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 
   1116 Bool 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 
   1129 Bool 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 
   1140 void 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 
   1152 Bool 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 
   1164 int 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 
   1178 int 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 
   1217 void 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 
   1278 Bool 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 
   1288 int 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 
   1344 Display *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 
   1387 int 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 
   1397 static unsigned int Bmask = (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
   1398 static unsigned int Mmask = (ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask);
   1399 
   1400 static unsigned int last_local_button_mask = 0;
   1401 static unsigned int last_local_mod_mask = 0;
   1402 static int last_local_x = 0;
   1403 static int last_local_y = 0;
   1404 
   1405 Bool 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 
   1450 Status 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 
   1474 int 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 
   1488 int 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 
   1509 void 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 
   1523