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 /* -- 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 */
curs_copy(cursor_info_t * dest,cursor_info_t * src)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
first_cursor(void)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
setup_cursors(void)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
setup_cursors_and_push(void)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 */
tree_descend_cursor(int * depth,Window * w,win_str_info_t * winfo)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
initialize_xfixes(void)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
pixels2curs(unsigned long * pixels,int w,int h,int xhot,int yhot,int Bpp)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
get_cursor_serial(int mode)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
get_exact_cursor(int init)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
store_cursor(int serial,unsigned long * data,int w,int h,int cbpp,int xhot,int yhot)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
known_cursors_mode(char * s)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
initialize_cursors_mode(void)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
get_which_cursor(void)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
set_cursor_was_changed(rfbScreenInfoPtr s)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
restore_cursor_shape_updates(rfbScreenInfoPtr s)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
disable_cursor_shape_updates(rfbScreenInfoPtr s)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
cursor_shape_updates_clients(rfbScreenInfoPtr s)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
cursor_noshape_updates_clients(rfbScreenInfoPtr s)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
cursor_pos_updates_clients(rfbScreenInfoPtr s)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 */
cursor_position(int x,int y)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
set_rfb_cursor(int which)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
set_no_cursor(void)1921 void set_no_cursor(void) {
1922 set_rfb_cursor(CURS_EMPTY);
1923 }
1924
set_warrow_cursor(void)1925 void set_warrow_cursor(void) {
1926 set_rfb_cursor(CURS_WARROW);
1927 }
1928
set_cursor(int x,int y,int which)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 */
check_x11_pointer(void)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