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 /* -- 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  */
guess_bits_per_color(int bits_per_pixel)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 
XFlush_wr(Display * disp)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  */
XShmGetImage_wr(Display * disp,Drawable d,XImage * image,int x,int y,unsigned long mask)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 
XShmCreateImage_wr(Display * disp,Visual * vis,unsigned int depth,int format,char * data,XShmSegmentInfo * shminfo,unsigned int width,unsigned int height)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 
XShmAttach_wr(Display * disp,XShmSegmentInfo * shminfo)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 
XShmDetach_wr(Display * disp,XShmSegmentInfo * shminfo)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 
XShmQueryExtension_wr(Display * disp)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 
XShmGetEventBase_wr(Display * disp)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 
xreadscreen(Display * disp,Drawable d,int x,int y,unsigned int width,unsigned int height,Bool show_cursor)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 
XGetSubImage_wr(Display * disp,Drawable d,int x,int y,unsigned int width,unsigned int height,unsigned long plane_mask,int format,XImage * dest_image,int dest_x,int dest_y)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 
XGetImage_wr(Display * disp,Drawable d,int x,int y,unsigned int width,unsigned int height,unsigned long plane_mask,int format)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 
XCreateImage_wr(Display * disp,Visual * visual,unsigned int depth,int format,int offset,char * data,unsigned int width,unsigned int height,int bitmap_pad,int bytes_per_line)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 
copy_raw_fb_low_bpp(XImage * dest,int x,int y,unsigned int w,unsigned int h)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 
copy_raw_fb_24_to_32(XImage * dest,int x,int y,unsigned int w,unsigned int h)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 
copy_raw_fb(XImage * dest,int x,int y,unsigned int w,unsigned int h)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 
copy_image(XImage * dest,int x,int y,unsigned int w,unsigned int h)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 
init_track_keycode_state(void)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 
upup_downdown_warning(KeyCode key,Bool down)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 
XTRAP_FakeKeyEvent_wr(Display * dpy,KeyCode key,Bool down,unsigned long delay)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 
XTestFakeKeyEvent_wr(Display * dpy,KeyCode key,Bool down,unsigned long delay)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 
XTRAP_FakeButtonEvent_wr(Display * dpy,unsigned int button,Bool is_press,unsigned long delay)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 
XTestFakeButtonEvent_wr(Display * dpy,unsigned int button,Bool is_press,unsigned long delay)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 
XTRAP_FakeMotionEvent_wr(Display * dpy,int screen,int x,int y,unsigned long delay)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 
XTestFakeMotionEvent_wr(Display * dpy,int screen,int x,int y,unsigned long delay)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 
XTestCompareCurrentCursorWithWindow_wr(Display * dpy,Window w)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 
XTestCompareCursorWithWindow_wr(Display * dpy,Window w,Cursor cursor)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 
XTestQueryExtension_wr(Display * dpy,int * ev,int * er,int * maj,int * min)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 
XTestDiscard_wr(Display * dpy)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 
XETrapQueryExtension_wr(Display * dpy,int * ev,int * er,int * op)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 
XTestGrabControl_wr(Display * dpy,Bool impervious)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 
XTRAP_GrabControl_wr(Display * dpy,Bool impervious)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 
disable_grabserver(Display * in_dpy,int change)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 
XRecordQueryVersion_wr(Display * dpy,int * maj,int * min)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 
xauth_raw(int on)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 
XOpenDisplay_wr(char * display_name)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 
XCloseDisplay_wr(Display * display)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 
XQueryPointer_wr(Display * display,Window w,Window * root_return,Window * child_return,int * root_x_return,int * root_y_return,int * win_x_return,int * win_y_return,unsigned int * mask_return)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 
XQueryTree_wr(Display * display,Window w,Window * root_return,Window * parent_return,Window ** children_return,unsigned int * nchildren_return)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 
XFree_wr(void * data)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 
XSelectInput_wr(Display * display,Window w,long event_mask)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 
nox11_exit(int rc)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