~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/x11vnc/cursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

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