diff --git a/prepare_x11vnc_dist.sh b/prepare_x11vnc_dist.sh index 9c1ff03..a2e7bbf 100644 --- a/prepare_x11vnc_dist.sh +++ b/prepare_x11vnc_dist.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="0.6.3pre" +VERSION="0.7pre" cd "$(dirname "$0")" diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index ee31689..42b6aef 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,7 @@ +2004-12-22 Karl Runge + * final polishing for 0.7 release, tkx11vnc tweaks + * more careful rfbPE in pick_window, start check_user_input4() + 2004-12-19 Karl Runge * cleanup putenv, snprint, other string manip. * add -sync mode to remote control for better control diff --git a/x11vnc/README b/x11vnc/README index 8e9a89b..b424684 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Mon Dec 20 11:34:56 EST 2004 +x11vnc README file Date: Wed Dec 22 23:18:56 EST 2004 The following information is taken from these URLs: @@ -895,31 +895,15 @@ int srandom(unsigned int seed); #undef LIBVNCSERVER_HAVE_LIBPTHREAD #define SHUT_RDWR 2 typedef unsigned int in_addr_t; -#define XConvertCase(sym, lower, upper) \ -*(lower) = sym; \ -*(upper) = sym; \ -if (sym >> 8 == 0) { \ - if ((sym >= XK_A) && (sym <= XK_Z)) \ - *(lower) += (XK_a - XK_A); \ - else if ((sym >= XK_a) && (sym <= XK_z)) \ - *(upper) -= (XK_a - XK_A); \ - else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) \ - *(lower) += (XK_agrave - XK_Agrave); \ - else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) \ - *(upper) -= (XK_agrave - XK_Agrave); \ - else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) \ - *(lower) += (XK_oslash - XK_Ooblique); \ - else if ((sym >= XK_oslash) && (sym <= XK_thorn)) \ - *(upper) -= (XK_oslash - XK_Ooblique); \ -} - - You will also have to change all the snprint() references to sprintf() - calls x11vnc.c (sorry I don't know how to do this in a macro since - snprint() is varargs). +#ifndef snprintf +#define snprintf(a, n, args...) sprintf((a), ## args) +#endif Then run make with the Solaris build script environment, everything should compile without problems, and the resulting x11vnc binary - should work OK (but note the above XConvertCase only covers Latin 1). + should work OK (but note the workaround for XConvertCase in x11vnc.c + only covers Latin 1). If some non-x11vnc related programs fail (e.g. + test programs) and the x11vnc binary is not created try "make -k". Similar sorts of kludges can be done on other older OS (Solaris, Linux, ...) releases. diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc index b32598f..d2e3782 100755 --- a/x11vnc/tkx11vnc +++ b/x11vnc/tkx11vnc @@ -73,6 +73,7 @@ Actions =RA update-all =GA clear-all -- + =RA stop+quit =GA Quit Help @@ -284,6 +285,10 @@ remote commands are not on a menu, but for those few you can run the command directly this way. Just enter the command into the Entry box when prompted. Use the prefix \"Q:\" to indicate a -Q query. Examples: \"zero:20,20,100,100\", \"Q:ext_xfixes\" +" + + set helptext(stop+quit) " +Send the stop command to the x11vnc server, then terminate the tkx11vnc gui. " set helptext(Quit) " @@ -778,10 +783,16 @@ proc menus_state {state} { } proc menus_enable {} { + global menus_disabled + menus_state "normal" + set menus_disabled 0 } proc menus_disable {} { + global menus_disabled + + set menus_disabled 1 menus_state "disabled" } @@ -1183,6 +1194,8 @@ proc see_if_ok {query item expected} { set query_result_list [split_query $query] foreach q $query_result_list { + # XXX following will crash if $item is not a good regexp + # need to protect it \Q$item\E style... # if {[regexp "^$item:" $q]} { # set found $q # } @@ -1409,6 +1422,12 @@ proc do_action {item} { } elseif {$item == "all-settings"} { show_all_settings return + } elseif {$item == "stop+quit"} { + push_new_value "stop" "stop" 1 0 + set_connected no + update + after 500 + destroy . } if {[value_is_string $item]} { @@ -1656,12 +1675,45 @@ proc disconnect_dialog {client} { } } +proc update_clients_and_repost {} { + global item_cascade menu_m menu_b + + append_text "Refreshing connected clients list... " + query_all 1 + update + + set saw 0 + set casc $item_cascade(current) + set last [$casc index end] + for {set i 0} {$i <= $last} {incr i} { + if {[$casc type $i] == "separator"} { + continue + } + set name [$casc entrycget $i -label] + if {[regexp {^#} $name]} { + continue + } + if {[regexp {^refresh-list} $name]} { + continue + } + if {! $saw} { + append_text "\n" + } + set saw 1 + append_text "client: $name\n" + } + if {! $saw} { + append_text "done.\n" + } +} + proc update_clients_menu {list} { global item_cascade set subm $item_cascade(current); catch {destroy $subm} menu $subm -tearoff 0 $subm add command + $subm add command -label "refresh-list" -command "update_clients_and_repost" $subm add separator set count 0 foreach client [split $list ","] { @@ -1762,7 +1814,16 @@ set v 0 set menu "$colf.menu$case.menu"; set menu_b($case) $menub set menu_m($case) $menu - menubutton $menub -text "$case" -underline 0 \ + set ul 0 + foreach char [split $case ""] { + set char [string tolower $char] + if {![info exists underlined($char)]} { + set underlined($char) 1 + break + } + incr ul + } + menubutton $menub -text "$case" -underline $ul \ -anchor w -menu $menu -background $fbg \ -font $bfont pack $menub -side top -fill x @@ -2036,16 +2097,31 @@ MenuSelect>> } proc key_bindings {} { - global env + global env menus_disabled if {[info exists env(USER)] && $env(USER) == "runge"} { # quick restart bind . {exec $argv0 $argv &; destroy .} } - bind . {try_connect_and_query_all} - bind . {query_all 0} - bind . {query_all 0} - bind . {detach_from_display} - bind . {try_connect_and_query_all} + bind . { \ + global menus_disabled; \ + if {!$menus_disabled} {try_connect_and_query_all} \ + } + bind . { \ + global menus_disabled; \ + if {!$menus_disabled} {query_all 0} \ + } + bind . { \ + global menus_disabled; \ + if {!$menus_disabled} {query_all 0} \ + } + bind . { \ + global menus_disabled; \ + if {!$menus_disabled} {detach_from_display} \ + } + bind . { \ + global menus_disabled; \ + if {!$menus_disabled} {try_connect_and_query_all} \ + } } proc stop_watch {onoff} { @@ -2337,7 +2413,7 @@ global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect; global helpall helptext helpremote helplabel hostname; global all_settings reply_xdisplay always_update global max_text_height max_text_width -global menu_var unset_str +global menu_var unset_str menus_disabled global bfont global connected_to_x11vnc global delay_sleep extra_sleep extra_sleep_split @@ -2345,6 +2421,7 @@ global cache_all_query_vars set unset_str "(unset)" set connected_to_x11vnc 0 +set menus_disabled 0 set max_text_height 40 set max_text_width 90 set bfont -adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*; diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h index 0f442a2..ddd5f23 100644 --- a/x11vnc/tkx11vnc.h +++ b/x11vnc/tkx11vnc.h @@ -79,6 +79,7 @@ " =RA update-all\n" " =GA clear-all\n" " --\n" +" =RA stop+quit \n" " =GA Quit \n" "\n" "Help\n" @@ -292,6 +293,10 @@ "a -Q query. Examples: \\\"zero:20,20,100,100\\\", \\\"Q:ext_xfixes\\\" \n" "\"\n" "\n" +" set helptext(stop+quit) \"\n" +"Send the stop command to the x11vnc server, then terminate the tkx11vnc gui.\n" +"\"\n" +"\n" " set helptext(Quit) \"\n" "Terminate the tkx11vnc gui. Any x11vnc servers will be left running.\n" "\"\n" @@ -784,10 +789,16 @@ "}\n" "\n" "proc menus_enable {} {\n" +" global menus_disabled\n" +"\n" " menus_state \"normal\"\n" +" set menus_disabled 0\n" "}\n" "\n" "proc menus_disable {} {\n" +" global menus_disabled\n" +"\n" +" set menus_disabled 1\n" " menus_state \"disabled\"\n" "}\n" "\n" @@ -1189,6 +1200,8 @@ " set query_result_list [split_query $query]\n" "\n" " foreach q $query_result_list {\n" +" # XXX following will crash if $item is not a good regexp\n" +" # need to protect it \\Q$item\\E style...\n" "# if {[regexp \"^$item:\" $q]} {\n" "# set found $q\n" "# }\n" @@ -1415,6 +1428,12 @@ " } elseif {$item == \"all-settings\"} {\n" " show_all_settings\n" " return\n" +" } elseif {$item == \"stop+quit\"} {\n" +" push_new_value \"stop\" \"stop\" 1 0\n" +" set_connected no\n" +" update\n" +" after 500\n" +" destroy .\n" " }\n" "\n" " if {[value_is_string $item]} {\n" @@ -1662,12 +1681,45 @@ " }\n" "}\n" "\n" +"proc update_clients_and_repost {} {\n" +" global item_cascade menu_m menu_b\n" +"\n" +" append_text \"Refreshing connected clients list... \"\n" +" query_all 1\n" +" update\n" +"\n" +" set saw 0\n" +" set casc $item_cascade(current)\n" +" set last [$casc index end]\n" +" for {set i 0} {$i <= $last} {incr i} {\n" +" if {[$casc type $i] == \"separator\"} {\n" +" continue\n" +" }\n" +" set name [$casc entrycget $i -label]\n" +" if {[regexp {^#} $name]} {\n" +" continue\n" +" }\n" +" if {[regexp {^refresh-list} $name]} {\n" +" continue\n" +" }\n" +" if {! $saw} {\n" +" append_text \"\\n\"\n" +" }\n" +" set saw 1\n" +" append_text \"client: $name\\n\"\n" +" }\n" +" if {! $saw} {\n" +" append_text \"done.\\n\"\n" +" }\n" +"}\n" +"\n" "proc update_clients_menu {list} {\n" " global item_cascade\n" " set subm $item_cascade(current);\n" " catch {destroy $subm}\n" " menu $subm -tearoff 0\n" " $subm add command\n" +" $subm add command -label \"refresh-list\" -command \"update_clients_and_repost\"\n" " $subm add separator\n" " set count 0\n" " foreach client [split $list \",\"] {\n" @@ -1768,7 +1820,16 @@ " set menu \"$colf.menu$case.menu\";\n" " set menu_b($case) $menub\n" " set menu_m($case) $menu\n" -" menubutton $menub -text \"$case\" -underline 0 \\\n" +" set ul 0\n" +" foreach char [split $case \"\"] {\n" +" set char [string tolower $char]\n" +" if {![info exists underlined($char)]} {\n" +" set underlined($char) 1\n" +" break\n" +" }\n" +" incr ul\n" +" }\n" +" menubutton $menub -text \"$case\" -underline $ul \\\n" " -anchor w -menu $menu -background $fbg \\\n" " -font $bfont\n" " pack $menub -side top -fill x\n" @@ -2042,16 +2103,31 @@ "}\n" "\n" "proc key_bindings {} {\n" -" global env\n" +" global env menus_disabled\n" " if {[info exists env(USER)] && $env(USER) == \"runge\"} {\n" " # quick restart\n" " bind . {exec $argv0 $argv &; destroy .}\n" " }\n" -" bind . {try_connect_and_query_all}\n" -" bind . {query_all 0}\n" -" bind . {query_all 0}\n" -" bind . {detach_from_display}\n" -" bind . {try_connect_and_query_all}\n" +" bind . { \\\n" +" global menus_disabled; \\\n" +" if {!$menus_disabled} {try_connect_and_query_all} \\\n" +" }\n" +" bind . { \\\n" +" global menus_disabled; \\\n" +" if {!$menus_disabled} {query_all 0} \\\n" +" }\n" +" bind . { \\\n" +" global menus_disabled; \\\n" +" if {!$menus_disabled} {query_all 0} \\\n" +" }\n" +" bind . { \\\n" +" global menus_disabled; \\\n" +" if {!$menus_disabled} {detach_from_display} \\\n" +" }\n" +" bind . { \\\n" +" global menus_disabled; \\\n" +" if {!$menus_disabled} {try_connect_and_query_all} \\\n" +" }\n" "}\n" "\n" "proc stop_watch {onoff} {\n" @@ -2343,7 +2419,7 @@ "global helpall helptext helpremote helplabel hostname;\n" "global all_settings reply_xdisplay always_update\n" "global max_text_height max_text_width\n" -"global menu_var unset_str\n" +"global menu_var unset_str menus_disabled\n" "global bfont\n" "global connected_to_x11vnc\n" "global delay_sleep extra_sleep extra_sleep_split\n" @@ -2351,6 +2427,7 @@ "\n" "set unset_str \"(unset)\"\n" "set connected_to_x11vnc 0\n" +"set menus_disabled 0\n" "set max_text_height 40\n" "set max_text_width 90\n" "set bfont -adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*;\n" diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index abf7273..2f15efc 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -2,7 +2,7 @@ .TH X11VNC "1" "December 2004" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.7pre, lastmod: 2004-12-20 + version: 0.7pre, lastmod: 2004-12-23 .SH SYNOPSIS .B x11vnc [OPTION]... diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 0a23219..96781a5 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -256,7 +256,7 @@ static int xdamage_base_event_type; #endif /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.7pre lastmod: 2004-12-20"; +char lastmod[] = "0.7pre lastmod: 2004-12-23"; /* X display info */ @@ -732,13 +732,21 @@ int pick_windowid(unsigned long *num) { if (screen && screen->clientHead) { /* they may be doing the pointer-pick thru vnc: */ + int nfds; tv.tv_sec = 0; tv.tv_usec = msec * 1000; FD_ZERO(&set); FD_SET(fileno(p), &set); - if (select(fileno(p)+1, &set, NULL, NULL, &tv) == 0) { - /* note that rfbPE takes about 30ms too */ + + nfds = select(fileno(p)+1, &set, NULL, NULL, &tv); + + if (nfds == 0 || nfds < 0) { + /* + * select timedout or error. + * note this rfbPE takes about 30ms too: + */ rfbPE(screen, -1); + XFlush(dpy); continue; } } @@ -12585,7 +12593,7 @@ static void check_user_input3(double dt, 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_min = 0.075; + 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; @@ -12593,12 +12601,13 @@ static void check_user_input3(double dt, int tile_diffs) { if (first) { char *p = getenv("SPIN"); if (p) { - sscanf(p, "%lf,%lf,%lf", &grind_spin_time, &dt_min, &quick_spin_fac); + sscanf(p, "%lf,%lf,%lf", &grind_spin_time, &dt_cut, &quick_spin_fac); } first = 0; } + /* * Try for some "quick" pointer input processing. * @@ -12615,8 +12624,8 @@ static void check_user_input3(double dt, int tile_diffs) { * 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 */ + 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; @@ -12723,8 +12732,167 @@ static void check_user_input3(double dt, int tile_diffs) { drag_in_progress = 0; } +/* quick-n-dirty copy of check_user_input3, merge later... */ + static void check_user_input4(double dt, int tile_diffs) { - return; + + 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; + + 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; + static double dt_min = -1.0, dt_max = -1.0; + + if (first) { + char *p = getenv("SPIN"); + if (p) { + sscanf(p, "%lf,%lf,%lf,%lf", &grind_spin_time, + &dt_cut, &quick_spin_fac, &Tfac); + } + first = 0; + } + + if (dt_min < 0 || dt < dt_min) { + dt_min = dt; + } + if (dt_max < 0 || dt > dt_max) { + dt_max = dt; + } + + /* + * 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; + + 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; + + 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 (button_mask) { + 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); + } + + dtm = dtime(&tm); + spin += dtm; + + if (spin > spin_max) { + /* get out if spin time over limit */ + spun_out = 1; + + } else if (tile_diffs > 200 && spin > Ttile * tile_diffs) { + /* XXX not finished. */ + /* we think we can push the frame */ + break; + + } 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 = 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; + } + } + drag_in_progress = 0; } static int check_user_input(double dt, int tile_diffs, int *cnt) {