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