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 /* -- cursor.c -- */ 34 35 #include "x11vnc.h" 36 #include "xwrappers.h" 37 #include "cleanup.h" 38 #include "screen.h" 39 #include "scan.h" 40 #include "unixpw.h" 41 #include "macosx.h" 42 43 int xfixes_present = 0; 44 int xfixes_first_initialized = 0; 45 int use_xfixes = 1; 46 int got_xfixes_cursor_notify = 0; 47 int cursor_changes = 0; 48 int alpha_threshold = 240; 49 double alpha_frac = 0.33; 50 int alpha_remove = 0; 51 int alpha_blend = 1; 52 int alt_arrow = 1; 53 54 55 void first_cursor(void); 56 void setup_cursors_and_push(void); 57 void initialize_xfixes(void); 58 int known_cursors_mode(char *s); 59 void initialize_cursors_mode(void); 60 int get_which_cursor(void); 61 void restore_cursor_shape_updates(rfbScreenInfoPtr s); 62 void disable_cursor_shape_updates(rfbScreenInfoPtr s); 63 int cursor_shape_updates_clients(rfbScreenInfoPtr s); 64 int cursor_pos_updates_clients(rfbScreenInfoPtr s); 65 void cursor_position(int x, int y); 66 void set_no_cursor(void); 67 void set_warrow_cursor(void); 68 int set_cursor(int x, int y, int which); 69 int check_x11_pointer(void); 70 int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot); 71 unsigned long get_cursor_serial(int mode); 72 73 74 typedef struct win_str_info { 75 char *wm_name; 76 char *res_name; 77 char *res_class; 78 } win_str_info_t; 79 80 typedef struct cursor_info { 81 char *data; /* data and mask pointers */ 82 char *mask; 83 int wx, wy; /* size of cursor */ 84 int sx, sy; /* shift to its centering point */ 85 int reverse; /* swap black and white */ 86 rfbCursorPtr rfb; 87 } cursor_info_t; 88 89 90 static void curs_copy(cursor_info_t *dest, cursor_info_t *src); 91 static void setup_cursors(void); 92 static void set_rfb_cursor(int which); 93 static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo); 94 static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h, 95 int xhot, int yhot, int Bpp); 96 static int get_exact_cursor(int init); 97 static void set_cursor_was_changed(rfbScreenInfoPtr s); 98 99 100 /* 101 * Here begins a bit of a mess to experiment with multiple cursors 102 * drawn on the remote background ... 103 */ 104 static void curs_copy(cursor_info_t *dest, cursor_info_t *src) { 105 if (src->data != NULL) { 106 dest->data = strdup(src->data); 107 } else { 108 dest->data = NULL; 109 } 110 if (src->mask != NULL) { 111 dest->mask = strdup(src->mask); 112 } else { 113 dest->mask = NULL; 114 } 115 dest->wx = src->wx; 116 dest->wy = src->wy; 117 dest->sx = src->sx; 118 dest->sy = src->sy; 119 dest->reverse = src->reverse; 120 dest->rfb = src->rfb; 121 122 if (rotating && rotating_cursors && dest->data != NULL) { 123 int tx, ty; 124 rotate_curs(dest->data, src->data, src->wx, src->wy, 1); 125 rotate_curs(dest->mask, src->mask, src->wx, src->wy, 1); 126 rotate_coords(dest->sx, dest->sy, &tx, &ty, src->wx, src->wy); 127 dest->sx = tx; 128 dest->sy = ty; 129 if (! rotating_same) { 130 dest->wx = src->wy; 131 dest->wy = src->wx; 132 } 133 } 134 } 135 136 /* empty cursor */ 137 static char* curs_empty_data = 138 " " 139 " "; 140 141 static char* curs_empty_mask = 142 " " 143 " "; 144 static cursor_info_t cur_empty = {NULL, NULL, 2, 2, 0, 0, 0, NULL}; 145 146 /* dot cursor */ 147 static char* curs_dot_data = 148 " " 149 " x"; 150 151 static char* curs_dot_mask = 152 " " 153 " x"; 154 static cursor_info_t cur_dot = {NULL, NULL, 2, 2, 0, 0, 0, NULL}; 155 156 157 /* main cursor */ 158 static char* curs_arrow_data = 159 " " 160 " x " 161 " xx " 162 " xxx " 163 " xxxx " 164 " xxxxx " 165 " xxxxxx " 166 " xxxxxxx " 167 " xxxxxxxx " 168 " xxxxx " 169 " xx xx " 170 " x xx " 171 " xx " 172 " xx " 173 " xx " 174 " " 175 " " 176 " "; 177 178 static char* curs_arrow_mask = 179 "xx " 180 "xxx " 181 "xxxx " 182 "xxxxx " 183 "xxxxxx " 184 "xxxxxxx " 185 "xxxxxxxx " 186 "xxxxxxxxx " 187 "xxxxxxxxxx " 188 "xxxxxxxxxx " 189 "xxxxxxx " 190 "xxx xxxx " 191 "xx xxxx " 192 " xxxx " 193 " xxxx " 194 " xx " 195 " " 196 " "; 197 static cursor_info_t cur_arrow = {NULL, NULL, 18, 18, 0, 0, 1, NULL}; 198 199 static char* curs_arrow2_data = 200 " " 201 " x " 202 " xx " 203 " xxx " 204 " xxxx " 205 " xxxxx " 206 " xxxxxx " 207 " xxxxxxx " 208 " xxxxxxxx " 209 " xxxxx " 210 " xx xx " 211 " x xx " 212 " xx " 213 " xx " 214 " xx " 215 " " 216 " " 217 " "; 218 219 static char* curs_arrow2_mask = 220 "xx " 221 "xxx " 222 "xxxx " 223 "xxxxx " 224 "xxxxxx " 225 "xxxxxxx " 226 "xxxxxxxx " 227 "xxxxxxxxx " 228 "xxxxxxxxxx " 229 "xxxxxxxxxx " 230 "xxxxxxx " 231 "xxx xxxx " 232 "xx xxxx " 233 " xxxx " 234 " xxxx " 235 " xx " 236 " " 237 " "; 238 static cursor_info_t cur_arrow2 = {NULL, NULL, 18, 18, 0, 0, 0, NULL}; 239 240 static char* curs_arrow3_data = 241 " " 242 " xx " 243 " xxxx " 244 " xxxxx " 245 " xxxxxxx " 246 " xxxxxxxx " 247 " xxxxxxxxxx " 248 " xxxxx " 249 " xxxxx " 250 " xx x " 251 " xx x " 252 " x x " 253 " x x " 254 " x " 255 " x " 256 " "; 257 258 static char* curs_arrow3_mask = 259 "xxx " 260 "xxxxx " 261 "xxxxxxx " 262 " xxxxxxxx " 263 " xxxxxxxxxx " 264 " xxxxxxxxxxxx " 265 " xxxxxxxxxxxx " 266 " xxxxxxxxxxx " 267 " xxxxxxx " 268 " xxxxxxx " 269 " xxxx xxx " 270 " xxx xxx " 271 " xxx xxx " 272 " xxx xxx " 273 " xxx" 274 " xx"; 275 276 static cursor_info_t cur_arrow3 = {NULL, NULL, 16, 16, 0, 0, 1, NULL}; 277 278 static char* curs_arrow4_data = 279 " " 280 " xx " 281 " xxxx " 282 " xxxxx " 283 " xxxxxxx " 284 " xxxxxxxx " 285 " xxxxxxxxxx " 286 " xxxxx " 287 " xxxxx " 288 " xx x " 289 " xx x " 290 " x x " 291 " x x " 292 " x " 293 " x " 294 " "; 295 296 static char* curs_arrow4_mask = 297 "xxx " 298 "xxxxx " 299 "xxxxxxx " 300 " xxxxxxxx " 301 " xxxxxxxxxx " 302 " xxxxxxxxxxxx " 303 " xxxxxxxxxxxx " 304 " xxxxxxxxxxx " 305 " xxxxxxx " 306 " xxxxxxx " 307 " xxxx xxx " 308 " xxx xxx " 309 " xxx xxx " 310 " xxx xxx " 311 " xxx" 312 " xx"; 313 314 static cursor_info_t cur_arrow4 = {NULL, NULL, 16, 16, 0, 0, 0, NULL}; 315 316 static char* curs_arrow5_data = 317 "x " 318 " xx " 319 " xxxx " 320 " xxxxx " 321 " xxxxxxx " 322 " xxx " 323 " xx x " 324 " x x " 325 " x x " 326 " x " 327 " x " 328 " x " 329 " x " 330 " x " 331 " x"; 332 333 static char* curs_arrow5_mask = 334 "xx " 335 "xxxx " 336 " xxxxx " 337 " xxxxxxx " 338 " xxxxxxxx " 339 " xxxxxxxx " 340 " xxxxx " 341 " xxxxxx " 342 " xx xxx " 343 " x xxx " 344 " xxx " 345 " xxx " 346 " xxx " 347 " xxx" 348 " xx"; 349 350 static cursor_info_t cur_arrow5 = {NULL, NULL, 15, 15, 0, 0, 1, NULL}; 351 352 static char* curs_arrow6_data = 353 "x " 354 " xx " 355 " xxxx " 356 " xxxxx " 357 " xxxxxxx " 358 " xxx " 359 " xx x " 360 " x x " 361 " x x " 362 " x " 363 " x " 364 " x " 365 " x " 366 " x " 367 " x"; 368 369 static char* curs_arrow6_mask = 370 "xx " 371 "xxxx " 372 " xxxxx " 373 " xxxxxxx " 374 " xxxxxxxx " 375 " xxxxxxxx " 376 " xxxxx " 377 " xxxxxx " 378 " xx xxx " 379 " x xxx " 380 " xxx " 381 " xxx " 382 " xxx " 383 " xxx" 384 " xx"; 385 386 static cursor_info_t cur_arrow6 = {NULL, NULL, 15, 15, 0, 0, 0, NULL}; 387 388 int alt_arrow_max = 6; 389 /* 390 * It turns out we can at least detect mouse is on the root window so 391 * show it (under -cursor X) with this familiar cursor... 392 */ 393 static char* curs_root_data = 394 " " 395 " " 396 " xxx xxx " 397 " xxxx xxxx " 398 " xxxxx xxxxx " 399 " xxxxx xxxxx " 400 " xxxxxxxxxx " 401 " xxxxxxxx " 402 " xxxxxx " 403 " xxxxxx " 404 " xxxxxxxx " 405 " xxxxxxxxxx " 406 " xxxxx xxxxx " 407 " xxxxx xxxxx " 408 " xxxx xxxx " 409 " xxx xxx " 410 " " 411 " "; 412 413 static char* curs_root_mask = 414 " " 415 " xxxx xxxx " 416 " xxxxx xxxxx " 417 " xxxxxx xxxxxx " 418 " xxxxxxx xxxxxxx " 419 " xxxxxxxxxxxxxx " 420 " xxxxxxxxxxxx " 421 " xxxxxxxxxx " 422 " xxxxxxxx " 423 " xxxxxxxx " 424 " xxxxxxxxxx " 425 " xxxxxxxxxxxx " 426 " xxxxxxxxxxxxxx " 427 " xxxxxxx xxxxxxx " 428 " xxxxxx xxxxxx " 429 " xxxxx xxxxx " 430 " xxxx xxxx " 431 " "; 432 static cursor_info_t cur_root = {NULL, NULL, 18, 18, 8, 8, 1, NULL}; 433 434 static char* curs_fleur_data = 435 " " 436 " xx " 437 " xxxx " 438 " xxxxxx " 439 " xx " 440 " x xx x " 441 " xx xx xx " 442 " xxxxxxxxxxxxxx " 443 " xxxxxxxxxxxxxx " 444 " xx xx xx " 445 " x xx x " 446 " xx " 447 " xxxxxx " 448 " xxxx " 449 " xx " 450 " "; 451 452 static char* curs_fleur_mask = 453 " xxxx " 454 " xxxxx " 455 " xxxxxx " 456 " xxxxxxxx " 457 " x xxxxxx x " 458 " xxx xxxx xxx " 459 "xxxxxxxxxxxxxxxx" 460 "xxxxxxxxxxxxxxxx" 461 "xxxxxxxxxxxxxxxx" 462 "xxxxxxxxxxxxxxxx" 463 " xxx xxxx xxx " 464 " x xxxxxx x " 465 " xxxxxxxx " 466 " xxxxxx " 467 " xxxx " 468 " xxxx "; 469 470 static cursor_info_t cur_fleur = {NULL, NULL, 16, 16, 8, 8, 1, NULL}; 471 472 static char* curs_plus_data = 473 " " 474 " xx " 475 " xx " 476 " xx " 477 " xx " 478 " xxxxxxxxxx " 479 " xxxxxxxxxx " 480 " xx " 481 " xx " 482 " xx " 483 " xx " 484 " "; 485 486 static char* curs_plus_mask = 487 " xxxx " 488 " xxxx " 489 " xxxx " 490 " xxxx " 491 "xxxxxxxxxxxx" 492 "xxxxxxxxxxxx" 493 "xxxxxxxxxxxx" 494 "xxxxxxxxxxxx" 495 " xxxx " 496 " xxxx " 497 " xxxx " 498 " xxxx "; 499 static cursor_info_t cur_plus = {NULL, NULL, 12, 12, 5, 6, 1, NULL}; 500 501 static char* curs_xterm_data = 502 " " 503 " xxx xxx " 504 " xxx " 505 " x " 506 " x " 507 " x " 508 " x " 509 " x " 510 " x " 511 " x " 512 " x " 513 " x " 514 " x " 515 " xxx " 516 " xxx xxx " 517 " "; 518 519 static char* curs_xterm_mask = 520 " xxxx xxxx " 521 " xxxxxxxxx " 522 " xxxxxxxxx " 523 " xxxxx " 524 " xxx " 525 " xxx " 526 " xxx " 527 " xxx " 528 " xxx " 529 " xxx " 530 " xxx " 531 " xxx " 532 " xxxxx " 533 " xxxxxxxxx " 534 " xxxxxxxxx " 535 " xxxx xxxx "; 536 static cursor_info_t cur_xterm = {NULL, NULL, 16, 16, 8, 8, 1, NULL}; 537 538 enum cursor_names { 539 CURS_EMPTY = 0, 540 CURS_DOT, 541 542 CURS_ARROW, 543 CURS_WARROW, 544 CURS_ROOT, 545 CURS_WM, 546 CURS_TERM, 547 CURS_PLUS, 548 549 CURS_DYN1, 550 CURS_DYN2, 551 CURS_DYN3, 552 CURS_DYN4, 553 CURS_DYN5, 554 CURS_DYN6, 555 CURS_DYN7, 556 CURS_DYN8, 557 CURS_DYN9, 558 CURS_DYN10, 559 CURS_DYN11, 560 CURS_DYN12, 561 CURS_DYN13, 562 CURS_DYN14, 563 CURS_DYN15, 564 CURS_DYN16 565 }; 566 567 #define CURS_DYN_MIN CURS_DYN1 568 #define CURS_DYN_MAX CURS_DYN16 569 #define CURS_DYN_NUM (CURS_DYN_MAX - CURS_DYN_MIN + 1) 570 571 #define CURS_MAX 32 572 static cursor_info_t *cursors[CURS_MAX]; 573 574 void first_cursor(void) { 575 if (! screen) { 576 return; 577 } 578 if (! show_cursor) { 579 LOCK(screen->cursorMutex); 580 screen->cursor = NULL; 581 UNLOCK(screen->cursorMutex); 582 } else { 583 got_xfixes_cursor_notify++; 584 set_rfb_cursor(get_which_cursor()); 585 set_cursor_was_changed(screen); 586 } 587 } 588 589 static void setup_cursors(void) { 590 rfbCursorPtr rfb_curs; 591 char *scale = NULL; 592 int i, j, n = 0; 593 int w_in = 0, h_in = 0; 594 static int first = 1; 595 596 if (verbose || use_threads) { 597 rfbLog("setting up %d cursors...\n", CURS_MAX); 598 } 599 600 if (first) { 601 for (i=0; i<CURS_MAX; i++) { 602 cursors[i] = NULL; 603 } 604 } 605 first = 0; 606 607 if (screen) { 608 LOCK(screen->cursorMutex); 609 screen->cursor = NULL; 610 } 611 612 for (i=0; i<CURS_MAX; i++) { 613 cursor_info_t *ci; 614 if (cursors[i]) { 615 /* clear out any existing ones: */ 616 ci = cursors[i]; 617 if (ci->rfb) { 618 /* this is the rfbCursor part: */ 619 if (ci->rfb->richSource) { 620 free(ci->rfb->richSource); 621 ci->rfb->richSource = NULL; 622 } 623 if (ci->rfb->source) { 624 free(ci->rfb->source); 625 ci->rfb->source = NULL; 626 } 627 if (ci->rfb->mask) { 628 free(ci->rfb->mask); 629 ci->rfb->mask = NULL; 630 } 631 free(ci->rfb); 632 ci->rfb = NULL; 633 } 634 if (ci->data) { 635 free(ci->data); 636 ci->data = NULL; 637 } 638 if (ci->mask) { 639 free(ci->mask); 640 ci->mask = NULL; 641 } 642 free(ci); 643 ci = NULL; 644 } 645 646 /* create new struct: */ 647 ci = (cursor_info_t *) malloc(sizeof(cursor_info_t)); 648 ci->data = NULL; 649 ci->mask = NULL; 650 ci->wx = 0; 651 ci->wy = 0; 652 ci->sx = 0; 653 ci->sy = 0; 654 ci->reverse = 0; 655 ci->rfb = NULL; 656 cursors[i] = ci; 657 } 658 659 /* clear any xfixes cursor cache (no freeing is done) */ 660 get_exact_cursor(1); 661 662 /* manually fill in the data+masks: */ 663 cur_empty.data = curs_empty_data; 664 cur_empty.mask = curs_empty_mask; 665 666 cur_dot.data = curs_dot_data; 667 cur_dot.mask = curs_dot_mask; 668 669 cur_arrow.data = curs_arrow_data; 670 cur_arrow.mask = curs_arrow_mask; 671 cur_arrow2.data = curs_arrow2_data; 672 cur_arrow2.mask = curs_arrow2_mask; 673 cur_arrow3.data = curs_arrow3_data; 674 cur_arrow3.mask = curs_arrow3_mask; 675 cur_arrow4.data = curs_arrow4_data; 676 cur_arrow4.mask = curs_arrow4_mask; 677 cur_arrow5.data = curs_arrow5_data; 678 cur_arrow5.mask = curs_arrow5_mask; 679 cur_arrow6.data = curs_arrow6_data; 680 cur_arrow6.mask = curs_arrow6_mask; 681 682 cur_root.data = curs_root_data; 683 cur_root.mask = curs_root_mask; 684 685 cur_plus.data = curs_plus_data; 686 cur_plus.mask = curs_plus_mask; 687 688 cur_fleur.data = curs_fleur_data; 689 cur_fleur.mask = curs_fleur_mask; 690 691 cur_xterm.data = curs_xterm_data; 692 cur_xterm.mask = curs_xterm_mask; 693 694 curs_copy(cursors[CURS_EMPTY], &cur_empty); n++; 695 curs_copy(cursors[CURS_DOT], &cur_dot); n++; 696 697 if (alt_arrow < 1 || alt_arrow > alt_arrow_max) { 698 alt_arrow = 1; 699 } 700 if (alt_arrow == 1) { 701 curs_copy(cursors[CURS_ARROW], &cur_arrow); n++; 702 } else if (alt_arrow == 2) { 703 curs_copy(cursors[CURS_ARROW], &cur_arrow2); n++; 704 } else if (alt_arrow == 3) { 705 curs_copy(cursors[CURS_ARROW], &cur_arrow3); n++; 706 } else if (alt_arrow == 4) { 707 curs_copy(cursors[CURS_ARROW], &cur_arrow4); n++; 708 } else if (alt_arrow == 5) { 709 curs_copy(cursors[CURS_ARROW], &cur_arrow5); n++; 710 } else if (alt_arrow == 6) { 711 curs_copy(cursors[CURS_ARROW], &cur_arrow6); n++; 712 } else { 713 alt_arrow = 1; 714 curs_copy(cursors[CURS_ARROW], &cur_arrow); n++; 715 } 716 curs_copy(cursors[CURS_WARROW], &cur_arrow2); n++; 717 718 curs_copy(cursors[CURS_ROOT], &cur_root); n++; 719 curs_copy(cursors[CURS_WM], &cur_fleur); n++; 720 curs_copy(cursors[CURS_TERM], &cur_xterm); n++; 721 curs_copy(cursors[CURS_PLUS], &cur_plus); n++; 722 723 if (scale_cursor_str) { 724 scale = scale_cursor_str; 725 } else if (scaling && scale_str) { 726 scale = scale_str; 727 } 728 if (scale && sscanf(scale, "%dx%d", &i, &j) == 2) { 729 if (wdpy_x > 0) { 730 w_in = wdpy_x; 731 h_in = wdpy_y; 732 } else { 733 w_in = dpy_x; 734 h_in = dpy_y; 735 } 736 } 737 738 /* scale = NULL zeroes everything */ 739 parse_scale_string(scale, &scale_cursor_fac_x, &scale_cursor_fac_y, &scaling_cursor, 740 &scaling_cursor_blend, &j, &j, &scaling_cursor_interpolate, 741 &scale_cursor_numer, &scale_cursor_denom, w_in, h_in); 742 743 for (i=0; i<n; i++) { 744 /* create rfbCursors for the special cursors: */ 745 746 cursor_info_t *ci = cursors[i]; 747 748 if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) { 749 int w, h, x, y, k; 750 unsigned long *pixels; 751 752 w = ci->wx; 753 h = ci->wy; 754 755 pixels = (unsigned long *) malloc(w * h 756 * sizeof(unsigned long)); 757 758 k = 0; 759 for (y=0; y<h; y++) { 760 for (x=0; x<w; x++) { 761 char d = ci->data[k]; 762 char m = ci->mask[k]; 763 unsigned long *p; 764 765 p = pixels + k; 766 767 /* set alpha on */ 768 *p = 0xff000000; 769 770 if (d == ' ' && m == ' ') { 771 /* alpha off */ 772 *p = 0x00000000; 773 } else if (d != ' ') { 774 /* body */ 775 if (ci->reverse) { 776 *p |= 0x00000000; 777 } else { 778 *p |= 0x00ffffff; 779 } 780 } else if (m != ' ') { 781 /* edge */ 782 if (ci->reverse) { 783 *p |= 0x00ffffff; 784 } else { 785 *p |= 0x00000000; 786 } 787 } 788 k++; 789 } 790 } 791 792 rfb_curs = pixels2curs(pixels, w, h, ci->sx, ci->sy, 793 bpp/8); 794 795 free(pixels); 796 797 } else { 798 799 /* standard X cursor */ 800 rfb_curs = rfbMakeXCursor(ci->wx, ci->wy, 801 ci->data, ci->mask); 802 803 if (ci->reverse) { 804 rfb_curs->foreRed = 0x0000; 805 rfb_curs->foreGreen = 0x0000; 806 rfb_curs->foreBlue = 0x0000; 807 rfb_curs->backRed = 0xffff; 808 rfb_curs->backGreen = 0xffff; 809 rfb_curs->backBlue = 0xffff; 810 } 811 rfb_curs->alphaSource = NULL; 812 813 rfb_curs->xhot = ci->sx; 814 rfb_curs->yhot = ci->sy; 815 rfb_curs->cleanup = FALSE; 816 rfb_curs->cleanupSource = FALSE; 817 rfb_curs->cleanupMask = FALSE; 818 rfb_curs->cleanupRichSource = FALSE; 819 820 if (bpp == 8 && indexed_color) { 821 /* 822 * use richsource in PseudoColor for better 823 * looking cursors (i.e. two-color). 824 */ 825 int x, y, k = 0, bw; 826 int black = 0, white = 1; 827 char d, m; 828 829 if (dpy) { /* raw_fb hack */ 830 black = BlackPixel(dpy, scr); 831 white = WhitePixel(dpy, scr); 832 } 833 834 rfb_curs->richSource = (unsigned char *) 835 calloc(ci->wx * ci->wy, 1); 836 837 for (y = 0; y < ci->wy; y++) { 838 for (x = 0; x < ci->wx; x++) { 839 d = *(ci->data + k); 840 m = *(ci->mask + k); 841 if (d == ' ' && m == ' ') { 842 k++; 843 continue; 844 } else if (m != ' ' && d == ' ') { 845 bw = black; 846 } else { 847 bw = white; 848 } 849 if (ci->reverse) { 850 if (bw == black) { 851 bw = white; 852 } else { 853 bw = black; 854 } 855 } 856 *(rfb_curs->richSource+k) = 857 (unsigned char) bw; 858 k++; 859 } 860 } 861 } 862 } 863 ci->rfb = rfb_curs; 864 } 865 if (screen) { 866 UNLOCK(screen->cursorMutex); 867 } 868 if (verbose) { 869 rfbLog(" done.\n"); 870 } 871 rfbLog("\n"); 872 } 873 874 void setup_cursors_and_push(void) { 875 setup_cursors(); 876 first_cursor(); 877 } 878 879 /* 880 * Descends window tree at pointer until the window cursor matches the current 881 * cursor. So far only used to detect if mouse is on root background or not. 882 * (returns 0 in that case, 1 otherwise). 883 * 884 */ 885 static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) { 886 #if NO_X11 887 RAWFB_RET_VOID 888 if (!depth || !w || !winfo) {} 889 return; 890 #else 891 Window r, c; 892 int i, rx, ry, wx, wy; 893 unsigned int mask; 894 Window wins[10]; 895 int descend, maxtries = 10; 896 char *name, *s = multiple_cursors_mode; 897 static XClassHint *classhint = NULL; 898 int nm_info = 1; 899 XErrorHandler old_handler; 900 901 RAWFB_RET_VOID 902 903 if (!strcmp(s, "default") || !strcmp(s, "X") || !strcmp(s, "arrow")) { 904 nm_info = 0; 905 } 906 907 *(winfo->wm_name) = '\0'; 908 *(winfo->res_name) = '\0'; 909 *(winfo->res_class) = '\0'; 910 911 for (i=0; i < maxtries; i++) { 912 wins[i] = None; 913 } 914 915 /* some times a window can go away before we get to it */ 916 trapped_xerror = 0; 917 old_handler = XSetErrorHandler(trap_xerror); 918 919 c = window; 920 descend = -1; 921 922 while (c) { 923 wins[++descend] = c; 924 if (descend >= maxtries - 1) { 925 break; 926 } 927 if ( XTestCompareCurrentCursorWithWindow_wr(dpy, c) ) { 928 break; 929 } 930 /* TBD: query_pointer() */ 931 XQueryPointer_wr(dpy, c, &r, &c, &rx, &ry, &wx, &wy, &mask); 932 } 933 934 if (nm_info) { 935 int got_wm_name = 0, got_res_name = 0, got_res_class = 0; 936 937 if (! classhint) { 938 classhint = XAllocClassHint(); 939 } 940 941 for (i = descend; i >=0; i--) { 942 c = wins[i]; 943 if (! c) { 944 continue; 945 } 946 947 if (! got_wm_name && XFetchName(dpy, c, &name)) { 948 if (name) { 949 if (*name != '\0') { 950 strcpy(winfo->wm_name, name); 951 got_wm_name = 1; 952 } 953 XFree_wr(name); 954 } 955 } 956 if (classhint && (! got_res_name || ! got_res_class)) { 957 if (XGetClassHint(dpy, c, classhint)) { 958 char *p; 959 p = classhint->res_name; 960 if (p) { 961 if (*p != '\0' && ! got_res_name) { 962 strcpy(winfo->res_name, p); 963 got_res_name = 1; 964 } 965 XFree_wr(p); 966 classhint->res_name = NULL; 967 } 968 p = classhint->res_class; 969 if (p) { 970 if (*p != '\0' && ! got_res_class) { 971 strcpy(winfo->res_class, p); 972 got_res_class = 1; 973 } 974 XFree_wr(p); 975 classhint->res_class = NULL; 976 } 977 } 978 } 979 } 980 } 981 982 XSetErrorHandler(old_handler); 983 trapped_xerror = 0; 984 985 *depth = descend; 986 *w = wins[descend]; 987 #endif /* NO_X11 */ 988 } 989 990 void initialize_xfixes(void) { 991 #if LIBVNCSERVER_HAVE_LIBXFIXES 992 if (xfixes_present) { 993 X_LOCK; 994 if (use_xfixes) { 995 XFixesSelectCursorInput(dpy, rootwin, 996 XFixesDisplayCursorNotifyMask); 997 } else { 998 XFixesSelectCursorInput(dpy, rootwin, 0); 999 } 1000 X_UNLOCK; 1001 xfixes_first_initialized = 1; 1002 } 1003 #endif 1004 } 1005 1006 static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h, 1007 int xhot, int yhot, int Bpp) { 1008 rfbCursorPtr c; 1009 static unsigned long black = 0, white = 1; 1010 static int first = 1; 1011 char *bitmap, *rich, *alpha; 1012 char *pixels_new = NULL; 1013 int n_opaque, n_trans, n_alpha, len, histo[256]; 1014 int send_alpha = 0, alpha_shift = 0, thresh; 1015 int i, x, y; 1016 1017 if (first && dpy) { /* raw_fb hack */ 1018 X_LOCK; 1019 black = BlackPixel(dpy, scr); 1020 white = WhitePixel(dpy, scr); 1021 X_UNLOCK; 1022 first = 0; 1023 } 1024 1025 if (cmap8to24 && cmap8to24_fb && depth <= 16) { 1026 if (Bpp <= 2) { 1027 Bpp = 4; 1028 } 1029 } 1030 1031 if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) { 1032 int W, H; 1033 char *pixels_use = (char *) pixels; 1034 unsigned int *pixels32 = NULL; 1035 1036 W = w; 1037 H = h; 1038 1039 w = scale_round(W, scale_cursor_fac_x); 1040 h = scale_round(H, scale_cursor_fac_y); 1041 1042 pixels_new = (char *) malloc(4*w*h); 1043 1044 if (sizeof(unsigned long) == 8) { 1045 int i, j, k = 0; 1046 /* 1047 * to avoid 64bpp code in scale_rect() we knock 1048 * down to unsigned int on 64bit machines: 1049 */ 1050 pixels32 = (unsigned int*) malloc(4*W*H); 1051 for (j=0; j<H; j++) { 1052 for (i=0; i<W; i++) { 1053 *(pixels32+k) = 0xffffffff & (*(pixels+k)); 1054 k++; 1055 } 1056 } 1057 pixels_use = (char *) pixels32; 1058 } 1059 1060 scale_rect(scale_cursor_fac_x, scale_cursor_fac_y, scaling_cursor_blend, 1061 scaling_cursor_interpolate, 1062 4, pixels_use, 4*W, pixels_new, 4*w, 1063 W, H, w, h, 0, 0, W, H, 0); 1064 1065 if (sizeof(unsigned long) == 8) { 1066 int i, j, k = 0; 1067 unsigned long *pixels64; 1068 unsigned int* source = (unsigned int*) pixels_new; 1069 /* 1070 * now knock it back up to unsigned long: 1071 */ 1072 pixels64 = (unsigned long*) malloc(8*w*h); 1073 for (j=0; j<h; j++) { 1074 for (i=0; i<w; i++) { 1075 *(pixels64+k) = (unsigned long) (*(source+k)); 1076 k++; 1077 } 1078 } 1079 free(pixels_new); 1080 pixels_new = (char *) pixels64; 1081 if (pixels32) { 1082 free(pixels32); 1083 pixels32 = NULL; 1084 } 1085 } 1086 1087 pixels = (unsigned long *) pixels_new; 1088 1089 xhot = scale_round(xhot, scale_cursor_fac_x); 1090 yhot = scale_round(yhot, scale_cursor_fac_y); 1091 } 1092 1093 len = w * h; 1094 /* for bitmap data */ 1095 bitmap = (char *) malloc(len+1); 1096 bitmap[len] = '\0'; 1097 1098 /* for rich cursor pixel data */ 1099 rich = (char *)calloc(Bpp*len, 1); 1100 alpha = (char *)calloc(1*len, 1); 1101 1102 n_opaque = 0; 1103 n_trans = 0; 1104 n_alpha = 0; 1105 for (i=0; i<256; i++) { 1106 histo[i] = 0; 1107 } 1108 1109 i = 0; 1110 for (y = 0; y < h; y++) { 1111 for (x = 0; x < w; x++) { 1112 unsigned long a; 1113 1114 a = 0xff000000 & (*(pixels+i)); 1115 a = a >> 24; /* alpha channel */ 1116 if (a > 0) { 1117 n_alpha++; 1118 } 1119 histo[a]++; 1120 if (a < (unsigned int) alpha_threshold) { 1121 n_trans++; 1122 } else { 1123 n_opaque++; 1124 } 1125 i++; 1126 } 1127 } 1128 if (alpha_blend) { 1129 send_alpha = 0; 1130 if (Bpp == 4) { 1131 send_alpha = 1; 1132 } 1133 alpha_shift = 24; 1134 if (main_red_shift == 24 || main_green_shift == 24 || 1135 main_blue_shift == 24) { 1136 alpha_shift = 0; /* XXX correct? */ 1137 } 1138 } 1139 if (n_opaque >= alpha_frac * n_alpha) { 1140 thresh = alpha_threshold; 1141 } else { 1142 n_opaque = 0; 1143 for (i=255; i>=0; i--) { 1144 n_opaque += histo[i]; 1145 thresh = i; 1146 if (n_opaque >= alpha_frac * n_alpha) { 1147 break; 1148 } 1149 } 1150 } 1151 1152 i = 0; 1153 for (y = 0; y < h; y++) { 1154 for (x = 0; x < w; x++) { 1155 unsigned long r, g, b, a; 1156 unsigned int ui; 1157 char *p; 1158 1159 a = 0xff000000 & (*(pixels+i)); 1160 a = a >> 24; /* alpha channel */ 1161 1162 if (a < (unsigned int) thresh) { 1163 bitmap[i] = ' '; 1164 } else { 1165 bitmap[i] = 'x'; 1166 } 1167 1168 r = 0x00ff0000 & (*(pixels+i)); 1169 g = 0x0000ff00 & (*(pixels+i)); 1170 b = 0x000000ff & (*(pixels+i)); 1171 r = r >> 16; /* red */ 1172 g = g >> 8; /* green */ 1173 b = b >> 0; /* blue */ 1174 1175 if (alpha_remove && a != 0) { 1176 r = (255 * r) / a; 1177 g = (255 * g) / a; 1178 b = (255 * b) / a; 1179 if (r > 255) r = 255; 1180 if (g > 255) g = 255; 1181 if (b > 255) b = 255; 1182 } 1183 1184 if (indexed_color) { 1185 /* 1186 * Choose black or white for 1187 * PseudoColor case. 1188 */ 1189 int value = (r+g+b)/3; 1190 if (value > 127) { 1191 ui = white; 1192 } else { 1193 ui = black; 1194 } 1195 } else { 1196 /* 1197 * Otherwise map the RGB data onto 1198 * the framebuffer format: 1199 */ 1200 r = (main_red_max * r)/255; 1201 g = (main_green_max * g)/255; 1202 b = (main_blue_max * b)/255; 1203 ui = 0; 1204 ui |= (r << main_red_shift); 1205 ui |= (g << main_green_shift); 1206 ui |= (b << main_blue_shift); 1207 if (send_alpha) { 1208 ui |= (a << alpha_shift); 1209 } 1210 } 1211 1212 /* insert value into rich source: */ 1213 p = rich + Bpp*i; 1214 1215 if (Bpp == 1) { 1216 *((unsigned char *)p) 1217 = (unsigned char) ui; 1218 } else if (Bpp == 2) { 1219 *((unsigned short *)p) 1220 = (unsigned short) ui; 1221 } else if (Bpp == 3) { 1222 *((unsigned char *)p) 1223 = (unsigned char) ((ui & 0x0000ff) >> 0); 1224 *((unsigned char *)(p+1)) 1225 = (unsigned char) ((ui & 0x00ff00) >> 8); 1226 *((unsigned char *)(p+2)) 1227 = (unsigned char) ((ui & 0xff0000) >> 16); 1228 } else if (Bpp == 4) { 1229 *((unsigned int *)p) 1230 = (unsigned int) ui; 1231 } 1232 1233 /* insert alpha value into alpha source: */ 1234 p = alpha + i; 1235 *((unsigned char *)p) = (unsigned char) a; 1236 1237 i++; 1238 } 1239 } 1240 1241 /* create the cursor with the bitmap: */ 1242 c = rfbMakeXCursor(w, h, bitmap, bitmap); 1243 free(bitmap); 1244 1245 if (pixels_new) { 1246 free(pixels_new); 1247 } 1248 1249 /* set up the cursor parameters: */ 1250 c->xhot = xhot; 1251 c->yhot = yhot; 1252 c->cleanup = FALSE; 1253 c->cleanupSource = FALSE; 1254 c->cleanupMask = FALSE; 1255 c->cleanupRichSource = FALSE; 1256 c->richSource = (unsigned char *) rich; 1257 1258 /* zeroes mean interpolate the rich cursor somehow and use B+W */ 1259 c->foreRed = 0; 1260 c->foreGreen = 0; 1261 c->foreBlue = 0; 1262 c->backRed = 0; 1263 c->backGreen = 0; 1264 c->backBlue = 0; 1265 1266 c->source = NULL; 1267 1268 if (alpha_blend && !indexed_color) { 1269 c->alphaSource = (unsigned char *) alpha; 1270 c->alphaPreMultiplied = TRUE; 1271 } else { 1272 free(alpha); 1273 c->alphaSource = NULL; 1274 } 1275 return c; 1276 } 1277 1278 static unsigned long last_cursor = 0; 1279 static int last_index = 0; 1280 static time_t curs_times[CURS_MAX]; 1281 static unsigned long curs_index[CURS_MAX]; 1282 1283 unsigned long get_cursor_serial(int mode) { 1284 if (mode == 0) { 1285 return last_cursor; 1286 } else if (mode == 1) { 1287 return (unsigned long) last_index; 1288 } else { 1289 return (unsigned long) last_index; 1290 } 1291 } 1292 1293 static int get_exact_cursor(int init) { 1294 int which = CURS_ARROW; 1295 1296 if (init) { 1297 /* zero out our cache (cursors are not freed) */ 1298 int i; 1299 for (i=0; i<CURS_MAX; i++) { 1300 curs_times[i] = 0; 1301 curs_index[i] = 0; 1302 } 1303 last_cursor = 0; 1304 last_index = 0; 1305 return -1; 1306 } 1307 1308 #ifdef MACOSX 1309 if (macosx_console) { 1310 return macosx_get_cursor(); 1311 } 1312 #endif 1313 1314 if (rawfb_vnc_reflect) { 1315 int last_idx = (int) get_cursor_serial(1); 1316 if (last_idx) { 1317 which = last_idx; 1318 } 1319 return which; 1320 } 1321 if (xfixes_present && dpy) { 1322 #if LIBVNCSERVER_HAVE_LIBXFIXES 1323 int last_idx = (int) get_cursor_serial(1); 1324 XFixesCursorImage *xfc; 1325 1326 if (last_idx) { 1327 which = last_idx; 1328 } 1329 if (! xfixes_first_initialized) { 1330 return which; 1331 } 1332 1333 X_LOCK; 1334 if (! got_xfixes_cursor_notify && xfixes_base_event_type) { 1335 /* try again for XFixesCursorNotify event */ 1336 XEvent xev; 1337 if (XCheckTypedEvent(dpy, xfixes_base_event_type + 1338 XFixesCursorNotify, &xev)) { 1339 got_xfixes_cursor_notify++; 1340 } 1341 } 1342 if (! got_xfixes_cursor_notify) { 1343 /* evidently no cursor change, just return last one */ 1344 X_UNLOCK; 1345 return which; 1346 } 1347 got_xfixes_cursor_notify = 0; 1348 1349 /* retrieve the cursor info + pixels from server: */ 1350 xfc = XFixesGetCursorImage(dpy); 1351 X_UNLOCK; 1352 if (! xfc) { 1353 /* failure. */ 1354 return which; 1355 } 1356 1357 which = store_cursor(xfc->cursor_serial, xfc->pixels, 1358 xfc->width, xfc->height, 32, xfc->xhot, xfc->yhot); 1359 1360 X_LOCK; 1361 XFree_wr(xfc); 1362 X_UNLOCK; 1363 #endif 1364 } 1365 return(which); 1366 } 1367 1368 int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, 1369 int xhot, int yhot) { 1370 int which = CURS_ARROW; 1371 int use, oldest, i; 1372 time_t oldtime, now; 1373 1374 #if 0 1375 fprintf(stderr, "sc: %d %d/%d %d - %d %d\n", serial, w, h, cbpp, xhot, yhot); 1376 #endif 1377 1378 oldest = CURS_DYN_MIN; 1379 if (screen && screen->cursor == cursors[oldest]->rfb) { 1380 oldest++; 1381 } 1382 oldtime = curs_times[oldest]; 1383 now = time(NULL); 1384 for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) { 1385 if (screen && screen->cursor == cursors[i]->rfb) { 1386 ; 1387 } else if (curs_times[i] < oldtime) { 1388 /* watch for oldest one to overwrite */ 1389 oldest = i; 1390 oldtime = curs_times[i]; 1391 } 1392 if (serial == (int) curs_index[i]) { 1393 /* 1394 * got a hit with an existing cursor, 1395 * use that one. 1396 */ 1397 #ifdef MACOSX 1398 if (now > curs_times[i] + 1) { 1399 continue; 1400 } 1401 #endif 1402 last_cursor = curs_index[i]; 1403 curs_times[i] = now; 1404 last_index = i; 1405 return last_index; 1406 } 1407 } 1408 1409 /* we need to create the cursor and overwrite oldest */ 1410 use = oldest; 1411 if (cursors[use]->rfb) { 1412 /* clean up oldest if it exists */ 1413 if (cursors[use]->rfb->richSource) { 1414 free(cursors[use]->rfb->richSource); 1415 cursors[use]->rfb->richSource = NULL; 1416 } 1417 if (cursors[use]->rfb->alphaSource) { 1418 free(cursors[use]->rfb->alphaSource); 1419 cursors[use]->rfb->alphaSource = NULL; 1420 } 1421 if (cursors[use]->rfb->source) { 1422 free(cursors[use]->rfb->source); 1423 cursors[use]->rfb->source = NULL; 1424 } 1425 if (cursors[use]->rfb->mask) { 1426 free(cursors[use]->rfb->mask); 1427 cursors[use]->rfb->mask = NULL; 1428 } 1429 free(cursors[use]->rfb); 1430 cursors[use]->rfb = NULL; 1431 } 1432 1433 if (rotating && rotating_cursors) { 1434 char *dst; 1435 int tx, ty; 1436 1437 dst = (char *) malloc(w * h * cbpp/8); 1438 rotate_curs(dst, (char *) data, w, h, cbpp/8); 1439 1440 memcpy(data, dst, w * h * cbpp/8); 1441 free(dst); 1442 1443 rotate_coords(xhot, yhot, &tx, &ty, w, h); 1444 xhot = tx; 1445 yhot = ty; 1446 if (! rotating_same) { 1447 int tmp = w; 1448 w = h; 1449 h = tmp; 1450 } 1451 } 1452 1453 /* place cursor into our collection */ 1454 cursors[use]->rfb = pixels2curs(data, w, h, xhot, yhot, bpp/8); 1455 1456 /* update time and serial index: */ 1457 curs_times[use] = now; 1458 curs_index[use] = serial; 1459 last_index = use; 1460 last_cursor = serial; 1461 1462 which = last_index; 1463 1464 return which; 1465 } 1466 1467 int known_cursors_mode(char *s) { 1468 /* 1469 * default: see initialize_cursors_mode() for default behavior. 1470 * arrow: unchanging white arrow. 1471 * Xn*: show X on root background. Optional n sets treedepth. 1472 * some: do the heuristics for root, wm, term detection. 1473 * most: if display have overlay or xfixes, show all cursors, 1474 * otherwise do the same as "some" 1475 * none: show no cursor. 1476 */ 1477 if (strcmp(s, "default") && strcmp(s, "arrow") && *s != 'X' && 1478 strcmp(s, "some") && strcmp(s, "most") && strcmp(s, "none")) { 1479 return 0; 1480 } else { 1481 return 1; 1482 } 1483 } 1484 1485 void initialize_cursors_mode(void) { 1486 char *s = multiple_cursors_mode; 1487 if (!s || !known_cursors_mode(s)) { 1488 rfbLog("unknown cursors mode: %s\n", s); 1489 rfbLog("resetting cursors mode to \"default\"\n"); 1490 if (multiple_cursors_mode) free(multiple_cursors_mode); 1491 multiple_cursors_mode = strdup("default"); 1492 s = multiple_cursors_mode; 1493 } 1494 if (!strcmp(s, "none")) { 1495 show_cursor = 0; 1496 } else { 1497 /* we do NOT set show_cursor = 1, let the caller do that */ 1498 } 1499 1500 show_multiple_cursors = 0; 1501 if (show_cursor) { 1502 if (!strcmp(s, "default")) { 1503 if(multiple_cursors_mode) free(multiple_cursors_mode); 1504 multiple_cursors_mode = strdup("X"); 1505 s = multiple_cursors_mode; 1506 } 1507 if (*s == 'X' || !strcmp(s, "some") || !strcmp(s, "most")) { 1508 show_multiple_cursors = 1; 1509 } else { 1510 show_multiple_cursors = 0; 1511 /* hmmm, some bug going back to arrow mode.. */ 1512 set_rfb_cursor(CURS_ARROW); 1513 } 1514 if (screen) { 1515 set_cursor_was_changed(screen); 1516 } 1517 } else { 1518 if (screen) { 1519 LOCK(screen->cursorMutex); 1520 screen->cursor = NULL; 1521 UNLOCK(screen->cursorMutex); 1522 set_cursor_was_changed(screen); 1523 } 1524 } 1525 } 1526 1527 int get_which_cursor(void) { 1528 int which = CURS_ARROW; 1529 int db = 0; 1530 1531 if (show_multiple_cursors) { 1532 int depth = 0, rint; 1533 static win_str_info_t winfo; 1534 static int first = 1, depth_cutoff = -1; 1535 Window win = None; 1536 XErrorHandler old_handler; 1537 int mode = 0; 1538 1539 if (drag_in_progress || button_mask) { 1540 /* XXX not exactly what we want for menus */ 1541 if (! cursor_drag_changes) { 1542 return -1; 1543 } 1544 } 1545 1546 if (!strcmp(multiple_cursors_mode, "arrow")) { 1547 /* should not happen... */ 1548 return CURS_ARROW; 1549 } else if (!strcmp(multiple_cursors_mode, "default")) { 1550 mode = 0; 1551 } else if (!strcmp(multiple_cursors_mode, "X")) { 1552 mode = 1; 1553 } else if (!strcmp(multiple_cursors_mode, "some")) { 1554 mode = 2; 1555 } else if (!strcmp(multiple_cursors_mode, "most")) { 1556 mode = 3; 1557 } 1558 1559 if (rawfb_vnc_reflect && mode > -1) { 1560 rint = get_exact_cursor(0); 1561 return rint; 1562 } 1563 if (mode == 3) { 1564 if ((xfixes_present && use_xfixes) || macosx_console) { 1565 if (db) fprintf(stderr, "get_which_cursor call get_exact_cursor\n"); 1566 rint = get_exact_cursor(0); 1567 return rint; 1568 } 1569 } 1570 1571 if (depth_cutoff < 0) { 1572 int din; 1573 if (sscanf(multiple_cursors_mode, "X%d", &din) == 1) { 1574 depth_cutoff = din; 1575 } else { 1576 depth_cutoff = 0; 1577 } 1578 } 1579 1580 if (first) { 1581 winfo.wm_name = (char *) malloc(1024); 1582 winfo.res_name = (char *) malloc(1024); 1583 winfo.res_class = (char *) malloc(1024); 1584 } 1585 first = 0; 1586 1587 X_LOCK; 1588 tree_descend_cursor(&depth, &win, &winfo); 1589 X_UNLOCK; 1590 1591 if (depth <= depth_cutoff && !subwin) { 1592 which = CURS_ROOT; 1593 1594 } else if (mode == 2 || mode == 3) { 1595 int which0 = which; 1596 1597 /* apply crude heuristics to choose a cursor... */ 1598 if (win && dpy) { 1599 int ratio = 10, x, y; 1600 unsigned int w, h, bw, d; 1601 Window r; 1602 1603 #if !NO_X11 1604 trapped_xerror = 0; 1605 X_LOCK; 1606 old_handler = XSetErrorHandler(trap_xerror); 1607 1608 /* "narrow" windows are WM */ 1609 if (XGetGeometry(dpy, win, &r, &x, &y, &w, &h, 1610 &bw, &d)) { 1611 if (w > ratio * h || h > ratio * w) { 1612 which = CURS_WM; 1613 } 1614 } 1615 XSetErrorHandler(old_handler); 1616 X_UNLOCK; 1617 trapped_xerror = 0; 1618 #else 1619 if (!r || !d || !bw || !h || !w || !y || !x || !ratio || !old_handler) {} 1620 #endif /* NO_X11 */ 1621 } 1622 if (which == which0) { 1623 /* the string "term" means I-beam. */ 1624 char *name, *class; 1625 lowercase(winfo.res_name); 1626 lowercase(winfo.res_class); 1627 name = winfo.res_name; 1628 class = winfo.res_class; 1629 if (strstr(name, "term")) { 1630 which = CURS_TERM; 1631 } else if (strstr(class, "term")) { 1632 which = CURS_TERM; 1633 } else if (strstr(name, "text")) { 1634 which = CURS_TERM; 1635 } else if (strstr(class, "text")) { 1636 which = CURS_TERM; 1637 } else if (strstr(name, "onsole")) { 1638 which = CURS_TERM; 1639 } else if (strstr(class, "onsole")) { 1640 which = CURS_TERM; 1641 } else if (strstr(name, "cmdtool")) { 1642 which = CURS_TERM; 1643 } else if (strstr(class, "cmdtool")) { 1644 which = CURS_TERM; 1645 } else if (strstr(name, "shelltool")) { 1646 which = CURS_TERM; 1647 } else if (strstr(class, "shelltool")) { 1648 which = CURS_TERM; 1649 } 1650 } 1651 } 1652 } 1653 if (db) fprintf(stderr, "get_which_cursor which: %d\n", which); 1654 return which; 1655 } 1656 1657 static void set_cursor_was_changed(rfbScreenInfoPtr s) { 1658 rfbClientIteratorPtr iter; 1659 rfbClientPtr cl; 1660 1661 if (! s) { 1662 return; 1663 } 1664 iter = rfbGetClientIterator(s); 1665 LOCK(screen->cursorMutex); 1666 while( (cl = rfbClientIteratorNext(iter)) ) { 1667 cl->cursorWasChanged = TRUE; 1668 } 1669 UNLOCK(screen->cursorMutex); 1670 rfbReleaseClientIterator(iter); 1671 } 1672 1673 #if 0 1674 /* not yet used */ 1675 static void set_cursor_was_moved(rfbScreenInfoPtr s) { 1676 rfbClientIteratorPtr iter; 1677 rfbClientPtr cl; 1678 1679 if (! s) { 1680 return; 1681 } 1682 iter = rfbGetClientIterator(s); 1683 while( (cl = rfbClientIteratorNext(iter)) ) { 1684 cl->cursorWasMoved = TRUE; 1685 } 1686 rfbReleaseClientIterator(iter); 1687 } 1688 #endif 1689 1690 void restore_cursor_shape_updates(rfbScreenInfoPtr s) { 1691 rfbClientIteratorPtr iter; 1692 rfbClientPtr cl; 1693 int count = 0; 1694 1695 if (! s || ! s->clientHead) { 1696 return; 1697 } 1698 iter = rfbGetClientIterator(s); 1699 while( (cl = rfbClientIteratorNext(iter)) ) { 1700 int changed = 0; 1701 ClientData *cd = (ClientData *) cl->clientData; 1702 1703 if (! cd) { 1704 continue; 1705 } 1706 if (cd->had_cursor_shape_updates) { 1707 rfbLog("restoring enableCursorShapeUpdates for client" 1708 " 0x%x\n", cl); 1709 cl->enableCursorShapeUpdates = TRUE; 1710 changed = 1; 1711 } 1712 if (cd->had_cursor_pos_updates) { 1713 rfbLog("restoring enableCursorPosUpdates for client" 1714 " 0x%x\n", cl); 1715 cl->enableCursorPosUpdates = TRUE; 1716 changed = 1; 1717 } 1718 if (changed) { 1719 cl->cursorWasChanged = TRUE; 1720 count++; 1721 } 1722 } 1723 rfbReleaseClientIterator(iter); 1724 } 1725 1726 void disable_cursor_shape_updates(rfbScreenInfoPtr s) { 1727 rfbClientIteratorPtr iter; 1728 rfbClientPtr cl; 1729 static int changed = 0; 1730 int count = 0; 1731 1732 if (! s || ! s->clientHead) { 1733 return; 1734 } 1735 if (unixpw_in_progress) return; 1736 1737 iter = rfbGetClientIterator(s); 1738 while( (cl = rfbClientIteratorNext(iter)) ) { 1739 ClientData *cd; 1740 cd = (ClientData *) cl->clientData; 1741 1742 if (cl->enableCursorShapeUpdates) { 1743 if (cd) { 1744 cd->had_cursor_shape_updates = 1; 1745 } 1746 count++; 1747 if (debug_pointer) { 1748 rfbLog("%s disable HCSU\n", cl->host); 1749 } 1750 } 1751 if (cl->enableCursorPosUpdates) { 1752 if (cd) { 1753 cd->had_cursor_pos_updates = 1; 1754 } 1755 count++; 1756 if (debug_pointer) { 1757 rfbLog("%s disable HCPU\n", cl->host); 1758 } 1759 } 1760 1761 cl->enableCursorShapeUpdates = FALSE; 1762 cl->enableCursorPosUpdates = FALSE; 1763 cl->cursorWasChanged = FALSE; 1764 } 1765 rfbReleaseClientIterator(iter); 1766 1767 if (count) { 1768 changed = 1; 1769 } 1770 } 1771 1772 int cursor_shape_updates_clients(rfbScreenInfoPtr s) { 1773 rfbClientIteratorPtr iter; 1774 rfbClientPtr cl; 1775 int count = 0; 1776 1777 if (! s) { 1778 return 0; 1779 } 1780 iter = rfbGetClientIterator(s); 1781 while( (cl = rfbClientIteratorNext(iter)) ) { 1782 if (cl->enableCursorShapeUpdates) { 1783 count++; 1784 } 1785 } 1786 rfbReleaseClientIterator(iter); 1787 return count; 1788 } 1789 1790 int cursor_noshape_updates_clients(rfbScreenInfoPtr s) { 1791 rfbClientIteratorPtr iter; 1792 rfbClientPtr cl; 1793 int count = 0; 1794 1795 if (! s) { 1796 return 0; 1797 } 1798 iter = rfbGetClientIterator(s); 1799 while( (cl = rfbClientIteratorNext(iter)) ) { 1800 if (!cl->enableCursorShapeUpdates) { 1801 count++; 1802 } 1803 } 1804 rfbReleaseClientIterator(iter); 1805 return count; 1806 } 1807 1808 int cursor_pos_updates_clients(rfbScreenInfoPtr s) { 1809 rfbClientIteratorPtr iter; 1810 rfbClientPtr cl; 1811 int count = 0; 1812 1813 if (! s) { 1814 return 0; 1815 } 1816 iter = rfbGetClientIterator(s); 1817 while( (cl = rfbClientIteratorNext(iter)) ) { 1818 if (cl->enableCursorPosUpdates) { 1819 count++; 1820 } 1821 } 1822 rfbReleaseClientIterator(iter); 1823 return count; 1824 } 1825 1826 /* 1827 * Record rfb cursor position screen->cursorX, etc (a la defaultPtrAddEvent()) 1828 * Then set up for sending rfbCursorPosUpdates back 1829 * to clients that understand them. This seems to be TightVNC specific. 1830 */ 1831 void cursor_position(int x, int y) { 1832 rfbClientIteratorPtr iter; 1833 rfbClientPtr cl; 1834 int cnt = 0, nonCursorPosUpdates_clients = 0; 1835 int x_in = x, y_in = y; 1836 1837 /* x and y are current positions of X11 pointer on the X11 display */ 1838 if (!screen) { 1839 return; 1840 } 1841 1842 if (scaling) { 1843 x = ((double) x / dpy_x) * scaled_x; 1844 x = nfix(x, scaled_x); 1845 y = ((double) y / dpy_y) * scaled_y; 1846 y = nfix(y, scaled_y); 1847 } 1848 1849 if (clipshift) { 1850 if (x < 0) x = 0; 1851 if (y < 0) y = 0; 1852 if (x >= dpy_x) x = dpy_x-1; 1853 if (y >= dpy_y) y = dpy_y-1; 1854 } 1855 1856 if (x == screen->cursorX && y == screen->cursorY) { 1857 return; 1858 } 1859 1860 LOCK(screen->cursorMutex); 1861 screen->cursorX = x; 1862 screen->cursorY = y; 1863 UNLOCK(screen->cursorMutex); 1864 1865 iter = rfbGetClientIterator(screen); 1866 while( (cl = rfbClientIteratorNext(iter)) ) { 1867 if (! cl->enableCursorPosUpdates) { 1868 nonCursorPosUpdates_clients++; 1869 continue; 1870 } 1871 if (! cursor_pos_updates) { 1872 continue; 1873 } 1874 if (cl == last_pointer_client) { 1875 /* 1876 * special case if this client was the last one to 1877 * send a pointer position. 1878 */ 1879 if (x_in == cursor_x && y_in == cursor_y) { 1880 cl->cursorWasMoved = FALSE; 1881 } else { 1882 /* an X11 app evidently warped the pointer */ 1883 if (debug_pointer) { 1884 rfbLog("cursor_position: warp " 1885 "detected dx=%3d dy=%3d\n", 1886 cursor_x - x, cursor_y - y); 1887 } 1888 cl->cursorWasMoved = TRUE; 1889 cnt++; 1890 } 1891 } else { 1892 cl->cursorWasMoved = TRUE; 1893 cnt++; 1894 } 1895 } 1896 rfbReleaseClientIterator(iter); 1897 1898 if (debug_pointer && cnt) { 1899 rfbLog("cursor_position: sent position x=%3d y=%3d to %d" 1900 " clients\n", x, y, cnt); 1901 } 1902 } 1903 1904 static void set_rfb_cursor(int which) { 1905 1906 if (! show_cursor) { 1907 return; 1908 } 1909 if (! screen) { 1910 return; 1911 } 1912 1913 if (!cursors[which] || !cursors[which]->rfb) { 1914 rfbLog("non-existent cursor: which=%d\n", which); 1915 return; 1916 } else { 1917 rfbSetCursor(screen, cursors[which]->rfb); 1918 } 1919 } 1920 1921 void set_no_cursor(void) { 1922 set_rfb_cursor(CURS_EMPTY); 1923 } 1924 1925 void set_warrow_cursor(void) { 1926 set_rfb_cursor(CURS_WARROW); 1927 } 1928 1929 int set_cursor(int x, int y, int which) { 1930 static int last = -1; 1931 int changed_cursor = 0; 1932 1933 if (x || y) {} /* unused vars warning: */ 1934 1935 if (which < 0) { 1936 which = last; 1937 } 1938 if (last < 0 || which != last) { 1939 set_rfb_cursor(which); 1940 changed_cursor = 1; 1941 } 1942 last = which; 1943 1944 return changed_cursor; 1945 } 1946 1947 /* 1948 * routine called periodically to update cursor aspects, this catches 1949 * warps and cursor shape changes. 1950 */ 1951 int check_x11_pointer(void) { 1952 Window root_w, child_w; 1953 rfbBool ret = 0; 1954 int root_x, root_y, win_x, win_y; 1955 int x, y, rint; 1956 unsigned int mask; 1957 1958 if (unixpw_in_progress) return 0; 1959 1960 #ifdef MACOSX 1961 if (macosx_console) { 1962 ret = macosx_get_cursor_pos(&root_x, &root_y); 1963 } else { 1964 RAWFB_RET(0) 1965 } 1966 #else 1967 1968 RAWFB_RET(0) 1969 1970 # if NO_X11 1971 return 0; 1972 # endif 1973 1974 #endif 1975 1976 1977 #if ! NO_X11 1978 if (dpy) { 1979 X_LOCK; 1980 ret = XQueryPointer_wr(dpy, rootwin, &root_w, &child_w, &root_x, &root_y, 1981 &win_x, &win_y, &mask); 1982 X_UNLOCK; 1983 } 1984 #else 1985 if (!mask || !win_y || !win_x || !child_w || !root_w) {} 1986 #endif /* NO_X11 */ 1987 1988 if (0) fprintf(stderr, "check_x11_pointer %d %d\n", root_x, root_y); 1989 if (! ret) { 1990 return 0; 1991 } 1992 if (debug_pointer) { 1993 static int last_x = -1, last_y = -1; 1994 if (root_x != last_x || root_y != last_y) { 1995 rfbLog("XQueryPointer: x:%4d, y:%4d)\n", 1996 root_x, root_y); 1997 } 1998 last_x = root_x; 1999 last_y = root_y; 2000 } 2001 2002 /* offset subtracted since XQueryPointer relative to rootwin */ 2003 x = root_x - off_x - coff_x; 2004 y = root_y - off_y - coff_y; 2005 2006 if (clipshift) { 2007 static int cnt = 0; 2008 if (x < 0 || y < 0 || x >= dpy_x || y >= dpy_y) { 2009 if (cnt++ % 4 != 0) { 2010 if (debug_pointer) { 2011 rfbLog("Skipping cursor_position() outside our clipshift\n"); 2012 } 2013 return 0; 2014 } 2015 } 2016 } 2017 2018 /* record the cursor position in the rfb screen */ 2019 cursor_position(x, y); 2020 2021 /* change the cursor shape if necessary */ 2022 rint = set_cursor(x, y, get_which_cursor()); 2023 return rint; 2024 } 2025 2026