summaryrefslogtreecommitdiffstats
path: root/x11vnc/x11vnc.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/x11vnc.c')
-rw-r--r--x11vnc/x11vnc.c2144
1 files changed, 1544 insertions, 600 deletions
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c
index d556e97..43c6ea5 100644
--- a/x11vnc/x11vnc.c
+++ b/x11vnc/x11vnc.c
@@ -248,12 +248,14 @@ 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;
-int alpha_threshold = 255;
+int alpha_threshold = 240;
double alpha_frac = 0.33;
int alpha_remove = 0;
+int alpha_blend = 0;
#if LIBVNCSERVER_HAVE_LIBXFIXES
#include <X11/extensions/Xfixes.h>
@@ -267,7 +269,7 @@ static int xdamage_base_event_type;
#endif
/* date +'lastmod: %Y-%m-%d' */
-char lastmod[] = "0.7.1pre lastmod: 2004-12-27";
+char lastmod[] = "0.7.1pre lastmod: 2005-01-16";
/* X display info */
@@ -287,6 +289,8 @@ XImage *scanline;
XImage *fullscreen;
XImage **tile_row; /* for all possible row runs */
XImage *fb0;
+XImage *snaprect = NULL; /* for XShmGetImage (fs_factor) */
+XImage *snap = NULL; /* the full snap fb */
#if !LIBVNCSERVER_HAVE_XSHM
/*
@@ -302,6 +306,7 @@ typedef struct {
XShmSegmentInfo scanline_shm;
XShmSegmentInfo fullscreen_shm;
XShmSegmentInfo *tile_row_shm; /* for all possible row runs */
+XShmSegmentInfo snaprect_shm;
/* rfb screen info */
rfbScreenInfoPtr screen = NULL;
@@ -310,6 +315,7 @@ char *http_dir = NULL;
char vnc_desktop_name[256];
char *main_fb; /* our copy of the X11 fb */
char *rfb_fb; /* same as main_fb unless transformation */
+char *snap_fb = NULL; /* used under -snapfb */
char *fake_fb = NULL; /* used under -padgeom */
int rfb_bytes_per_line;
int main_bytes_per_line;
@@ -318,6 +324,7 @@ unsigned short main_red_max, main_green_max, main_blue_max;
unsigned short main_red_shift, main_green_shift, main_blue_shift;
/* we now have a struct with client specific data: */
+#define RATE_SAMPLES 5
typedef struct _ClientData {
int had_cursor_shape_updates;
int had_cursor_pos_updates;
@@ -325,6 +332,14 @@ typedef struct _ClientData {
int client_port;
int server_port;
char *server_ip;
+ double timer;
+ double send_cmp_rate;
+ double send_raw_rate;
+ int set_cmp_bytes;
+ int set_raw_bytes;
+ double cmp_samp[RATE_SAMPLES];
+ double raw_samp[RATE_SAMPLES];
+ int sample;
} ClientData;
/* scaling parameters */
@@ -344,7 +359,7 @@ int tile_y = 32;
int ntiles, ntiles_x, ntiles_y;
/* arrays that indicate changed or checked tiles. */
-unsigned char *tile_has_diff, *tile_tried;
+unsigned char *tile_has_diff, *tile_tried, *tile_copied;
/* times of recent events */
time_t last_event, last_input, last_client = 0;
@@ -373,6 +388,8 @@ char *program_cmdline = NULL;
char vnc_connect_str[VNC_CONNECT_MAX+1];
Atom vnc_connect_prop = None;
+struct utsname UT;
+
/* function prototypes (see filename comment above) */
int all_clients_initialized(void);
@@ -410,6 +427,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb);
void initialize_polling_images(void);
void initialize_signals(void);
void initialize_tiles(void);
+void initialize_speeds(void);
void free_tiles(void);
void initialize_watch_bell(void);
void initialize_xinerama(void);
@@ -446,16 +464,18 @@ void set_vnc_connect_prop(char *);
char *process_remote_cmd(char *, int);
void rfbPE(rfbScreenInfoPtr, long);
void rfbCFD(rfbScreenInfoPtr, long);
-int scan_for_updates(void);
+int scan_for_updates(int);
void set_colormap(int);
void set_offset(void);
void set_rfb_cursor(int);
void set_visual(char *vstring);
void set_cursor(int, int, int);
void setup_cursors(void);
+void setup_cursors_and_push(void);
void first_cursor(void);
void set_no_cursor(void);
void set_cursor_was_changed(rfbScreenInfoPtr);
+void set_cursor_was_moved(rfbScreenInfoPtr);
int get_which_cursor(void);
int get_xfixes_cursor(int);
@@ -470,6 +490,14 @@ void check_x11_pointer(void);
void check_bell_event(void);
void check_xevents(void);
char *this_host(void);
+void set_vnc_desktop_name(void);
+
+int get_cmp_rate(void);
+int get_raw_rate(void);
+int get_read_rate(void);
+int get_net_rate(void);
+int get_net_latency(void);
+void measure_send_rates(int);
int get_remote_port(int sock);
int get_local_port(int sock);
@@ -491,8 +519,16 @@ char *use_dpy = NULL;
char *auth_file = NULL;
char *visual_str = NULL;
char *logfile = NULL;
+int logfile_append = 0;
char *passwdfile = NULL;
-char *blackout_string = NULL;
+char *blackout_str = NULL;
+
+char *speeds_str = NULL;
+int measure_speeds = 1;
+int speeds_net_rate = 0;
+int speeds_net_latency = 0;
+int speeds_read_rate = 0;
+
char *rc_rcfile = NULL;
int rc_norc = 0;
int opts_bg = 0;
@@ -519,6 +555,7 @@ int clear_mods = 0; /* -clear_mods (1) and -clear_keys (2) */
int nofb = 0; /* do not send any fb updates */
unsigned long subwin = 0x0; /* -id, -sid */
+int subwin_wait_mapped = 0;
int xinerama = 0; /* -xinerama */
int xrandr = 0; /* -xrandr */
@@ -531,6 +568,7 @@ Time xrandr_cfg_time = 0;
char *xrandr_mode = NULL;
char *pad_geometry = NULL;
time_t pad_geometry_time;
+int use_snapfb = 0;
char *client_connect = NULL; /* strings for -connect option */
char *client_connect_file = NULL;
@@ -554,7 +592,9 @@ int add_keysyms = 0; /* automatically add keysyms to X server */
char *remap_file = NULL; /* -remap */
char *pointer_remap = NULL;
-int pointer_mode = 2; /* use the various ways of updating pointer */
+/* use the various ways of updating pointer */
+#define POINTER_MODE_DEFAULT 2
+int pointer_mode = POINTER_MODE_DEFAULT;
int pointer_mode_max = 4;
int single_copytile = 0; /* use the old way copy_tiles() */
int single_copytile_orig = 0;
@@ -930,6 +970,10 @@ int new_fb_size_clients(rfbScreenInfoPtr s) {
rfbClientPtr cl;
int count = 0;
+ if (! s) {
+ return 0;
+ }
+
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->useNewFBSize) {
@@ -1097,6 +1141,35 @@ XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth,
width, height, bitmap_pad, bytes_per_line);
}
+void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h) {
+
+ /* default (w=0,h=0) is the fill the entire XImage */
+ if (w < 1) {
+ w = dest->width;
+ }
+ if (h < 1) {
+ h = dest->height;
+ }
+
+ if (use_snapfb && snap_fb && dest != snaprect) {
+ char *src, *dst;
+ int line, pixelsize = bpp/8;
+
+ src = snap->data + snap->bytes_per_line*y + pixelsize*x;
+ dst = dest->data;
+ for (line = 0; line < h; line++) {
+ memcpy(dst, src, w * pixelsize);
+ src += snap->bytes_per_line;
+ dst += dest->bytes_per_line;
+ }
+ } else if (using_shm && w == dest->width && h == dest->height) {
+ XShmGetImage_wr(dpy, window, dest, x, y, AllPlanes);
+ } else {
+ XGetSubImage_wr(dpy, window, x, y, w, h, AllPlanes,
+ ZPixmap, dest, 0, 0);
+ }
+}
+
/*
* wrappers for XTestFakeKeyEvent, etc..
*/
@@ -1210,9 +1283,11 @@ void clean_shm(int quick) {
if (quick) {
shm_delete(&scanline_shm);
shm_delete(&fullscreen_shm);
+ shm_delete(&snaprect_shm);
} else {
shm_clean(&scanline_shm, scanline);
shm_clean(&fullscreen_shm, fullscreen);
+ shm_clean(&snaprect_shm, snaprect);
}
/*
@@ -1404,6 +1479,30 @@ int valid_window(Window win) {
return ok;
}
+int wait_until_mapped(Window win) {
+ int ms = 50, waittime = 30;
+ time_t start = time(0);
+ XWindowAttributes attr;
+
+ while (1) {
+ if (! valid_window(win)) {
+ if (time(0) > start + waittime) {
+ return 0;
+ }
+ usleep(ms * 1000);
+ continue;
+ }
+ if (! XGetWindowAttributes(dpy, win, &attr)) {
+ return 0;
+ }
+ if (attr.map_state == IsViewable) {
+ return 1;
+ }
+ usleep(ms * 1000);
+ }
+ return 0;
+}
+
int get_window_size(Window win, int *x, int *y) {
XWindowAttributes attr;
/* valid_window? */
@@ -1461,6 +1560,10 @@ int all_clients_initialized(void) {
rfbClientPtr cl;
int ok = 1;
+ if (! screen) {
+ return ok;
+ }
+
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->state != RFB_NORMAL) {
@@ -1479,6 +1582,10 @@ char *list_clients(void) {
char *list, tmp[32];
int count = 0;
+ if (!screen) {
+ return strdup("");
+ }
+
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
count++;
@@ -1487,7 +1594,7 @@ char *list_clients(void) {
/*
* each client: 123.123.123.123:60000/0x11111111-rw, = 36 bytes
- * so count+1 * 100 should cover it.
+ * so count+1 * 100 must cover it.
*/
list = (char *) malloc((count+1)*100);
@@ -1516,6 +1623,10 @@ void close_all_clients(void) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
+ if (! screen) {
+ return;
+ }
+
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
rfbCloseClient(cl);
@@ -1534,6 +1645,10 @@ void close_clients(char *str) {
return;
}
+ if (! screen) {
+ return;
+ }
+
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (strstr(str, "0x")) {
@@ -1554,7 +1669,7 @@ void close_clients(char *str) {
char *rstr = str;
if (! dotted_ip(str)) {
rstr = host2ip(str);
- if (rstr == NULL) {
+ if (rstr == NULL || *rstr == '\0') {
if (host_warn++) {
continue;
}
@@ -1738,23 +1853,23 @@ static int check_access(char *addr) {
"blocked.\n");
return 0;
}
-
- if (allow_list == NULL || *allow_list == '\0') {
- if (allow_once == NULL) {
- return 1;
- }
+ if (addr == NULL || *addr == '\0') {
+ rfbLog("check_access: denying empty host IP address string.\n");
+ return 0;
}
+
if (allow_list == NULL) {
+ /* set to "" to possibly append allow_once */
allow_list = strdup("");
}
- if (addr == NULL || *addr == '\0') {
- rfbLog("check_access: denying empty host IP address string.\n");
- return 0;
+ if (*allow_list == '\0' && allow_once == NULL) {
+ /* no constraints, accept it */
+ return 1;
}
if (strchr(allow_list, '/')) {
/* a file of IP addresess or prefixes */
- int len;
+ int len, len2 = 0;
struct stat sbuf;
FILE *in;
char line[1024], *q;
@@ -1767,7 +1882,8 @@ static int check_access(char *addr) {
}
len = sbuf.st_size + 1; /* 1 more for '\0' at end */
if (allow_once) {
- len += strlen(allow_once) + 2;
+ len2 = strlen(allow_once) + 2;
+ len += len2;
}
list = malloc(len);
list[0] = '\0';
@@ -1782,20 +1898,22 @@ static int check_access(char *addr) {
if ( (q = strchr(line, '#')) != NULL) {
*q = '\0';
}
- if (strlen(list) + strlen(line) >= len) {
+ if (strlen(list) + strlen(line) >= len - len2) {
+ /* file grew since our stat() */
break;
}
strcat(list, line);
}
fclose(in);
if (allow_once) {
+ strcat(list, "\n");
strcat(list, allow_once);
strcat(list, "\n");
}
} else {
- int len = strlen(allow_list);
+ int len = strlen(allow_list) + 1;
if (allow_once) {
- len += strlen(allow_once) + 2;
+ len += strlen(allow_once) + 1;
}
list = malloc(len);
list[0] = '\0';
@@ -1813,28 +1931,43 @@ static int check_access(char *addr) {
p = strtok(list, ", \t\n\r");
while (p) {
- char *q, *r = NULL;
+ char *chk, *q, *r = NULL;
if (*p == '\0') {
p = strtok(NULL, ", \t\n\r");
continue;
}
if (! dotted_ip(p)) {
r = host2ip(p);
- if (r == NULL) {
+ if (r == NULL || *r == '\0') {
rfbLog("check_access: bad lookup \"%s\"\n", p);
p = strtok(NULL, ", \t\n\r");
continue;
}
rfbLog("check_access: lookup %s -> %s\n", p, r);
- p = r;
+ chk = r;
+ } else {
+ chk = p;
}
- q = strstr(addr, p);
- if (q == addr) {
- rfbLog("check_access: client %s matches pattern %s\n",
- addr, p);
- allowed = 1;
- } else if(!strcmp(p,"localhost") && !strcmp(addr,"127.0.0.1")) {
+ q = strstr(addr, chk);
+ if (chk[strlen(chk)-1] != '.') {
+ if (!strcmp(addr, chk)) {
+ if (chk != p) {
+ rfbLog("check_access: client %s "
+ "matches host %s=%s\n", addr,
+ chk, p);
+ } else {
+ rfbLog("check_access: client %s "
+ "matches host %s\n", addr, chk);
+ }
+ allowed = 1;
+ } else if(!strcmp(chk, "localhost") &&
+ !strcmp(addr, "127.0.0.1")) {
+ allowed = 1;
+ }
+ } else if (q == addr) {
+ rfbLog("check_access: client %s matches pattern %s\n",
+ addr, chk);
allowed = 1;
}
p = strtok(NULL, ", \t\n\r");
@@ -2449,6 +2582,10 @@ static int do_reverse_connect(char *str) {
rfbLog("reverse_connect: string too long: %d bytes\n", len);
return 0;
}
+ if (!screen) {
+ rfbLog("reverse_connect: screen not setup yet.\n");
+ return 0;
+ }
/* copy in to host */
host = (char *) malloc((size_t) len+1);
@@ -2634,6 +2771,7 @@ void check_connect_inputs(void) {
*/
enum rfbNewClientAction new_client(rfbClientPtr client) {
ClientData *cd;
+ int i;
last_event = last_input = time(0);
if (inetd) {
@@ -2692,6 +2830,12 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
install_padded_fb(pad_geometry);
}
+ for (i=0; i<RATE_SAMPLES; i++) {
+ cd->cmp_samp[i] = 5000; /* 56k modem */
+ cd->raw_samp[i] = 50000;
+ }
+ cd->sample = 0;
+
accepted_client = 1;
last_client = time(0);
@@ -4780,7 +4924,9 @@ void check_bell_event(void) {
rfbLog("check_bell_event: not sending bell: "
"uninitialized clients\n");
} else {
- rfbSendBell(screen);
+ if (screen) {
+ rfbSendBell(screen);
+ }
}
}
}
@@ -4796,7 +4942,6 @@ int subwin_trap_count = 0;
XErrorHandler old_getimage_handler;
#define XRANDR_SET_TRAP_RET(x,y) \
if (subwin || xrandr) { \
- if (0) fprintf(stderr, " SET_TRAP: '%d' '%s'\n", x, y); \
trapped_getimage_xerror = 0; \
old_getimage_handler = XSetErrorHandler(trap_getimage_xerror); \
if (check_xrandr_event(y)) { \
@@ -4807,7 +4952,6 @@ XErrorHandler old_getimage_handler;
}
#define XRANDR_CHK_TRAP_RET(x,y) \
if (subwin || xrandr) { \
- if (0) fprintf(stderr, " CHK_TRAP: '%d' '%s'\n", x, y); \
if (trapped_getimage_xerror) { \
if (subwin) { \
static int last = 0; \
@@ -4926,7 +5070,7 @@ void handle_xrandr_change(int new_x, int new_y) {
rfbLog(" shutting down due to XRANDR event.\n");
clean_up_exit(0);
}
- if (!strcmp(xrandr_mode, "newfbsize")) {
+ if (!strcmp(xrandr_mode, "newfbsize") && screen) {
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->useNewFBSize) {
@@ -4958,7 +5102,6 @@ int check_xrandr_event(char *msg) {
if (! xrandr || ! xrandr_present) {
return 0;
}
- if (0) fprintf(stderr, "IN check_xrandr_event('%s')\n", msg);
if (XCheckTypedEvent(dpy, xrandr_base_event_type +
RRScreenChangeNotify, &xev)) {
int do_change;
@@ -5005,12 +5148,9 @@ int check_xrandr_event(char *msg) {
XDisplayWidth(dpy, scr), XDisplayHeight(dpy, scr));
rfbLog("check_xrandr_event(): returning control to"
" caller...\n");
- if (0) fprintf(stderr, "OUT-%d check_xrandr_event('%s')\n",
- do_change, msg);
return do_change;
}
#endif
- if (0) fprintf(stderr, "OUT-0 check_xrandr_event('%s')\n", msg);
return 0;
}
@@ -5055,7 +5195,7 @@ static Window selwin; /* special window for our selection */
* This is where we keep our selection: the string sent TO us from VNC
* clients, and the string sent BY us to requesting X11 clients.
*/
-static char *xcut_string = NULL;
+static char *xcut_str = NULL;
/*
* Our callbacks instruct us to check for changes in the cutbuffer
@@ -5098,8 +5238,8 @@ static void selection_request(XEvent *ev) {
} else {
notify_event.property = req_event->property;
}
- if (xcut_string) {
- length = strlen(xcut_string);
+ if (xcut_str) {
+ length = strlen(xcut_str);
} else {
length = 0;
}
@@ -5120,7 +5260,7 @@ static void selection_request(XEvent *ev) {
} else {
/* data request */
- data = (unsigned char *)xcut_string;
+ data = (unsigned char *)xcut_str;
XChangeProperty(ev->xselectionrequest.display,
ev->xselectionrequest.requestor,
@@ -5188,6 +5328,9 @@ static void cutbuffer_send(void) {
}
/* now send it to any connected VNC clients (rfbServerCutText) */
+ if (!screen) {
+ return;
+ }
rfbSendServerCutText(screen, selection_str, strlen(selection_str));
}
@@ -5281,6 +5424,9 @@ static void selection_send(XEvent *ev) {
}
/* now send it to any connected VNC clients (rfbServerCutText) */
+ if (!screen) {
+ return;
+ }
rfbSendServerCutText(screen, selection_str, newlen);
}
@@ -5339,7 +5485,7 @@ void check_xevents(void) {
static int first = 1, sent_some_sel = 0;
static time_t last_request = 0;
time_t now = time(0);
- int have_clients = screen->clientHead ? 1 : 0;
+ int have_clients = 0;
if (first) {
@@ -5347,6 +5493,9 @@ void check_xevents(void) {
}
first = 0;
+ if (screen && screen->clientHead) {
+ have_clients = 1;
+ }
X_LOCK;
/*
* There is a bug where we have to wait before sending text to
@@ -5457,9 +5606,9 @@ void check_xevents(void) {
xev.xselectionclear.selection == XA_PRIMARY) {
own_selection = 0;
- if (xcut_string) {
- free(xcut_string);
- xcut_string = NULL;
+ if (xcut_str) {
+ free(xcut_str);
+ xcut_str = NULL;
}
}
}
@@ -5472,6 +5621,9 @@ void check_xevents(void) {
*/
void xcut_receive(char *text, int len, rfbClientPtr cl) {
+ if (!watch_selection) {
+ return;
+ }
if (cl && cl->viewOnly) {
return;
}
@@ -5490,13 +5642,13 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
}
/* duplicate the text string for our own use. */
- if (xcut_string != NULL) {
- free(xcut_string);
+ if (xcut_str != NULL) {
+ free(xcut_str);
}
- xcut_string = (unsigned char *)
+ xcut_str = (unsigned char *)
malloc((size_t) (len+1) * sizeof(unsigned char));
- strncpy(xcut_string, text, len);
- xcut_string[len] = '\0'; /* make sure null terminated */
+ strncpy(xcut_str, text, len);
+ xcut_str[len] = '\0'; /* make sure null terminated */
/* copy this text to CUT_BUFFER0 as well: */
XChangeProperty(dpy, rootwin, XA_CUT_BUFFER0, XA_STRING, 8,
@@ -5549,6 +5701,10 @@ int send_remote_cmd(char *cmd, int query, int wait) {
if (query || wait) {
char line[VNC_CONNECT_MAX];
int rc=1, i=0, max=70, ms_sl=50;
+
+ if (!strcmp(cmd, "cmd=stop")) {
+ max = 20;
+ }
for (i=0; i<max; i++) {
usleep(ms_sl * 1000);
if (client_connect_file) {
@@ -5629,14 +5785,15 @@ char *add_item(char *instr, char *item) {
char *p, *str;
int len, saw_item = 0;
- if (! instr) {
+ if (! instr || *instr == '\0') {
str = strdup(item);
return str;
}
- len = strlen(instr) + strlen(item) + 2;
+ len = strlen(instr) + 1 + strlen(item) + 1;
str = (char *)malloc(len);
str[0] = '\0';
+ /* n.b. instr will be modified; caller replaces with returned string */
p = strtok(instr, ",");
while (p) {
if (!strcmp(p, item)) {
@@ -5660,7 +5817,6 @@ char *add_item(char *instr, char *item) {
strcat(str, ",");
}
strcat(str, item);
-
}
return str;
}
@@ -5669,7 +5825,7 @@ char *delete_item(char *instr, char *item) {
char *p, *str;
int len;
- if (! instr) {
+ if (! instr || *instr == '\0') {
str = strdup("");
return str;
}
@@ -5677,6 +5833,7 @@ char *delete_item(char *instr, char *item) {
str = (char *)malloc(len);
str[0] = '\0';
+ /* n.b. instr will be modified; caller replaces with returned string */
p = strtok(instr, ",");
while (p) {
if (!strcmp(p, item) || *p == '\0') {
@@ -5701,6 +5858,9 @@ void if_8bpp_do_new_fb(void) {
}
void check_black_fb(void) {
+ if (!screen) {
+ return;
+ }
if (new_fb_size_clients(screen) != client_count) {
rfbLog("trying to send a black fb for non-newfbsize"
" clients %d != %d\n", client_count,
@@ -5713,7 +5873,7 @@ int check_httpdir(void) {
if (http_dir) {
return 1;
} else {
- char *prog, *httpdir, *q;
+ char *prog = NULL, *httpdir, *q;
struct stat sbuf;
int len;
@@ -5760,6 +5920,7 @@ int check_httpdir(void) {
free(prog);
return 0;
}
+
len = strlen(prog) + 17 + 1;
*q = '\0';
httpdir = (char *) malloc(len);
@@ -5773,7 +5934,8 @@ int check_httpdir(void) {
return 1;
} else {
/* try some hardwires: */
- if (stat("/usr/local/share/x11vnc/classes", &sbuf) == 0) {
+ if (stat("/usr/local/share/x11vnc/classes",
+ &sbuf) == 0) {
http_dir =
strdup("/usr/local/share/x11vnc/classes");
return 1;
@@ -5789,6 +5951,9 @@ int check_httpdir(void) {
}
void http_connections(int on) {
+ if (!screen) {
+ return;
+ }
if (on) {
rfbLog("http_connections: turning on http service.\n");
screen->httpInitDone = FALSE;
@@ -5815,7 +5980,7 @@ void reset_httpport(int old, int new) {
} else if (inetd) {
rfbLog("reset_httpport: cannot set httpport: %d"
" in inetd.\n", hp);
- } else {
+ } else if (screen) {
screen->httpPort = hp;
screen->httpInitDone = FALSE;
if (screen->httpListenSock > -1) {
@@ -5836,7 +6001,7 @@ void reset_rfbport(int old, int new) {
} else if (inetd) {
rfbLog("reset_rfbport: cannot set rfbport: %d"
" in inetd.\n", rp);
- } else {
+ } else if (screen) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
int maxfd;
@@ -5872,6 +6037,8 @@ void reset_rfbport(int old, int new) {
rfbReleaseClientIterator(iter);
screen->maxFd = maxfd;
+
+ set_vnc_desktop_name();
}
}
@@ -6109,6 +6276,20 @@ char *process_remote_cmd(char *cmd, int stringonly) {
do_new_fb(1);
}
}
+ } else if (strstr(p, "waitmapped") == p) {
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p,
+ subwin_wait_mapped);
+ goto qry;
+ }
+ subwin_wait_mapped = 1;
+ } else if (strstr(p, "nowaitmapped") == p) {
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p,
+ !subwin_wait_mapped);
+ goto qry;
+ }
+ subwin_wait_mapped = 0;
} else if (!strcmp(p, "flashcmap")) {
if (query) {
@@ -6275,16 +6456,20 @@ char *process_remote_cmd(char *cmd, int stringonly) {
}
rfbLog("process_remote_cmd: enable sharing.\n");
shared = 1;
- screen->alwaysShared = TRUE;
- screen->neverShared = FALSE;
+ if (screen) {
+ screen->alwaysShared = TRUE;
+ screen->neverShared = FALSE;
+ }
} else if (!strcmp(p, "noshared")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !shared); goto qry;
}
rfbLog("process_remote_cmd: disable sharing.\n");
shared = 0;
- screen->alwaysShared = FALSE;
- screen->neverShared = TRUE;
+ if (screen) {
+ screen->alwaysShared = FALSE;
+ screen->neverShared = TRUE;
+ }
} else if (!strcmp(p, "forever")) {
if (query) {
@@ -6321,12 +6506,15 @@ char *process_remote_cmd(char *cmd, int stringonly) {
COLON_CHECK("connect:")
p += strlen("connect:");
/* this is a reverse connection */
- strncpy(vnc_connect_str, p, VNC_CONNECT_MAX);
- vnc_connect_str[VNC_CONNECT_MAX] = '\0';
+ reverse_connect(p);
} else if (strstr(p, "allowonce") == p) {
- NOTAPP
COLON_CHECK("allowonce:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%s", p, co,
+ NONUL(allow_once));
+ goto qry;
+ }
p += strlen("allowonce:");
allow_once = strdup(p);
rfbLog("process_remote_cmd: set allow_once %s\n", allow_once);
@@ -6536,30 +6724,30 @@ char *process_remote_cmd(char *cmd, int stringonly) {
COLON_CHECK("blackout:")
if (query) {
snprintf(buf, bufn, "ans=%s%s%s", p, co,
- NONUL(blackout_string));
+ NONUL(blackout_str));
goto qry;
}
p += strlen("blackout:");
- if (blackout_string) {
- before = strdup(blackout_string);
+ if (blackout_str) {
+ before = strdup(blackout_str);
} else {
before = strdup("");
}
- old = blackout_string;
+ old = blackout_str;
if (*p == '+') {
p++;
- blackout_string = add_item(blackout_string, p);
+ blackout_str = add_item(blackout_str, p);
} else if (*p == '-') {
p++;
- blackout_string = delete_item(blackout_string, p);
+ blackout_str = delete_item(blackout_str, p);
} else {
- blackout_string = strdup(p);
+ blackout_str = strdup(p);
}
- if (strcmp(before, blackout_string)) {
+ if (strcmp(before, blackout_str)) {
rfbLog("process_remote_cmd: changing -blackout\n");
rfbLog(" from: %s\n", before);
- rfbLog(" to: %s\n", blackout_string);
- if (0 && !strcmp(blackout_string, "") &&
+ rfbLog(" to: %s\n", blackout_str);
+ if (0 && !strcmp(blackout_str, "") &&
single_copytile_orig != single_copytile) {
rfbLog("resetting single_copytile to: %d\n",
single_copytile_orig);
@@ -6978,6 +7166,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
set_no_cursor();
cursor_shape_updates = 1;
restore_cursor_shape_updates(screen);
+ first_cursor();
} else if (!strcmp(p, "nocursorshape")) {
int i, max = 5;
if (query) {
@@ -6995,6 +7184,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
}
cursor_shape_updates = 0;
disable_cursor_shape_updates(screen);
+ first_cursor();
} else if (!strcmp(p, "cursorpos")) {
if (query) {
@@ -7037,6 +7227,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
"to: %d\n", show_cursor);
}
initialize_cursors_mode();
+ first_cursor();
} else if (!strcmp(p, "show_cursor")) {
if (query) {
@@ -7058,6 +7249,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
"to: %s\n", multiple_cursors_mode);
}
initialize_cursors_mode();
+ first_cursor();
} else if (!strcmp(p, "noshow_cursor") || !strcmp(p, "nocursor")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !show_cursor);
@@ -7069,6 +7261,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: disabling show_cursor.\n");
show_cursor = 0;
initialize_cursors_mode();
+ first_cursor();
} else if (!strcmp(p, "xfixes")) {
if (query) {
@@ -7084,6 +7277,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
" (if supported).\n");
use_xfixes = 1;
initialize_xfixes();
+ first_cursor();
} else if (!strcmp(p, "noxfixes")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !use_xfixes);
@@ -7097,6 +7291,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: disabling -xfixes.\n");
use_xfixes = 0;
initialize_xfixes();
+ first_cursor();
} else if (strstr(p, "alphacut") == p) {
int a;
@@ -7118,8 +7313,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
" transparent cursors.\n");
}
alpha_threshold = a;
- setup_cursors();
- first_cursor();
+ setup_cursors_and_push();
}
} else if (strstr(p, "alphafrac") == p) {
double a;
@@ -7137,8 +7331,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: setting alphafrac "
"%f -> %f.\n", alpha_frac, a);
alpha_frac = a;
- setup_cursors();
- first_cursor();
+ setup_cursors_and_push();
}
} else if (strstr(p, "alpharemove") == p) {
if (query) {
@@ -7148,8 +7341,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (!alpha_remove) {
rfbLog("process_remote_cmd: enable alpharemove\n");
alpha_remove = 1;
- setup_cursors();
- first_cursor();
+ setup_cursors_and_push();
}
} else if (strstr(p, "noalpharemove") == p) {
if (query) {
@@ -7159,8 +7351,28 @@ char *process_remote_cmd(char *cmd, int stringonly) {
if (alpha_remove) {
rfbLog("process_remote_cmd: disable alpharemove\n");
alpha_remove = 0;
- setup_cursors();
- first_cursor();
+ setup_cursors_and_push();
+ }
+ } else if (strstr(p, "alphablend") == p) {
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, alpha_blend);
+ goto qry;
+ }
+ if (!alpha_blend) {
+ rfbLog("process_remote_cmd: enable alphablend\n");
+ alpha_remove = 0;
+ alpha_blend = 1;
+ setup_cursors_and_push();
+ }
+ } else if (strstr(p, "noalphablend") == p) {
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, !alpha_blend);
+ goto qry;
+ }
+ if (alpha_blend) {
+ rfbLog("process_remote_cmd: disable alphablend\n");
+ alpha_blend = 0;
+ setup_cursors_and_push();
}
} else if (strstr(p, "xwarp") == p || strstr(p, "xwarppointer") == p) {
@@ -7218,7 +7430,24 @@ char *process_remote_cmd(char *cmd, int stringonly) {
}
p += strlen("pointer_mode:");
pm = atoi(p);
- if (pm < 1 || pm > pointer_mode_max) {
+ if (pm < 0 || pm > pointer_mode_max) {
+ rfbLog("process_remote_cmd: pointer_mode out of range:"
+ " 1-%d: %d\n", pointer_mode_max, pm);
+ } else {
+ rfbLog("process_remote_cmd: setting pointer_mode %d\n",
+ pm);
+ pointer_mode = pm;
+ }
+ } else if (strstr(p, "pm") == p) {
+ int pm;
+ COLON_CHECK("pm:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%d", p, co, pointer_mode);
+ goto qry;
+ }
+ p += strlen("pm:");
+ pm = atoi(p);
+ if (pm < 0 || pm > pointer_mode_max) {
rfbLog("process_remote_cmd: pointer_mode out of range:"
" 1-%d: %d\n", pointer_mode_max, pm);
} else {
@@ -7226,6 +7455,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
pm);
pointer_mode = pm;
}
+
} else if (strstr(p, "input_skip") == p) {
int is;
COLON_CHECK("input_skip:")
@@ -7238,6 +7468,21 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: setting input_skip %d\n", is);
ui_skip = is;
+ } else if (strstr(p, "speeds") == p) {
+ COLON_CHECK("speeds:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%s", p, co,
+ NONUL(speeds_str));
+ goto qry;
+ }
+ p += strlen("speeds:");
+ if (speeds_str) free(speeds_str);
+ speeds_str = strdup(p);
+
+ rfbLog("process_remote_cmd: setting -speeds to:\n"
+ "\t'%s'\n", p);
+ initialize_speeds();
+
} else if (!strcmp(p, "debug_pointer") || !strcmp(p, "dp")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, debug_pointer);
@@ -7422,6 +7667,29 @@ char *process_remote_cmd(char *cmd, int stringonly) {
tile_fuzz, f);
grow_fill = f;
+ } else if (!strcmp(p, "snapfb")) {
+ int orig = use_snapfb;
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, use_snapfb);
+ goto qry;
+ }
+ rfbLog("process_remote_cmd: turning on snapfb mode.\n");
+ use_snapfb = 1;
+ if (orig != use_snapfb) {
+ do_new_fb(1);
+ }
+ } else if (!strcmp(p, "nosnapfb")) {
+ int orig = use_snapfb;
+ if (query) {
+ snprintf(buf, bufn, "ans=%s:%d", p, !use_snapfb);
+ goto qry;
+ }
+ rfbLog("process_remote_cmd: turning off snapfb mode.\n");
+ use_snapfb = 0;
+ if (orig != use_snapfb) {
+ do_new_fb(1);
+ }
+
} else if (strstr(p, "progressive") == p) {
int f;
COLON_CHECK("progressive:")
@@ -7504,9 +7772,8 @@ char *process_remote_cmd(char *cmd, int stringonly) {
free(http_dir);
}
http_dir = strdup(p);
- if (*p == '\0') {
- http_connections(0);
- } else {
+ http_connections(0);
+ if (*p != '\0') {
http_connections(1);
}
}
@@ -8019,12 +8286,21 @@ enum cursor_names {
#define CURS_MAX 32
static cursor_info_t *cursors[CURS_MAX];
+void setup_cursors_and_push(void) {
+ setup_cursors();
+ first_cursor();
+}
+
void first_cursor(void) {
+ if (! screen) {
+ return;
+ }
if (! show_cursor) {
screen->cursor = NULL;
} else {
- /* just set it to the arrow for now. */
- set_rfb_cursor(CURS_ARROW);
+ got_xfixes_cursor_notify++;
+ set_rfb_cursor(get_which_cursor());
+ set_cursor_was_changed(screen);
}
}
@@ -8338,10 +8614,11 @@ int get_xfixes_cursor(int init) {
int use, oldest, i, x, y, w, h, len;
int Bpp = bpp/8;
time_t oldtime, now;
- char *bitmap, *rich;
+ 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) {
@@ -8419,6 +8696,11 @@ int get_xfixes_cursor(int init) {
if (cursors[use]->rfb->richSource) {
free(cursors[use]->rfb->richSource);
}
+#if !OLD_TREE && CURSOR_TRANSPARENCY
+ if (cursors[use]->rfb->alphaSource) {
+ free(cursors[use]->rfb->alphaSource);
+ }
+#endif
if (cursors[use]->rfb->source) {
free(cursors[use]->rfb->source);
}
@@ -8443,6 +8725,7 @@ int get_xfixes_cursor(int init) {
/* for rich cursor pixel data */
rich = (char *)calloc(Bpp*len, 1);
+ alpha = (char *)calloc(1*len, 1);
n_opaque = 0;
n_trans = 0;
@@ -8470,6 +8753,19 @@ int get_xfixes_cursor(int init) {
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 {
@@ -8493,10 +8789,9 @@ int get_xfixes_cursor(int init) {
a = 0xff000000 & (*(xfc->pixels+i));
a = a >> 24; /* alpha channel */
+
if (a < thresh) {
bitmap[i] = ' ';
- i++;
- continue;
} else {
bitmap[i] = 'x';
}
@@ -8540,20 +8835,40 @@ int get_xfixes_cursor(int init) {
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++;
}
}
@@ -8571,6 +8886,15 @@ int get_xfixes_cursor(int init) {
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;
@@ -8711,6 +9035,7 @@ int get_which_cursor(void) {
Window r;
trapped_xerror = 0;
+ X_LOCK;
old_handler = XSetErrorHandler(trap_xerror);
/* "narrow" windows are WM */
@@ -8721,6 +9046,7 @@ int get_which_cursor(void) {
}
}
XSetErrorHandler(old_handler);
+ X_UNLOCK;
trapped_xerror = 0;
}
if (which == which0) {
@@ -8750,7 +9076,7 @@ void mark_cursor_patch_modified(rfbScreenInfoPtr s, int old) {
int curx, cury, xhot, yhot, w, h;
int x1, x2, y1, y2;
- if (! s->cursor) {
+ if (! s || ! s->cursor) {
return;
}
@@ -8785,6 +9111,9 @@ void set_cursor_was_changed(rfbScreenInfoPtr s) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
+ if (! s) {
+ return;
+ }
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
cl->cursorWasChanged = TRUE;
@@ -8796,6 +9125,9 @@ void set_cursor_was_moved(rfbScreenInfoPtr s) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
+ if (! s) {
+ return;
+ }
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
cl->cursorWasMoved = TRUE;
@@ -8808,6 +9140,9 @@ void restore_cursor_shape_updates(rfbScreenInfoPtr s) {
rfbClientPtr cl;
int count = 0;
+ if (! s || ! s->clientHead) {
+ return;
+ }
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
int changed = 0;
@@ -8837,6 +9172,10 @@ void disable_cursor_shape_updates(rfbScreenInfoPtr s) {
rfbClientIteratorPtr iter;
rfbClientPtr cl;
+ if (! s || ! s->clientHead) {
+ return;
+ }
+
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
ClientData *cd;
@@ -8861,6 +9200,9 @@ int cursor_shape_updates_clients(rfbScreenInfoPtr s) {
rfbClientPtr cl;
int count = 0;
+ if (! s) {
+ return 0;
+ }
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->enableCursorShapeUpdates) {
@@ -8876,6 +9218,9 @@ int cursor_pos_updates_clients(rfbScreenInfoPtr s) {
rfbClientPtr cl;
int count = 0;
+ if (! s) {
+ return 0;
+ }
iter = rfbGetClientIterator(s);
while( (cl = rfbClientIteratorNext(iter)) ) {
if (cl->enableCursorPosUpdates) {
@@ -8898,6 +9243,9 @@ void cursor_position(int x, int y) {
int x_old, y_old, 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;
@@ -8978,6 +9326,9 @@ void set_rfb_cursor(int which) {
if (! show_cursor) {
return;
}
+ if (! screen) {
+ return;
+ }
if (workaround && screen->cursor) {
int all_are_cursor_pos = 1;
@@ -9415,6 +9766,15 @@ void install_padded_fb(char *geom) {
pad_geometry_time = time(0);
}
+void initialize_snap_fb(void) {
+ if (snap_fb) {
+ free(snap_fb);
+ }
+ snap = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes,
+ ZPixmap);
+ snap_fb = snap->data;
+}
+
/*
* initialize a fb for the X display
*/
@@ -9426,10 +9786,15 @@ XImage *initialize_xdisplay_fb(void) {
int subwin_bs;
X_LOCK;
- if (subwin && !valid_window((Window) subwin)) {
- rfbLog("invalid sub-window: 0x%lx\n", subwin);
- X_UNLOCK;
- clean_up_exit(1);
+ if (subwin) {
+ if (subwin_wait_mapped) {
+ wait_until_mapped(subwin);
+ }
+ if (!valid_window((Window) subwin)) {
+ rfbLog("invalid sub-window: 0x%lx\n", subwin);
+ X_UNLOCK;
+ clean_up_exit(1);
+ }
}
if (overlay) {
@@ -9638,6 +10003,9 @@ XImage *initialize_xdisplay_fb(void) {
usleep(250 * 1000);
goto again;
}
+ if (use_snapfb) {
+ initialize_snap_fb();
+ }
X_UNLOCK;
if (fb->bits_per_pixel == 24 && ! quiet) {
@@ -10080,8 +10448,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
bpp = screen->serverFormat.bitsPerPixel;
depth = screen->serverFormat.depth;
- setup_cursors();
- first_cursor();
+ setup_cursors_and_push();
if (scaling) {
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
@@ -10150,9 +10517,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
screen->newClientHook = new_client;
screen->kbdAddEvent = keyboard;
screen->ptrAddEvent = pointer;
- if (watch_selection) {
- screen->setXCutText = xcut_receive;
- }
+ screen->setXCutText = xcut_receive;
rfbInitServer(screen);
@@ -10464,7 +10829,7 @@ void initialize_xinerama (void) {
/* max len is 10000x10000+10000+10000 (23 chars) per geometry */
rcnt = (int) sraRgnCountRects(black_region);
- bstr = (char *) malloc(30 * rcnt * sizeof(char));
+ bstr = (char *) malloc(30 * (rcnt+1) * sizeof(char));
tstr = (char *) malloc(30 * sizeof(char));
bstr[0] = '\0';
@@ -10498,8 +10863,8 @@ void initialize_xinerama (void) {
}
void initialize_blackouts_and_xinerama(void) {
- if (blackout_string != NULL) {
- initialize_blackouts(blackout_string);
+ if (blackout_str != NULL) {
+ initialize_blackouts(blackout_str);
}
if (xinerama) {
initialize_xinerama();
@@ -10525,12 +10890,18 @@ void push_sleep(n) {
* try to forcefully push a black screen to all connected clients
*/
void push_black_screen(int n) {
+ if (!screen) {
+ return;
+ }
zero_fb(0, 0, dpy_x, dpy_y);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
push_sleep(n);
}
void refresh_screen(void) {
+ if (!screen) {
+ return;
+ }
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 1);
rfbPE(screen, -1);
}
@@ -10539,7 +10910,7 @@ void refresh_screen(void) {
* Fill the framebuffer with zero for the prescribed rectangle
*/
void zero_fb(int x1, int y1, int x2, int y2) {
- int pixelsize = bpp >> 3;
+ int pixelsize = bpp/8;
int line, fill = 0;
char *dst;
@@ -10549,6 +10920,9 @@ void zero_fb(int x1, int y1, int x2, int y2) {
if (y1 < 0 || y2 <= y1 || y2 > dpy_y) {
return;
}
+ if (! main_fb) {
+ return;
+ }
dst = main_fb + y1 * main_bytes_per_line + x1 * pixelsize;
line = y1;
@@ -10607,6 +10981,8 @@ void initialize_tiles(void) {
malloc((size_t) (ntiles * sizeof(unsigned char)));
tile_tried = (unsigned char *)
malloc((size_t) (ntiles * sizeof(unsigned char)));
+ tile_copied = (unsigned char *)
+ malloc((size_t) (ntiles * sizeof(unsigned char)));
tile_blackout = (tile_blackout_t *)
malloc((size_t) (ntiles * sizeof(tile_blackout_t)));
tile_region = (region_t *) malloc((size_t) (ntiles * sizeof(region_t)));
@@ -10629,6 +11005,10 @@ void free_tiles(void) {
free(tile_tried);
tile_tried = NULL;
}
+ if (tile_copied) {
+ free(tile_copied);
+ tile_copied = NULL;
+ }
if (tile_blackout) {
free(tile_blackout);
tile_blackout = NULL;
@@ -10661,7 +11041,8 @@ static int fs_factor = 0;
static void set_fs_factor(int max) {
int f, fac = 1, n = dpy_y;
- if ( (bpp/8) * dpy_x * dpy_y <= max ) {
+ fs_factor = 0;
+ if ((bpp/8) * dpy_x * dpy_y <= max) {
fs_factor = 1;
return;
}
@@ -10830,7 +11211,7 @@ void shm_clean(XShmSegmentInfo *shm, XImage *xim) {
}
void initialize_polling_images(void) {
- int i;
+ int i, MB = 1024 * 1024;
/* set all shm areas to "none" before trying to create any */
scanline_shm.shmid = -1;
@@ -10839,6 +11220,9 @@ void initialize_polling_images(void) {
fullscreen_shm.shmid = -1;
fullscreen_shm.shmaddr = (char *) -1;
fullscreen = NULL;
+ snaprect_shm.shmid = -1;
+ snaprect_shm.shmaddr = (char *) -1;
+ snaprect = NULL;
for (i=1; i<=ntiles_x; i++) {
tile_row_shm[i].shmid = -1;
tile_row_shm[i].shmaddr = (char *) -1;
@@ -10850,20 +11234,17 @@ void initialize_polling_images(void) {
if (! shm_create(&scanline_shm, &scanline, dpy_x, 1, "scanline")) {
clean_up_exit(1);
}
- if (0 && !quiet) {
- if (using_shm) {
- rfbLog("created \"scanline\" shm polling image.\n");
- } else {
- rfbLog("created \"scanline\" polling image.\n");
- }
- }
/*
* the fullscreen (e.g. 1280x1024/fs_factor) shared memory area image:
* (we cut down the size of the shm area to try avoid and shm segment
* limits, e.g. the default 1MB on Solaris)
*/
- set_fs_factor(1024 * 1024);
+ if (UT.sysname && strstr(UT.sysname, "Linux")) {
+ set_fs_factor(10 * MB);
+ } else {
+ set_fs_factor(1 * MB);
+ }
if (fs_frac >= 1.0) {
fs_frac = 1.1;
fs_factor = 0;
@@ -10875,13 +11256,15 @@ void initialize_polling_images(void) {
dpy_y/fs_factor, "fullscreen")) {
clean_up_exit(1);
}
- if (0 && !quiet) {
- if (using_shm) {
- rfbLog("created \"scanline\" shm polling image.\n");
- } else {
- rfbLog("created \"scanline\" polling image.\n");
- }
- }
+ }
+ if (use_snapfb) {
+ if (! fs_factor) {
+ rfbLog("warning: disabling -snapfb mode.\n");
+ use_snapfb = 0;
+ } else if (! shm_create(&snaprect_shm, &snaprect, dpy_x,
+ dpy_y/fs_factor, "snaprect")) {
+ clean_up_exit(1);
+ }
}
/*
@@ -11214,6 +11597,9 @@ static void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
*/
shrink = 0;
}
+ if (!screen || !rfb_fb || !main_fb) {
+ return;
+ }
if (! screen->serverFormat.trueColour) {
/*
@@ -11579,7 +11965,7 @@ static int copy_tiles(int tx, int ty, int nt) {
int size_x, size_y, width1, width2;
int off, len, n, dw, dx, t;
int w1, w2, dx1, dx2; /* tmps for normal and short tiles */
- int pixelsize = bpp >> 3;
+ int pixelsize = bpp/8;
int first_min, last_max;
char *src, *dst, *s_src, *s_dst, *m_src, *m_dst;
@@ -11629,18 +12015,9 @@ static int copy_tiles(int tx, int ty, int nt) {
X_LOCK;
XRANDR_SET_TRAP_RET(-1, "copy_tile-set");
/* read in the whole tile run at once: */
- if (using_shm && size_x == tile_x * nt && size_y == tile_y) {
- /* general case: */
- XShmGetImage_wr(dpy, window, tile_row[nt], x, y, AllPlanes);
- } else {
- /*
- * No shm or near bottom/rhs edge case:
- * (but only if tile size does not divide screen size)
- */
- XGetSubImage_wr(dpy, window, x, y, size_x, size_y, AllPlanes,
- ZPixmap, tile_row[nt], 0, 0);
- }
+ copy_image(tile_row[nt], x, y, size_x, size_y);
XRANDR_CHK_TRAP_RET(-1, "copy_tile-chk");
+
X_UNLOCK;
if (blackouts && tile_blackout[n].cover == 1) {
@@ -11872,6 +12249,8 @@ static int copy_tiles(int tx, int ty, int nt) {
tile_region[n+s].left_diff = left_diff[t];
tile_region[n+s].right_diff = right_diff[t];
+
+ tile_copied[n+s] = 1;
}
return(1);
@@ -12043,6 +12422,33 @@ static int copy_tiles_backward_pass(void) {
return diffs;
}
+static int copy_tiles_additional_pass(void) {
+ int x, y, n;
+ int diffs = 0, ct;
+
+ for (y=0; y < ntiles_y; y++) {
+ for (x=0; x < ntiles_x; x++) {
+ n = x + y * ntiles_x; /* number of this tile */
+
+ if (! tile_has_diff[n]) {
+ continue;
+ }
+ if (tile_copied[n]) {
+ continue;
+ }
+
+ ct = copy_tiles(x, y, 1);
+ if (ct < 0) return ct; /* fatal */
+ }
+ }
+ for (n=0; n < ntiles; n++) {
+ if (tile_has_diff[n]) {
+ diffs++;
+ }
+ }
+ return diffs;
+}
+
static int gap_try(int x, int y, int *run, int *saw, int along_x) {
int n, m, i, xt, yt, ct;
@@ -12204,7 +12610,7 @@ static void blackout_regions(void) {
* are other issues... use -fs 1.0 to disable.
*/
int copy_screen(void) {
- int pixelsize = bpp >> 3;
+ int pixelsize = bpp/8;
char *fbp;
int i, y, block_size;
@@ -12214,6 +12620,9 @@ int copy_screen(void) {
block_size = (dpy_x * (dpy_y/fs_factor) * pixelsize);
+ if (! main_fb) {
+ return 0;
+ }
fbp = main_fb;
y = 0;
@@ -12222,15 +12631,9 @@ int copy_screen(void) {
/* screen may be too big for 1 shm area, so broken into fs_factor */
for (i=0; i < fs_factor; i++) {
XRANDR_SET_TRAP_RET(-1, "copy_screen-set");
- if (using_shm) {
- XShmGetImage_wr(dpy, window, fullscreen, 0, y,
- AllPlanes);
- } else {
- XGetSubImage_wr(dpy, window, 0, y, fullscreen->width,
- fullscreen->height, AllPlanes, ZPixmap, fullscreen,
- 0, 0);
- }
+ copy_image(fullscreen, 0, y, 0, 0);
XRANDR_CHK_TRAP_RET(-1, "copy_screen-chk");
+
memcpy(fbp, fullscreen->data, (size_t) block_size);
y += dpy_y / fs_factor;
@@ -12247,6 +12650,50 @@ int copy_screen(void) {
return 0;
}
+int copy_snap(void) {
+ int pixelsize = bpp/8;
+ char *fbp;
+ int i, y, block_size;
+ double dt = 0.0;
+ static int first = 1;
+
+ if (! fs_factor) {
+ return 0;
+ }
+
+ block_size = (dpy_x * (dpy_y/fs_factor) * pixelsize);
+
+ if (! snap_fb || ! snap || ! snaprect) {
+ return 0;
+ }
+ fbp = snap_fb;
+ y = 0;
+
+ dtime(&dt);
+ X_LOCK;
+
+ /* screen may be too big for 1 shm area, so broken into fs_factor */
+ for (i=0; i < fs_factor; i++) {
+ XRANDR_SET_TRAP_RET(-1, "copy_snap-set");
+ copy_image(snaprect, 0, y, 0, 0);
+ XRANDR_CHK_TRAP_RET(-1, "copy_snap-chk");
+
+ memcpy(fbp, snaprect->data, (size_t) block_size);
+
+ y += dpy_y / fs_factor;
+ fbp += block_size;
+ }
+
+ X_UNLOCK;
+ dt = dtime(&dt);
+ if (first) {
+ rfbLog("copy_snap: time for -snapfb snapshot: %.3f sec\n", dt);
+ first = 0;
+ }
+
+ return 0;
+}
+
/*
* Utilities for managing the "naps" to cut down on amount of polling.
@@ -12473,25 +12920,24 @@ void set_offset(void) {
*/
static int scan_display(int ystart, int rescan) {
char *src, *dst;
- int pixelsize = bpp >> 3;
+ int pixelsize = bpp/8;
int x, y, w, n;
int tile_count = 0;
int whole_line = 1, nodiffs = 0;
y = ystart;
+ if (! main_fb) {
+ rfbLog("scan_display: no main_fb!\n");
+ return 0;
+ }
+
while (y < dpy_y) {
/* grab the horizontal scanline from the display: */
X_LOCK;
XRANDR_SET_TRAP_RET(-1, "scan_display-set");
- if (using_shm) {
- XShmGetImage_wr(dpy, window, scanline, 0, y, AllPlanes);
- } else {
- XGetSubImage_wr(dpy, window, 0, y, scanline->width,
- scanline->height, AllPlanes, ZPixmap, scanline,
- 0, 0);
- }
+ copy_image(scanline, 0, y, 0, 0);
XRANDR_CHK_TRAP_RET(-1, "scan_display-chk");
X_UNLOCK;
@@ -12566,13 +13012,16 @@ static int scan_display(int ystart, int rescan) {
* toplevel for the scanning, rescanning, and applying the heuristics.
* returns number of changed tiles.
*/
-int scan_for_updates(void) {
+int scan_for_updates(int count_only) {
int i, tile_count, tile_diffs;
+ int old_copy_tile;
double frac1 = 0.1; /* tweak parameter to try a 2nd scan_display() */
double frac2 = 0.35; /* or 3rd */
+ double frac3 = 0.02; /* do scan_display() again after copy_tiles() */
for (i=0; i < ntiles; i++) {
tile_has_diff[i] = 0;
tile_tried[i] = 0;
+ tile_copied[i] = 0;
}
/*
@@ -12580,17 +13029,19 @@ int scan_for_updates(void) {
* tile_x = tile_y = NSCAN = 32!
*/
- scan_count++;
- scan_count %= NSCAN;
+ if (!count_only) {
+ scan_count++;
+ scan_count %= NSCAN;
- if (scan_count % (NSCAN/4) == 0) {
- /* some periodic maintenance */
+ if (scan_count % (NSCAN/4) == 0) {
+ /* some periodic maintenance */
- if (subwin) {
- set_offset(); /* follow the subwindow */
- }
- if (indexed_color) { /* check for changed colormap */
- set_colormap(0);
+ if (subwin) {
+ set_offset(); /* follow the subwindow */
+ }
+ if (indexed_color) { /* check for changed colormap */
+ set_colormap(0);
+ }
}
}
@@ -12606,6 +13057,12 @@ int scan_for_updates(void) {
tile_count = scan_display(scanlines[scan_count], 0);
SCAN_FATAL(tile_count);
+ if (count_only) {
+ scan_in_progress = 0;
+ fb_copy_in_progress = 0;
+ return tile_count;
+ }
+
nap_set(tile_count);
if (fs_factor && frac1 >= fs_frac) {
@@ -12674,13 +13131,18 @@ int scan_for_updates(void) {
/*
* Old way, copy I/O one tile at a time.
*/
- tile_diffs = copy_all_tiles();
+ old_copy_tile = 1;
} else {
/*
* New way, does runs of horizontal tiles at once.
* Note that below, for simplicity, the extra tile finding
* (e.g. copy_tiles_backward_pass) is done the old way.
*/
+ old_copy_tile = 0;
+ }
+ if (old_copy_tile) {
+ tile_diffs = copy_all_tiles();
+ } else {
tile_diffs = copy_all_tile_runs();
}
SCAN_FATAL(tile_diffs);
@@ -12692,6 +13154,22 @@ int scan_for_updates(void) {
tile_diffs = copy_tiles_backward_pass();
SCAN_FATAL(tile_diffs);
+ if (tile_diffs > frac3 * ntiles) {
+ /*
+ * we spent a lot of time in those copy_tiles, run
+ * another scan, maybe more of the screen changed.
+ */
+ int cp = (NSCAN - scan_count + 13) % NSCAN;
+
+ scan_in_progress = 1;
+ tile_count = scan_display(scanlines[cp], 1);
+ SCAN_FATAL(tile_count);
+ scan_in_progress = 0;
+
+ tile_diffs = copy_tiles_additional_pass();
+ SCAN_FATAL(tile_diffs);
+ }
+
/* Given enough tile diffs, try the islands: */
if (grow_fill && tile_diffs > 4) {
tile_diffs = grow_islands();
@@ -12753,7 +13231,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) {
char *wish = NULL, *orig_path, *full_path, *tpath, *p;
int try_max = 4, sleep = 300;
pid_t mypid = getpid();
- FILE *pipe;
+ FILE *pipe, *tmpf;
if (*gui_code == '\0') {
rfbLog("gui not available in this program.\n");
@@ -12822,7 +13300,8 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) {
char *wishes[] = {"wish", "wish8.3", "wish8.4"};
int nwishes = 3, i;
- try = (char *)malloc(strlen(p) + 10);
+ /* strlen("wish8.4") is 7 */
+ try = (char *)malloc(strlen(p) + 1 + 7 + 1);
for (i=0; i<nwishes; i++) {
sprintf(try, "%s/%s", p, wishes[i]);
if (stat(try, &sbuf) == 0) {
@@ -12846,13 +13325,32 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) {
set_env("X11VNC_CMDLINE", program_cmdline);
sprintf(cmd, "%s -", wish);
- pipe = popen(cmd, "w");
- if (! pipe) {
- fprintf(stderr, "could not run: %s\n", cmd);
- perror("popen");
+ tmpf = tmpfile();
+ if (tmpf == NULL) {
+ /* if no tmpfile, use a pipe */
+ pipe = popen(cmd, "w");
+ if (! pipe) {
+ fprintf(stderr, "could not run: %s\n", cmd);
+ perror("popen");
+ }
+ fprintf(pipe, "%s", gui_code);
+ pclose(pipe);
+ } else {
+ /*
+ * we prefer a tmpfile since then this x11vnc process
+ * will then be gone, otherwise the x11vnc program text
+ * will still be in use.
+ */
+ int n = fileno(tmpf);
+ fprintf(tmpf, "%s", gui_code);
+ fflush(tmpf);
+ rewind(tmpf);
+ dup2(n, 0);
+ close(n);
+ execlp(wish, wish, "-", (char *) NULL);
+ fprintf(stderr, "could not exec wish: %s -\n", wish);
+ perror("execlp");
}
- fprintf(pipe, "%s", gui_code);
- pclose(pipe);
exit(0);
}
@@ -12990,433 +13488,477 @@ static int defer_update_nofb = 6; /* defer a shorter time under -nofb */
static void check_user_input2(double dt) {
+ int eaten = 0, miss = 0, max_eat = 50;
+ int g, g_in;
+ double spin = 0.0, tm = 0.0;
+ double quick_spin_fac = 0.40;
+ double grind_spin_time = 0.175;
- if (got_pointer_input) {
- int eaten = 0, miss = 0, max_eat = 50;
- int g, g_in;
- double spin = 0.0, tm = 0.0;
- double quick_spin_fac = 0.40;
- double grind_spin_time = 0.175;
- dtime(&tm);
- g = g_in = got_pointer_input;
+
+ dtime(&tm);
+ g = g_in = got_pointer_input;
+ if (!got_pointer_input) {
+ return;
+ }
+ /*
+ * Try for some "quick" pointer input processing.
+ *
+ * About as fast as we can, we try to process user input calling
+ * rfbProcessEvents or rfbCheckFds. We do this for a time on
+ * order of the last scan_for_updates() time, dt, but if we stop
+ * getting user input we break out. We will also break out if
+ * we have processed max_eat inputs.
+ *
+ * Note that rfbCheckFds() does not send any framebuffer updates,
+ * so is more what we want here, although it is likely they have
+ * all be sent already.
+ */
+ while (1) {
+ if (show_multiple_cursors) {
+ rfbPE(screen, 1000);
+ } else {
+ rfbCFD(screen, 1000);
+ }
+ XFlush(dpy);
+
+ spin += dtime(&tm);
+
+ if (spin > quick_spin_fac * dt) {
+ /* get out if spin time comparable to last scan time */
+ break;
+ }
+ if (got_pointer_input > g) {
+ g = got_pointer_input;
+ if (eaten++ < max_eat) {
+ continue;
+ }
+ } else {
+ miss++;
+ }
+ if (miss > 1) { /* 1 means out on 2nd miss */
+ break;
+ }
+ }
+
+
+ /*
+ * Probably grinding with a lot of fb I/O if dt is this large.
+ * (need to do this more elegantly)
+ *
+ * Current idea is to spin our wheels here *not* processing any
+ * fb I/O, but still processing the user input. This user input
+ * goes to the X display and changes it, but we don't poll it
+ * while we "rest" here for a time on order of dt, the previous
+ * scan_for_updates() time. We also break out if we miss enough
+ * user input.
+ */
+ if (dt > grind_spin_time) {
+ int i, ms, split = 30;
+ double shim;
/*
- * Try for some "quick" pointer input processing.
- *
- * About as fast as we can, we try to process user input
- * calling rfbProcessEvents or rfbCheckFds. We do this
- * for a time on order of the last scan_for_updates() time,
- * dt, but if we stop getting user input we break out.
- * We will also break out if we have processed max_eat
- * inputs.
- *
- * Note that rfbCheckFds() does not send any framebuffer
- * updates, so is more what we want here, although it is
- * likely they have all be sent already.
+ * Break up our pause into 'split' steps. We get at
+ * most one input per step.
*/
- while (1) {
+ shim = 0.75 * dt / split;
+
+ ms = (int) (1000 * shim);
+
+ /* cutoff how long the pause can be */
+ if (split * ms > 300) {
+ ms = 300 / split;
+ }
+
+ spin = 0.0;
+ tm = 0.0;
+ dtime(&tm);
+
+ g = got_pointer_input;
+ miss = 0;
+ for (i=0; i<split; i++) {
+ usleep(ms * 1000);
if (show_multiple_cursors) {
rfbPE(screen, 1000);
} else {
rfbCFD(screen, 1000);
}
- XFlush(dpy);
-
spin += dtime(&tm);
-
- if (spin > quick_spin_fac * dt) {
- /* get out if spin time comparable to last scan time */
- break;
- }
if (got_pointer_input > g) {
- g = got_pointer_input;
- if (eaten++ < max_eat) {
- continue;
- }
+ XFlush(dpy);
+ miss = 0;
} else {
miss++;
}
- if (miss > 1) { /* 1 means out on 2nd miss */
+ g = got_pointer_input;
+ if (miss > 2) {
+ break;
+ }
+ if (1000 * spin > ms * split) {
break;
}
}
+ }
+}
+static void check_user_input3(double dt, double dtr, int tile_diffs) {
- /*
- * Probably grinding with a lot of fb I/O if dt is
- * this large. (need to do this more elegantly)
- *
- * Current idea is to spin our wheels here *not* processing
- * any fb I/O, but still processing the user input.
- * This user input goes to the X display and changes it,
- * but we don't poll it while we "rest" here for a time
- * on order of dt, the previous scan_for_updates() time.
- * We also break out if we miss enough user input.
- */
- if (dt > grind_spin_time) {
- int i, ms, split = 30;
- double shim;
-
- /*
- * Break up our pause into 'split' steps.
- * We get at most one input per step.
- */
- shim = 0.75 * dt / split;
-
- ms = (int) (1000 * shim);
-
- /* cutoff how long the pause can be */
- if (split * ms > 300) {
- ms = 300 / split;
- }
+ int allowed_misses, miss_tweak, i, g, g_in;
+ int last_was_miss, consecutive_misses;
+ double spin, spin_max, tm, to, dtm;
+ int rfb_wait_ms = 2;
+ static double dt_cut = 0.075;
+ int gcnt, ginput;
+ static int first = 1;
- spin = 0.0;
- tm = 0.0;
- dtime(&tm);
- g = got_pointer_input;
- miss = 0;
- for (i=0; i<split; i++) {
- usleep(ms * 1000);
- if (show_multiple_cursors) {
- rfbPE(screen, 1000);
- } else {
- rfbCFD(screen, 1000);
- }
- spin += dtime(&tm);
- if (got_pointer_input > g) {
- XFlush(dpy);
- miss = 0;
- } else {
- miss++;
- }
- g = got_pointer_input;
- if (miss > 2) {
- break;
- }
- if (1000 * spin > ms * split) {
- break;
- }
- }
+ if (first) {
+ char *p = getenv("SPIN");
+ if (p) {
+ double junk;
+ sscanf(p, "%lf,%lf", &dt_cut, &junk);
}
+ first = 0;
}
-}
-static void check_user_input3(double dt, int tile_diffs) {
+ if (!got_pointer_input) {
+ return;
+ }
- if (got_pointer_input) {
- int spun_out, missed_out, allowed_misses, g, g_in;
- double spin, spin_max, tm, to, dtm, rpe_last;
- static int rfb_wait_ms = 2;
- static double grind_spin_time = 0.30, dt_cut = 0.075;
- static double quick_spin_fac = 0.65, spin_max_fac = 2.0;
- static double rpe_wait = 0.15;
- int grinding, gcnt, ms, split = 200;
- static int first = 1;
- if (first) {
- char *p = getenv("SPIN");
- if (p) {
- sscanf(p, "%lf,%lf,%lf", &grind_spin_time, &dt_cut, &quick_spin_fac);
- }
- first = 0;
- }
+ if (dt < dt_cut) {
+ dt = dt_cut; /* this is to try to avoid early exit */
+ }
+ spin_max = 0.5;
+ spin = 0.0; /* amount of time spinning */
+ allowed_misses = 10; /* number of ptr inputs we can miss */
+ miss_tweak = 8;
+ last_was_miss = 0;
+ consecutive_misses = 1;
+ gcnt = 0;
+ ginput = 0;
- /*
- * Try for some "quick" pointer input processing.
- *
- * About as fast as we can, we try to process user input
- * calling rfbProcessEvents or rfbCheckFds. We do this
- * for a time on order of the last scan_for_updates() time,
- * dt, but if we stop getting user input we break out.
- *
- * Note that rfbCheckFds() does not send any framebuffer
- * updates, so is more what we want here, although it is
- * likely they have all be sent already.
- *
- * After our first spin_out or missed_out, we decide if we
- * should continue, if we do so we say we are "grinding"
- */
+ tm = 0.0; /* timer variable */
+ dtime(&tm);
+ to = tm; /* last time we did rfbPE() */
- if (dt < dt_cut) {
- dt = dt_cut; /* this is to try to avoid early exit */
- }
- /* max spin time in 1st pass, comparable to last dt */
- spin_max = quick_spin_fac * dt;
+ g = g_in = got_pointer_input;
- grinding = 0; /* 1st pass is "not grinding" */
- spin = 0.0; /* amount of time spinning */
- spun_out = 0; /* whether we spun out of time */
- missed_out = 0; /* whether we received no ptr input */
- allowed_misses = 3; /* number of ptr inputs we can miss */
- gcnt = 0;
+ while (1) {
+ int got_input = 0;
- tm = 0.0; /* timer variable */
- dtime(&tm);
- rpe_last = to = tm; /* last time we did rfbPE() */
- g = g_in = got_pointer_input;
+ gcnt++;
+ if (button_mask) {
+ drag_in_progress = 1;
+ }
- while (1) {
- int got_input = 0;
+ rfbCFD(screen, rfb_wait_ms * 1000);
- gcnt++;
- if (grinding) {
- if (gcnt >= split) {
- break;
- }
- usleep(ms * 1000);
- }
+ dtm = dtime(&tm);
+ spin += dtm;
- if (button_mask) {
- drag_in_progress = 1;
+ if (got_pointer_input == g) {
+ if (last_was_miss) {
+ consecutive_misses++;
}
-
- if (show_multiple_cursors && tm > rpe_last + rpe_wait) {
- rfbPE(screen, rfb_wait_ms * 1000);
- rpe_last = tm;
- } else {
- rfbCFD(screen, rfb_wait_ms * 1000);
+ last_was_miss = 1;
+ } else {
+ ginput++;
+ if (ginput % miss_tweak == 0) {
+ allowed_misses++;
}
+ consecutive_misses = 1;
+ last_was_miss = 0;
+ }
- dtm = dtime(&tm);
- spin += dtm;
+ if (spin > spin_max) {
+ /* get out if spin time over limit */
+ break;
- if (spin > spin_max) {
- /* get out if spin time over limit */
- spun_out = 1;
- } else if (got_pointer_input > g) {
- /* received some input, flush to display. */
- got_input = 1;
- g = got_pointer_input;
- XFlush(dpy);
- } else if (--allowed_misses <= 0) {
- /* too many misses */
- missed_out = 1;
+ } else if (got_pointer_input > g) {
+ /* received some input, flush to display. */
+ got_input = 1;
+ g = got_pointer_input;
+ X_LOCK;
+ XFlush(dpy);
+ X_UNLOCK;
+ } else if (--allowed_misses <= 0) {
+ /* too many misses */
+ break;
+ } else if (consecutive_misses >=3) {
+ /* too many misses */
+ break;
+ } else {
+ /* these are misses */
+ int wms = 0;
+ if (gcnt == 1 && button_mask) {
+ /*
+ * missed our first input, wait
+ * for a defer time. (e.g. on
+ * slow link) hopefully client
+ * will batch them.
+ */
+ wms = 50;
+ } else if (button_mask) {
+ wms = 10;
} else {
- /* these are misses */
- int wms = 0;
- if (! grinding && gcnt == 1 && button_mask) {
- /*
- * missed our first input, wait
- * for a defer time. (e.g. on
- * slow link) hopefully client
- * will batch them.
- */
- wms = 1000 * (0.5 * (spin_max - spin));
- } else if (button_mask) {
- wms = 10;
- } else {
- }
- if (wms) {
- usleep(wms * 1000);
- }
}
- if (spun_out && ! grinding) {
- /* set parameters for grinding mode. */
-
- grinding = 1;
-
- if (spin > grind_spin_time || button_mask) {
- spin_max = spin +
- grind_spin_time * spin_max_fac;
- } else {
- spin_max = spin + dt * spin_max_fac;
- }
- ms = (int) (1000 * ((spin_max - spin)/split));
- if (ms < 1) {
- ms = 1;
- }
-
- /* reset for second pass */
- spun_out = 0;
- missed_out = 0;
- allowed_misses = 3;
- g = got_pointer_input;
- gcnt = 0;
- } else if (spun_out && grinding) {
- /* done in 2nd pass */
- break;
- } else if (missed_out) {
- /* done in either pass */
- break;
+ if (wms) {
+ usleep(wms * 1000);
}
}
}
+
+ if (ginput >= 2) {
+ /* try for a couple more quick ones */
+ for (i=0; i<2; i++) {
+ rfbCFD(screen, rfb_wait_ms * 1000);
+ }
+ }
+
drag_in_progress = 0;
}
-/* quick-n-dirty copy of check_user_input3, merge later... */
+int fb_update_sent(int *count) {
+ static int last_count = 0;
+ int sent = 0, rc = 0;
+ rfbClientIteratorPtr i;
+ rfbClientPtr cl;
-static void check_user_input4(double dt, int tile_diffs) {
+ i = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(i)) ) {
+ sent += cl->framebufferUpdateMessagesSent;
+ }
+ rfbReleaseClientIterator(i);
+ if (sent != last_count) {
+ rc = 1;
+ }
+ if (count != NULL) {
+ *count = sent;
+ }
+ last_count = sent;
+ return rc;
+}
+
+static void check_user_input4(double dt, double dtr, int tile_diffs) {
- int spun_out, missed_out, allowed_misses, g, g_in;
- double spin, spin_max, tm, to, dtm, rpe_last;
- static int rfb_wait_ms = 2;
- static double grind_spin_time = 0.30, dt_cut = 0.075;
- static double quick_spin_fac = 0.65, spin_max_fac = 2.0;
- static double rpe_wait = 0.15;
- int grinding, gcnt, ms, split = 200;
+ int g, g_in, i, ginput, gcnt, tmp;
+ int last_was_miss, consecutive_misses;
+ int min_frame_size = 10; /* 10 tiles */
+ double spin, tm, to, tc, dtm, rpe_last;
+ int rfb_wait_ms = 2;
+ static double dt_cut = 0.050;
static int first = 1;
- int Btile = tile_x * tile_y * bpp/8;
- double Ttile;
- double screen_rate = 5000000.; /* 5 MB/sec */
- double client_rate = 80 * 100000.; /* 20 KB/sec @ 80X compression */
- static double Tfac = 1.0;
+ int Btile = tile_x * tile_y * bpp/8; /* Bytes per tile */
+ double Ttile, dt_use;
+ double screen_rate = 6000000.; /* 5 MB/sec */
+ double vnccpu_rate = 80 * 100000.; /* 20 KB/sec @ 80X compression */
+ double net_rate = 50000.;
+ static double Tfac_r = 1.0, Tfac_v = 1.0, Tfac_n = 1.0, Tdelay = 0.001;
static double dt_min = -1.0, dt_max = -1.0;
+ double dt_min_fallback = 0.050;
+ static int ssec = 0, total_calls = 0;
+ static int push_frame = 0, update_count = 0;
if (first) {
char *p = getenv("SPIN");
if (p) {
- sscanf(p, "%lf,%lf,%lf,%lf", &grind_spin_time,
- &dt_cut, &quick_spin_fac, &Tfac);
+ sscanf(p, "%lf,%lf,%lf,%lf", &dt_cut, &Tfac_r, &Tfac_v, &Tfac_n);
}
first = 0;
+ ssec = time(0);
}
- if (dt_min < 0 || dt < dt_min) {
- dt_min = dt;
+ total_calls++;
+
+ if (dt_min < 0.0 || dt < dt_min) {
+ if (dt > 0.0) {
+ dt_min = dt;
+ }
+ }
+ if (dt_min < 0.0) {
+ /* sensible value for the very 1st call if dt = 0.0 */
+ dt_min = dt_min_fallback;
}
- if (dt_max < 0 || dt > dt_max) {
+ if (dt_max < 0.0 || dt > dt_max) {
dt_max = dt;
}
+ if (total_calls > 30 && dt_min > 0.0) {
+ static int first = 1;
+ /*
+ * dt_min will soon be the quickest time to do
+ * one scan_for_updates with no tiles copied.
+ * use this (instead of copy_tiles) to estimate
+ * screen read rate.
+ */
+ screen_rate = (main_bytes_per_line * ntiles_y) / dt_min;
+ if (first) {
+ rfbLog("measured screen read rate: %.2f Bytes/sec\n",
+ screen_rate);
+ }
+ first = 0;
+ }
+
+ tm = 0.0; /* timer variable */
+ dtime(&tm);
+
+ if (dt < dt_cut) {
+ dt_use = dt_cut;
+ } else {
+ dt_use = dt;
+ }
+
+ if (push_frame) {
+ int cnt, iter = 0;
+ double tp = 0.0, push_spin = 0.0;
+ dtime(&tp);
+ while (push_spin < dt_use * 0.5) {
+ fb_update_sent(&cnt);
+ if (cnt != update_count) {
+ break;
+ }
+ /* damn, they didn't push our frame! */
+ iter++;
+ rfbPE(screen, rfb_wait_ms * 1000);
+
+ push_spin += dtime(&tp);
+ }
+ if (iter) {
+ X_LOCK;
+ XFlush(dpy);
+ X_UNLOCK;
+ }
+ push_frame = 0;
+ update_count = 0;
+ }
+
/*
* when we first enter we require some pointer input
*/
if (!got_pointer_input) {
- drag_in_progress = 0;
return;
}
- Ttile = Btile * (1.0/screen_rate + 1.0/client_rate);
- Ttile = Tfac * Ttile;
+ vnccpu_rate = get_raw_rate();
- if (dt < dt_cut) {
- dt = dt_cut; /* this is to try to avoid early exit */
+ if ((tmp = get_read_rate()) != 0) {
+ screen_rate = (double) tmp;
+ }
+ if ((tmp = get_net_rate()) != 0) {
+ net_rate = (double) tmp;
}
+ net_rate = (vnccpu_rate/get_cmp_rate()) * net_rate;
- /* max spin time in 1st pass, comparable to last dt */
- spin_max = quick_spin_fac * dt;
+ if ((tmp = get_net_latency()) != 0) {
+ Tdelay = 0.5 * ((double) tmp)/1000.;
+ }
+
+ Ttile = Btile * (Tfac_r/screen_rate + Tfac_v/vnccpu_rate + Tfac_n/net_rate);
- grinding = 0; /* 1st pass is "not grinding" */
spin = 0.0; /* amount of time spinning */
- spun_out = 0; /* whether we spun out of time */
- missed_out = 0; /* whether we received no ptr input */
- allowed_misses = 3; /* number of ptr inputs we can miss */
+ last_was_miss = 0;
+ consecutive_misses = 1;
gcnt = 0;
+ ginput = 0;
- tm = 0.0; /* timer variable */
- dtime(&tm);
- rpe_last = to = tm; /* last time we did rfbPE() */
+ rpe_last = to = tc = tm; /* last time we did rfbPE() */
g = g_in = got_pointer_input;
+ tile_diffs = 0; /* reset our knowlegde of tile_diffs to zero */
while (1) {
int got_input = 0;
gcnt++;
- if (grinding) {
- if (gcnt >= split) {
- break;
- }
- usleep(ms * 1000);
- }
if (button_mask) {
+ /* this varible is used by our pointer handler */
drag_in_progress = 1;
}
- if (show_multiple_cursors && tm > rpe_last + rpe_wait) {
- rfbPE(screen, rfb_wait_ms * 1000);
- rpe_last = tm;
- } else {
- rfbCFD(screen, rfb_wait_ms * 1000);
- }
+ /* turn libvncserver crank to process events: */
+ rfbCFD(screen, rfb_wait_ms * 1000);
dtm = dtime(&tm);
spin += dtm;
- if (spin > spin_max) {
- /* get out if spin time over limit */
- spun_out = 1;
+ if ( (gcnt == 1 && got_pointer_input > g) || tm-tc > 2*dt_min) {
+ tile_diffs = scan_for_updates(1);
+ tc = tm;
+ }
- } else if (tile_diffs > 200 && spin > Ttile * tile_diffs) {
- /* XXX not finished. */
+ if (got_pointer_input == g) {
+ if (last_was_miss) {
+ consecutive_misses++;
+ }
+ last_was_miss = 1;
+ } else {
+ ginput++;
+ consecutive_misses = 1;
+ last_was_miss = 0;
+ }
+
+ if (tile_diffs > min_frame_size && spin > Ttile * tile_diffs + Tdelay) {
/* we think we can push the frame */
+ push_frame = 1;
+ fb_update_sent(&update_count);
break;
} else if (got_pointer_input > g) {
- /* received some input, flush to display. */
+ /* received some input, flush it to display. */
got_input = 1;
g = got_pointer_input;
+ X_LOCK;
XFlush(dpy);
+ X_UNLOCK;
- } else if (--allowed_misses <= 0) {
- /* too many misses */
- missed_out = 1;
+ } else if (consecutive_misses >= 2) {
+ /* too many misses in a row */
+ break;
} else {
- /* these are misses */
- int wms = 0;
- if (! grinding && gcnt == 1 && button_mask) {
+ /* these are pointer input misses */
+ int wms;
+ if (gcnt == 1 && button_mask) {
/*
* missed our first input, wait for
* a defer time. (e.g. on slow link)
- * hopefully client will batch them.
+ * hopefully client will batch many
+ * of them for the next read.
*/
- wms = 1000 * (0.5 * (spin_max - spin));
+ wms = 50;
} else if (button_mask) {
wms = 10;
+ } else {
+ wms = 0;
}
if (wms) {
usleep(wms * 1000);
}
}
- if (spun_out && ! grinding) {
- /* set parameters for grinding mode. */
-
- grinding = 1;
-
- if (spin > grind_spin_time || button_mask) {
- spin_max = spin +
- grind_spin_time * spin_max_fac;
- } else {
- spin_max = spin + dt * spin_max_fac;
- }
- ms = (int) (1000 * ((spin_max - spin)/split));
- if (ms < 1) {
- ms = 1;
- }
-
- /* reset for second pass */
- spun_out = 0;
- missed_out = 0;
- allowed_misses = 3;
- g = got_pointer_input;
- gcnt = 0;
-
- } else if (spun_out && grinding) {
- /* done in 2nd pass */
- break;
- } else if (missed_out) {
- /* done in either pass */
- break;
+ }
+ if (ginput >= 2) {
+ /* try for a couple more quick ones */
+ for (i=0; i<2; i++) {
+ rfbCFD(screen, rfb_wait_ms * 1000);
}
}
drag_in_progress = 0;
}
-static int check_user_input(double dt, int tile_diffs, int *cnt) {
+static int check_user_input(double dt, double dtr, int tile_diffs, int *cnt) {
if (pointer_mode == 1) {
if ((got_user_input || ui_skip < 0) && *cnt % ui_skip != 0) {
/* every ui_skip-th drops thru to scan */
*cnt++;
+ X_LOCK;
XFlush(dpy);
+ X_UNLOCK;
return 1; /* short circuit watch_loop */
} else {
return 0;
@@ -13424,19 +13966,24 @@ static int check_user_input(double dt, int tile_diffs, int *cnt) {
}
if (pointer_mode >= 2 && pointer_mode <= 4) {
if (got_keyboard_input) {
+ /*
+ * for these modes, short circuit watch_loop on
+ * *keyboard* input.
+ */
if (*cnt % ui_skip != 0) {
*cnt++;
- return 1; /* short circuit watch_loop */
+ return 1;
}
}
- /* otherwise continue with pointer input */
+ /* otherwise continue below with pointer input method */
}
+
if (pointer_mode == 2) {
check_user_input2(dt);
} else if (pointer_mode == 3) {
- check_user_input3(dt, tile_diffs);
+ check_user_input3(dt, dtr, tile_diffs);
} else if (pointer_mode == 4) {
- check_user_input4(dt, tile_diffs);
+ check_user_input4(dt, dtr, tile_diffs);
}
return 0;
}
@@ -13448,7 +13995,7 @@ static int check_user_input(double dt, int tile_diffs, int *cnt) {
double dtime(double *t_old) {
/*
* usage: call with 0.0 to initialize, subsequent calls give
- * the time differences.
+ * the time difference since last call.
*/
double t_now, dt;
struct timeval now;
@@ -13464,17 +14011,273 @@ double dtime(double *t_old) {
return(dt);
}
+void measure_display_hook(rfbClientPtr cl) {
+ ClientData *cd = (ClientData *) cl->clientData;
+ cd->timer = 0.0;
+ dtime(&cd->timer);
+}
+
+void measure_send_rates_init(void) {
+ int i, bs, rbs;
+ rfbClientIteratorPtr iter;
+ rfbClientPtr cl;
+
+ screen->displayHook = measure_display_hook;
+
+ iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) ) {
+ ClientData *cd = (ClientData *) cl->clientData;
+ bs = 0;
+ for (i=0; i<MAX_ENCODINGS; i++) {
+ bs += cl->bytesSent[i];
+ }
+ rbs = cl->rawBytesEquivalent;
+
+ cd->set_cmp_bytes = bs;
+ cd->set_raw_bytes = rbs;
+ cd->timer = -1.0;
+ }
+ rfbReleaseClientIterator(iter);
+}
+
+int get_rate(int which) {
+ rfbClientIteratorPtr iter;
+ rfbClientPtr cl;
+ int i, samples = RATE_SAMPLES;
+ double dslowest = -1.0, dsum;
+
+ iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) ) {
+ ClientData *cd = (ClientData *) cl->clientData;
+
+ dsum = 0.0;
+ for (i=0; i<samples; i++) {
+ if (which == 0) {
+ dsum += cd->cmp_samp[i];
+ } else {
+ dsum += cd->raw_samp[i];
+ }
+ }
+ dsum = dsum / samples;
+ if (dsum > dslowest) {
+ dslowest = dsum;
+ }
+
+ }
+ rfbReleaseClientIterator(iter);
+
+ if (dslowest < 0.0) {
+ if (which == 0) {
+ dslowest = 5000.0;
+ } else {
+ dslowest = 50000.0;
+ }
+ }
+ return (int) dslowest;
+}
+
+int get_cmp_rate(void) {
+ return get_rate(0);
+}
+
+int get_raw_rate(void) {
+ return get_rate(1);
+}
+
+void initialize_speeds(void) {
+ char *s, *p;
+ int i;
+
+ speeds_read_rate = 0;
+ speeds_net_rate = 0;
+ speeds_net_latency = 0;
+ if (! speeds_str || *speeds_str == '\0') {
+ return;
+ }
+
+ if (!strcmp(speeds_str, "modem")) {
+ s = strdup("6,4,200");
+ } else if (!strcmp(speeds_str, "dsl")) {
+ s = strdup("6,100,50");
+ } else if (!strcmp(speeds_str, "modem")) {
+ s = strdup("6,5000,1");
+ } else {
+ s = strdup(speeds_str);
+ }
+
+ p = strtok(s, ",");
+ i = 0;
+ while (p) {
+ double val;
+ if (*p != '\0') {
+ val = atof(p);
+ if (i==0) {
+ speeds_read_rate = (int) 1000000 * val;
+ } else if (i==1) {
+ speeds_net_rate = (int) 1000 * val;
+ } else if (i==2) {
+ speeds_net_latency = (int) val;
+ }
+ }
+ i++;
+ p = strtok(NULL, ",");
+ }
+ free(s);
+}
+
+int get_read_rate(void) {
+ if (speeds_read_rate) {
+ return speeds_read_rate;
+ }
+ return 0;
+}
+
+int get_net_rate(void) {
+ if (speeds_net_rate) {
+ return speeds_net_rate;
+ }
+ return 0;
+}
+
+int get_net_latency(void) {
+ if (speeds_net_latency) {
+ return speeds_net_latency;
+ }
+ return 0;
+}
+
+void measure_send_rates(int init) {
+ int i, j, nclient = 0;
+ int min_width = 200;
+ double dt, cmp_rate, raw_rate;
+ rfbClientPtr id[100];
+ double dts[100], dts_sorted[100], dtmp;
+ int sorted[100], did[100], best;
+ rfbClientIteratorPtr iter;
+ rfbClientPtr cl;
+
+ if (! measure_speeds) {
+ return;
+ }
+ if (init) {
+ measure_send_rates_init();
+ return;
+ }
+
+ iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) ) {
+ double tmp2;
+ ClientData *cd = (ClientData *) cl->clientData;
+ tmp2 = 0.0;
+ dtime(&tmp2);
+if (init) {
+ continue;
+}
+ if (cd->timer <= 0.0) {
+ continue;
+ }
+ dt = dtime(&cd->timer);
+ cd->timer = dt;
+ if (nclient < 100) {
+ id[nclient] = cl;
+ dts[nclient] = dt;
+ nclient++;
+ }
+ }
+ rfbReleaseClientIterator(iter);
+if (init) {
+ return;
+}
+
+ for (i=0; i<nclient; i++) {
+ did[i] = 0;
+ }
+ for (i=0; i<nclient; i++) {
+ dtmp = -1.0;
+ best = -1;
+ for (j=0; j<nclient; j++) {
+ if (did[j]) {
+ continue;
+ }
+ if (dts[j] > dtmp) {
+ best = j;
+ dtmp = dts[j];
+ }
+ }
+ did[best] = 1;
+ sorted[i] = best;
+ dts_sorted[i] = dts[best];
+ }
+
+
+ iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) ) {
+ int db, dbr, cbs, rbs;
+ ClientData *cd = (ClientData *) cl->clientData;
+
+ dt = cd->timer;
+ if (dt <= 0.0) {
+ continue;
+ }
+ if (nclient > 1) {
+ for (i=0; i<nclient; i++) {
+ if (cl != id[i]) {
+ continue;
+ }
+ for (j=0; j<nclient; j++) {
+ if (sorted[j] == i) {
+ if (j < nclient - 1) {
+ dt -= dts_sorted[j+1];
+ }
+ }
+ }
+ break;
+ }
+ }
+ if (dt <= 0.0) {
+ continue;
+ }
+
+ cbs = 0;
+ for (i=0; i<MAX_ENCODINGS; i++) {
+ cbs += cl->bytesSent[i];
+ }
+ rbs = cl->rawBytesEquivalent;
+
+ db = cbs - cd->set_cmp_bytes;
+ dbr = rbs - cd->set_raw_bytes;
+ cmp_rate = db/dt;
+ raw_rate = dbr/dt;
+ if (dbr > min_width * min_width * bpp/8) {
+ cd->sample++;
+ if (cd->sample >= RATE_SAMPLES) {
+ cd->sample = 0;
+ }
+ i = cd->sample;
+ cd->cmp_samp[i] = cmp_rate;
+ cd->raw_samp[i] = raw_rate;
+ }
+ }
+ rfbReleaseClientIterator(iter);
+}
+
/*
* utility wrapper to call rfbProcessEvents
* checks that we are not in threaded mode.
*/
void rfbPE(rfbScreenInfoPtr scr, long usec) {
+ if (! scr) {
+ return;
+ }
if (! use_threads) {
rfbProcessEvents(scr, usec);
}
}
void rfbCFD(rfbScreenInfoPtr scr, long usec) {
+ if (! scr) {
+ return;
+ }
if (! use_threads) {
rfbCheckFds(scr, usec);
}
@@ -13485,7 +14288,7 @@ void rfbCFD(rfbScreenInfoPtr scr, long usec) {
*/
static void watch_loop(void) {
int cnt = 0, tile_diffs = 0;
- double dt = 0.0;
+ double dt = 0.0, dtr = 0.0;
if (use_threads) {
rfbRunEventLoop(screen, -1, TRUE);
@@ -13498,12 +14301,18 @@ static void watch_loop(void) {
got_keyboard_input = 0;
if (! use_threads) {
+ double tm = 0.0;
+ dtime(&tm);
rfbPE(screen, -1);
+ dtr = dtime(&tm);
+ fb_update_sent(NULL);
+
if (! cursor_shape_updates) {
/* undo any cursor shape requests */
disable_cursor_shape_updates(screen);
}
- if (check_user_input(dt, tile_diffs, &cnt)) {
+ if (screen && screen->clientHead &&
+ check_user_input(dt, dtr, tile_diffs, &cnt)) {
/* true means loop back for more input */
continue;
}
@@ -13522,7 +14331,8 @@ static void watch_loop(void) {
check_connect_inputs();
check_padded_fb();
- if (! screen->clientHead) { /* waiting for a client */
+ if (! screen || ! screen->clientHead) {
+ /* waiting for a client */
usleep(200 * 1000);
continue;
}
@@ -13542,7 +14352,8 @@ static void watch_loop(void) {
*/
check_bell_event();
}
- if (! show_dragging && button_mask) {
+
+ if (button_mask && (!show_dragging || pointer_mode == 0)) {
/*
* if any button is pressed do not update rfb
* screen, but do flush the X11 display.
@@ -13556,7 +14367,15 @@ static void watch_loop(void) {
dtime(&tm);
rfbUndrawCursor(screen);
- tile_diffs = scan_for_updates();
+ if (use_snapfb) {
+ int t, tries = 5;
+ copy_snap();
+ for (t =0; t < tries; t++) {
+ tile_diffs = scan_for_updates(0);
+ }
+ } else {
+ tile_diffs = scan_for_updates(0);
+ }
dt = dtime(&tm);
check_x11_pointer();
}
@@ -13618,7 +14437,7 @@ static void print_help(void) {
" support MIT-SHM. Equivalent to setting the DISPLAY\n"
" environment variable to \"disp\".\n"
"-auth file Set the X authority file to be \"file\", equivalent to\n"
-" setting the XAUTHORITY environment varirable to \"file\"\n"
+" setting the XAUTHORITY environment variable to \"file\"\n"
" before startup. See Xsecurity(7), xauth(1) man pages.\n"
"\n"
"-id windowid Show the window corresponding to \"windowid\" not\n"
@@ -13864,7 +14683,8 @@ static void print_help(void) {
" -remote id:windowid, rescaling, etc.\n"
"\n"
"-o logfile Write stderr messages to file \"logfile\" instead of\n"
-" to the terminal. Same as \"-logfile file\".\n"
+" to the terminal. Same as \"-logfile file\". To append\n"
+" to the file use \"-oa file\" or \"-logappend file\".\n"
"-rc filename Use \"filename\" instead of $HOME/.x11vncrc for rc file.\n"
"-norc Do not process any .x11vncrc file for options.\n"
"-h, -help Print this help text.\n"
@@ -14045,6 +14865,14 @@ static void print_help(void) {
" black background). Specify this option to remove the\n"
" alpha factor. (useful for light colored semi-transparent\n"
" cursors).\n"
+"-alphablend In XFIXES mode send cursor alpha channel data to\n"
+" libvncserver. The blending effect will only be\n"
+" visible in -nocursorshape mode or for clients with\n"
+" cursorshapeupdates turned off. (However there is a\n"
+" hack for 32bpp with depth 24, it uses the extra 8 bits\n"
+" to store cursor transparency for use with a hacked\n"
+" vncviewer that applies the transparency locally.\n"
+" See the FAQ for more info).\n"
"\n"
"-nocursorshape Do not use the TightVNC CursorShapeUpdates extension\n"
" even if clients support it. See -cursor above.\n"
@@ -14081,38 +14909,85 @@ static void print_help(void) {
" initial state of the modifier is ignored and not reset)\n"
" To include button events use \"Button1\", ... etc.\n"
"\n"
-"-nodragging Do not update the display during mouse dragging\n"
-" events (mouse motion with a button held down).\n"
-" Greatly improves response on slow setups, but you lose\n"
-" all visual feedback for drags, text selection, and some\n"
-" menu traversals. It overrides any -pointer_mode setting\n"
-" (think of it as pointer_mode 0)\n"
-"-pointer_mode n Various pointer update schemes. The problem is pointer\n"
-" motion can cause rapid changes on the screen, e.g. a\n"
-" window drag. Neither x11vnc's screen polling nor the\n"
+"-nodragging Do not update the display during mouse dragging events\n"
+" (mouse button held down). Greatly improves response on\n"
+" slow setups, but you lose all visual feedback for drags,\n"
+" text selection, and some menu traversals. It overrides\n"
+" any -pointer_mode setting\n"
+"-pointer_mode n Various pointer motion update schemes. \"-pm\" is\n"
+" an alias. The problem is pointer motion can cause\n"
+" rapid changes on the screen: consider the rapid changes\n"
+" when you drag a large window around. Neither x11vnc's\n"
+" screen polling and vnc compression routines nor the\n"
" bandwidth to the vncviewers can keep up these rapid\n"
-" screen changes: everything bogs down when dragging\n"
-" or scrolling. Note that most video h/w is optimized\n"
-" for writing, not reading (a 50X rate difference is\n"
-" possible) and x11vnc is reading all the time. So a\n"
-" scheme has to be used to \"eat\" much of that pointer\n"
-" input before re-polling the screen. n can be 1 to %d.\n"
+" screen changes: everything will bog down when dragging\n"
+" or scrolling. So a scheme has to be used to \"eat\"\n"
+" much of that pointer input before re-polling the screen\n"
+" and sending out framebuffer updates. The mode number\n"
+" \"n\" can be 0 to %d and selects one of the schemes\n"
+" desribed below.\n"
+"\n"
+" n=0: does the same as -nodragging. (all screen polling\n"
+" is suspended if a mouse button is pressed.)\n"
+"\n"
+" n=1: was the original scheme used to about Jan 2004:\n"
+" it basically just skips -input_skip keyboard or pointer\n"
+" events before repolling the screen.\n"
+"\n"
+" n=2 is an improved scheme: by watching the current rate\n"
+" of input events it tries to detect if it should try to\n"
+" \"eat\" additional pointer events before continuing.\n"
+"\n"
+" n=3 is basically a dynamic -nodragging mode: it detects\n"
+" when the mouse motion has paused and then refreshes\n"
+" the display.\n"
+"\n"
+" n=4: attempts to measures network rates and latency,\n"
+" the video card read rate, and how many tiles have been\n"
+" changed on the screen. From this, it aggressively tries\n"
+" to push screen \"frames\" when it decides it has enough\n"
+" resources to do so. NOT FINISHED.\n"
+"\n"
+" The default n is %d. Note that modes 2, 3, 4 will skip\n"
+" -input_skip keyboard events (but it will not count\n"
+" pointer events). Also note that these modes are not\n"
+" available in -threads mode which has its own pointer\n"
+" event handling mechanism.\n"
+"\n"
+" To try out the different pointer modes to see\n"
+" which one gives the best response for your usage,\n"
+" it is convenient to use the remote control function,\n"
+" e.g. \"x11vnc -R pointer_mode:4\" or the tcl/tk gui\n"
+" (Tuning -> pointer_mode -> n).\n"
"\n"
-" n=1 was the original scheme used to about Jan 2004: it\n"
-" basically just skips -input_skip pointer events before\n"
-" repolling the screen. n=2 is an improved scheme:\n"
-" by watching the current rate it tries to detect if\n"
-" it should try to \"eat\" more pointer events. n=3 is\n"
-" basically a dynamic -nodragging mode: it detects if the\n"
-" mouse drag motion has paused and refreshes the display.\n"
-" n=4 is TBD, it will try measure screen read and client\n"
-" write rates and try to insert \"frames\" between the\n"
-" on/off states of mode 3. The default n is %d.\n"
"-input_skip n For the pointer handling when non-threaded: try to\n"
" read n user input events before scanning display. n < 0\n"
" means to act as though there is always user input.\n"
" Default: %d\n"
"\n"
+"-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that\n"
+" are used to optimize scheduling (e.g. -pointer_mode\n"
+" 4) and other things. Use the -speeds option to set\n"
+" these manually. The triple \"rd,bw,lat\" corresponds\n"
+" to video h/w read rate in MB/sec, network bandwidth to\n"
+" clients in KB/sec, and network latency to clients in\n"
+" milliseconds, respectively. If a value is left blank,\n"
+" e.g. \"-speeds ,100,15\", then the internal scheme is\n"
+" used to estimate the empty value(s).\n"
+"\n"
+" Typical PC video cards have read rates of 5-10 MB/sec.\n"
+" If the framebuffer is in main memory instead of video\n"
+" h/w (e.g. SunRay, shadowfb, Xvfb), the read rate may\n"
+" be much faster. \"x11perf -getimage500\" can be used\n"
+" to get a lower bound (remember to factor in the bytes\n"
+" per pixel). It is up to you to estimate the network\n"
+" bandwith to clients. For the latency the ping(1)\n"
+" command can be used.\n"
+"\n"
+" For convenience there are some aliases provided,\n"
+" e.g. \"-speeds modem\". The aliases are: \"modem\" for\n"
+" 6,4,200; \"dsl\" for 6,100,50; and \"lan\" for 6,5000,1\n"
+"\n"
"-debug_pointer Print debugging output for every pointer event.\n"
"-debug_keyboard Print debugging output for every keyboard event.\n"
" Same as -dp and -dk, respectively. Use multiple\n"
@@ -14145,6 +15020,19 @@ static void print_help(void) {
" by checking the tile near the boundary. Default: %d\n"
"-fuzz n Tolerance in pixels to mark a tiles edges as changed.\n"
" Default: %d\n"
+"-snapfb Instead of polling the X display framebuffer (fb) for\n"
+" changes, periodically copy all of X display fb into main\n"
+" memory and examine that copy for changes. Under some\n"
+" circumstances this will improve interactive response,\n"
+" or at least make things look smoother, but in others\n"
+" (many) it will make the response worse. If the video\n"
+" h/w fb is such that reading small tiles is very slow\n"
+" this mode could help. To keep the \"framerate\" up\n"
+" the screen size x bpp cannot be too large. Note that\n"
+" this mode is very wasteful of memory I/O resources\n"
+" (it makes full screen copies even if nothing changes).\n"
+" It may be of use in video capture-like applications,\n"
+" or where window tearing is a problem.\n"
"\n"
"-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote\n"
" control options -remote/-query described below.\n"
@@ -14331,6 +15219,8 @@ static void print_help(void) {
" alphafrac:f set -alphafrac to f.\n"
" alpharemove enable -alpharemove mode.\n"
" noalpharemove disable -alpharemove mode.\n"
+" alphablend enable -alphablend mode.\n"
+" noalphablend disable -alphablend mode.\n"
" cursorshape disable -nocursorshape mode.\n"
" nocursorshape enable -nocursorshape mode.\n"
" cursorpos disable -nocursorpos mode.\n"
@@ -14340,8 +15230,9 @@ static void print_help(void) {
" buttonmap:str set -buttonmap \"str\", empty to disable\n"
" dragging disable -nodragging mode.\n"
" nodragging enable -nodragging mode.\n"
-" pointer_mode n set -pointer_mode to n.\n"
-" input_skip n set -input_skip to n.\n"
+" pointer_mode:n set -pointer_mode to n. same as \"pm\"\n"
+" input_skip:n set -input_skip to n.\n"
+" speeds:str set -speeds to str.\n"
" debug_pointer enable -debug_pointer, same as \"dp\"\n"
" nodebug_pointer disable -debug_pointer, same as \"nodp\"\n"
" debug_keyboard enable -debug_keyboard, same as \"dk\"\n"
@@ -14356,6 +15247,8 @@ static void print_help(void) {
" gaps:n set -gaps to n.\n"
" grow:n set -grow to n.\n"
" fuzz:n set -fuzz to n.\n"
+" snapfb enable -snapfb mode.\n"
+" nosnapfb disable -snapfb mode.\n"
" progressive:n set libvncserver -progressive slice\n"
" height parameter to n.\n"
" desktop:str set -desktop name to str for new clients.\n"
@@ -14415,29 +15308,30 @@ static void print_help(void) {
" 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 flashcmap\n"
-" noflashcmap truecolor notruecolor overlay nooverlay\n"
-" overlay_cursor overlay_yescursor nooverlay_nocursor\n"
-" nooverlay_cursor nooverlay_yescursor overlay_nocursor\n"
-" visual scale viewonly noviewonly shared noshared\n"
-" forever noforever once deny lock nodeny unlock\n"
-" connect allowonce allow localhost nolocalhost accept\n"
-" gone shm noshm flipbyteorder noflipbyteorder onetile\n"
-" noonetile 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"
+" refresh reset close disconnect id sid waitmapped\n"
+" nowaitmapped 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 deny lock nodeny\n"
+" unlock connect allowonce allow localhost nolocalhost\n"
+" accept gone shm noshm flipbyteorder noflipbyteorder\n"
+" onetile noonetile blackout xinerama noxinerama xrandr\n"
+" noxrandr xrandr_mode padgeom quiet q noquiet modtweak\n"
+" nomodtweak xkb noxkb skip_keycodes add_keysyms\n"
+" noadd_keysyms clear_mods noclear_mods clear_keys\n"
+" noclear_keys remap repeat norepeat fb nofb bell nobell\n"
+" sel nosel primary noprimary cursorshape nocursorshape\n"
" cursorpos nocursorpos cursor show_cursor noshow_cursor\n"
-" nocursor xfixes noxfixes alphacut alphafrac alpharemove\n"
-" noalpharemove xwarp xwarppointer noxwarp noxwarppointer\n"
-" buttonmap dragging nodragging pointer_mode input_skip\n"
-" debug_pointer dp nodebug_pointer nodp debug_keyboard\n"
-" dk nodebug_keyboard nodk deferupdate defer wait\n"
-" rfbwait nap nonap sb screen_blank fs gaps grow fuzz\n"
-" progressive rfbport http nohttp httpport httpdir\n"
-" enablehttpproxy noenablehttpproxy alwaysshared\n"
+" nocursor xfixes noxfixes alphacut alphafrac\n"
+" alpharemove noalpharemove alphablend noalphablend\n"
+" xwarp xwarppointer noxwarp noxwarppointer buttonmap\n"
+" dragging nodragging pointer_mode pm input_skip speeds\n"
+" debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n"
+" nodebug_keyboard nodk deferupdate defer wait rfbwait\n"
+" nap nonap sb screen_blank fs gaps grow fuzz snapfb\n"
+" nosnapfb progressive rfbport http nohttp httpport\n"
+" httpdir enablehttpproxy noenablehttpproxy alwaysshared\n"
" noalwaysshared nevershared noalwaysshared dontdisconnect\n"
" nodontdisconnect desktop noremote\n"
"\n"
@@ -14533,6 +15427,59 @@ static void print_help(void) {
exit(1);
}
+void set_vnc_desktop_name(void) {
+ int sz = 256;
+ sprintf(vnc_desktop_name, "unknown");
+ if (screen->port) {
+ char *host = this_host();
+ int lport = screen->port;
+ if (host != NULL) {
+ /* note that vncviewer special cases 5900-5999 */
+ if (inetd) {
+ ; /* should not occur (port) */
+ } else if (quiet) {
+ if (lport >= 5900) {
+ snprintf(vnc_desktop_name, sz, "%s:%d",
+ host, lport - 5900);
+ fprintf(stderr, "The VNC desktop is "
+ "%s\n", vnc_desktop_name);
+ } else {
+ snprintf(vnc_desktop_name, sz, "%s:%d",
+ host, lport);
+ fprintf(stderr, "The VNC desktop is "
+ "%s\n", vnc_desktop_name);
+ }
+ } else if (lport >= 5900) {
+ snprintf(vnc_desktop_name, sz, "%s:%d",
+ host, lport - 5900);
+ rfbLog("\n");
+ rfbLog("The VNC desktop is %s\n",
+ vnc_desktop_name);
+ if (lport >= 6000) {
+ rfbLog("possible aliases: %s:%d, "
+ "%s::%d\n", host, lport,
+ host, lport);
+ }
+ } else {
+ snprintf(vnc_desktop_name, sz, "%s:%d",
+ host, lport);
+ rfbLog("\n");
+ rfbLog("The VNC desktop is %s\n",
+ vnc_desktop_name);
+ rfbLog("possible alias: %s::%d\n",
+ host, lport);
+ }
+ }
+ fflush(stderr);
+ if (inetd) {
+ ; /* should not occur (port) */
+ } else {
+ fprintf(stdout, "PORT=%d\n", screen->port);
+ }
+ fflush(stdout);
+ }
+}
+
/*
* utility to get the current host name
*/
@@ -14582,14 +15529,13 @@ static char *choose_title(char *display) {
* check blacklist for OSs with tight shm limits.
*/
static int limit_shm(void) {
- struct utsname ut;
int limit = 0;
- if (uname(&ut) == -1) {
+ if (UT.sysname == NULL) {
return 0;
}
- if (!strcmp(ut.sysname, "SunOS")) {
- char *r = ut.release;
+ if (!strcmp(UT.sysname, "SunOS")) {
+ char *r = UT.release;
if (*r == '5' && *(r+1) == '.') {
if (strchr("2345678", *(r+2)) != NULL) {
limit = 1;
@@ -14598,7 +15544,7 @@ static int limit_shm(void) {
}
if (limit && ! quiet) {
fprintf(stderr, "reducing shm usage on %s %s (adding "
- "-onetile)\n", ut.sysname, ut.release);
+ "-onetile)\n", UT.sysname, UT.release);
}
return limit;
}
@@ -14670,12 +15616,12 @@ static void check_rcfile(int argc, char **argv) {
perror("fstat");
exit(1);
}
- sz = sbuf.st_size+1;
+ sz = sbuf.st_size+1; /* allocate whole file size */
if (sz < 1024) {
sz = 1024;
}
- buf = (char *) malloc(sz);
+ buf = (char *) malloc(sz);
while (fgets(line, 4096, rc) != NULL) {
char *q, *p = line;
@@ -14791,7 +15737,7 @@ int main(int argc, char* argv[]) {
int remote_sync = 0;
char *remote_cmd = NULL;
char *query_cmd = NULL;
- char *gui_string = NULL;
+ char *gui_str = NULL;
int pw_loc = -1;
int vpw_loc = -1;
int dt = 0, bg = 0;
@@ -14873,6 +15819,8 @@ int main(int argc, char* argv[]) {
argv[i]);
exit(1);
}
+ } else if (!strcmp(arg, "-waitmapped")) {
+ subwin_wait_mapped = 1;
} else if (!strcmp(arg, "-flashcmap")) {
flash_cmap = 1;
} else if (!strcmp(arg, "-notruecolor")) {
@@ -14948,7 +15896,7 @@ int main(int argc, char* argv[]) {
single_copytile = 1;
} else if (!strcmp(arg, "-blackout")) {
CHECK_ARGC
- blackout_string = strdup(argv[++i]);
+ blackout_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-xinerama")) {
xinerama = 1;
} else if (!strcmp(arg, "-xrandr")) {
@@ -14966,6 +15914,11 @@ int main(int argc, char* argv[]) {
pad_geometry = strdup(argv[++i]);
} else if (!strcmp(arg, "-o") || !strcmp(arg, "-logfile")) {
CHECK_ARGC
+ logfile_append = 0;
+ logfile = strdup(argv[++i]);
+ } else if (!strcmp(arg, "-oa") || !strcmp(arg, "-logappend")) {
+ CHECK_ARGC
+ logfile_append = 1;
logfile = strdup(argv[++i]);
} else if (!strcmp(arg, "-rc")) {
i++; /* done above */
@@ -15045,6 +15998,8 @@ int main(int argc, char* argv[]) {
alpha_frac = atof(argv[++i]);
} else if (!strcmp(arg, "-alpharemove")) {
alpha_remove = 1;
+ } else if (!strcmp(arg, "-alphablend")) {
+ alpha_blend = 1;
} else if (!strcmp(arg, "-nocursorshape")) {
cursor_shape_updates = 0;
} else if (!strcmp(arg, "-cursorpos")) {
@@ -15058,7 +16013,8 @@ int main(int argc, char* argv[]) {
pointer_remap = strdup(argv[++i]);
} else if (!strcmp(arg, "-nodragging")) {
show_dragging = 0;
- } else if (!strcmp(arg, "-pointer_mode")) {
+ } else if (!strcmp(arg, "-pointer_mode")
+ || !strcmp(arg, "-pm")) {
char *p, *s;
CHECK_ARGC
s = argv[++i];
@@ -15077,6 +16033,9 @@ int main(int argc, char* argv[]) {
CHECK_ARGC
ui_skip = atoi(argv[++i]);
if (! ui_skip) ui_skip = 1;
+ } else if (!strcmp(arg, "-speeds")) {
+ CHECK_ARGC
+ speeds_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-debug_pointer")
|| !strcmp(arg, "-dp")) {
debug_pointer++;
@@ -15122,12 +16081,14 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-fuzz")) {
CHECK_ARGC
tile_fuzz = atoi(argv[++i]);
+ } else if (!strcmp(arg, "-snapfb")) {
+ use_snapfb = 1;
} else if (!strcmp(arg, "-gui")) {
launch_gui = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (*s != '-') {
- gui_string = strdup(s);
+ gui_str = strdup(s);
i++;
}
}
@@ -15191,11 +16152,16 @@ int main(int argc, char* argv[]) {
}
if (launch_gui) {
- do_gui(gui_string);
+ do_gui(gui_str);
}
if (logfile) {
int n;
- if ((n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) {
+ if (logfile_append) {
+ n = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666);
+ } else {
+ n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ }
+ if (n < 0) {
fprintf(stderr, "error opening logfile: %s\n", logfile);
perror("open");
exit(1);
@@ -15324,6 +16290,7 @@ int main(int argc, char* argv[]) {
if (waitms < 0) {
waitms = 0;
}
+
if (alpha_threshold < 0) {
alpha_threshold = 0;
}
@@ -15336,6 +16303,10 @@ int main(int argc, char* argv[]) {
if (alpha_frac > 1.0) {
alpha_frac = 1.0;
}
+ if (alpha_blend) {
+ alpha_remove = 0;
+ }
+
if (inetd) {
shared = 0;
connect_once = 1;
@@ -15404,13 +16375,13 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " authfile: %s\n", auth_file ? auth_file
: "null");
fprintf(stderr, " subwin: 0x%lx\n", subwin);
- fprintf(stderr, " rootshift: %d\n", rootshift);
+ fprintf(stderr, " -sid mode: %d\n", rootshift);
fprintf(stderr, " flashcmap: %d\n", flash_cmap);
fprintf(stderr, " force_idx: %d\n", force_indexed_color);
- fprintf(stderr, " overlay: %d\n", overlay);
- fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor);
fprintf(stderr, " visual: %s\n", visual_str ? visual_str
: "null");
+ fprintf(stderr, " overlay: %d\n", overlay);
+ fprintf(stderr, " ovl_cursor: %d\n", overlay_cursor);
fprintf(stderr, " scaling: %d %.5f\n", scaling, scale_fac);
fprintf(stderr, " viewonly: %d\n", view_only);
fprintf(stderr, " shared: %d\n", shared);
@@ -15432,14 +16403,17 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " using_shm: %d\n", using_shm);
fprintf(stderr, " flipbytes: %d\n", flip_byte_order);
fprintf(stderr, " onetile: %d\n", single_copytile);
- fprintf(stderr, " blackout: %s\n", blackout_string
- ? blackout_string : "null");
+ fprintf(stderr, " blackout: %s\n", blackout_str
+ ? blackout_str : "null");
fprintf(stderr, " xinerama: %d\n", xinerama);
fprintf(stderr, " xrandr: %d\n", xrandr);
fprintf(stderr, " xrandrmode: %s\n", xrandr_mode ? xrandr_mode
: "null");
+ fprintf(stderr, " padgeom: %s\n", pad_geometry
+ ? pad_geometry : "null");
fprintf(stderr, " logfile: %s\n", logfile ? logfile
: "null");
+ fprintf(stderr, " logappend: %d\n", logfile_append);
fprintf(stderr, " rc_file: %s\n", rc_rcfile ? rc_rcfile
: "null");
fprintf(stderr, " norc: %d\n", rc_norc);
@@ -15460,11 +16434,15 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " watchsel: %d\n", watch_selection);
fprintf(stderr, " watchprim: %d\n", watch_primary);
fprintf(stderr, " cursor: %d\n", show_cursor);
- fprintf(stderr, " root_curs: %d\n", show_multiple_cursors);
+ fprintf(stderr, " multicurs: %d\n", show_multiple_cursors);
fprintf(stderr, " curs_mode: %s\n", multiple_cursors_mode
? multiple_cursors_mode : "null");
fprintf(stderr, " xfixes: %d\n", use_xfixes);
- fprintf(stderr, " cursorshp: %d\n", cursor_shape_updates);
+ fprintf(stderr, " alphacut: %d\n", alpha_threshold);
+ fprintf(stderr, " alphafrac: %.2f\n", alpha_frac);
+ fprintf(stderr, " alpharemove:%d\n", alpha_remove);
+ fprintf(stderr, " alphablend: %d\n", alpha_blend);
+ fprintf(stderr, " cursorshape:%d\n", cursor_shape_updates);
fprintf(stderr, " cursorpos: %d\n", cursor_pos_updates);
fprintf(stderr, " xwarpptr: %d\n", use_xwarppointer);
fprintf(stderr, " buttonmap: %s\n", pointer_remap
@@ -15472,6 +16450,8 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " dragging: %d\n", show_dragging);
fprintf(stderr, " ptr_mode: %d\n", pointer_mode);
fprintf(stderr, " inputskip: %d\n", ui_skip);
+ fprintf(stderr, " speeds: %s\n", speeds_str
+ ? speeds_str : "null");
fprintf(stderr, " debug_ptr: %d\n", debug_pointer);
fprintf(stderr, " debug_key: %d\n", debug_keyboard);
fprintf(stderr, " defer: %d\n", defer_update);
@@ -15485,8 +16465,13 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " gaps_fill: %d\n", gaps_fill);
fprintf(stderr, " grow_fill: %d\n", grow_fill);
fprintf(stderr, " tile_fuzz: %d\n", tile_fuzz);
- fprintf(stderr, " deny_all: %d\n", deny_all);
+ fprintf(stderr, " snapfb: %d\n", use_snapfb);
+ fprintf(stderr, " gui: %d\n", launch_gui);
+ fprintf(stderr, " gui_mode: %s\n", gui_str
+ ? gui_str : "null");
fprintf(stderr, " noremote: %d\n", !accept_remote_cmds);
+ fprintf(stderr, " safemode: %d\n", safe_remote_only);
+ fprintf(stderr, " deny_all: %d\n", deny_all);
fprintf(stderr, "\n");
rfbLog("x11vnc version: %s\n", lastmod);
} else {
@@ -15689,6 +16674,9 @@ int main(int argc, char* argv[]) {
*/
XTestGrabControl_wr(dpy, True);
+ /* set OS struct UT */
+ uname(&UT);
+
/* check for OS with small shm limits */
if (using_shm && ! single_copytile) {
if (limit_shm()) {
@@ -15778,6 +16766,8 @@ int main(int argc, char* argv[]) {
initialize_signals();
+ initialize_speeds();
+
initialize_keyboard_and_pointer();
if (! inetd) {
@@ -15789,53 +16779,7 @@ int main(int argc, char* argv[]) {
if (! quiet) {
rfbLog("screen setup finished.\n");
}
- sprintf(vnc_desktop_name, "unknown");
- if (screen->port) {
- char *host = this_host();
- int lport = screen->port;
- if (host != NULL) {
- /* note that vncviewer special cases 5900-5999 */
- if (inetd) {
- ; /* should not occur (port) */
- } else if (quiet) {
- if (lport >= 5900) {
- sprintf(vnc_desktop_name, "%s:%d",
- host, lport - 5900);
- fprintf(stderr, "The VNC desktop is "
- "%s\n", vnc_desktop_name);
- } else {
- sprintf(vnc_desktop_name, "%s:%d",
- host, lport);
- fprintf(stderr, "The VNC desktop is "
- "%s\n", vnc_desktop_name);
- }
- } else if (lport >= 5900) {
- sprintf(vnc_desktop_name, "%s:%d",
- host, lport - 5900);
- rfbLog("\n");
- rfbLog("The VNC desktop is %s\n",
- vnc_desktop_name);
- if (lport >= 6000) {
- rfbLog("possible aliases: %s:%d, "
- "%s::%d\n", host, lport, host, lport);
- }
- } else {
- sprintf(vnc_desktop_name, "%s:%d", host, lport);
- rfbLog("\n");
- rfbLog("The VNC desktop is %s\n",
- vnc_desktop_name);
- rfbLog("possible alias: %s::%d\n",
- host, lport);
- }
- }
- fflush(stderr);
- if (inetd) {
- ; /* should not occur (port) */
- } else {
- fprintf(stdout, "PORT=%d\n", screen->port);
- }
- fflush(stdout);
- }
+ set_vnc_desktop_name();
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SETSID
if (bg) {