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