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