summaryrefslogtreecommitdiffstats
path: root/x11vnc/x11vnc.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/x11vnc.c')
-rw-r--r--x11vnc/x11vnc.c1527
1 files changed, 1064 insertions, 463 deletions
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c
index d64a318..cb38347 100644
--- a/x11vnc/x11vnc.c
+++ b/x11vnc/x11vnc.c
@@ -314,7 +314,6 @@ int overlay_present = 0;
static int xrandr_base_event_type;
#endif
-#define CURSOR_TRANSPARENCY 1
int xfixes_present = 0;
int use_xfixes = 1;
int got_xfixes_cursor_notify = 0;
@@ -323,6 +322,8 @@ double alpha_frac = 0.33;
int alpha_remove = 0;
int alpha_blend = 1;
+int alt_arrow = 1;
+
#if LIBVNCSERVER_HAVE_LIBXFIXES
#include <X11/extensions/Xfixes.h>
static int xfixes_base_event_type;
@@ -343,7 +344,7 @@ int xdamage_tile_count;
int hack_val = 0;
/* date +'lastmod: %Y-%m-%d' */
-char lastmod[] = "0.7.2pre lastmod: 2005-03-12";
+char lastmod[] = "0.7.2pre lastmod: 2005-03-19";
/* X display info */
@@ -436,6 +437,15 @@ int scaling_interpolate = 0; /* use interpolation scheme when shrinking */
int scaled_x = 0, scaled_y = 0; /* dimensions of scaled display */
int scale_numer = 0, scale_denom = 0; /* n/m */
+/* scale cursor */
+char *scale_cursor_str = NULL;
+double scale_cursor_fac = 1.0;
+int scaling_cursor = 0;
+int scaling_cursor_noblend = 0;
+int scaling_cursor_interpolate = 0;
+int scale_cursor_numer = 0, scale_cursor_denom = 0;
+
+
/* size of the basic tile unit that is polled for changes: */
int tile_x = 32;
int tile_y = 32;
@@ -492,6 +502,7 @@ int scanlines[NSCAN] = {
int all_clients_initialized(void);
void close_all_clients(void);
void close_clients(char *);
+int get_autorepeat_state(void);
void autorepeat(int restore);
char *bitprint(unsigned int, int);
void blackout_tiles(void);
@@ -576,6 +587,7 @@ void set_cursor(int, int, int);
void setup_cursors(void);
void setup_cursors_and_push(void);
void first_cursor(void);
+rfbCursorPtr pixels2curs(unsigned long *, int, int, int, int, int);
void set_no_cursor(void);
void set_cursor_was_changed(rfbScreenInfoPtr);
void set_cursor_was_moved(rfbScreenInfoPtr);
@@ -611,6 +623,13 @@ char *get_local_host(int sock);
void xcut_receive(char *text, int len, rfbClientPtr client);
+void parse_scale_string(char *, double *, int *, int *,
+ int *, int *, int *, int *, int *);
+void scale_rect(double, int, int, int,
+ char *, int, char *, int,
+ int, int, int, int, int, int, int, int, int);
+int scale_round(int, double);
+
void zero_fb(int, int, int, int);
void push_black_screen(int);
void push_sleep(int);
@@ -698,6 +717,7 @@ int cursor_shape_updates = 1; /* cursor shape updates -nocursorshape */
int use_xwarppointer = 0; /* use XWarpPointer instead of XTestFake... */
int show_dragging = 1; /* process mouse movement events */
int no_autorepeat = 1; /* turn off autorepeat with clients */
+int no_repeat_countdown = 2;
int watch_bell = 1; /* watch for the bell using XKEYBOARD */
int sound_bell = 1; /* actually send it */
int xkbcompat = 0; /* ignore XKEYBOARD extension */
@@ -2889,6 +2909,7 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) {
rfbLog("running command:\n");
rfbLog(" %s\n", cmd);
+ /* XXX need to close port 5900, etc.. */
rc = system(cmd);
if (rc >= 256) {
@@ -4152,8 +4173,16 @@ void clear_keys(void) {
* keystroke autorepeating as well, it kind of makes sense to shut it
* off if no one is at the physical display...
*/
-void autorepeat(int restore) {
+int get_autorepeat_state(void) {
XKeyboardState kstate;
+ X_LOCK;
+ XGetKeyboardControl(dpy, &kstate);
+ X_UNLOCK;
+ return kstate.global_auto_repeat;
+}
+
+void autorepeat(int restore) {
+ int global_auto_repeat;
XKeyboardControl kctrl;
static int save_auto_repeat = -1;
@@ -4161,10 +4190,10 @@ void autorepeat(int restore) {
if (save_auto_repeat < 0) {
return; /* nothing to restore */
}
+ global_auto_repeat = get_autorepeat_state();
X_LOCK;
/* read state and skip restore if equal (e.g. no clients) */
- XGetKeyboardControl(dpy, &kstate);
- if (kstate.global_auto_repeat == save_auto_repeat) {
+ if (global_auto_repeat == save_auto_repeat) {
X_UNLOCK;
return;
}
@@ -4177,17 +4206,21 @@ void autorepeat(int restore) {
rfbLog("Restored X server key autorepeat to: %d\n",
save_auto_repeat);
} else {
- X_LOCK;
- XGetKeyboardControl(dpy, &kstate);
- save_auto_repeat = kstate.global_auto_repeat;
+ global_auto_repeat = get_autorepeat_state();
+ save_auto_repeat = global_auto_repeat;
+ X_LOCK;
kctrl.auto_repeat_mode = AutoRepeatModeOff;
XChangeKeyboardControl(dpy, KBAutoRepeatMode, &kctrl);
XFlush(dpy);
X_UNLOCK;
- rfbLog("Disabled X server key autorepeat. (you can run the\n");
- rfbLog("command: 'xset r on' to force it back on)\n");
+ rfbLog("Disabled X server key autorepeat.\n");
+ if (no_repeat_countdown >= 0) {
+ rfbLog(" you can run the command: 'xset r on' (%d "
+ "times)\n", no_repeat_countdown+1);
+ rfbLog(" to force it back on.\n");
+ }
}
}
@@ -6884,6 +6917,30 @@ void check_xevents(void) {
}
}
+ if (no_autorepeat && client_count && no_repeat_countdown) {
+ static time_t last_check = 0;
+ if (now > last_check + 1) {
+ last_check = now;
+ X_UNLOCK;
+ if (get_autorepeat_state() != 0) {
+ int n = no_repeat_countdown - 1;
+ if (n >= 0) {
+ rfbLog("Battling with something for "
+ "-norepeat!! (%d resets left)\n",n);
+ } else {
+ rfbLog("Battling with something for "
+ "-norepeat!!\n");
+ }
+ if (no_repeat_countdown > 0) {
+ no_repeat_countdown--;
+ }
+ autorepeat(1);
+ autorepeat(0);
+ }
+ X_LOCK;
+ }
+ }
+
if (XCheckTypedEvent(dpy, MappingNotify, &xev)) {
XRefreshKeyboardMapping((XMappingEvent *) &xev);
if (use_modifier_tweak) {
@@ -7658,20 +7715,6 @@ char *process_remote_cmd(char *cmd, int stringonly) {
do_new_fb(1);
}
}
- } else if (strstr(p, "clip") == p) {
- COLON_CHECK("clip:")
- if (query) {
- snprintf(buf, bufn, "ans=%s%s%s", p, co,
- NONUL(clip_str));
- goto qry;
- }
- p += strlen("clip:");
- if (clip_str) free(clip_str);
- clip_str = strdup(p);
-
- /* OK, this requires a new fb... */
- do_new_fb(1);
-
} else if (strstr(p, "waitmapped") == p) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p,
@@ -7687,6 +7730,20 @@ char *process_remote_cmd(char *cmd, int stringonly) {
}
subwin_wait_mapped = 0;
+ } else if (strstr(p, "clip") == p) {
+ COLON_CHECK("clip:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%s", p, co,
+ NONUL(clip_str));
+ goto qry;
+ }
+ p += strlen("clip:");
+ if (clip_str) free(clip_str);
+ clip_str = strdup(p);
+
+ /* OK, this requires a new fb... */
+ do_new_fb(1);
+
} else if (!strcmp(p, "flashcmap")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, flash_cmap);
@@ -7831,6 +7888,23 @@ char *process_remote_cmd(char *cmd, int stringonly) {
check_black_fb();
do_new_fb(0);
+ } else if (!strcmp(p, "scale_cursor") ||
+ strstr(p, "scale_cursor:") == p) { /* skip-cmd-list */
+ COLON_CHECK("scale_cursor:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%s", p, co,
+ NONUL(scale_cursor_str));
+ goto qry;
+ }
+ p += strlen("scale_cursor:");
+ if (scale_cursor_str) free(scale_cursor_str);
+ if (*p == '\0') {
+ scale_cursor_str = NULL;
+ } else {
+ scale_cursor_str = strdup(p);
+ }
+ setup_cursors_and_push();
+
} else if (!strcmp(p, "viewonly")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, view_only);
@@ -8657,6 +8731,9 @@ char *process_remote_cmd(char *cmd, int stringonly) {
}
rfbLog("process_remote_cmd: enabling -norepeat mode.\n");
no_autorepeat = 1;
+ if (no_repeat_countdown >= 0) {
+ no_repeat_countdown = 2;
+ }
if (client_count) {
autorepeat(0); /* disable if any clients */
}
@@ -8843,6 +8920,18 @@ char *process_remote_cmd(char *cmd, int stringonly) {
initialize_cursors_mode();
first_cursor();
+ } else if (strstr(p, "arrow") == p) {
+ COLON_CHECK("arrow:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%d", p, co, alt_arrow);
+ goto qry;
+ }
+ p += strlen("arrow:");
+ alt_arrow = atoi(p);
+ rfbLog("process_remote_cmd: setting alt_arrow: %d.\n",
+ alt_arrow);
+ setup_cursors_and_push();
+
} else if (!strcmp(p, "xfixes")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, use_xfixes);
@@ -9547,7 +9636,11 @@ char *process_remote_cmd(char *cmd, int stringonly) {
accept_remote_cmds = 0; /* cannot be turned back on. */
} else if (strstr(p, "hack:") == p) { /* skip-cmd-list */
- NOTAPP
+ COLON_CHECK("hack:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%d", p, co, hack_val);
+ goto qry;
+ }
p += strlen("hack:");
hack_val = atoi(p);
rfbLog("set hack_val to: %d\n", hack_val);
@@ -9921,24 +10014,23 @@ void collect_xdamage(int scancnt) {
X_UNLOCK;
now = time(0);
-if (! last_rpt) {
- last_rpt = now;
-}
-if (now > last_rpt + 15) {
- double rat = -1.0;
+ if (! last_rpt) {
+ last_rpt = now;
+ }
+ if (now > last_rpt + 15) {
+ double rat = -1.0;
- if (XD_tot) {
- rat = ((double) XD_skip)/XD_tot;
+ if (XD_tot) {
+ rat = ((double) XD_skip)/XD_tot;
+ }
+
+if (0) fprintf(stderr, "skip/tot: %04d/%04d rat=%.3f rect_count: %d desired_rects: %d\n", XD_skip, XD_tot, rat, rect_count, XD_des);
+ XD_skip = 0;
+ XD_tot = 0;
+ XD_des = 0;
+ rect_count = 0;
+ last_rpt = now;
}
-
- if (0) fprintf(stderr, "skip/tot: %04d/%04d rat=%.3f rect_count: %d desired_rects: %d\n",
- XD_skip, XD_tot, rat, rect_count, XD_des);
- XD_skip = 0;
- XD_tot = 0;
- XD_des = 0;
- rect_count = 0;
- last_rpt = now;
-}
#endif
}
@@ -10072,6 +10164,25 @@ typedef struct cursor_info {
rfbCursorPtr rfb;
} cursor_info_t;
+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;
+}
+
/* empty cursor */
static char* curs_empty_data =
" "
@@ -10092,6 +10203,7 @@ 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 =
" "
@@ -10132,8 +10244,198 @@ static char* curs_arrow_mask =
" xx "
" "
" ";
-static cursor_info_t cur_arrow = {NULL, NULL, 18, 18, 0, 0, 0, NULL};
+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...
@@ -10338,7 +10640,8 @@ void first_cursor(void) {
void setup_cursors(void) {
rfbCursorPtr rfb_curs;
- int i, n = 0;
+ char *scale = NULL;
+ int i, j, n = 0;
static int first = 1;
rfbLog("setting up %d cursors...\n", CURS_MAX);
@@ -10380,6 +10683,7 @@ void setup_cursors(void) {
if (ci->mask) {
free(ci->mask);
}
+ free(ci);
}
/* create new struct: */
@@ -10407,6 +10711,16 @@ void setup_cursors(void) {
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;
@@ -10420,74 +10734,155 @@ void setup_cursors(void) {
cur_xterm.data = curs_xterm_data;
cur_xterm.mask = curs_xterm_mask;
- cursors[CURS_EMPTY] = &cur_empty; n++;
- cursors[CURS_DOT] = &cur_dot; n++;
- cursors[CURS_ARROW] = &cur_arrow; n++;
- cursors[CURS_ROOT] = &cur_root; n++;
- cursors[CURS_WM] = &cur_fleur; n++;
- cursors[CURS_TERM] = &cur_xterm; n++;
- cursors[CURS_PLUS] = &cur_plus; n++;
+ 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_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;
+ }
+ /* scale = NULL zeroes everything */
+ parse_scale_string(scale, &scale_cursor_fac, &scaling_cursor,
+ &scaling_cursor_noblend, &j, &j, &scaling_cursor_interpolate,
+ &scale_cursor_numer, &scale_cursor_denom);
for (i=0; i<n; i++) {
/* create rfbCursors for the special cursors: */
cursor_info_t *ci = cursors[i];
- ci->data = strdup(ci->data);
- ci->mask = strdup(ci->mask);
+ if (scaling_cursor && scale_cursor_fac != 1.0) {
+ int w, h, x, y, i;
+ unsigned long *pixels;
- rfb_curs = rfbMakeXCursor(ci->wx, ci->wy, ci->data, ci->mask);
+ w = ci->wx;
+ h = ci->wy;
- 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->xhot = ci->sx;
- rfb_curs->yhot = ci->sy;
- rfb_curs->cleanup = FALSE;
- rfb_curs->cleanupSource = FALSE;
- rfb_curs->cleanupMask = FALSE;
- rfb_curs->cleanupRichSource = FALSE;
+ pixels = (unsigned long *) malloc(4*w*h);
- if (bpp == 8 && indexed_color) {
- /*
- * use richsource in PseudoColor for better
- * looking cursors (i.e. two-color).
- */
- int x, y, k = 0, bw;
- char d, m;
- int black = BlackPixel(dpy, scr);
- int white = WhitePixel(dpy, scr);
-
- rfb_curs->richSource
- = (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;
+ i = 0;
+ for (y=0; y<h; y++) {
+ for (x=0; x<w; x++) {
+ char d = ci->data[i];
+ char m = ci->mask[i];
+ unsigned long *p;
+
+ p = pixels + i;
+
+ /* 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;
+ }
+ }
+ i++;
}
- if (ci->reverse) {
- if (bw == black) {
- bw = white;
- } else {
+ }
+
+ 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->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;
+ char d, m;
+ int black = BlackPixel(dpy, scr);
+ int white = WhitePixel(dpy, scr);
+
+ rfb_curs->richSource
+ = (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++;
+ }
}
- *(rfb_curs->richSource+k) = (unsigned char) bw;
- k++;
- }
}
}
ci->rfb = rfb_curs;
@@ -10622,6 +11017,227 @@ void initialize_xfixes(void) {
#endif
}
+rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
+ int xhot, int yhot, int Bpp) {
+ rfbCursorPtr c;
+ static unsigned long black, white;
+ static int first = 1;
+ char *bitmap, *rich, *alpha;
+ char *new_pixels = NULL;
+ int n_opaque, n_trans, n_alpha, len, histo[256];
+ int send_alpha = 0, alpha_shift, thresh;
+ int i, x, y;
+
+ if (first) {
+ X_LOCK;
+ black = BlackPixel(dpy, scr);
+ white = WhitePixel(dpy, scr);
+ X_UNLOCK;
+ first = 0;
+ }
+
+ if (scaling_cursor && scale_cursor_fac != 1.0) {
+ int W, H;
+
+ W = w;
+ H = h;
+
+ w = scale_round(W, scale_cursor_fac);
+ h = scale_round(H, scale_cursor_fac);
+
+ new_pixels = (char *) malloc(4 * w * h);
+
+ scale_rect(scale_cursor_fac, scaling_cursor_noblend,
+ scaling_cursor_interpolate, 4,
+ (char *) pixels, 4*W, new_pixels, 4*w,
+ W, H, w, h,
+ 0, 0, W, H, 0);
+
+ pixels = (unsigned long *) new_pixels;
+
+ xhot = scale_round(xhot, scale_cursor_fac);
+ yhot = scale_round(yhot, scale_cursor_fac);
+ }
+
+ 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 < 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 < 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 (new_pixels) {
+ free(new_pixels);
+ }
+
+ /* 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 = rich;
+
+#if !OLD_TREE
+ if (alpha_blend && !indexed_color) {
+ c->alphaSource = alpha;
+ c->alphaPreMultiplied = TRUE;
+ } else {
+ free(alpha);
+ c->alphaSource = NULL;
+ }
+#endif
+
+ return c;
+}
+
int get_xfixes_cursor(int init) {
static unsigned long last_cursor = 0;
static int last_index = 0;
@@ -10643,14 +11259,8 @@ int get_xfixes_cursor(int init) {
if (xfixes_present) {
#if LIBVNCSERVER_HAVE_LIBXFIXES
- int use, oldest, i, x, y, w, h, len;
- int Bpp = bpp/8;
+ int use, oldest, i;
time_t oldtime, now;
- char *bitmap, *rich, *alpha;
- unsigned long black, white;
- rfbCursorPtr c;
- int thresh, n_opaque, n_trans, n_alpha, histo[256];
- int send_alpha = 0, alpha_shift;
XFixesCursorImage *xfc;
if (! got_xfixes_cursor_notify) {
@@ -10727,7 +11337,7 @@ int get_xfixes_cursor(int init) {
if (cursors[use]->rfb->richSource) {
free(cursors[use]->rfb->richSource);
}
-#if !OLD_TREE && CURSOR_TRANSPARENCY
+#if !OLD_TREE
if (cursors[use]->rfb->alphaSource) {
free(cursors[use]->rfb->alphaSource);
}
@@ -10741,193 +11351,9 @@ int get_xfixes_cursor(int init) {
free(cursors[use]->rfb);
}
- X_LOCK;
- black = BlackPixel(dpy, scr);
- white = WhitePixel(dpy, scr);
- X_UNLOCK;
-
- w = xfc->width;
- h = xfc->height;
- 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 & (*(xfc->pixels+i));
- a = a >> 24; /* alpha channel */
- if (a > 0) {
- n_alpha++;
- }
- histo[a]++;
- if (a < alpha_threshold) {
- n_trans++;
- } else {
- n_opaque++;
- }
- i++;
- }
- }
- if (alpha_blend) {
- send_alpha = 0;
-#if CURSOR_TRANSPARENCY
- if (Bpp == 4) {
- send_alpha = 1;
- }
-#endif
- 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 & (*(xfc->pixels+i));
- a = a >> 24; /* alpha channel */
-
-
- if (a < thresh) {
- bitmap[i] = ' ';
- } else {
- bitmap[i] = 'x';
- }
-
- r = 0x00ff0000 & (*(xfc->pixels+i));
- g = 0x0000ff00 & (*(xfc->pixels+i));
- b = 0x000000ff & (*(xfc->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 0
- memcpy(p, (char *)&ui, Bpp);
-#else
- 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;
- }
-#endif
-
- /* 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);
-
- /* set up the cursor parameters: */
- c->xhot = xfc->xhot;
- c->yhot = xfc->yhot;
- c->cleanup = FALSE;
- c->cleanupSource = FALSE;
- c->cleanupMask = FALSE;
- c->cleanupRichSource = FALSE;
- c->richSource = rich;
-
-#if !OLD_TREE && CURSOR_TRANSPARENCY
- if (alpha_blend && !indexed_color) {
- c->alphaSource = alpha;
- c->alphaPreMultiplied = TRUE;
- } else {
- c->alphaSource = NULL;
- }
-#endif
-
/* place cursor into our collection */
- cursors[use]->rfb = c;
+ cursors[use]->rfb = pixels2curs(xfc->pixels, xfc->width,
+ xfc->height, xfc->xhot, xfc->yhot, bpp/8);
/* update time and serial index: */
curs_times[use] = now;
@@ -12116,19 +12542,20 @@ XImage *initialize_xdisplay_fb(void) {
return fb;
}
-void parse_scale_string(char *str) {
+void parse_scale_string(char *str, double *factor, int *scaling, int *noblend,
+ int *nomult4, int *pad, int *interpolate, int *numer, int *denom) {
+
int m, n;
char *p, *tstr;
double f;
- scale_fac = 1.0;
- scaling = 0;
- scaling_noblend = 0;
- scaling_nomult4 = 0;
- scaling_pad = 0;
- scaling_interpolate = 0;
- scaled_x = 0, scaled_y = 0;
- scale_numer = 0, scale_denom = 0;
+ *factor = 1.0;
+ *scaling = 0;
+ *noblend = 0;
+ *nomult4 = 0;
+ *pad = 0;
+ *interpolate = 0;
+ *numer = 0, *denom = 0;
if (str == NULL || str[0] == '\0') {
return;
@@ -12138,16 +12565,16 @@ void parse_scale_string(char *str) {
if ( (p = strchr(tstr, ':')) != NULL) {
/* options */
if (strstr(p+1, "nb") != NULL) {
- scaling_noblend = 1;
+ *noblend = 1;
}
if (strstr(p+1, "n4") != NULL) {
- scaling_nomult4 = 1;
+ *nomult4 = 1;
}
if (strstr(p+1, "in") != NULL) {
- scaling_interpolate = 1;
+ *interpolate = 1;
}
if (strstr(p+1, "pad") != NULL) {
- scaling_pad = 1;
+ *pad = 1;
}
*p = '\0';
}
@@ -12157,24 +12584,24 @@ void parse_scale_string(char *str) {
rfbLog("bad -scale arg: %s\n", tstr);
clean_up_exit(1);
}
- scale_fac = (double) f;
+ *factor = (double) f;
/* look for common fractions from small ints: */
for (n=2; n<=10; n++) {
for (m=1; m<n; m++) {
test = ((double) m)/ n;
- diff = scale_fac - test;
+ diff = *factor - test;
if (-eps < diff && diff < eps) {
- scale_numer = m;
- scale_denom = n;
+ *numer = m;
+ *denom = n;
break;
}
}
- if (scale_denom) {
+ if (*denom) {
break;
}
}
- if (scale_fac < 0.01) {
+ if (*factor < 0.01) {
rfbLog("-scale factor too small: %f\n", scale_fac);
clean_up_exit(1);
}
@@ -12192,34 +12619,42 @@ void parse_scale_string(char *str) {
rfbLog("bad -scale arg: %s\n", tstr);
clean_up_exit(1);
}
- scale_fac = ((double) m)/ n;
- if (scale_fac < 0.01) {
- rfbLog("-scale factor too small: %f\n", scale_fac);
+ *factor = ((double) m)/ n;
+ if (*factor < 0.01) {
+ rfbLog("-scale factor too small: %f\n", *factor);
clean_up_exit(1);
}
- scale_numer = m;
- scale_denom = n;
+ *numer = m;
+ *denom = n;
}
- if (scale_fac == 1.0) {
+ if (*factor == 1.0) {
if (! quiet) {
- rfbLog("scaling disabled for factor %f\n", scale_fac);
+ rfbLog("scaling disabled for factor %f\n", *factor);
}
} else {
- scaling = 1;
+ *scaling = 1;
}
free(tstr);
}
+int scale_round(int len, double fac) {
+ double eps = 0.000001;
+
+ len = (int) (len * fac + eps);
+ return len;
+}
+
void setup_scaling(int *width_in, int *height_in) {
int width = *width_in;
int height = *height_in;
- parse_scale_string(scale_str);
+ parse_scale_string(scale_str, &scale_fac, &scaling, &scaling_noblend,
+ &scaling_nomult4, &scaling_pad, &scaling_interpolate,
+ &scale_numer, &scale_denom);
if (scaling) {
- double eps = 0.000001;
- width = (int) (width * scale_fac + eps);
- height = (int) (height * scale_fac + eps);
+ width = scale_round(width, scale_fac);
+ height = scale_round(height, scale_fac);
if (scale_denom && scaling_pad) {
/* it is not clear this padding is useful anymore */
rfbLog("width %% denom: %d %% %d = %d\n", width,
@@ -14304,7 +14739,9 @@ weights for this scaled pixel are:
* the loop over the 4 pixels.
*/
-static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
+void scale_rect(double factor, int noblend, int interpolate, int Bpp,
+ char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
+ int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark) {
/*
* Notation:
* "i" an x pixel index in the destination (scaled) framebuffer
@@ -14314,8 +14751,6 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
*
* Similarly for nx, ny, Nx, Ny, etc. Lowercase: dest, Uppercase: source.
*/
- int Nx, Ny, nx, ny, Bpp, b;
-
int i, j, i1, i2, j1, j2; /* indices for scaled fb (dest) */
int I, J, I1, I2, J1, J2; /* indices for main fb (source) */
@@ -14323,95 +14758,39 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
double x1, y1, x2, y2; /* x-y coords for destination pixels edges */
double dx, dy; /* size of destination pixel */
-
double ddx, ddy; /* for interpolation expansion */
char *src, *dest; /* pointers to the two framebuffers */
- double pixave[4]; /* for averaging pixel values */
unsigned short us;
+ unsigned char uc;
+ unsigned int ui;
+ int use_noblend_shortcut = 1;
int shrink; /* whether shrinking or expanding */
- static int constant_weights = -1, cnt = 0;
+ static int constant_weights = -1, mag_int = -1;
+ static int last_Nx = -1, last_Ny = -1, cnt = 0;
+ static double last_factor = -1.0;
+ int b, k;
+ double pixave[4]; /* for averaging pixel values */
- if (scale_fac <= 1.0) {
+ if (factor <= 1.0) {
shrink = 1;
} else {
shrink = 0;
}
- if (shrink && scaling_interpolate) {
- /*
- * User asked for interpolation scheme, presumably for
- * small shrink.
- */
- shrink = 0;
- }
- if (!screen || !rfb_fb || !main_fb) {
- return;
- }
-
- if (! screen->serverFormat.trueColour) {
- /*
- * PseudoColor colormap... blending leads to random colors.
- */
- scaling_noblend = 1;
- }
-
- Bpp = bpp/8; /* Bytes per pixel */
-
- Nx = dpy_x; /* extent of source (the whole main fb) */
- Ny = dpy_y;
-
- nx = scaled_x; /* extent of dest (the whole scaled rfb fb) */
- ny = scaled_y;
/*
- * width and height (real numbers) of a scaled pixel.
+ * N.B. width and height (real numbers) of a scaled pixel.
* both are > 1 (e.g. 1.333 for -scale 3/4)
* they should also be equal but we don't assume it.
- */
-
- /*
- * This original way is probably incorrect, giving rise to dx and
- * dy that will not exactly line up with the grid for 2/3, etc.
- * This gives rise to a whole spectrum of weights, leading to poor
- * tightvnc (and other encoding) compression.
- */
-#if 0
- dx = (double) Nx / nx;
- dy = (double) Ny / ny;
-#else
-
- /*
+ *
* This new way is probably the best we can do, take the inverse
* of the scaling factor to double precision.
*/
- dx = 1.0/scale_fac;
- dy = 1.0/scale_fac;
-#endif
-
- /*
- * find the extent of the change the input rectangle induces in
- * the scaled framebuffer.
- */
-
- /* Left edges: find largest i such that i * dx <= X1 */
- i1 = FLOOR(X1/dx);
-
- /* Right edges: find smallest i such that (i+1) * dx >= X2+1 */
- i2 = CEIL( (X2+1)/dx ) - 1;
-
- /* To be safe, correct any overflows: */
- i1 = nfix(i1, nx);
- i2 = nfix(i2, nx) + 1; /* add 1 to make a rectangle upper boundary */
-
- /* Repeat above for y direction: */
- j1 = FLOOR(Y1/dy);
- j2 = CEIL( (Y2+1)/dy ) - 1;
-
- j1 = nfix(j1, ny);
- j2 = nfix(j2, ny) + 1;
+ dx = 1.0/factor;
+ dy = 1.0/factor;
/*
* There is some speedup if the pixel weights are constant, so
@@ -14420,29 +14799,129 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
* If scale = 1/n and n divides Nx and Ny, the pixel weights
* are constant (e.g. 1/2 => equal on 2x2 square).
*/
+ if (factor != last_factor || Nx != last_Nx || Ny != last_Ny) {
+ constant_weights = -1;
+ mag_int = -1;
+ last_Nx = Nx;
+ last_Ny = Ny;
+ last_factor = factor;
+ }
+
if (constant_weights < 0) {
int n = 0;
+
constant_weights = 0;
+ mag_int = 0;
for (i = 2; i<=128; i++) {
double test = ((double) 1)/ i;
double diff, eps = 1.0e-7;
- diff = scale_fac - test;
+ diff = factor - test;
if (-eps < diff && diff < eps) {
n = i;
break;
}
}
- if (scaling_noblend || ! shrink) {
+ if (noblend || ! shrink || interpolate) {
;
} else if (n != 0) {
if (Nx % n == 0 && Ny % n == 0) {
- rfbLog("scale_and_mark_rect: using constant "
- "pixel weight speedup for 1/%d\n", n);
+ static int didmsg = 0;
+ if (mark && ! didmsg) {
+ didmsg = 1;
+ rfbLog("scale_and_mark_rect: using "
+ "constant pixel weight speedup "
+ "for 1/%d\n", n);
+ }
constant_weights = 1;
}
}
+
+ n = 0;
+ for (i = 2; i<=32; i++) {
+ double test = (double) i;
+ double diff, eps = 1.0e-7;
+ diff = factor - test;
+ if (-eps < diff && diff < eps) {
+ n = i;
+ break;
+ }
+ }
+ if (noblend && factor > 1.0 && n) {
+ mag_int = n;
+ }
+ }
+
+ if (mark && factor > 1.0 && ! noblend) {
+ /*
+ * kludge: correct for interpolating blurring leaking
+ * up or left 1 destination pixel.
+ */
+ if (X1 > 0) X1--;
+ if (Y1 > 0) Y1--;
+ }
+
+ /*
+ * find the extent of the change the input rectangle induces in
+ * the scaled framebuffer.
+ */
+
+ /* Left edges: find largest i such that i * dx <= X1 */
+ i1 = FLOOR(X1/dx);
+
+ /* Right edges: find smallest i such that (i+1) * dx >= X2+1 */
+ i2 = CEIL( (X2+1)/dx ) - 1;
+
+ /* To be safe, correct any overflows: */
+ i1 = nfix(i1, nx);
+ i2 = nfix(i2, nx) + 1; /* add 1 to make a rectangle upper boundary */
+
+ /* Repeat above for y direction: */
+ j1 = FLOOR(Y1/dy);
+ j2 = CEIL( (Y2+1)/dy ) - 1;
+
+ j1 = nfix(j1, ny);
+ j2 = nfix(j2, ny) + 1;
+
+ /* special case integer magnification with no blending */
+ if (mark && noblend && mag_int && Bpp != 3) {
+ int jmin, jmax, imin, imax;
+
+ /* outer loop over *source* pixels */
+ for (J=Y1; J < Y2; J++) {
+ jmin = J * mag_int;
+ jmax = jmin + mag_int;
+ for (I=X1; I < X2; I++) {
+ /* extract value */
+ src = src_fb + J*src_bytes_per_line + I*Bpp;
+ if (Bpp == 4) {
+ ui = *((unsigned int *)src);
+ } else if (Bpp == 2) {
+ us = *((unsigned short *)src);
+ } else if (Bpp == 1) {
+ uc = *((unsigned char *)src);
+ }
+ imin = I * mag_int;
+ imax = imin + mag_int;
+ /* inner loop over *dest* pixels */
+ for (j=jmin; j<jmax; j++) {
+ dest = dst_fb + j*dst_bytes_per_line + imin*Bpp;
+ for (i=imin; i<imax; i++) {
+ if (Bpp == 4) {
+ *((unsigned int *)dest) = ui;
+ } else if (Bpp == 2) {
+ *((unsigned short *)dest) = us;
+ } else if (Bpp == 1) {
+ *((unsigned char *)dest) = uc;
+ }
+ dest += Bpp;
+ }
+ }
+ }
+ }
+ goto markit;
}
+
/* set these all to 1.0 to begin with */
wx = 1.0;
wy = 1.0;
@@ -14463,7 +14942,7 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
J1 = (int) FLOOR(y1);
J1 = nfix(J1, Ny);
- if (shrink) {
+ if (shrink && ! interpolate) {
J2 = (int) CEIL(y2) - 1;
J2 = nfix(J2, Ny);
} else {
@@ -14472,9 +14951,10 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
}
/* destination char* pointer: */
- dest = rfb_fb + j*rfb_bytes_per_line + i1*Bpp;
+ dest = dst_fb + j*dst_bytes_per_line + i1*Bpp;
for (i=i1; i<i2; i++) {
+
x1 = i * dx; /* left edge */
if (x1 > Nx - 1) {
/* can go over with dx = 1/scale_fac */
@@ -14488,14 +14968,39 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
I1 = (int) FLOOR(x1);
if (I1 >= Nx) I1 = Nx - 1;
- if (shrink) {
+ if (noblend && use_noblend_shortcut) {
+ /*
+ * The noblend case involves no weights,
+ * and 1 pixel, so just copy the value
+ * directly.
+ */
+ src = src_fb + J1*src_bytes_per_line + I1*Bpp;
+ if (Bpp == 4) {
+ *((unsigned int *)dest)
+ = *((unsigned int *)src);
+ } else if (Bpp == 2) {
+ *((unsigned short *)dest)
+ = *((unsigned short *)src);
+ } else if (Bpp == 1) {
+ *(dest) = *(src);
+ } else if (Bpp == 3) {
+ /* rare case */
+ for (k=0; k<=2; k++) {
+ *(dest+k) = *(src+k);
+ }
+ }
+ dest += Bpp;
+ continue;
+ }
+
+ if (shrink && ! interpolate) {
I2 = (int) CEIL(x2) - 1;
if (I2 >= Nx) I2 = Nx - 1;
} else {
I2 = I1 + 1; /* simple interpolation */
ddx = x1 - I1;
}
-
+
/* Zero out accumulators for next pixel average: */
for (b=0; b<4; b++) {
pixave[b] = 0.0; /* for RGB weighted sums */
@@ -14517,19 +15022,22 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
* after the J > 0 data have been accessed and
* we are at j, i+1, J=0? The stride in J is
* main_bytes_per_line, and so ~4 KB.
+ *
+ * Typical case when shrinking are 2x2 loop, so
+ * just two lines to worry about.
*/
for (J=J1; J<=J2; J++) {
/* see comments for I, x1, x2, etc. below */
if (constant_weights) {
;
- } else if (scaling_noblend) {
+ } else if (noblend) {
if (J != J1) {
continue;
}
wy = 1.0;
/* interpolation scheme: */
- } else if (!shrink) {
+ } else if (!shrink || interpolate) {
if (J >= Ny) {
continue;
} else if (J == J1) {
@@ -14547,7 +15055,7 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
wy = 1.0;
}
- src = main_fb + J*main_bytes_per_line + I1*Bpp;
+ src = src_fb + J*src_bytes_per_line + I1*Bpp;
for (I=I1; I<=I2; I++) {
@@ -14555,7 +15063,7 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
if (constant_weights) {
;
- } else if (scaling_noblend) {
+ } else if (noblend) {
/*
* Ugh, PseudoColor colormap is
* bad news, to avoid random
@@ -14569,7 +15077,7 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
wx = 1.0;
/* interpolation scheme: */
- } else if (!shrink) {
+ } else if (!shrink || interpolate) {
if (I >= Nx) {
continue; /* off edge */
} else if (I == I1) {
@@ -14605,7 +15113,6 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
w = wx * wy;
wtot += w;
-
/*
* We average the unsigned char value
* instead of char value: otherwise
@@ -14613,21 +15120,34 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
* to the maximum (char -1)! This way
* they are spread between 0 and 255.
*/
- if (Bpp != 2) {
- for (b=0; b<Bpp; b++) {
- pixave[b] += w *
- ((unsigned char) *(src+b));
- }
- } else {
+ if (Bpp == 4) {
+ /* unroll the loops, can give 20% */
+ pixave[0] += w *
+ ((unsigned char) *(src ));
+ pixave[1] += w *
+ ((unsigned char) *(src+1));
+ pixave[2] += w *
+ ((unsigned char) *(src+2));
+ pixave[3] += w *
+ ((unsigned char) *(src+3));
+ } else if (Bpp == 2) {
/*
* 16bpp: trickier with green
* split over two bytes, so we
* use the masks:
*/
- us = *( (unsigned short *) src );
+ us = *((unsigned short *) src);
pixave[0] += w*(us & main_red_mask);
pixave[1] += w*(us & main_green_mask);
pixave[2] += w*(us & main_blue_mask);
+ } else if (Bpp == 1) {
+ pixave[0] += w *
+ ((unsigned char) *(src));
+ } else {
+ for (b=0; b<Bpp; b++) {
+ pixave[b] += w *
+ ((unsigned char) *(src+b));
+ }
}
src += Bpp;
}
@@ -14639,11 +15159,12 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
wtot = 1.0/wtot; /* normalization factor */
/* place weighted average pixel in the scaled fb: */
- if (Bpp != 2) {
- for (b=0; b<Bpp; b++) {
- *(dest + b) = (char) (wtot * pixave[b]);
- }
- } else {
+ if (Bpp == 4) {
+ *(dest ) = (char) (wtot * pixave[0]);
+ *(dest+1) = (char) (wtot * pixave[1]);
+ *(dest+2) = (char) (wtot * pixave[2]);
+ *(dest+3) = (char) (wtot * pixave[3]);
+ } else if (Bpp == 2) {
/* 16bpp / 565 case: */
pixave[0] *= wtot;
pixave[1] *= wtot;
@@ -14652,12 +15173,37 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
| (main_green_mask & (int) pixave[1])
| (main_blue_mask & (int) pixave[2]);
*( (unsigned short *) dest ) = us;
+ } else if (Bpp == 1) {
+ *(dest) = (char) (wtot * pixave[0]);
+ } else {
+ for (b=0; b<Bpp; b++) {
+ *(dest+b) = (char) (wtot * pixave[b]);
+ }
}
dest += Bpp;
}
}
+ markit:
+ if (mark) {
+ mark_rect_as_modified(i1, j1, i2, j2, 1);
+ }
+}
- mark_rect_as_modified(i1, j1, i2, j2, 1);
+static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
+
+ if (!screen || !rfb_fb || !main_fb) {
+ return;
+ }
+ if (! screen->serverFormat.trueColour) {
+ /*
+ * PseudoColor colormap... blending leads to random colors.
+ */
+ scaling_noblend = 1;
+ }
+
+ scale_rect(scale_fac, scaling_noblend, scaling_interpolate, bpp/8,
+ main_fb, main_bytes_per_line, rfb_fb, rfb_bytes_per_line,
+ dpy_x, dpy_y, scaled_x, scaled_y, X1, Y1, X2, Y2, 1);
}
void mark_rect_as_modified(int x1, int y1, int x2, int y2, int force) {
@@ -15449,6 +15995,7 @@ int copy_snap(void) {
* Utilities for managing the "naps" to cut down on amount of polling.
*/
static void nap_set(int tile_cnt) {
+ int nap_in = nap_ok;
if (scan_count == 0) {
/* roll up check for all NSCAN scans */
@@ -15459,6 +16006,12 @@ static void nap_set(int tile_cnt) {
}
nap_diff_count = 0;
}
+ if (nap_ok && ! nap_in && using_xdamage) {
+ if (XD_skip > 0.8 * XD_tot) {
+ /* X DAMAGE is keeping load low, so skip nap */
+ nap_ok = 0;
+ }
+ }
if (show_cursor) {
/* kludge for the up to 4 tiles the mouse patch could occupy */
@@ -17315,6 +17868,7 @@ static void print_help(int mode) {
" the full display). This also works for -id/-sid mode\n"
" where the offset is relative to the upper left corner\n"
" of the selected window.\n"
+"\n"
"-flashcmap In 8bpp indexed color, let the installed colormap flash\n"
" as the pointer moves from window to window (slow).\n"
"-notruecolor For 8bpp displays, force indexed color (i.e. a colormap)\n"
@@ -17326,7 +17880,7 @@ static void print_help(int mode) {
" and for some workarounds. n may be a decimal number,\n"
" or 0x hex. Run xdpyinfo(1) for the values. One may\n"
" also use \"TrueColor\", etc. see <X11/X.h> for a list.\n"
-" If the string ends in \":m\" the for better or for\n"
+" If the string ends in \":m\" then for better or for\n"
" worse the visual depth is forced to be m.\n"
"-overlay Handle multiple depth visuals on one screen, e.g. 8+24\n"
" and 24+8 overlay visuals (the 32 bits per pixel are\n"
@@ -17360,9 +17914,8 @@ static void print_help(int mode) {
" cursor shape using the overlay mechanism.\n"
"\n"
"-scale fraction Scale the framebuffer by factor \"fraction\". Values\n"
-" less than 1 shrink the fb, larger ones expand it.\n"
-" Note: image may not be sharp and response may be\n"
-" slower. Currently the cursor shape is not scaled.\n"
+" less than 1 shrink the fb, larger ones expand it. Note:\n"
+" image may not be sharp and response may be slower.\n"
" If \"fraction\" contains a decimal point \".\" it\n"
" is taken as a floating point number, alternatively\n"
" the notation \"m/n\" may be used to denote fractions\n"
@@ -17379,6 +17932,15 @@ static void print_help(int mode) {
" pad scaled width and height to be multiples of scaling\n"
" denominator (e.g. 3 for 2/3).\n"
"\n"
+"-scale_cursor frac By default if -scale is supplied the cursor shape is\n"
+" scaled by the same factor. Depending on your usage,\n"
+" you may want to scale the cursor independently of the\n"
+" screen or not at all. If you specify -scale_cursor\n"
+" the cursor will be scaled by that factor. When using\n"
+" -scale mode to keep the cursor at its \"natural\" size\n"
+" use \"-scale_cursor 1\". Most of the \":\" scaling\n"
+" options apply here as well.\n"
+"\n"
"-viewonly All VNC clients can only watch (default %s).\n"
"-shared VNC display is shared (default %s).\n"
"-once Exit after the first successfully connected viewer\n"
@@ -17746,6 +18308,11 @@ static void print_help(int mode) {
" so this is no loss unless someone is simultaneously at\n"
" the real X display. Default: %s\n"
"\n"
+" Use \"-norepeat N\" to set how many times norepeat will\n"
+" be reset if something else (e.g. X session manager)\n"
+" disables it. The default is 2. Use a negative value\n"
+" for unlimited resets.\n"
+"\n"
"-nofb Ignore video framebuffer: only process keyboard and\n"
" pointer. Intended for use with Win2VNC and x2vnc\n"
" dual-monitor setups.\n"
@@ -17826,6 +18393,9 @@ static void print_help(int mode) {
" extensions available. On Solaris and IRIX if XFIXES\n"
" is not available, -overlay mode will be attempted.\n"
"\n"
+"-arrow n Choose an alternate \"arrow\" cursor from a set of\n"
+" some common ones. n can be 1 to %d. Default is: %d\n"
+"\n"
"-noxfixes Do not use the XFIXES extension to draw the exact cursor\n"
" shape even if it is available.\n"
"-alphacut n When using the XFIXES extension for the cursor shape,\n"
@@ -18144,6 +18714,8 @@ static void print_help(int mode) {
" id:windowid set -id window to \"windowid\". empty\n"
" or \"root\" to go back to root window\n"
" sid:windowid set -sid window to \"windowid\"\n"
+" waitmapped wait until subwin is mapped.\n"
+" nowaitmapped do not wait until subwin is mapped.\n"
" clip:WxH+X+Y set -clip mode to \"WxH+X+Y\"\n"
" flashcmap enable -flashcmap mode.\n"
" noflashcmap disable -flashcmap mode.\n"
@@ -18156,6 +18728,7 @@ static void print_help(int mode) {
" nooverlay_cursor.\n"
" visual:vis set -visual to \"vis\"\n"
" scale:frac set -scale to \"frac\"\n"
+" scale_cursor:f set -scale_cursor to \"f\"\n"
" viewonly enable -viewonly mode.\n"
/* access view,share,forever */
" noviewonly disable -viewonly mode.\n"
@@ -18257,6 +18830,7 @@ static void print_help(int mode) {
" show_cursor enable showing a cursor.\n"
" noshow_cursor disable showing a cursor. (same as\n"
" \"nocursor\")\n"
+" arrow:n set -arrow to alternate n.\n"
" xfixes enable xfixes cursor shape mode.\n"
" noxfixes disable xfixes cursor shape mode.\n"
" alphacut:n set -alphacut to n.\n"
@@ -18356,27 +18930,27 @@ static void print_help(int mode) {
" the returned value corresponds to (hint: the ext_*\n"
" variables correspond to the presence of X extensions):\n"
"\n"
-" ans= stop quit exit shutdown ping blacken zero\n"
-" refresh reset close disconnect id sid clip waitmapped\n"
-" nowaitmapped flashcmap noflashcmap truecolor notruecolor\n"
+" ans= stop quit exit shutdown ping blacken zero refresh\n"
+" reset close disconnect id sid waitmapped nowaitmapped\n"
+" clip flashcmap noflashcmap truecolor notruecolor\n"
" overlay nooverlay overlay_cursor overlay_yescursor\n"
" nooverlay_nocursor nooverlay_cursor nooverlay_yescursor\n"
-" overlay_nocursor visual scale viewonly noviewonly\n"
-" shared noshared forever noforever once timeout deny\n"
-" lock nodeny unlock connect allowonce allow localhost\n"
-" nolocalhost listen accept gone shm noshm flipbyteorder\n"
-" noflipbyteorder onetile noonetile solid_color solid\n"
-" nosolid blackout xinerama noxinerama xrandr noxrandr\n"
-" xrandr_mode padgeom quiet q noquiet modtweak nomodtweak\n"
-" xkb noxkb skip_keycodes add_keysyms noadd_keysyms\n"
-" clear_mods noclear_mods clear_keys noclear_keys\n"
-" remap repeat norepeat fb nofb bell nobell sel\n"
-" nosel primary noprimary cursorshape nocursorshape\n"
-" cursorpos nocursorpos cursor show_cursor noshow_cursor\n"
-" nocursor xfixes noxfixes xdamage noxdamage xd_area\n"
-" xd_mem alphacut alphafrac alpharemove noalpharemove\n"
-" alphablend noalphablend xwarp xwarppointer noxwarp\n"
-" noxwarppointer buttonmap dragging nodragging\n"
+" overlay_nocursor visual scale scale_cursor viewonly\n"
+" noviewonly shared noshared forever noforever once\n"
+" timeout deny lock nodeny unlock connect allowonce\n"
+" allow localhost nolocalhost listen accept gone\n"
+" shm noshm flipbyteorder noflipbyteorder onetile\n"
+" noonetile solid_color solid nosolid blackout xinerama\n"
+" noxinerama xrandr noxrandr xrandr_mode padgeom quiet\n"
+" q noquiet modtweak nomodtweak xkb noxkb skip_keycodes\n"
+" add_keysyms noadd_keysyms clear_mods noclear_mods\n"
+" clear_keys noclear_keys remap repeat norepeat fb nofb\n"
+" bell nobell sel nosel primary noprimary cursorshape\n"
+" nocursorshape cursorpos nocursorpos cursor show_cursor\n"
+" noshow_cursor nocursor arrow xfixes noxfixes xdamage\n"
+" noxdamage xd_area xd_mem alphacut alphafrac alpharemove\n"
+" noalpharemove alphablend noalphablend xwarp xwarppointer\n"
+" noxwarp noxwarppointer buttonmap dragging nodragging\n"
" pointer_mode pm input_skip input client_input speeds\n"
" debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n"
" nodebug_keyboard nodk deferupdate defer wait rfbwait\n"
@@ -18486,6 +19060,7 @@ static void print_help(int mode) {
vnc_connect ? "-vncconnect":"-novncconnect",
use_modifier_tweak ? "-modtweak":"-nomodtweak",
no_autorepeat ? "-norepeat":"-repeat",
+ alt_arrow_max, alt_arrow,
alpha_threshold,
alpha_frac,
cursor_pos_updates ? "-cursorpos":"-nocursorpos",
@@ -18968,6 +19543,9 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-scale")) {
CHECK_ARGC
scale_str = strdup(argv[++i]);
+ } else if (!strcmp(arg, "-scale_cursor")) {
+ CHECK_ARGC
+ scale_cursor_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-viewonly")) {
view_only = 1;
} else if (!strcmp(arg, "-shared")) {
@@ -19114,6 +19692,15 @@ int main(int argc, char* argv[]) {
remap_file = strdup(argv[++i]);
} else if (!strcmp(arg, "-norepeat")) {
no_autorepeat = 1;
+ if (i < argc-1) {
+ char *s = argv[i+1];
+ if (*s == '-') {
+ s++;
+ }
+ if (isdigit(*s)) {
+ no_repeat_countdown = atoi(argv[++i]);
+ }
+ }
} else if (!strcmp(arg, "-repeat")) {
no_autorepeat = 0;
} else if (!strcmp(arg, "-nofb")) {
@@ -19139,6 +19726,9 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-nocursor")) {
multiple_cursors_mode = strdup("none");
show_cursor = 0;
+ } else if (!strcmp(arg, "-arrow")) {
+ CHECK_ARGC
+ alt_arrow = atoi(argv[++i]);
} else if (!strcmp(arg, "-noxfixes")) {
use_xfixes = 0;
} else if (!strcmp(arg, "-alphacut")) {
@@ -19639,6 +20229,7 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " remap: %s\n", remap_file ? remap_file
: "null");
fprintf(stderr, " norepeat: %d\n", no_autorepeat);
+ fprintf(stderr, " norepeatcnt:%d\n", no_repeat_countdown);
fprintf(stderr, " nofb: %d\n", nofb);
fprintf(stderr, " watchbell: %d\n", watch_bell);
fprintf(stderr, " watchsel: %d\n", watch_selection);
@@ -19711,11 +20302,12 @@ int main(int argc, char* argv[]) {
if (xkbcompat) {
Bool rc = XkbIgnoreExtension(True);
if (! quiet) {
- rfbLog("disabling xkb extension. rc=%d\n", rc);
+ rfbLog("Disabling xkb XKEYBOARD extension. rc=%d\n",
+ rc);
}
if (watch_bell) {
watch_bell = 0;
- if (! quiet) rfbLog("disabling bell.\n");
+ if (! quiet) rfbLog("Disabling bell.\n");
}
}
#else
@@ -19792,7 +20384,7 @@ int main(int argc, char* argv[]) {
#if LIBVNCSERVER_HAVE_LIBXFIXES
if (! XFixesQueryExtension(dpy, &xfixes_base_event_type, &er)) {
if (! quiet) {
- rfbLog("disabling xfixes mode: display does not "
+ rfbLog("Disabling XFIXES mode: display does not "
"support it.\n");
}
xfixes_present = 0;
@@ -19803,8 +20395,8 @@ int main(int argc, char* argv[]) {
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
if (! XDamageQueryExtension(dpy, &xdamage_base_event_type, &er)) {
- if (0 && ! quiet) {
- rfbLog("disabling xdamage mode: display does not "
+ if (! quiet) {
+ rfbLog("Disabling X DAMAGE mode: display does not "
"support it.\n");
}
xdamage_present = 0;
@@ -19823,7 +20415,7 @@ int main(int argc, char* argv[]) {
#ifdef SOLARIS_OVERLAY
if (! XQueryExtension(dpy, "SUN_OVL", &maj, &ev, &er)) {
if (! quiet && overlay) {
- rfbLog("disabling -overlay: SUN_OVL "
+ rfbLog("Disabling -overlay: SUN_OVL "
"extension not available.\n");
}
} else {
@@ -19833,7 +20425,7 @@ int main(int argc, char* argv[]) {
#ifdef IRIX_OVERLAY
if (! XReadDisplayQueryExtension(dpy, &ev, &er)) {
if (! quiet && overlay) {
- rfbLog("disabling -overlay: IRIX ReadDisplay "
+ rfbLog("Disabling -overlay: IRIX ReadDisplay "
"extension not available.\n");
}
} else {
@@ -19905,15 +20497,24 @@ int main(int argc, char* argv[]) {
/* check for XTEST */
if (! XTestQueryExtension_wr(dpy, &ev, &er, &maj, &min)) {
- if (! quiet) {
- rfbLog("warning: XTest extension not available, most user"
- " input\n");
- rfbLog("(pointer and keyboard) will be discarded.\n");
- rfbLog("no XTest extension, switching to -xwarppointer mode\n");
- rfbLog("for pointer motion input.\n");
- }
- xtest_present = 0;
- use_xwarppointer = 1;
+ if (! quiet) {
+ rfbLog("WARNING: XTEST extension not available "
+ "(either missing from\n");
+ rfbLog(" display or client library libXtst "
+ "missing at build time).\n");
+ rfbLog(" MOST user input (pointer and keyboard) "
+ "will be DISCARDED.\n");
+ rfbLog(" If display does have XTEST, be sure to "
+ "build x11vnc with\n");
+ rfbLog(" a working libXtst build environment "
+ "(e.g. libxtst-dev,\n");
+ rfbLog(" or other packages).\n");
+ rfbLog("No XTEST extension, switching to "
+ "-xwarppointer mode for\n");
+ rfbLog(" pointer motion input.\n");
+ }
+ xtest_present = 0;
+ use_xwarppointer = 1;
}
/*
* Window managers will often grab the display during resize, etc.
@@ -19980,8 +20581,8 @@ int main(int argc, char* argv[]) {
#if LIBVNCSERVER_HAVE_LIBXRANDR
if (! XRRQueryExtension(dpy, &xrandr_base_event_type, &er)) {
if (xrandr && ! quiet) {
- rfbLog("disabling -xrandr mode: display does not"
- " support it.\n");
+ rfbLog("Disabling -xrandr mode: display does not"
+ " support X RANDR.\n");
}
xrandr = 0;
xrandr_present = 0;