diff options
Diffstat (limited to 'x11vnc/cursor.c')
-rw-r--r-- | x11vnc/cursor.c | 2025 |
1 files changed, 0 insertions, 2025 deletions
diff --git a/x11vnc/cursor.c b/x11vnc/cursor.c deleted file mode 100644 index 3d613a6..0000000 --- a/x11vnc/cursor.c +++ /dev/null @@ -1,2025 +0,0 @@ -/* - Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> - All rights reserved. - -This file is part of x11vnc. - -x11vnc is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -x11vnc is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with x11vnc; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -or see <http://www.gnu.org/licenses/>. - -In addition, as a special exception, Karl J. Runge -gives permission to link the code of its release of x11vnc with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. -*/ - -/* -- cursor.c -- */ - -#include "x11vnc.h" -#include "xwrappers.h" -#include "cleanup.h" -#include "screen.h" -#include "scan.h" -#include "unixpw.h" -#include "macosx.h" - -int xfixes_present = 0; -int xfixes_first_initialized = 0; -int use_xfixes = 1; -int got_xfixes_cursor_notify = 0; -int cursor_changes = 0; -int alpha_threshold = 240; -double alpha_frac = 0.33; -int alpha_remove = 0; -int alpha_blend = 1; -int alt_arrow = 1; - - -void first_cursor(void); -void setup_cursors_and_push(void); -void initialize_xfixes(void); -int known_cursors_mode(char *s); -void initialize_cursors_mode(void); -int get_which_cursor(void); -void restore_cursor_shape_updates(rfbScreenInfoPtr s); -void disable_cursor_shape_updates(rfbScreenInfoPtr s); -int cursor_shape_updates_clients(rfbScreenInfoPtr s); -int cursor_pos_updates_clients(rfbScreenInfoPtr s); -void cursor_position(int x, int y); -void set_no_cursor(void); -void set_warrow_cursor(void); -int set_cursor(int x, int y, int which); -int check_x11_pointer(void); -int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot); -unsigned long get_cursor_serial(int mode); - - -typedef struct win_str_info { - char *wm_name; - char *res_name; - char *res_class; -} win_str_info_t; - -typedef struct cursor_info { - char *data; /* data and mask pointers */ - char *mask; - int wx, wy; /* size of cursor */ - int sx, sy; /* shift to its centering point */ - int reverse; /* swap black and white */ - rfbCursorPtr rfb; -} cursor_info_t; - - -static void curs_copy(cursor_info_t *dest, cursor_info_t *src); -static void setup_cursors(void); -static void set_rfb_cursor(int which); -static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo); -static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h, - int xhot, int yhot, int Bpp); -static int get_exact_cursor(int init); -static void set_cursor_was_changed(rfbScreenInfoPtr s); - - -/* - * Here begins a bit of a mess to experiment with multiple cursors - * drawn on the remote background ... - */ -static void curs_copy(cursor_info_t *dest, cursor_info_t *src) { - if (src->data != NULL) { - dest->data = strdup(src->data); - } else { - dest->data = NULL; - } - if (src->mask != NULL) { - dest->mask = strdup(src->mask); - } else { - dest->mask = NULL; - } - dest->wx = src->wx; - dest->wy = src->wy; - dest->sx = src->sx; - dest->sy = src->sy; - dest->reverse = src->reverse; - dest->rfb = src->rfb; - - if (rotating && rotating_cursors && dest->data != NULL) { - int tx, ty; - rotate_curs(dest->data, src->data, src->wx, src->wy, 1); - rotate_curs(dest->mask, src->mask, src->wx, src->wy, 1); - rotate_coords(dest->sx, dest->sy, &tx, &ty, src->wx, src->wy); - dest->sx = tx; - dest->sy = ty; - if (! rotating_same) { - dest->wx = src->wy; - dest->wy = src->wx; - } - } -} - -/* empty cursor */ -static char* curs_empty_data = -" " -" "; - -static char* curs_empty_mask = -" " -" "; -static cursor_info_t cur_empty = {NULL, NULL, 2, 2, 0, 0, 0, NULL}; - -/* dot cursor */ -static char* curs_dot_data = -" " -" x"; - -static char* curs_dot_mask = -" " -" x"; -static cursor_info_t cur_dot = {NULL, NULL, 2, 2, 0, 0, 0, NULL}; - - -/* main cursor */ -static char* curs_arrow_data = -" " -" x " -" xx " -" xxx " -" xxxx " -" xxxxx " -" xxxxxx " -" xxxxxxx " -" xxxxxxxx " -" xxxxx " -" xx xx " -" x xx " -" xx " -" xx " -" xx " -" " -" " -" "; - -static char* curs_arrow_mask = -"xx " -"xxx " -"xxxx " -"xxxxx " -"xxxxxx " -"xxxxxxx " -"xxxxxxxx " -"xxxxxxxxx " -"xxxxxxxxxx " -"xxxxxxxxxx " -"xxxxxxx " -"xxx xxxx " -"xx xxxx " -" xxxx " -" xxxx " -" xx " -" " -" "; -static cursor_info_t cur_arrow = {NULL, NULL, 18, 18, 0, 0, 1, NULL}; - -static char* curs_arrow2_data = -" " -" x " -" xx " -" xxx " -" xxxx " -" xxxxx " -" xxxxxx " -" xxxxxxx " -" xxxxxxxx " -" xxxxx " -" xx xx " -" x xx " -" xx " -" xx " -" xx " -" " -" " -" "; - -static char* curs_arrow2_mask = -"xx " -"xxx " -"xxxx " -"xxxxx " -"xxxxxx " -"xxxxxxx " -"xxxxxxxx " -"xxxxxxxxx " -"xxxxxxxxxx " -"xxxxxxxxxx " -"xxxxxxx " -"xxx xxxx " -"xx xxxx " -" xxxx " -" xxxx " -" xx " -" " -" "; -static cursor_info_t cur_arrow2 = {NULL, NULL, 18, 18, 0, 0, 0, NULL}; - -static char* curs_arrow3_data = -" " -" xx " -" xxxx " -" xxxxx " -" xxxxxxx " -" xxxxxxxx " -" xxxxxxxxxx " -" xxxxx " -" xxxxx " -" xx x " -" xx x " -" x x " -" x x " -" x " -" x " -" "; - -static char* curs_arrow3_mask = -"xxx " -"xxxxx " -"xxxxxxx " -" xxxxxxxx " -" xxxxxxxxxx " -" xxxxxxxxxxxx " -" xxxxxxxxxxxx " -" xxxxxxxxxxx " -" xxxxxxx " -" xxxxxxx " -" xxxx xxx " -" xxx xxx " -" xxx xxx " -" xxx xxx " -" xxx" -" xx"; - -static cursor_info_t cur_arrow3 = {NULL, NULL, 16, 16, 0, 0, 1, NULL}; - -static char* curs_arrow4_data = -" " -" xx " -" xxxx " -" xxxxx " -" xxxxxxx " -" xxxxxxxx " -" xxxxxxxxxx " -" xxxxx " -" xxxxx " -" xx x " -" xx x " -" x x " -" x x " -" x " -" x " -" "; - -static char* curs_arrow4_mask = -"xxx " -"xxxxx " -"xxxxxxx " -" xxxxxxxx " -" xxxxxxxxxx " -" xxxxxxxxxxxx " -" xxxxxxxxxxxx " -" xxxxxxxxxxx " -" xxxxxxx " -" xxxxxxx " -" xxxx xxx " -" xxx xxx " -" xxx xxx " -" xxx xxx " -" xxx" -" xx"; - -static cursor_info_t cur_arrow4 = {NULL, NULL, 16, 16, 0, 0, 0, NULL}; - -static char* curs_arrow5_data = -"x " -" xx " -" xxxx " -" xxxxx " -" xxxxxxx " -" xxx " -" xx x " -" x x " -" x x " -" x " -" x " -" x " -" x " -" x " -" x"; - -static char* curs_arrow5_mask = -"xx " -"xxxx " -" xxxxx " -" xxxxxxx " -" xxxxxxxx " -" xxxxxxxx " -" xxxxx " -" xxxxxx " -" xx xxx " -" x xxx " -" xxx " -" xxx " -" xxx " -" xxx" -" xx"; - -static cursor_info_t cur_arrow5 = {NULL, NULL, 15, 15, 0, 0, 1, NULL}; - -static char* curs_arrow6_data = -"x " -" xx " -" xxxx " -" xxxxx " -" xxxxxxx " -" xxx " -" xx x " -" x x " -" x x " -" x " -" x " -" x " -" x " -" x " -" x"; - -static char* curs_arrow6_mask = -"xx " -"xxxx " -" xxxxx " -" xxxxxxx " -" xxxxxxxx " -" xxxxxxxx " -" xxxxx " -" xxxxxx " -" xx xxx " -" x xxx " -" xxx " -" xxx " -" xxx " -" xxx" -" xx"; - -static cursor_info_t cur_arrow6 = {NULL, NULL, 15, 15, 0, 0, 0, NULL}; - -int alt_arrow_max = 6; -/* - * It turns out we can at least detect mouse is on the root window so - * show it (under -cursor X) with this familiar cursor... - */ -static char* curs_root_data = -" " -" " -" xxx xxx " -" xxxx xxxx " -" xxxxx xxxxx " -" xxxxx xxxxx " -" xxxxxxxxxx " -" xxxxxxxx " -" xxxxxx " -" xxxxxx " -" xxxxxxxx " -" xxxxxxxxxx " -" xxxxx xxxxx " -" xxxxx xxxxx " -" xxxx xxxx " -" xxx xxx " -" " -" "; - -static char* curs_root_mask = -" " -" xxxx xxxx " -" xxxxx xxxxx " -" xxxxxx xxxxxx " -" xxxxxxx xxxxxxx " -" xxxxxxxxxxxxxx " -" xxxxxxxxxxxx " -" xxxxxxxxxx " -" xxxxxxxx " -" xxxxxxxx " -" xxxxxxxxxx " -" xxxxxxxxxxxx " -" xxxxxxxxxxxxxx " -" xxxxxxx xxxxxxx " -" xxxxxx xxxxxx " -" xxxxx xxxxx " -" xxxx xxxx " -" "; -static cursor_info_t cur_root = {NULL, NULL, 18, 18, 8, 8, 1, NULL}; - -static char* curs_fleur_data = -" " -" xx " -" xxxx " -" xxxxxx " -" xx " -" x xx x " -" xx xx xx " -" xxxxxxxxxxxxxx " -" xxxxxxxxxxxxxx " -" xx xx xx " -" x xx x " -" xx " -" xxxxxx " -" xxxx " -" xx " -" "; - -static char* curs_fleur_mask = -" xxxx " -" xxxxx " -" xxxxxx " -" xxxxxxxx " -" x xxxxxx x " -" xxx xxxx xxx " -"xxxxxxxxxxxxxxxx" -"xxxxxxxxxxxxxxxx" -"xxxxxxxxxxxxxxxx" -"xxxxxxxxxxxxxxxx" -" xxx xxxx xxx " -" x xxxxxx x " -" xxxxxxxx " -" xxxxxx " -" xxxx " -" xxxx "; - -static cursor_info_t cur_fleur = {NULL, NULL, 16, 16, 8, 8, 1, NULL}; - -static char* curs_plus_data = -" " -" xx " -" xx " -" xx " -" xx " -" xxxxxxxxxx " -" xxxxxxxxxx " -" xx " -" xx " -" xx " -" xx " -" "; - -static char* curs_plus_mask = -" xxxx " -" xxxx " -" xxxx " -" xxxx " -"xxxxxxxxxxxx" -"xxxxxxxxxxxx" -"xxxxxxxxxxxx" -"xxxxxxxxxxxx" -" xxxx " -" xxxx " -" xxxx " -" xxxx "; -static cursor_info_t cur_plus = {NULL, NULL, 12, 12, 5, 6, 1, NULL}; - -static char* curs_xterm_data = -" " -" xxx xxx " -" xxx " -" x " -" x " -" x " -" x " -" x " -" x " -" x " -" x " -" x " -" x " -" xxx " -" xxx xxx " -" "; - -static char* curs_xterm_mask = -" xxxx xxxx " -" xxxxxxxxx " -" xxxxxxxxx " -" xxxxx " -" xxx " -" xxx " -" xxx " -" xxx " -" xxx " -" xxx " -" xxx " -" xxx " -" xxxxx " -" xxxxxxxxx " -" xxxxxxxxx " -" xxxx xxxx "; -static cursor_info_t cur_xterm = {NULL, NULL, 16, 16, 8, 8, 1, NULL}; - -enum cursor_names { - CURS_EMPTY = 0, - CURS_DOT, - - CURS_ARROW, - CURS_WARROW, - CURS_ROOT, - CURS_WM, - CURS_TERM, - CURS_PLUS, - - CURS_DYN1, - CURS_DYN2, - CURS_DYN3, - CURS_DYN4, - CURS_DYN5, - CURS_DYN6, - CURS_DYN7, - CURS_DYN8, - CURS_DYN9, - CURS_DYN10, - CURS_DYN11, - CURS_DYN12, - CURS_DYN13, - CURS_DYN14, - CURS_DYN15, - CURS_DYN16 -}; - -#define CURS_DYN_MIN CURS_DYN1 -#define CURS_DYN_MAX CURS_DYN16 -#define CURS_DYN_NUM (CURS_DYN_MAX - CURS_DYN_MIN + 1) - -#define CURS_MAX 32 -static cursor_info_t *cursors[CURS_MAX]; - -void first_cursor(void) { - if (! screen) { - return; - } - if (! show_cursor) { - LOCK(screen->cursorMutex); - screen->cursor = NULL; - UNLOCK(screen->cursorMutex); - } else { - got_xfixes_cursor_notify++; - set_rfb_cursor(get_which_cursor()); - set_cursor_was_changed(screen); - } -} - -static void setup_cursors(void) { - rfbCursorPtr rfb_curs; - char *scale = NULL; - int i, j, n = 0; - int w_in = 0, h_in = 0; - static int first = 1; - - if (verbose || use_threads) { - rfbLog("setting up %d cursors...\n", CURS_MAX); - } - - if (first) { - for (i=0; i<CURS_MAX; i++) { - cursors[i] = NULL; - } - } - first = 0; - - if (screen) { - LOCK(screen->cursorMutex); - screen->cursor = NULL; - } - - for (i=0; i<CURS_MAX; i++) { - cursor_info_t *ci; - if (cursors[i]) { - /* clear out any existing ones: */ - ci = cursors[i]; - if (ci->rfb) { - /* this is the rfbCursor part: */ - if (ci->rfb->richSource) { - free(ci->rfb->richSource); - ci->rfb->richSource = NULL; - } - if (ci->rfb->source) { - free(ci->rfb->source); - ci->rfb->source = NULL; - } - if (ci->rfb->mask) { - free(ci->rfb->mask); - ci->rfb->mask = NULL; - } - free(ci->rfb); - ci->rfb = NULL; - } - if (ci->data) { - free(ci->data); - ci->data = NULL; - } - if (ci->mask) { - free(ci->mask); - ci->mask = NULL; - } - free(ci); - ci = NULL; - } - - /* create new struct: */ - ci = (cursor_info_t *) malloc(sizeof(cursor_info_t)); - ci->data = NULL; - ci->mask = NULL; - ci->wx = 0; - ci->wy = 0; - ci->sx = 0; - ci->sy = 0; - ci->reverse = 0; - ci->rfb = NULL; - cursors[i] = ci; - } - - /* clear any xfixes cursor cache (no freeing is done) */ - get_exact_cursor(1); - - /* manually fill in the data+masks: */ - cur_empty.data = curs_empty_data; - cur_empty.mask = curs_empty_mask; - - cur_dot.data = curs_dot_data; - cur_dot.mask = curs_dot_mask; - - cur_arrow.data = curs_arrow_data; - cur_arrow.mask = curs_arrow_mask; - cur_arrow2.data = curs_arrow2_data; - cur_arrow2.mask = curs_arrow2_mask; - cur_arrow3.data = curs_arrow3_data; - cur_arrow3.mask = curs_arrow3_mask; - cur_arrow4.data = curs_arrow4_data; - cur_arrow4.mask = curs_arrow4_mask; - cur_arrow5.data = curs_arrow5_data; - cur_arrow5.mask = curs_arrow5_mask; - cur_arrow6.data = curs_arrow6_data; - cur_arrow6.mask = curs_arrow6_mask; - - cur_root.data = curs_root_data; - cur_root.mask = curs_root_mask; - - cur_plus.data = curs_plus_data; - cur_plus.mask = curs_plus_mask; - - cur_fleur.data = curs_fleur_data; - cur_fleur.mask = curs_fleur_mask; - - cur_xterm.data = curs_xterm_data; - cur_xterm.mask = curs_xterm_mask; - - curs_copy(cursors[CURS_EMPTY], &cur_empty); n++; - curs_copy(cursors[CURS_DOT], &cur_dot); n++; - - if (alt_arrow < 1 || alt_arrow > alt_arrow_max) { - alt_arrow = 1; - } - if (alt_arrow == 1) { - curs_copy(cursors[CURS_ARROW], &cur_arrow); n++; - } else if (alt_arrow == 2) { - curs_copy(cursors[CURS_ARROW], &cur_arrow2); n++; - } else if (alt_arrow == 3) { - curs_copy(cursors[CURS_ARROW], &cur_arrow3); n++; - } else if (alt_arrow == 4) { - curs_copy(cursors[CURS_ARROW], &cur_arrow4); n++; - } else if (alt_arrow == 5) { - curs_copy(cursors[CURS_ARROW], &cur_arrow5); n++; - } else if (alt_arrow == 6) { - curs_copy(cursors[CURS_ARROW], &cur_arrow6); n++; - } else { - alt_arrow = 1; - curs_copy(cursors[CURS_ARROW], &cur_arrow); n++; - } - curs_copy(cursors[CURS_WARROW], &cur_arrow2); n++; - - curs_copy(cursors[CURS_ROOT], &cur_root); n++; - curs_copy(cursors[CURS_WM], &cur_fleur); n++; - curs_copy(cursors[CURS_TERM], &cur_xterm); n++; - curs_copy(cursors[CURS_PLUS], &cur_plus); n++; - - if (scale_cursor_str) { - scale = scale_cursor_str; - } else if (scaling && scale_str) { - scale = scale_str; - } - if (scale && sscanf(scale, "%dx%d", &i, &j) == 2) { - if (wdpy_x > 0) { - w_in = wdpy_x; - h_in = wdpy_y; - } else { - w_in = dpy_x; - h_in = dpy_y; - } - } - - /* scale = NULL zeroes everything */ - parse_scale_string(scale, &scale_cursor_fac_x, &scale_cursor_fac_y, &scaling_cursor, - &scaling_cursor_blend, &j, &j, &scaling_cursor_interpolate, - &scale_cursor_numer, &scale_cursor_denom, w_in, h_in); - - for (i=0; i<n; i++) { - /* create rfbCursors for the special cursors: */ - - cursor_info_t *ci = cursors[i]; - - if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) { - int w, h, x, y, k; - unsigned long *pixels; - - w = ci->wx; - h = ci->wy; - - pixels = (unsigned long *) malloc(w * h - * sizeof(unsigned long)); - - k = 0; - for (y=0; y<h; y++) { - for (x=0; x<w; x++) { - char d = ci->data[k]; - char m = ci->mask[k]; - unsigned long *p; - - p = pixels + k; - - /* set alpha on */ - *p = 0xff000000; - - if (d == ' ' && m == ' ') { - /* alpha off */ - *p = 0x00000000; - } else if (d != ' ') { - /* body */ - if (ci->reverse) { - *p |= 0x00000000; - } else { - *p |= 0x00ffffff; - } - } else if (m != ' ') { - /* edge */ - if (ci->reverse) { - *p |= 0x00ffffff; - } else { - *p |= 0x00000000; - } - } - k++; - } - } - - rfb_curs = pixels2curs(pixels, w, h, ci->sx, ci->sy, - bpp/8); - - free(pixels); - - } else { - - /* standard X cursor */ - rfb_curs = rfbMakeXCursor(ci->wx, ci->wy, - ci->data, ci->mask); - - if (ci->reverse) { - rfb_curs->foreRed = 0x0000; - rfb_curs->foreGreen = 0x0000; - rfb_curs->foreBlue = 0x0000; - rfb_curs->backRed = 0xffff; - rfb_curs->backGreen = 0xffff; - rfb_curs->backBlue = 0xffff; - } - rfb_curs->alphaSource = NULL; - - rfb_curs->xhot = ci->sx; - rfb_curs->yhot = ci->sy; - rfb_curs->cleanup = FALSE; - rfb_curs->cleanupSource = FALSE; - rfb_curs->cleanupMask = FALSE; - rfb_curs->cleanupRichSource = FALSE; - - if (bpp == 8 && indexed_color) { - /* - * use richsource in PseudoColor for better - * looking cursors (i.e. two-color). - */ - int x, y, k = 0, bw; - int black = 0, white = 1; - char d, m; - - if (dpy) { /* raw_fb hack */ - black = BlackPixel(dpy, scr); - white = WhitePixel(dpy, scr); - } - - rfb_curs->richSource = (unsigned char *) - calloc(ci->wx * ci->wy, 1); - - for (y = 0; y < ci->wy; y++) { - for (x = 0; x < ci->wx; x++) { - d = *(ci->data + k); - m = *(ci->mask + k); - if (d == ' ' && m == ' ') { - k++; - continue; - } else if (m != ' ' && d == ' ') { - bw = black; - } else { - bw = white; - } - if (ci->reverse) { - if (bw == black) { - bw = white; - } else { - bw = black; - } - } - *(rfb_curs->richSource+k) = - (unsigned char) bw; - k++; - } - } - } - } - ci->rfb = rfb_curs; - } - if (screen) { - UNLOCK(screen->cursorMutex); - } - if (verbose) { - rfbLog(" done.\n"); - } - rfbLog("\n"); -} - -void setup_cursors_and_push(void) { - setup_cursors(); - first_cursor(); -} - -/* - * Descends window tree at pointer until the window cursor matches the current - * cursor. So far only used to detect if mouse is on root background or not. - * (returns 0 in that case, 1 otherwise). - * - */ -static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) { -#if NO_X11 - RAWFB_RET_VOID - if (!depth || !w || !winfo) {} - return; -#else - Window r, c; - int i, rx, ry, wx, wy; - unsigned int mask; - Window wins[10]; - int descend, maxtries = 10; - char *name, *s = multiple_cursors_mode; - static XClassHint *classhint = NULL; - int nm_info = 1; - XErrorHandler old_handler; - - RAWFB_RET_VOID - - if (!strcmp(s, "default") || !strcmp(s, "X") || !strcmp(s, "arrow")) { - nm_info = 0; - } - - *(winfo->wm_name) = '\0'; - *(winfo->res_name) = '\0'; - *(winfo->res_class) = '\0'; - - for (i=0; i < maxtries; i++) { - wins[i] = None; - } - - /* some times a window can go away before we get to it */ - trapped_xerror = 0; - old_handler = XSetErrorHandler(trap_xerror); - - c = window; - descend = -1; - - while (c) { - wins[++descend] = c; - if (descend >= maxtries - 1) { - break; - } - if ( XTestCompareCurrentCursorWithWindow_wr(dpy, c) ) { - break; - } - /* TBD: query_pointer() */ - XQueryPointer_wr(dpy, c, &r, &c, &rx, &ry, &wx, &wy, &mask); - } - - if (nm_info) { - int got_wm_name = 0, got_res_name = 0, got_res_class = 0; - - if (! classhint) { - classhint = XAllocClassHint(); - } - - for (i = descend; i >=0; i--) { - c = wins[i]; - if (! c) { - continue; - } - - if (! got_wm_name && XFetchName(dpy, c, &name)) { - if (name) { - if (*name != '\0') { - strcpy(winfo->wm_name, name); - got_wm_name = 1; - } - XFree_wr(name); - } - } - if (classhint && (! got_res_name || ! got_res_class)) { - if (XGetClassHint(dpy, c, classhint)) { - char *p; - p = classhint->res_name; - if (p) { - if (*p != '\0' && ! got_res_name) { - strcpy(winfo->res_name, p); - got_res_name = 1; - } - XFree_wr(p); - classhint->res_name = NULL; - } - p = classhint->res_class; - if (p) { - if (*p != '\0' && ! got_res_class) { - strcpy(winfo->res_class, p); - got_res_class = 1; - } - XFree_wr(p); - classhint->res_class = NULL; - } - } - } - } - } - - XSetErrorHandler(old_handler); - trapped_xerror = 0; - - *depth = descend; - *w = wins[descend]; -#endif /* NO_X11 */ -} - -void initialize_xfixes(void) { -#if LIBVNCSERVER_HAVE_LIBXFIXES - if (xfixes_present) { - X_LOCK; - if (use_xfixes) { - XFixesSelectCursorInput(dpy, rootwin, - XFixesDisplayCursorNotifyMask); - } else { - XFixesSelectCursorInput(dpy, rootwin, 0); - } - X_UNLOCK; - xfixes_first_initialized = 1; - } -#endif -} - -static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h, - int xhot, int yhot, int Bpp) { - rfbCursorPtr c; - static unsigned long black = 0, white = 1; - static int first = 1; - char *bitmap, *rich, *alpha; - char *pixels_new = NULL; - int n_opaque, n_trans, n_alpha, len, histo[256]; - int send_alpha = 0, alpha_shift = 0, thresh; - int i, x, y; - - if (first && dpy) { /* raw_fb hack */ - X_LOCK; - black = BlackPixel(dpy, scr); - white = WhitePixel(dpy, scr); - X_UNLOCK; - first = 0; - } - - if (cmap8to24 && cmap8to24_fb && depth <= 16) { - if (Bpp <= 2) { - Bpp = 4; - } - } - - if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) { - int W, H; - char *pixels_use = (char *) pixels; - unsigned int *pixels32 = NULL; - - W = w; - H = h; - - w = scale_round(W, scale_cursor_fac_x); - h = scale_round(H, scale_cursor_fac_y); - - pixels_new = (char *) malloc(4*w*h); - - if (sizeof(unsigned long) == 8) { - int i, j, k = 0; - /* - * to avoid 64bpp code in scale_rect() we knock - * down to unsigned int on 64bit machines: - */ - pixels32 = (unsigned int*) malloc(4*W*H); - for (j=0; j<H; j++) { - for (i=0; i<W; i++) { - *(pixels32+k) = 0xffffffff & (*(pixels+k)); - k++; - } - } - pixels_use = (char *) pixels32; - } - - scale_rect(scale_cursor_fac_x, scale_cursor_fac_y, scaling_cursor_blend, - scaling_cursor_interpolate, - 4, pixels_use, 4*W, pixels_new, 4*w, - W, H, w, h, 0, 0, W, H, 0); - - if (sizeof(unsigned long) == 8) { - int i, j, k = 0; - unsigned long *pixels64; - unsigned int* source = (unsigned int*) pixels_new; - /* - * now knock it back up to unsigned long: - */ - pixels64 = (unsigned long*) malloc(8*w*h); - for (j=0; j<h; j++) { - for (i=0; i<w; i++) { - *(pixels64+k) = (unsigned long) (*(source+k)); - k++; - } - } - free(pixels_new); - pixels_new = (char *) pixels64; - if (pixels32) { - free(pixels32); - pixels32 = NULL; - } - } - - pixels = (unsigned long *) pixels_new; - - xhot = scale_round(xhot, scale_cursor_fac_x); - yhot = scale_round(yhot, scale_cursor_fac_y); - } - - len = w * h; - /* for bitmap data */ - bitmap = (char *) malloc(len+1); - bitmap[len] = '\0'; - - /* for rich cursor pixel data */ - rich = (char *)calloc(Bpp*len, 1); - alpha = (char *)calloc(1*len, 1); - - n_opaque = 0; - n_trans = 0; - n_alpha = 0; - for (i=0; i<256; i++) { - histo[i] = 0; - } - - i = 0; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - unsigned long a; - - a = 0xff000000 & (*(pixels+i)); - a = a >> 24; /* alpha channel */ - if (a > 0) { - n_alpha++; - } - histo[a]++; - if (a < (unsigned int) alpha_threshold) { - n_trans++; - } else { - n_opaque++; - } - i++; - } - } - if (alpha_blend) { - send_alpha = 0; - if (Bpp == 4) { - send_alpha = 1; - } - alpha_shift = 24; - if (main_red_shift == 24 || main_green_shift == 24 || - main_blue_shift == 24) { - alpha_shift = 0; /* XXX correct? */ - } - } - if (n_opaque >= alpha_frac * n_alpha) { - thresh = alpha_threshold; - } else { - n_opaque = 0; - for (i=255; i>=0; i--) { - n_opaque += histo[i]; - thresh = i; - if (n_opaque >= alpha_frac * n_alpha) { - break; - } - } - } - - i = 0; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - unsigned long r, g, b, a; - unsigned int ui; - char *p; - - a = 0xff000000 & (*(pixels+i)); - a = a >> 24; /* alpha channel */ - - if (a < (unsigned int) thresh) { - bitmap[i] = ' '; - } else { - bitmap[i] = 'x'; - } - - r = 0x00ff0000 & (*(pixels+i)); - g = 0x0000ff00 & (*(pixels+i)); - b = 0x000000ff & (*(pixels+i)); - r = r >> 16; /* red */ - g = g >> 8; /* green */ - b = b >> 0; /* blue */ - - if (alpha_remove && a != 0) { - r = (255 * r) / a; - g = (255 * g) / a; - b = (255 * b) / a; - if (r > 255) r = 255; - if (g > 255) g = 255; - if (b > 255) b = 255; - } - - if (indexed_color) { - /* - * Choose black or white for - * PseudoColor case. - */ - int value = (r+g+b)/3; - if (value > 127) { - ui = white; - } else { - ui = black; - } - } else { - /* - * Otherwise map the RGB data onto - * the framebuffer format: - */ - r = (main_red_max * r)/255; - g = (main_green_max * g)/255; - b = (main_blue_max * b)/255; - ui = 0; - ui |= (r << main_red_shift); - ui |= (g << main_green_shift); - ui |= (b << main_blue_shift); - if (send_alpha) { - ui |= (a << alpha_shift); - } - } - - /* insert value into rich source: */ - p = rich + Bpp*i; - - if (Bpp == 1) { - *((unsigned char *)p) - = (unsigned char) ui; - } else if (Bpp == 2) { - *((unsigned short *)p) - = (unsigned short) ui; - } else if (Bpp == 3) { - *((unsigned char *)p) - = (unsigned char) ((ui & 0x0000ff) >> 0); - *((unsigned char *)(p+1)) - = (unsigned char) ((ui & 0x00ff00) >> 8); - *((unsigned char *)(p+2)) - = (unsigned char) ((ui & 0xff0000) >> 16); - } else if (Bpp == 4) { - *((unsigned int *)p) - = (unsigned int) ui; - } - - /* insert alpha value into alpha source: */ - p = alpha + i; - *((unsigned char *)p) = (unsigned char) a; - - i++; - } - } - - /* create the cursor with the bitmap: */ - c = rfbMakeXCursor(w, h, bitmap, bitmap); - free(bitmap); - - if (pixels_new) { - free(pixels_new); - } - - /* set up the cursor parameters: */ - c->xhot = xhot; - c->yhot = yhot; - c->cleanup = FALSE; - c->cleanupSource = FALSE; - c->cleanupMask = FALSE; - c->cleanupRichSource = FALSE; - c->richSource = (unsigned char *) rich; - - /* zeroes mean interpolate the rich cursor somehow and use B+W */ - c->foreRed = 0; - c->foreGreen = 0; - c->foreBlue = 0; - c->backRed = 0; - c->backGreen = 0; - c->backBlue = 0; - - c->source = NULL; - - if (alpha_blend && !indexed_color) { - c->alphaSource = (unsigned char *) alpha; - c->alphaPreMultiplied = TRUE; - } else { - free(alpha); - c->alphaSource = NULL; - } - return c; -} - -static unsigned long last_cursor = 0; -static int last_index = 0; -static time_t curs_times[CURS_MAX]; -static unsigned long curs_index[CURS_MAX]; - -unsigned long get_cursor_serial(int mode) { - if (mode == 0) { - return last_cursor; - } else if (mode == 1) { - return (unsigned long) last_index; - } else { - return (unsigned long) last_index; - } -} - -static int get_exact_cursor(int init) { - int which = CURS_ARROW; - - if (init) { - /* zero out our cache (cursors are not freed) */ - int i; - for (i=0; i<CURS_MAX; i++) { - curs_times[i] = 0; - curs_index[i] = 0; - } - last_cursor = 0; - last_index = 0; - return -1; - } - -#ifdef MACOSX - if (macosx_console) { - return macosx_get_cursor(); - } -#endif - - if (rawfb_vnc_reflect) { - int last_idx = (int) get_cursor_serial(1); - if (last_idx) { - which = last_idx; - } - return which; - } - if (xfixes_present && dpy) { -#if LIBVNCSERVER_HAVE_LIBXFIXES - int last_idx = (int) get_cursor_serial(1); - XFixesCursorImage *xfc; - - if (last_idx) { - which = last_idx; - } - if (! xfixes_first_initialized) { - return which; - } - - X_LOCK; - if (! got_xfixes_cursor_notify && xfixes_base_event_type) { - /* try again for XFixesCursorNotify event */ - XEvent xev; - if (XCheckTypedEvent(dpy, xfixes_base_event_type + - XFixesCursorNotify, &xev)) { - got_xfixes_cursor_notify++; - } - } - if (! got_xfixes_cursor_notify) { - /* evidently no cursor change, just return last one */ - X_UNLOCK; - return which; - } - got_xfixes_cursor_notify = 0; - - /* retrieve the cursor info + pixels from server: */ - xfc = XFixesGetCursorImage(dpy); - X_UNLOCK; - if (! xfc) { - /* failure. */ - return which; - } - - which = store_cursor(xfc->cursor_serial, xfc->pixels, - xfc->width, xfc->height, 32, xfc->xhot, xfc->yhot); - - X_LOCK; - XFree_wr(xfc); - X_UNLOCK; -#endif - } - return(which); -} - -int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, - int xhot, int yhot) { - int which = CURS_ARROW; - int use, oldest, i; - time_t oldtime, now; - -#if 0 -fprintf(stderr, "sc: %d %d/%d %d - %d %d\n", serial, w, h, cbpp, xhot, yhot); -#endif - - oldest = CURS_DYN_MIN; - if (screen && screen->cursor == cursors[oldest]->rfb) { - oldest++; - } - oldtime = curs_times[oldest]; - now = time(NULL); - for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) { - if (screen && screen->cursor == cursors[i]->rfb) { - ; - } else if (curs_times[i] < oldtime) { - /* watch for oldest one to overwrite */ - oldest = i; - oldtime = curs_times[i]; - } - if (serial == (int) curs_index[i]) { - /* - * got a hit with an existing cursor, - * use that one. - */ -#ifdef MACOSX - if (now > curs_times[i] + 1) { - continue; - } -#endif - last_cursor = curs_index[i]; - curs_times[i] = now; - last_index = i; - return last_index; - } - } - - /* we need to create the cursor and overwrite oldest */ - use = oldest; - if (cursors[use]->rfb) { - /* clean up oldest if it exists */ - if (cursors[use]->rfb->richSource) { - free(cursors[use]->rfb->richSource); - cursors[use]->rfb->richSource = NULL; - } - if (cursors[use]->rfb->alphaSource) { - free(cursors[use]->rfb->alphaSource); - cursors[use]->rfb->alphaSource = NULL; - } - if (cursors[use]->rfb->source) { - free(cursors[use]->rfb->source); - cursors[use]->rfb->source = NULL; - } - if (cursors[use]->rfb->mask) { - free(cursors[use]->rfb->mask); - cursors[use]->rfb->mask = NULL; - } - free(cursors[use]->rfb); - cursors[use]->rfb = NULL; - } - - if (rotating && rotating_cursors) { - char *dst; - int tx, ty; - - dst = (char *) malloc(w * h * cbpp/8); - rotate_curs(dst, (char *) data, w, h, cbpp/8); - - memcpy(data, dst, w * h * cbpp/8); - free(dst); - - rotate_coords(xhot, yhot, &tx, &ty, w, h); - xhot = tx; - yhot = ty; - if (! rotating_same) { - int tmp = w; - w = h; - h = tmp; - } - } - - /* place cursor into our collection */ - cursors[use]->rfb = pixels2curs(data, w, h, xhot, yhot, bpp/8); - - /* update time and serial index: */ - curs_times[use] = now; - curs_index[use] = serial; - last_index = use; - last_cursor = serial; - - which = last_index; - - return which; -} - -int known_cursors_mode(char *s) { -/* - * default: see initialize_cursors_mode() for default behavior. - * arrow: unchanging white arrow. - * Xn*: show X on root background. Optional n sets treedepth. - * some: do the heuristics for root, wm, term detection. - * most: if display have overlay or xfixes, show all cursors, - * otherwise do the same as "some" - * none: show no cursor. - */ - if (strcmp(s, "default") && strcmp(s, "arrow") && *s != 'X' && - strcmp(s, "some") && strcmp(s, "most") && strcmp(s, "none")) { - return 0; - } else { - return 1; - } -} - -void initialize_cursors_mode(void) { - char *s = multiple_cursors_mode; - if (!s || !known_cursors_mode(s)) { - rfbLog("unknown cursors mode: %s\n", s); - rfbLog("resetting cursors mode to \"default\"\n"); - if (multiple_cursors_mode) free(multiple_cursors_mode); - multiple_cursors_mode = strdup("default"); - s = multiple_cursors_mode; - } - if (!strcmp(s, "none")) { - show_cursor = 0; - } else { - /* we do NOT set show_cursor = 1, let the caller do that */ - } - - show_multiple_cursors = 0; - if (show_cursor) { - if (!strcmp(s, "default")) { - if(multiple_cursors_mode) free(multiple_cursors_mode); - multiple_cursors_mode = strdup("X"); - s = multiple_cursors_mode; - } - if (*s == 'X' || !strcmp(s, "some") || !strcmp(s, "most")) { - show_multiple_cursors = 1; - } else { - show_multiple_cursors = 0; - /* hmmm, some bug going back to arrow mode.. */ - set_rfb_cursor(CURS_ARROW); - } - if (screen) { - set_cursor_was_changed(screen); - } - } else { - if (screen) { - LOCK(screen->cursorMutex); - screen->cursor = NULL; - UNLOCK(screen->cursorMutex); - set_cursor_was_changed(screen); - } - } -} - -int get_which_cursor(void) { - int which = CURS_ARROW; - int db = 0; - - if (show_multiple_cursors) { - int depth = 0, rint; - static win_str_info_t winfo; - static int first = 1, depth_cutoff = -1; - Window win = None; - XErrorHandler old_handler; - int mode = 0; - - if (drag_in_progress || button_mask) { - /* XXX not exactly what we want for menus */ - if (! cursor_drag_changes) { - return -1; - } - } - - if (!strcmp(multiple_cursors_mode, "arrow")) { - /* should not happen... */ - return CURS_ARROW; - } else if (!strcmp(multiple_cursors_mode, "default")) { - mode = 0; - } else if (!strcmp(multiple_cursors_mode, "X")) { - mode = 1; - } else if (!strcmp(multiple_cursors_mode, "some")) { - mode = 2; - } else if (!strcmp(multiple_cursors_mode, "most")) { - mode = 3; - } - - if (rawfb_vnc_reflect && mode > -1) { - rint = get_exact_cursor(0); - return rint; - } - if (mode == 3) { - if ((xfixes_present && use_xfixes) || macosx_console) { - if (db) fprintf(stderr, "get_which_cursor call get_exact_cursor\n"); - rint = get_exact_cursor(0); - return rint; - } - } - - if (depth_cutoff < 0) { - int din; - if (sscanf(multiple_cursors_mode, "X%d", &din) == 1) { - depth_cutoff = din; - } else { - depth_cutoff = 0; - } - } - - if (first) { - winfo.wm_name = (char *) malloc(1024); - winfo.res_name = (char *) malloc(1024); - winfo.res_class = (char *) malloc(1024); - } - first = 0; - - X_LOCK; - tree_descend_cursor(&depth, &win, &winfo); - X_UNLOCK; - - if (depth <= depth_cutoff && !subwin) { - which = CURS_ROOT; - - } else if (mode == 2 || mode == 3) { - int which0 = which; - - /* apply crude heuristics to choose a cursor... */ - if (win && dpy) { - int ratio = 10, x, y; - unsigned int w, h, bw, d; - Window r; - -#if !NO_X11 - trapped_xerror = 0; - X_LOCK; - old_handler = XSetErrorHandler(trap_xerror); - - /* "narrow" windows are WM */ - if (XGetGeometry(dpy, win, &r, &x, &y, &w, &h, - &bw, &d)) { - if (w > ratio * h || h > ratio * w) { - which = CURS_WM; - } - } - XSetErrorHandler(old_handler); - X_UNLOCK; - trapped_xerror = 0; -#else - if (!r || !d || !bw || !h || !w || !y || !x || !ratio || !old_handler) {} -#endif /* NO_X11 */ - } - if (which == which0) { - /* the string "term" means I-beam. */ - char *name, *class; - lowercase(winfo.res_name); - lowercase(winfo.res_class); - name = winfo.res_name; - class = winfo.res_class; - if (strstr(name, "term")) { - which = CURS_TERM; - } else if (strstr(class, "term")) { - which = CURS_TERM; - } else if (strstr(name, "text")) { - which = CURS_TERM; - } else if (strstr(class, "text")) { - which = CURS_TERM; - } else if (strstr(name, "onsole")) { - which = CURS_TERM; - } else if (strstr(class, "onsole")) { - which = CURS_TERM; - } else if (strstr(name, "cmdtool")) { - which = CURS_TERM; - } else if (strstr(class, "cmdtool")) { - which = CURS_TERM; - } else if (strstr(name, "shelltool")) { - which = CURS_TERM; - } else if (strstr(class, "shelltool")) { - which = CURS_TERM; - } - } - } - } - if (db) fprintf(stderr, "get_which_cursor which: %d\n", which); - return which; -} - -static void set_cursor_was_changed(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - - if (! s) { - return; - } - iter = rfbGetClientIterator(s); - LOCK(screen->cursorMutex); - while( (cl = rfbClientIteratorNext(iter)) ) { - cl->cursorWasChanged = TRUE; - } - UNLOCK(screen->cursorMutex); - rfbReleaseClientIterator(iter); -} - -#if 0 -/* not yet used */ -static void set_cursor_was_moved(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - - if (! s) { - return; - } - iter = rfbGetClientIterator(s); - while( (cl = rfbClientIteratorNext(iter)) ) { - cl->cursorWasMoved = TRUE; - } - rfbReleaseClientIterator(iter); -} -#endif - -void restore_cursor_shape_updates(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int count = 0; - - if (! s || ! s->clientHead) { - return; - } - iter = rfbGetClientIterator(s); - while( (cl = rfbClientIteratorNext(iter)) ) { - int changed = 0; - ClientData *cd = (ClientData *) cl->clientData; - - if (! cd) { - continue; - } - if (cd->had_cursor_shape_updates) { - rfbLog("restoring enableCursorShapeUpdates for client" - " 0x%x\n", cl); - cl->enableCursorShapeUpdates = TRUE; - changed = 1; - } - if (cd->had_cursor_pos_updates) { - rfbLog("restoring enableCursorPosUpdates for client" - " 0x%x\n", cl); - cl->enableCursorPosUpdates = TRUE; - changed = 1; - } - if (changed) { - cl->cursorWasChanged = TRUE; - count++; - } - } - rfbReleaseClientIterator(iter); -} - -void disable_cursor_shape_updates(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - static int changed = 0; - int count = 0; - - if (! s || ! s->clientHead) { - return; - } - if (unixpw_in_progress) return; - - iter = rfbGetClientIterator(s); - while( (cl = rfbClientIteratorNext(iter)) ) { - ClientData *cd; - cd = (ClientData *) cl->clientData; - - if (cl->enableCursorShapeUpdates) { - if (cd) { - cd->had_cursor_shape_updates = 1; - } - count++; - if (debug_pointer) { - rfbLog("%s disable HCSU\n", cl->host); - } - } - if (cl->enableCursorPosUpdates) { - if (cd) { - cd->had_cursor_pos_updates = 1; - } - count++; - if (debug_pointer) { - rfbLog("%s disable HCPU\n", cl->host); - } - } - - cl->enableCursorShapeUpdates = FALSE; - cl->enableCursorPosUpdates = FALSE; - cl->cursorWasChanged = FALSE; - } - rfbReleaseClientIterator(iter); - - if (count) { - changed = 1; - } -} - -int cursor_shape_updates_clients(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int count = 0; - - if (! s) { - return 0; - } - iter = rfbGetClientIterator(s); - while( (cl = rfbClientIteratorNext(iter)) ) { - if (cl->enableCursorShapeUpdates) { - count++; - } - } - rfbReleaseClientIterator(iter); - return count; -} - -int cursor_noshape_updates_clients(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int count = 0; - - if (! s) { - return 0; - } - iter = rfbGetClientIterator(s); - while( (cl = rfbClientIteratorNext(iter)) ) { - if (!cl->enableCursorShapeUpdates) { - count++; - } - } - rfbReleaseClientIterator(iter); - return count; -} - -int cursor_pos_updates_clients(rfbScreenInfoPtr s) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int count = 0; - - if (! s) { - return 0; - } - iter = rfbGetClientIterator(s); - while( (cl = rfbClientIteratorNext(iter)) ) { - if (cl->enableCursorPosUpdates) { - count++; - } - } - rfbReleaseClientIterator(iter); - return count; -} - -/* - * Record rfb cursor position screen->cursorX, etc (a la defaultPtrAddEvent()) - * Then set up for sending rfbCursorPosUpdates back - * to clients that understand them. This seems to be TightVNC specific. - */ -void cursor_position(int x, int y) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int cnt = 0, nonCursorPosUpdates_clients = 0; - int x_in = x, y_in = y; - - /* x and y are current positions of X11 pointer on the X11 display */ - if (!screen) { - return; - } - - if (scaling) { - x = ((double) x / dpy_x) * scaled_x; - x = nfix(x, scaled_x); - y = ((double) y / dpy_y) * scaled_y; - y = nfix(y, scaled_y); - } - - if (clipshift) { - if (x < 0) x = 0; - if (y < 0) y = 0; - if (x >= dpy_x) x = dpy_x-1; - if (y >= dpy_y) y = dpy_y-1; - } - - if (x == screen->cursorX && y == screen->cursorY) { - return; - } - - LOCK(screen->cursorMutex); - screen->cursorX = x; - screen->cursorY = y; - UNLOCK(screen->cursorMutex); - - iter = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(iter)) ) { - if (! cl->enableCursorPosUpdates) { - nonCursorPosUpdates_clients++; - continue; - } - if (! cursor_pos_updates) { - continue; - } - if (cl == last_pointer_client) { - /* - * special case if this client was the last one to - * send a pointer position. - */ - if (x_in == cursor_x && y_in == cursor_y) { - cl->cursorWasMoved = FALSE; - } else { - /* an X11 app evidently warped the pointer */ - if (debug_pointer) { - rfbLog("cursor_position: warp " - "detected dx=%3d dy=%3d\n", - cursor_x - x, cursor_y - y); - } - cl->cursorWasMoved = TRUE; - cnt++; - } - } else { - cl->cursorWasMoved = TRUE; - cnt++; - } - } - rfbReleaseClientIterator(iter); - - if (debug_pointer && cnt) { - rfbLog("cursor_position: sent position x=%3d y=%3d to %d" - " clients\n", x, y, cnt); - } -} - -static void set_rfb_cursor(int which) { - - if (! show_cursor) { - return; - } - if (! screen) { - return; - } - - if (!cursors[which] || !cursors[which]->rfb) { - rfbLog("non-existent cursor: which=%d\n", which); - return; - } else { - rfbSetCursor(screen, cursors[which]->rfb); - } -} - -void set_no_cursor(void) { - set_rfb_cursor(CURS_EMPTY); -} - -void set_warrow_cursor(void) { - set_rfb_cursor(CURS_WARROW); -} - -int set_cursor(int x, int y, int which) { - static int last = -1; - int changed_cursor = 0; - - if (x || y) {} /* unused vars warning: */ - - if (which < 0) { - which = last; - } - if (last < 0 || which != last) { - set_rfb_cursor(which); - changed_cursor = 1; - } - last = which; - - return changed_cursor; -} - -/* - * routine called periodically to update cursor aspects, this catches - * warps and cursor shape changes. - */ -int check_x11_pointer(void) { - Window root_w, child_w; - rfbBool ret = 0; - int root_x, root_y, win_x, win_y; - int x, y, rint; - unsigned int mask; - - if (unixpw_in_progress) return 0; - -#ifdef MACOSX - if (macosx_console) { - ret = macosx_get_cursor_pos(&root_x, &root_y); - } else { - RAWFB_RET(0) - } -#else - - RAWFB_RET(0) - -# if NO_X11 - return 0; -# endif - -#endif - - -#if ! NO_X11 - if (dpy) { - X_LOCK; - ret = XQueryPointer_wr(dpy, rootwin, &root_w, &child_w, &root_x, &root_y, - &win_x, &win_y, &mask); - X_UNLOCK; - } -#else - if (!mask || !win_y || !win_x || !child_w || !root_w) {} -#endif /* NO_X11 */ - -if (0) fprintf(stderr, "check_x11_pointer %d %d\n", root_x, root_y); - if (! ret) { - return 0; - } - if (debug_pointer) { - static int last_x = -1, last_y = -1; - if (root_x != last_x || root_y != last_y) { - rfbLog("XQueryPointer: x:%4d, y:%4d)\n", - root_x, root_y); - } - last_x = root_x; - last_y = root_y; - } - - /* offset subtracted since XQueryPointer relative to rootwin */ - x = root_x - off_x - coff_x; - y = root_y - off_y - coff_y; - - if (clipshift) { - static int cnt = 0; - if (x < 0 || y < 0 || x >= dpy_x || y >= dpy_y) { - if (cnt++ % 4 != 0) { - if (debug_pointer) { - rfbLog("Skipping cursor_position() outside our clipshift\n"); - } - return 0; - } - } - } - - /* record the cursor position in the rfb screen */ - cursor_position(x, y); - - /* change the cursor shape if necessary */ - rint = set_cursor(x, y, get_which_cursor()); - return rint; -} - |