From 3495019ada3acd3114679704b8d686fb1bb429f6 Mon Sep 17 00:00:00 2001 From: runge Date: Wed, 1 Sep 2004 02:19:06 +0000 Subject: [PATCH] x11vnc: new pointer input handling algorithm; x11vnc pkg installs java viewer --- ChangeLog | 6 + prepare_x11vnc_dist.sh | 8 +- x11vnc/ChangeLog | 5 + x11vnc/README | 2 +- x11vnc/x11vnc.1 | 11 +- x11vnc/x11vnc.c | 292 ++++++++++++++++++++++++++++++++--------- 6 files changed, 258 insertions(+), 66 deletions(-) diff --git a/ChangeLog b/ChangeLog index fcf68ae..a91b296 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-08-29 Karl Runge + * x11vnc: yet another pointer input handling algorithm in + check_user_input(), revert to previous with -old_pointer2. + * modifiy prepare_x11vnc_dist.sh to install tightvnc Java viewer + in $prefix/share/x11vnc/classes + 2004-08-29 Johannes E. Schindelin * */*.[ch]: API changes: global functions/structures should have * either "rfb", "sra" or "zrle" as prefix, while structure members diff --git a/prepare_x11vnc_dist.sh b/prepare_x11vnc_dist.sh index 8cbe8cc..9c1ff03 100644 --- a/prepare_x11vnc_dist.sh +++ b/prepare_x11vnc_dist.sh @@ -16,7 +16,7 @@ sed -e "s/LibVNCServer, [^,)]*\([(,]\)*/x11vnc, $VERSION\1/g" \ mv Makefile.am Makefile.am.LibVNCServer cat Makefile.am.LibVNCServer | \ -sed -e "s/^SUBDIRS.*$/SUBDIRS=libvncserver x11vnc/" \ +sed -e "s/^SUBDIRS.*$/SUBDIRS=libvncserver x11vnc classes/" \ -e "s/^DIST_SUBDIRS.*$/DIST_SUBDIRS=libvncserver x11vnc classes/" \ -e "/all: make_config_executable/,\$d" \ -e "/^.*bin_SCRIPTS.*$/d" \ @@ -49,6 +49,10 @@ cat libvncserver/Makefile.am.LibVNCServer | \ sed -e "s/\(include\|LIB\|lib\)_/noinst_/g" \ > libvncserver/Makefile.am +cp classes/Makefile.am classes/Makefile.am.LibVNCServer +echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes' >> classes/Makefile.am +echo 'pkgdata_DATA=VncViewer.jar index.vnc' >> classes/Makefile.am + mv acinclude.m4 acinclude.m4.LibVNCServer cat acinclude.m4.LibVNCServer | \ @@ -56,7 +60,7 @@ sed -e "s/^\(_PKG.*\)\$PACKAGE\(.*\)$/\1LibVNCServer\2/" \ > acinclude.m4 make x11vnc-${VERSION}.tar.gz -for f in configure.ac Makefile.am libvncserver/Makefile.am acinclude.m4; do +for f in configure.ac Makefile.am libvncserver/Makefile.am classes/Makefile.am acinclude.m4; do mv -f $f.LibVNCServer $f done diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 89d6daf..12fb239 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,8 @@ +2004-08-31 Karl Runge + * new check_user_input() pointer input algorithm, it tries to avoid + extra-draws. still needs tuning, get previous one with -old_pointer2 + * add NON_CVS macro for building in older CVS trees. + 2004-08-29 Karl Runge * remove old mouse patch code, now use rfbSetCursor (+ workarounds) * changed cursor shape options (no more -mouse, ...) to '-cursor mode' diff --git a/x11vnc/README b/x11vnc/README index 0359c96..f3ed566 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Sun Aug 29 15:33:42 EDT 2004 +x11vnc README file Date: Tue Aug 31 22:39:00 EDT 2004 The following information is taken from these URLs: diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 7ac129e..d711f71 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -2,7 +2,7 @@ .TH X11VNC "1" "August 2004" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.6.3pre, lastmod: 2004-08-29 + version: 0.6.3pre, lastmod: 2004-08-31 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -588,10 +588,15 @@ menu traversals. .PP \fB-old_pointer\fR .IP -Do not use the new pointer input handling mechanisms. +Use the original pointer input handling mechanism. See check_input() and pointer() in source file for details. .PP +\fB-old_pointer2\fR +.IP +The default pointer input handling algorithm was changed +again, this option indicates to use the second one. +.PP \fB-input_skip\fR \fIn\fR .IP For the old pointer handling when non-threaded: try to @@ -612,7 +617,7 @@ times for more output. \fB-defer\fR \fItime\fR .IP Time in ms to wait for updates before sending to client -[rfbDeferUpdateTime] Default: 30 +(deferUpdateTime) Default: 30 .PP \fB-wait\fR \fItime\fR .IP diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 1ece2ec..5df5db3 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -105,13 +105,16 @@ /* -- x11vnc.h -- */ +#define NON_CVS 0 /* * At some point beyond 0.7pre remove these two definitions since we * have them set in configure (for all users of this x11vnc.c file). * Then move them to the comment below. */ +#if NON_CVS #define LIBVNCSERVER_HAVE_XSHM #define LIBVNCSERVER_HAVE_XTEST +#endif /* * If you are building in an older libvncserver tree with this newer @@ -127,6 +130,22 @@ * */ +/* + * This is another transient for building in older libvncserver trees. + */ +#if NON_CVS +#define dontDisconnect rfbDontDisconnect +#define neverShared rfbNeverShared +#define alwaysShared rfbAlwaysShared +#define clientHead rfbClientHead +#define serverFormat rfbServerFormat +#define port rfbPort +#define listenSock rfbListenSock +#define deferUpdateTime rfbDeferUpdateTime +#define authPasswdData rfbAuthPasswdData +#define rfbEncryptAndStorePasswd vncEncryptAndStorePasswd +#endif + #include #include #include @@ -135,16 +154,6 @@ #include #include -#ifdef LIBVNCSERVER_HAVE_XSHM -#include -#include -#include -#endif - -#ifdef LIBVNCSERVER_HAVE_XTEST -#include -#endif - #include #include @@ -155,17 +164,22 @@ #include #include +#ifdef LIBVNCSERVER_HAVE_XSHM +#include +#include +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_XTEST +#include +#endif + #ifdef LIBVNCSERVER_HAVE_XKEYBOARD #include #endif -#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H -#include -#endif -#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H -#include -#include -#include +#ifdef LIBVNCSERVER_HAVE_LIBXINERAMA +#include #endif #if defined (__SVR4) && defined (__sun) @@ -173,12 +187,18 @@ #include #endif -#ifdef LIBVNCSERVER_HAVE_LIBXINERAMA -#include +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include #endif /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.6.3pre lastmod: 2004-08-29"; +char lastmod[] = "0.6.3pre lastmod: 2004-08-31"; /* X display info */ @@ -317,7 +337,7 @@ void cursor_position(int, int); void read_vnc_connect_prop(void); void rfbPE(rfbScreenInfoPtr, long); void rfbCFD(rfbScreenInfoPtr, long); -void scan_for_updates(void); +int scan_for_updates(void); void set_colormap(void); void set_offset(void); void set_visual(char *vstring); @@ -379,7 +399,7 @@ int use_xkb_modtweak = 0; /* -xkb */ char *skip_keycodes = NULL; int add_keysyms = 0; /* automatically add keysyms to X server */ -int old_pointer = 0; /* use the old way of updating the pointer */ +int old_pointer = 0; /* use the old ways of updating the pointer */ int single_copytile = 0; /* use the old way copy_tiles() */ int using_shm = 1; /* whether mit-shm is used */ @@ -389,7 +409,7 @@ int flip_byte_order = 0; /* sometimes needed when using_shm = 0 */ * poll times of 10-35ms, so maybe this value cuts the idle load by 2 or so. */ int waitms = 30; -int defer_update = 30; /* rfbDeferUpdateTime ms to wait before sends. */ +int defer_update = 30; /* deferUpdateTime ms to wait before sends. */ int screen_blank = 60; /* number of seconds of no activity to throttle */ /* down the screen polls. zero to disable. */ @@ -1722,7 +1742,7 @@ static void check_connect_file(char *file) { static int do_reverse_connect(char *str) { rfbClientPtr cl; char *host, *p; - int port = 5500, len = strlen(str); + int rport = 5500, len = strlen(str); if (len < 1) { return 0; @@ -1743,11 +1763,11 @@ static int do_reverse_connect(char *str) { /* extract port, if any */ if ((p = strchr(host, ':')) != NULL) { - port = atoi(p+1); + rport = atoi(p+1); *p = '\0'; } - cl = rfbReverseConnection(screen, host, port); + cl = rfbReverseConnection(screen, host, rport); free(host); if (cl == NULL) { @@ -3823,7 +3843,7 @@ void pointer(int mask, int x, int y, rfbClientPtr client) { * See check_user_input() for the more complicated things we do * in the non-threaded case. */ - if (use_threads && ! old_pointer) { + if (use_threads && old_pointer != 1) { # define NEV 32 /* storage for the event queue */ static int mutex_init = 0; @@ -5448,9 +5468,10 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { * the x11vnc.c file by itself and plop it down into their libvncserver tree. * Remove at some point. BTW, this assumes no usage of earlier "0.7pre". */ -#ifdef LIBVNCSERVER_VERSION - if (strcmp(LIBVNCSERVER_VERSION, "0.5") - && strcmp(LIBVNCSERVER_VERSION, "0.6")) { +#if NON_CVS && defined(LIBVNCSERVER_VERSION) + if (strcmp(LIBVNCSERVER_VERSION, "0.6")) +#endif + { if (*argc != 1) { int i; rfbLog("*** unrecognized option(s) ***\n"); @@ -5474,7 +5495,6 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { clean_up_exit(1); } } -#endif screen->paddedWidthInBytes = rfb_bytes_per_line; screen->serverFormat.bitsPerPixel = fb->bits_per_pixel; @@ -7876,8 +7896,9 @@ static int scan_display(int ystart, int rescan) { /* * toplevel for the scanning, rescanning, and applying the heuristics. + * returns number of changed tiles. */ -void scan_for_updates(void) { +int scan_for_updates(void) { int i, tile_count, tile_diffs; double frac1 = 0.1; /* tweak parameter to try a 2nd scan_display() */ double frac2 = 0.35; /* or 3rd */ @@ -7957,11 +7978,11 @@ void scan_for_updates(void) { fb_copy_in_progress = 1; copy_screen(); fb_copy_in_progress = 0; - if (use_threads && ! old_pointer) { + if (use_threads && old_pointer != 1) { pointer(-1, 0, 0, NULL); } nap_check(tile_count); - return; + return tile_count; } } scan_in_progress = 0; @@ -8000,7 +8021,7 @@ void scan_for_updates(void) { } fb_copy_in_progress = 0; - if (use_threads && ! old_pointer) { + if (use_threads && old_pointer != 1) { /* * tell the pointer handler it can process any queued * pointer events: @@ -8030,6 +8051,7 @@ void scan_for_updates(void) { nap_check(tile_diffs); + return tile_diffs; } /* -- x11vnc.c -- */ @@ -8055,10 +8077,14 @@ static int defer_update_nofb = 6; /* defer a shorter time under -nofb */ * * return of 1 means watch_loop should short-circuit and reloop, * return of 0 means watch_loop should proceed to scan_for_updates(). + * (this is for old_pointer == 1 mode, the others do it all internally, + * cnt is also only for that mode). */ -static int check_user_input(double dt, int *cnt) { +static int check_user_input_old(double dt, int *cnt); - if (old_pointer) { +static int check_user_input(double dt, int tile_diffs, int *cnt) { + + if (old_pointer == 1) { /* every n-th drops thru to scan */ if ((got_user_input || ui_skip < 0) && *cnt % ui_skip != 0) { *cnt++; @@ -8067,6 +8093,9 @@ static int check_user_input(double dt, int *cnt) { } else { return 0; } + } else if (old_pointer == 2) { + /* this older way is similar to the method below */ + return check_user_input_old(dt, cnt); } if (got_keyboard_input) { @@ -8077,6 +8106,145 @@ static int check_user_input(double dt, int *cnt) { /* otherwise continue with pointer input */ } + 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_min = 0.15; + static double quick_spin_fac = 0.65, spin_max_fac = 2.0; + static double rpe_wait = 0.15; + int grinding, gcnt, ms, split = 200; + + + /* + * 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" + */ + + if (dt < dt_min) { + dt = dt_min; /* this is to try to avoid early exit */ + } + /* max spin time in 1st pass, comparable to last dt */ + spin_max = quick_spin_fac * dt; + + 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; + + tm = 0.0; /* timer variable */ + dtime(&tm); + rpe_last = to = tm; /* last time we did rfbPE() */ + g = g_in = got_pointer_input; + + while (1) { + int got_input = 0; + + gcnt++; + if (grinding) { + if (gcnt >= split) { + break; + } + usleep(ms * 1000); + } + + 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); + } + + dtm = dtime(&tm); + spin += dtm; + + 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 { + /* 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; + } + 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 = 5; + 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; + } + } + } + return 0; +} + +/* this is the -old_pointer2 way */ +static int check_user_input_old(double dt, int *cnt) { + + if (got_keyboard_input) { + if (*cnt % ui_skip != 0) { + *cnt++; + return 1; /* short circuit watch_loop */ + } + /* otherwise continue with pointer input */ + } + if (got_pointer_input) { int eaten = 0, miss = 0, max_eat = 50; int g, g_in; @@ -8084,7 +8252,6 @@ static int check_user_input(double dt, int *cnt) { double quick_spin_fac = 0.40; double grind_spin_time = 0.175; - dtime(&tm); g = g_in = got_pointer_input; @@ -8234,7 +8401,7 @@ void rfbCFD(rfbScreenInfoPtr scr, long usec) { * main x11vnc loop: polls, checks for events, iterate libvncserver, etc. */ static void watch_loop(void) { - int cnt = 0; + int cnt = 0, tile_diffs = 0; double dt = 0.0; if (use_threads) { @@ -8250,9 +8417,10 @@ static void watch_loop(void) { if (! use_threads) { rfbPE(screen, -1); if (! cursor_shape_updates) { + /* undo any cursor shape requests */ unset_cursor_shape_updates(screen); } - if (check_user_input(dt, &cnt)) { + if (check_user_input(dt, tile_diffs, &cnt)) { /* true means loop back for more input */ continue; } @@ -8273,7 +8441,6 @@ static void watch_loop(void) { if (nofb) { /* no framebuffer polling needed */ if (cursor_pos_updates) { - /* -nofb -cursorpos usage is rare */ check_x11_pointer(); } continue; @@ -8287,8 +8454,10 @@ static void watch_loop(void) { check_bell_event(); } if (! show_dragging && button_mask) { - /* if any button is pressed do not update screen */ - /* XXX consider: use_threads || got_pointer_input */ + /* + * if any button is pressed do not update rfb + * screen, but do flush the X11 display. + */ X_LOCK; XFlush(dpy); X_UNLOCK; @@ -8298,10 +8467,9 @@ static void watch_loop(void) { dtime(&tm); rfbUndrawCursor(screen); - scan_for_updates(); - check_x11_pointer(); - + tile_diffs = scan_for_updates(); dt = dtime(&tm); + check_x11_pointer(); } /* sleep a bit to lessen load */ @@ -8731,9 +8899,11 @@ static void print_help(void) { " improves response on slow setups, but you lose all\n" " visual feedback for drags, text selection, and some\n" " menu traversals.\n" -"-old_pointer Do not use the new pointer input handling mechanisms.\n" +"-old_pointer Use the original pointer input handling mechanism.\n" " See check_input() and pointer() in source file for\n" " details.\n" +"-old_pointer2 The default pointer input handling algorithm was changed\n" +" again, this option indicates to use the second one.\n" "-input_skip n For the old 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" @@ -8744,7 +8914,7 @@ static void print_help(void) { " times for more output.\n" "\n" "-defer time Time in ms to wait for updates before sending to client\n" -" [rfbDeferUpdateTime] Default: %d\n" +" (deferUpdateTime) Default: %d\n" "-wait time Time in ms to pause between screen polls. Used to cut\n" " down on load. Default: %d\n" "-nap Monitor activity and if low take longer naps between\n" @@ -9295,6 +9465,8 @@ int main(int argc, char* argv[]) { if (! ui_skip) ui_skip = 1; } else if (!strcmp(arg, "-old_pointer")) { old_pointer = 1; + } else if (!strcmp(arg, "-old_pointer2")) { + old_pointer = 2; } else if (!strcmp(arg, "-norepeat")) { no_autorepeat = 1; } else if (!strcmp(arg, "-repeat")) { @@ -10030,36 +10202,36 @@ int main(int argc, char* argv[]) { } if (screen->port) { char *host = this_host(); - int port = screen->port; + int lport = screen->port; if (host != NULL) { /* note that vncviewer special cases 5900-5999 */ if (inetd) { - ; /* should not occur (rfbPort) */ + ; /* should not occur (port) */ } else if (quiet) { - if (port >= 5900) { + if (lport >= 5900) { fprintf(stderr, "The VNC desktop is " - "%s:%d\n", host, port - 5900); + "%s:%d\n", host, lport - 5900); } else { fprintf(stderr, "The VNC desktop is " - "%s:%d\n", host, port); + "%s:%d\n", host, lport); } - } else if (port >= 5900) { + } else if (lport >= 5900) { rfbLog("The VNC desktop is %s:%d\n", host, - port - 5900); - if (port >= 6000) { + lport - 5900); + if (lport >= 6000) { rfbLog("possible aliases: %s:%d, " - "%s::%d\n", host, port, host, port); + "%s::%d\n", host, lport, host, lport); } } else { rfbLog("The VNC desktop is %s:%d\n", host, - port); + lport); rfbLog("possible alias: %s::%d\n", - host, port); + host, lport); } } fflush(stderr); if (inetd) { - ; /* should not occur (rfbPort) */ + ; /* should not occur (port) */ } else { fprintf(stdout, "PORT=%d\n", screen->port); }