diff options
Diffstat (limited to 'x11vnc/tkx11vnc')
-rwxr-xr-x | x11vnc/tkx11vnc | 2187 |
1 files changed, 2187 insertions, 0 deletions
diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc new file mode 100755 index 0000000..2119d02 --- /dev/null +++ b/x11vnc/tkx11vnc @@ -0,0 +1,2187 @@ +#!/bin/sh +# the next line restarts using wish. \ +exec wish "$0" "$@" +catch {rename send {}} +# +# Copyright (c) 2004 Karl J. Runge <runge@karlrunge.com> +# All rights reserved. +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. + +# +# tkx11vnc v0.1 +# This is a simple frontend to x11vnc. It uses the remote control +# and query features (-remote/-query aka -R/-Q) to interact with it. +# It is just a quick-n-dirty hack (it parses -help output, etc), but +# it could be of use playing with or learning about the (way too) many +# parameters x11vnc has. +# +# It can be used to interact with a running x11vnc (see the x11vnc +# -gui option), or to set the parameters and then start up x11vnc. +# + +# +# Below is a simple picture of how the gui should be laid out and how +# the menus should be organized. Most menu items correspond to remote +# control commands. A trailing ":" after the item name means it is a string +# to be set rather than a boolean that can be toggled (e.g. the entry +# box must be used). +# +# Some tweak options may be set in the prefix "=" string. +# A means it is an "Action" (not a true variable) +# R means it is an action only valid in remote mode. +# S means it is an action only valid in startup mode. +# Q means it is an action worth querying after running. +# D means it is a good idea to delay a little before querying +# (i.e. perhaps it causes x11vnc to do a lot of work, new fb) +# P means the string can be +/- appended/deleted (string may not +# be the same after the remote command) +# G means gui internal item +# F means can be set via file browse +# -C:val1,... means it will be a checkbox (radio button) +# the "-" means no other options follow +# 0 means to skip the item. +# -- means add a separator +# +proc set_template {} { + global template + set template " +Row: Actions Clients Permissions Keyboard Pointer Help +Row: Displays Screen Tuning Debugging Misc + +Actions + =SA start + =RA stop + =GA attach + =RA detach + -- + =RA ping + =RA update-all + =GA clear-all + -- + =GA Quit + +Help + =GA gui + =GA all + +Clients + =RQA current: + =F connect: + =RQA disconnect: + -- + accept: + gone: + vncconnect + -- + =F httpdir: + httpport: + enablehttpproxy + +Displays + display: + =F auth: + desktop: + rfbport: + =0 gui: + +Screen + =DRA refresh + =DRA reset + =DRA blacken + -- + =D id: + =D sid: + =D scale: + -- + =D overlay + overlay_nocursor + -- + =D visual: + flashcmap + notruecolor + -- + =DP blackout: + =D xinerama + -- + = xrandr + =-C:resize,newfbsize,exit xrandr_mode: + padgeom: + +Keyboard + norepeat + add_keysyms + modtweak + xkb + skip_keycodes: + -- + =FP remap: + -- + clear_mods + clear_keys + +Pointer + =-C:none,arrow,X,some,most cursor: + noxfixes + -- + cursorpos + nocursorshape + -- + buttonmap: + -- + xwarppointer + +Misc + =F rc: + norc + -- + nofb + -- + nobell + nosel + noprimary + -- + bg + =-C:ignore,exit sigpipe: + =0 inetd + -- + =RA remote-cmd: + =GA all-settings + +Debugging + debug_pointer + debug_keyboard + =F logfile: + quiet + -- + =G debug_gui + +Permissions + =RQA lock + =RQA unlock + =SQA deny_all + -- + =FP allow: + localhost + =RA allowonce: + -- + viewonly + shared + forever + -- + =RA noremote + -- + alwaysshared + nevershared + dontdisconnect + -- + viewpasswd: + =F passwdfile: + =0 storepasswd + =F rfbauth: + passwd: + -- + safer + unsafe + +Tuning + =-C:1,2,3,4 pointer_mode: + input_skip: + nodragging + -- + =D noshm + flipbyteorder + onetile + -- + wait: + defer: + nap + screen_blank: + -- + fs: + gaps: + grow: + fuzz: + -- + threads + rfbwait: + -- + progressive: +" +} + +proc set_internal_help {} { + global helptext helpall + + # set some internal item help here: + set helptext(start) " +Launch x11vnc with the settings you have prescribed in the gui. +The x11vnc process is started in an xterm window so you can see the +output, kill it, etc. +" + + set helptext(debug_gui) " +Set debug_gui to get more output printed in the text area. +" + + set helptext(detach) " +No longer be associated with the x11vnc server. Switch to non-connected +state. +" + + set helptext(attach) " +Attach to the x11vnc server, if possible. Switches to connected state +if successful. To change or set the X display use \"Displays -> display\" +" + + set helptext(ping) " +Check if x11vnc still responds to \"ping\" remote command. +" + + set helptext(update-all) " +Query the x11vnc server for the current values of all variables. +Populate the values into the gui's database. +" + + set helptext(clear-all) " +Forget any variable settings either entered in by you or retrieved +from a running x11vnc server. Basically sets everything to 0 or +the string (unset). +" + + set helptext(all-settings) " +Displays the gui's database of all of the x11vnc server's current +settings. Use \"Actions -> update-all\" or \"Control+R\" to +refresh this list if it ever gets out of sync. +" + + set helptext(remote-cmd) " +Run a remote command (-R) or query (-Q) directly. Only a few +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(Quit) " +Terminate the tkx11vnc gui. Any x11vnc servers will be left running. +" + + set helptext(current) " +Shows a menu of currently connected VNC clients on the x11vnc server. + +Allows you to find more information about them or disconnect them. +You will be prompted to confirm any disconnections. +" + + set helptext(xrandr_mode) " +Set the -xrandr mode value. +" + + set helptext(all) $helpall + + set helptext(gui) " +tkx11vnc is a simple frontend to x11vnc. Nothing fancy, it merely +provides an interface to each of the many x11vnc command line options and +remote control commands. See \"Help -> all\" for much info about x11vnc. + +Most menu items have a (?) button one can click on to get more information +about the option or command. In most cases it will be text extracted +from that in \"Help -> all\". + +There are two states tkx11vnc can be in: + + 1) Available to control a running x11vnc process. + 2) Getting ready to start a x11vnc process. + +In state 1) the Menu items available in the menus are those that +correspond to the x11vnc \"remote control\" commands. See the -remote +entry under \"Help -> all\" for a complete list. Also available is +the \"Actions -> stop\" item to shut down the running x11vnc server, +thereby changing to state 2). One could also simply \"Actions -> detach\" +leaving the x11vnc server running. \"Actions -> attach\" would +reestablish the connection. + +In state 2) the Menu items available in the menus (Actions, Clients, +etc.) are those that correspond to command line options used in starting +an x11vnc process, and the \"Actions -> start\" item executes +x11vnc thereby changing to state 1). To see what x11vnc startup command +you have built so far, look at the (?) help for \"Actions -> start\" +and it will show you what the command looks like. + +There is much overlap between the menu items available in state 1) +and state 2), but it is worth keeping in mind it is not 100%. +For example, you cannot set passwords or password files in state 1). + +Also note that there may be *two* separate X displays involved, not just +one: 1) the X display x11vnc will be polling (and making available to +VNC viewers), and 2) the X display this GUI is intended to display on. +For example, one might use ssh to access the remote machine where the +GUI would display on :11 and x11vnc would poll display :0. + + +GUI components: +--- ---------- + +At the top of the gui is a info text label where information will +be posted, e.g. when traversing menu items text indicating how to get +help on the item and its current value will be displayed. + +Below the info label is the area where the menu buttons, Actions, +Clients, etc., are presented. If a menu item has a checkbox, +it corresponds to a boolean on/off variable. Otherwise it is +either a string variable, or an action not associated with a +variable (for the most part). + +Below the menu button area is a text label indicating the current x11vnc +X display being polled and the corresponding VNC display name. Both +will be \"(*none*)\" when there is no connection established. + +Below the x11 and vnc displays text label is a text area there scrolling +information about actions being taken and commands being run is displayed. +To scroll use PageUp/PageDown or the arrow keys. + +At the bottom is an entry area. When one selects a menu item that +requires supplying a string value, the label will be set to the +parameter name and one types in the new value. Then one presses the +\"OK\" button or presses \"Enter\" to set the value. Or you can press +\"Skip\" or \"Escape\" to avoid changing the variable. Some variables +are boolean toggles (for example, \"Permissions -> viewonly\") or Radio +button selections. Selecting these menu items will not activate the +entry area but rather toggle the variable directly. + +Cascades: There is a bug not yet worked around for the cascade menus +where the (?) help button gets in the way. To get the mouse over to +the cascade menu click and release mouse to activate the cascade, then +you can click on its items. Dragging with a mouse button held down +will not work (sorry). + +Key Bindings: + + In the Text Area: Control-/ selects all of the text. + Anywhere: Control-d invokes \"Actions -> detach\" + Anywhere: Control-a invokes \"Actions -> attach\" + Anywhere: Control-p invokes \"Actions -> ping\" + Anywhere: Control-u and Control-r invoke \"Actions -> update-all\" + +" +} + +proc center_win {w} { + wm withdraw $w + set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2]; + set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2]; + wm geom $w +$x+$y + wm deiconify $w + update +} + +proc textwidth {text} { + set min 0; + foreach line [split $text "\n"] { + set n [string length $line] + if {$n > $min} { + set min $n + } + } + return $min +} + +proc textheight {text} { + set count 0; + foreach line [split $text "\n"] { + incr count + } + return $count +} + +proc make_toplevel {w {title ""}} { + catch {destroy $w} + toplevel $w; + bind $w <Escape> "destroy $w" + if {$title != ""} { + wm title $w $title + } +} + +proc textwin {name title text} { + global max_text_height max_text_width + global bfont + + set width [textwidth $text] + incr width + if {$width > $max_text_width} { + set width $max_text_width + } + set height [textheight $text] + if {$height > $max_text_height} { + set height $max_text_height + } + + set w ".text_$name" + make_toplevel $w $title + + frame $w.f -bd 0; + pack $w.f -fill both -expand 1 + text $w.f.t -width $width -height $height -setgrid 1 -bd 2 \ + -yscrollcommand "$w.f.y set" -relief ridge -font fixed; + scrollbar $w.f.y -orient v -relief sunken -command "$w.f.t yview"; + button $w.f.b -text "Dismiss" -command "destroy $w" -font $bfont + + $w.f.t insert 1.0 $text; + + bind $w <Enter> "focus $w.f.t" + + wm withdraw $w + pack $w.f.b -side bottom -fill x + pack $w.f.y -side right -fill y; + pack $w.f.t -side top -fill both -expand 1; + update + + center_win $w +} + +proc active_when_connected {item} { + global helpremote helptext + + if {[opt_match G $item]} { + return 1 + } elseif {[is_action $item]} { + if {[opt_match R $item]} { + return 1 + } else { + return 0 + } + } elseif {[info exists helpremote($item)]} { + return 1 + } else { + return 0 + } +} + +proc active_when_starting {item} { + global helpremote helptext + + if {[opt_match G $item]} { + return 1 + } elseif {[is_action $item]} { + if {[opt_match S $item]} { + return 1 + } else { + return 0 + } + } elseif {[info exists helptext($item)]} { + return 1 + } else { + return 0 + } +} + +proc help_win {item} { + global helptext helpremote + global query_ans query_aro; + + set ok 0 + set text "Help on $item:\n\n" + + if {[is_gui_internal $item]} { + ; + } elseif {[is_action $item]} { + append text " + Is a remote control Action (cannot be set).\n"; + } elseif {[active_when_connected $item]} { + append text " + Can be changed in a running x11vnc.\n"; + } else { + append text " - Cannot be changed in a running x11vnc.\n"; + } + if {[is_gui_internal $item]} { + ; + } elseif {[active_when_starting $item]} { + append text " + Can be set at x11vnc startup.\n"; + } else { + append text " - Cannot be set at x11vnc startup.\n"; + } + append text "\n" + + if {[info exists helptext($item)]} { + append text "\n" + if {[is_gui_internal $item]} { + append text "==== x11vnc help: ====\n"; + } else { + append text "==== x11vnc startup option help: ====\n"; + } + append text "\n" + append text $helptext($item) + append text "\n" + set ok 1 + } + + if {[info exists helpremote($item)]} { + append text "\n" + append text "==== x11vnc remote control help: ====\n"; + append text "\n" + append text $helpremote($item) + set ok 1 + } + + if {$item == "start"} { + set str [get_start_x11vnc_txt] + append text $str + append_text "$str\n" + } + + regsub -all { } $item " " name + + if {$ok} { + textwin $name "x11vnc help: $item" "$text"; + } + return $ok +} + +proc parse_help {} { + global env x11vnc_prog; + global helpall helptext; + + set helppipe [open "| $x11vnc_prog -help" "r"]; + if {$helppipe == ""} { + puts stderr "failed to run $x11vnc_prog -help"; + exit 1; + } + + set sawopts 0; + set curropt ""; + while {[gets $helppipe line] > -1} { + append helpall "$line\n" + + # XXX + if {[regexp {^Options:} $line]} { + set sawopts 1; + continue; + } + # XXX + if {[regexp {^These options} $line]} { + continue; + } + + if {! $sawopts} { + continue; + } + if {[regexp {^-([A-z_][A-z_]*)} $line match name]} { + set allnames($name) 1; + if {"$curropt" != "no$name" && "no$curropt" != "$name"} { + set curropt $name; + set helptext($curropt) "$line\n"; + } else { + append helptext($curropt) "$line\n"; + } + } elseif {$curropt != ""} { + append helptext($curropt) "$line\n"; + } + } + foreach name [array names allnames] { + if {[regexp {^no} $name]} { + regsub {^no} $name "" pair + } else { + set pair "no$name" + } + if {[info exists helptext($name)]} { + if ![info exists helptext($pair)] { + set helptext($pair) $helptext($name); + } + } elseif {[info exists helptext($pair)]} { + if ![info exists helptext($name)] { + set helptext($name) $helptext($pair); + } + } + } + + set_internal_help +} + +proc tweak_both {new old} { + tweak_help $new $old + tweak_remote_help $new $old +} + +proc tweak_remote_help {new old} { + global helpremote + if ![info exists helpremote($new)] { + if {[info exists helpremote($old)]} { + set helpremote($new) $helpremote($old) + } + } +} + +proc tweak_help {new old} { + global helptext + if ![info exists helptext($new)] { + if {[info exists helptext($old)]} { + set helptext($new) $helptext($old) + } + } +} + +proc parse_remote_help {} { + global helpremote helptext help_indent remote_name; + + set sawopts 0; + set curropt ""; + set possopts ""; + set offset [expr $help_indent - 1]; + foreach line [split $helptext(remote) "\n"] { + + set line [string range $line $offset end]; + + # XXX + if {[regexp {^The following -remote/-R commands} $line]} { + set sawopts 1; + continue; + } + # XXX + if {[regexp {^The vncconnect.*command} $line]} { + set sawopts 0; + } + + if {! $sawopts} { + continue; + } + if {[regexp {^([A-z_][A-z_:]*)} $line match name]} { + regsub {:.*$} $name "" popt + lappend possopts $popt + if {"$curropt" != "no$name" && "no$curropt" != "$name"} { + set curropt $name; + regsub {:.*$} $curropt "" curropt + set remote_name($curropt) $name + set helpremote($curropt) "$line\n"; + } else { + append helpremote($curropt) "$line\n"; + } + } elseif {$curropt != ""} { + append helpremote($curropt) "$line\n"; + } + } + + foreach popt $possopts { + if {[info exists helpremote($popt)]} { + continue + } + if {[regexp {^no} $popt]} { + regsub {^no} $popt "" try + } else { + set try "no$popt" + } + if {[info exists helpremote($try)]} { + set helpremote($popt) $helpremote($try) + } + } +} + +proc parse_query_help {} { + global query_ans query_aro query_ans_list query_aro_list helptext; + + set sawans 0; + set sawaro 0; + set ans_str "" + set aro_str "" + + foreach line [split $helptext(query) "\n"] { + + if {! $sawans && [regexp {^ *ans=} $line]} { + set sawans 1 + } + if {! $sawans} { + continue + } + + if {[regexp {^ *aro=} $line]} { + set sawaro 1 + } + if {$sawaro && [regexp {^[ ]*$} $line]} { + set sawans 0 + break + } + + regsub {ans=} $line "" line + regsub {aro=} $line "" line + set line [string trim $line] + + if {$sawaro} { + set aro_str "$aro_str $line" + } else { + set ans_str "$ans_str $line" + } + } + + regsub -all { *} $ans_str " " ans_str + regsub -all { *} $aro_str " " aro_str + + set ans_str [string trim $ans_str] + set aro_str [string trim $aro_str] + set query_ans_list [split $ans_str] + set query_aro_list [split $aro_str] + + foreach item $query_ans_list { + if {[regexp {^[ ]*$} $item]} { + continue + } + set query_ans($item) 1 + } + foreach item $query_aro_list { + if {[regexp {^[ ]*$} $item]} { + continue + } + set query_aro($item) 1 + } +} + +proc in_debug_mode {} { + global menu_var + if {![info exists menu_var(debug_gui)]} { + return 0 + } + return $menu_var(debug_gui) +} + +# Menubar utilities: +proc menus_state {state} { + global menu_b + + foreach case [array names menu_b] { + set menu_button $menu_b($case) + $menu_button configure -state $state + } +} + +proc menus_enable {} { + menus_state "normal" +} + +proc menus_disable {} { + menus_state "disabled" +} + +# Entry box utilities: +proc entry_state {x state} { + global entry_box entry_label entry_ok entry_help entry_skip entry_browse + if {$x == "all"} { + $entry_label configure -state $state + $entry_box configure -state $state + $entry_ok configure -state $state + $entry_skip configure -state $state + $entry_help configure -state $state + $entry_browse configure -state $state + } elseif {$x == "label"} { + $entry_label configure -state $state + } elseif {$x == "box"} { + $entry_box configure -state $state + } elseif {$x == "ok"} { + $entry_ok configure -state $state + } elseif {$x == "skip"} { + $entry_skip configure -state $state + } elseif {$x == "help"} { + $entry_help configure -state $state + } elseif {$x == "browse"} { + $entry_browse configure -state $state + } +} + +proc entry_enable {{x "all"}} { + entry_state $x normal +} + +proc entry_disable {{x "all"}} { + entry_state $x disabled +} + +proc entry_browse_button {{show 1}} { + global entry_browse + if {$show} { + pack $entry_browse -side left + } else { + pack forget $entry_browse + } +} +proc entry_focus {} { + global entry_box + focus $entry_box +} +proc entry_select {} { + global entry_box + $entry_box selection range 0 end +} +proc entry_get {} { + global entry_box + return [$entry_box get] +} +proc entry_insert {str} { + global entry_box + entry_delete + $entry_box insert end $str + $entry_box icursor end +} +proc entry_delete {} { + global entry_box + $entry_box delete 0 end +} + + +# Utilities for remote control and updating vars. + +proc push_new_value {item name new {query 1}} { + global menu_var always_update remote_output query_output + global delay_sleep extra_sleep extra_sleep_split + + set debug [in_debug_mode] + set do_query_all 0 + set getout 0 + + if {$item == "remote-cmd"} { + # kludge for arbitrary remote command: + if {[regexp {^Q:} $new]} { + # extra kludge for Q:var to mean -Q var + regsub {^Q:} $new "" new + set qonly 1 + } else { + set qonly 0 + } + # need to extract item from new: + set qtmp $new + regsub {:.*$} $qtmp "" qtmp + if {! $qonly} { + set rargs [list "-R" "$new"] + set qargs [list "-Q" "$qtmp"] + set getout 1 + } else { + set rargs [list "-Q" "$qtmp"] + set qargs [list "-Q" "$qtmp"] + } + + } elseif {[value_is_string $item]} { + set rargs [list "-R" "$name:$new"] + set qargs [list "-Q" "$name"] + } else { + set rargs [list "-R" "$name"] + set qargs [list "-Q" "$name"] + } + + if {!$debug} { + append_text "x11vnc $rargs ..." + } + set remote_output [run_remote_cmd $rargs] + + if {[lindex $rargs 0] == "-Q"} { + append_text "\t$remote_output" + set getout 1 + } elseif {! $query && ! $always_update} { + set getout 1 + } elseif {$item == "noremote"} { + set getout 1 + } elseif {[is_action $item] && ![opt_match Q $item] && $rargs != ""} { + set getout 1 + } elseif {[regexp {^(sid|id)$} $item] && ![regexp {^0x} $new]} { + set getout 1 + } + + if {$getout} { + append_text "\n" + return + } + + stop_watch on + after $delay_sleep + if {[opt_match D $item]} { + set s [expr $extra_sleep/$extra_sleep_split] + append_text " " + for {set i 0} {$i<$extra_sleep_split} {incr i} { + after $s + append_text "." + update + } + } + stop_watch off + + if {!$debug} { + append_text ", -Q ..." + } + + if {$item == "disconnect"} { + set new "N/A" + set do_query_all 1 + } + + if {$always_update || $do_query_all} { + set query [query_all 1] + } else { + set query [run_remote_cmd $qargs] + } + set query_output $query + + if {![see_if_ok $query $item "$name:$new"]} { + # failed + if {[regexp {^a..=} $query]} { + # but some result came back + if {! $always_update} { + # synchronize everything + set query_output [query_all 1] + } + } else { + # server may be dead + if {$item != "ping" && $item != "attach"} { + try_connect + } + } + } else { + # succeeded + if {! $always_update} { + # synchronize this variable + update_menu_vars $query + } else { + # already done in query_all + } + } +} + +# For updating a string variable. Also used for simple OK/Skip dialogs +# with entry = 0. +proc entry_dialog {item {entry 1}} { + global menu_var entry_str entry_set entry_dialog_item + global unset_str connected_to_x11vnc + + set entry_str "Set $item" + set entry_set 0 + set entry_dialog_item $item + + entry_enable + menus_disable + + if {$entry} { + entry_insert "" + if {[info exists menu_var($item)] && + $menu_var($item) != $unset_str} { + entry_insert $menu_var($item) + entry_select + } + + if {[is_browse $item]} { + entry_browse_button + } + set_info "Set parameter in entry box, " + entry_focus + } else { + entry_disable box + } + + update + + # wait for user reply: + vwait entry_set + + set rc $entry_set + set entry_set 0 + + set value [entry_get] + update + + entry_browse_button 0 + set entry_str "Set... :" + + entry_delete + entry_disable + menus_enable + update + + if {! $entry} { + ; + } elseif {$rc} { + set menu_var($item) $value + } else { + if {[in_debug_mode]} { + append_text "skipped setting $item\n" + } + } + return $rc +} + +proc warning_dialog {msg {item "gui"} } { + append_text $msg + # just reuse the entry widgets for a yes/no dialog + return [entry_dialog $item 0] +} + +# For updating a boolean toggle: +proc check_var {item} { + global menu_var + + set inval $menu_var($item); + + if {$item == "debug_gui"} { + return ""; + } + + set rname $item + if {! $inval} { + if {[regexp {^no} $item]} { + regsub {^no} $rname "" rname + } else { + set rname "no$rname" + } + } + return $rname +} + +proc see_if_ok {query item expected} { + set ok 0 + set found "" + foreach q [split_query $query] { + if {[regexp "^$item:" $q]} { + set found $q + } + if {$q == $expected} { + set ok 1 + } + } + if {$found == ""} { + set msg $query + regsub {^a..=} $msg {} msg + if {[string length $msg] > 60} { + set msg [string range $msg 0 60] + } + } else { + set msg $found + } + if {$ok} { + append_text "\tSet OK ($msg)\n" + return 1 + + } elseif {[opt_match P $item] && [regexp {:(-|\+)} $expected]} { + # e.g. blackout:+30x30+20+20 + append_text "\t($msg)\n" + return 1 + } else { + append_text "\t*FAILED* $msg\n" + return 0 + } +} + +proc update_menu_vars {{query ""}} { + global all_settings menu_var + + set debug [in_debug_mode] + + if {$query == ""} { + set qstr $all_settings + } else { + set qstr $query + } + foreach piece [split_query $qstr] { + if {[regexp {^([^:][^:]*):(.*)$} $piece m0 item val]} { + if {[info exists menu_var($item)]} { + set old $menu_var($item) + if {$val == "N/A"} { + continue + } + if {$debug} { + puts "setting menuvar: $item: $old -> $val" + } + set menu_var($item) $val + } + if {$item == "clients"} { + update_clients_menu $val + } + } + } +} + +proc clear_all {} { + global menu_var unset_str + + set debug [in_debug_mode] + + foreach item [array names menu_var] { + if {$item == "debug_gui"} { + continue + } + if {[info exists menu_var($item)]} { + if [is_action $item] { + set menu_var($item) "" + } elseif {[value_is_bool $item]} { + set menu_var($item) 0 + } elseif {[value_is_string $item]} { + set menu_var($item) $unset_str + } + } + } +} + +proc all_query_vars {} { + global query_ans_list query_aro_list all_settings + + set qry "" + foreach item $query_ans_list { + if {$qry == ""} { + set qry $item + } else { + append qry ",$item" + } + } + foreach item $query_aro_list { + if {$qry == ""} { + set qry $item + } else { + append qry ",$item" + } + } + return $qry +} + +proc query_all {{quiet 0}} { + global query_ans_list query_aro_list all_settings + + set qry [all_query_vars] + + #puts "into query_all $quiet" + + set qargs [list "-Q" $qry] + set all [run_remote_cmd $qargs] + + if {[regexp {ans=} $all]} { + if {! $quiet} { + append_text "Retrieved all settings.\n" + } + set all_settings $all + update_menu_vars $all + } else { + if {! $quiet} { + append_text "Failed to retrieve settings.\n" + } + } + return $all +} + +proc set_info {str} { + global info_str + set info_str "$str" + update +} + +proc append_text {str} { + global text_area + $text_area insert end $str + $text_area see end +} + +proc show_all_settings {} { + global all_settings + set txt "\nRead-Write setting:\n\n" + foreach item [split_query $all_settings] { + regsub {:} $item {: } item + append txt " $item\n" + if {[regexp {noremote} $item]} { + append txt "\nRead-Only setting:\n\n" + } + } + textwin "Settings" "All Current Settings" $txt +} + +proc set_connected {yesno} { + global connected_to_x11vnc + set orig $connected_to_x11vnc + + if {$yesno == "yes"} { + set connected_to_x11vnc 1 + } else { + set connected_to_x11vnc 0 + no_x11_display + no_vnc_display + } + if {$orig != $connected_to_x11vnc} { + set_widgets + } +} + +proc detach_from_display {} { + global connected_to_x11vnc reply_xdisplay x11vnc_xdisplay + set str "Detaching from X display." + if {$reply_xdisplay != ""} { + set str "Detaching from $reply_xdisplay." + } elseif {$x11vnc_xdisplay != ""} { + set str "Detaching from $x11vnc_xdisplay." + } + if {$connected_to_x11vnc} { + append_text "$str\n" + } + set_connected no +} + +# Menu item is an action: +proc do_action {item} { + global menu_var connected_to_x11vnc + + if {[in_debug_mode]} { + append_text "action: \"$item\"\n" + } + + if {$item == "ping"} { + try_connect + return + } elseif {$item == "start"} { + start_x11vnc + return + } elseif {$item == "detach"} { + detach_from_display + return + } elseif {$item == "attach"} { + try_connect_and_query_all + return + } elseif {$item == "update-all"} { + query_all + return + } elseif {$item == "clear-all"} { + clear_all + return + } elseif {$item == "all-settings"} { + show_all_settings + return + } + + if {[value_is_string $item]} { + if {! [entry_dialog $item]} { + return + } + set new $menu_var($item) + set name $item + } else { + set new 1 + set name $item + } + + if {! $connected_to_x11vnc} { + ; + } elseif {[regexp {^(stop|quit|exit|shutdown)$} $item]} { + # just do -R + append_text "stopping remote x11vnc server...\n" + push_new_value $item $name $new 0 + set_connected no + + } elseif [opt_match Q $item] { + push_new_value $item $name $new 1 + } else { + push_new_value $item $name $new 0 + } +} + +proc do_var {item} { + global connected_to_x11vnc item_cascade menu_var + + set string 0 + if {[is_action $item]} { + # Menu item is action: + do_action $item + return + } + + if {[value_is_string $item]} { + # Menu item is a string: + if {$item_cascade($item) != ""} { + # Cascade sets variable automatically + } else { + # Otherwise Entry box + if {![entry_dialog $item]} { + return + } + } + set new $menu_var($item) + set name $item + } else { + # Menu item is a boolean: + set name [check_var $item] + if {$name == ""} { + return + } + set new 1 + } + if {$connected_to_x11vnc} { + push_new_value $item $name $new 1 + } +} + +proc menu_help {item} { + if ![help_win $item] { + textwin "nohelp" "No help available" \ + "Sorry, no help avaiable for \"$item\"" + } +} + +proc opt_match {c item} { + global item_opts + if {[info exists item_opts($item)]} { + if {[regexp "^\[A-z\]*$c" $item_opts($item)]} { + return 1 + } + } + return 0 +} + +proc is_action {item} { + return [opt_match A $item] +} + +proc is_gui_internal {item} { + return [opt_match G $item] +} + +proc is_browse {item} { + return [opt_match F $item] +} + +proc value_is_string {item} { + global item_bool + if {! $item_bool($item)} { + return 1 + } else { + return 0 + } +} + +proc value_is_bool {item} { + global item_bool + if {$item_bool($item)} { + return 1 + } else { + return 0 + } +} + +proc split_query {query} { + regsub -all {aro=} $query {ans=} query + set items {} + while {1} { + if {! [regexp {^ans=(.*)$} $query m0 m1]} { + break + } + set item $m1 + set m2 "" + regexp {,ans=.*$} $item m2 + regsub {,ans=.*$} $item "" item + if {$item != ""} { + lappend items $item + } + set query $m2 + regsub {^,} $query "" query + } + return $items +} + +proc set_x11_display {name} { + global x11_display + set x11_display "x11vnc X display: $name" +} +proc set_vnc_display {name} { + global vnc_display + set vnc_display "VNC display: $name" +} +proc no_x11_display {} { + set_x11_display "(*none*)" +} +proc no_vnc_display {} { + set_vnc_display "(*none*)" +} +proc fetch_displays {} { + + set qargs [list "-Q" "display,vncdisplay"] + set result [run_remote_cmd $qargs] + + set got_x11 0 + set got_vnc 0 + + foreach item [split_query $result] { + if {[regexp {^display:(.*)$} $item m0 m1]} { + set_x11_display $m1 + set got_x11 1 + } elseif {[regexp {^vncdisplay:(.*)$} $item m0 m1]} { + set_vnc_display $m1 + set got_vnc 1 + } + } + if {! $got_x11} { + no_x11_display + } + if {! $got_vnc} { + no_vnc_display + } +} + +proc disconnect_dialog {client} { + set cid "" + set host "" + set msg "\n" + append msg "*** Client info string: $client\n" + if {[regexp {^(.*):(.*)/(.*)-(.*)$} $client m0 m1 m2 m3 m4]} { + if {$m4 == "ro"} { + set view "(viewonly)" + } else { + set view "(interactive)" + } + set host $m1 + set cid $m3 + append msg "*** Host: $m1, Port: $m2 Id: $m3 $view\n" + } + if {$cid == ""} { + append_text "Invalid client info string: $client\n" + return + } + append msg "*** To disconnect this client press \"OK\", otherwise press \"Skip\"\n" + bell + if [warning_dialog $msg "current"] { + push_new_value "disconnect" "disconnect" $cid 1 + } else { + append_text "disconnect cancelled.\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 separator + set count 0 + foreach client [split $list ","] { + regsub {:[0-9][0-9]*/} $client {/} lab + $subm add command -label "$client" \ + -command "disconnect_dialog $client" + incr count + } + $subm entryconfigure 0 -label "#clients: $count" +} + +proc set_widgets {} { + global connected_to_x11vnc item_case item_entry menu_m + + foreach item [array names item_case] { + set case $item_case($item) + set menu $menu_m($case) + set entry $item_entry($item) + set type [$menu type $entry] + if {$type == "separator" || $type == "tearoff"} { + continue + } + if {$connected_to_x11vnc} { + if {[active_when_connected $item]} { + $menu entryconfigure $entry -state normal + } else { + $menu entryconfigure $entry -state disabled + } + } else { + if {[active_when_starting $item]} { + $menu entryconfigure $entry -state normal + } else { + $menu entryconfigure $entry -state disabled + } + } + } +} + +proc make_widgets {} { + global template + global menu_b menu_m + global item_opts item_bool item_case item_entry menu_var unset_str + global item_cascade + global info_str x11_display vnc_display + global text_area + global entry_box entry_str entry_set entry_label entry_ok entry_browse + global entry_help entry_skip + global bfont + global helptext helpremote helplabel + +set v 0 + + label .info -textvariable info_str -bd 2 -relief groove -anchor w + pack .info -side top -fill x + + # Extract the Rows: + set row 0; + set colmax 0; + foreach line [split $template "\n"] { + if {[regexp {^Row: (.*)} $line rest]} { + set col 0 + foreach case [split $rest] { + if {$case == "" || $case == "Row:"} { + continue + } + set menu_row($case) $row + set menu_col($case) $col + set menu_count($case) 0 + + lappend cases($col) $case; + set len [string length $case] + if {[info exists max_len($col)]} { + if {$len > $max_len($col)} { + set max_len($col) $len + } + } else { + set max_len($col) $len + } + incr col + if {$col > $colmax} { + set colmax $col + } + } + incr row; + } + } + + # Make frames for the rows and make the menu buttons. + set f ".menuframe" + frame $f + for {set c 0} {$c < $colmax} {incr c} { + set colf "$f.menuframe$c" + frame $colf + pack $colf -side left -fill y + set fbg [$colf cget -background] + foreach case $cases($c) { + set menub "$colf.menu$case"; + set menu "$colf.menu$case.menu"; + set menu_b($case) $menub + set menu_m($case) $menu + menubutton $menub -text "$case" -underline 0 \ + -anchor w -menu $menu -background $fbg \ + -font $bfont + pack $menub -side top -fill x + menu $menu -tearoff 0 + } + } + pack $f -side top -fill x + + # Now extract the menu items: + set case ""; + foreach line [split $template "\n"] { + if {[regexp {^Row:} $line]} { + continue + } + if {[regexp {^[A-z]} $line]} { + set case [string trim $line] + continue; + } + set item [string trim $line] + regsub -all { *} $item " " item + if {$item == ""} { + continue; + } + set opts "" + if {[regexp {^=} $item]} { + set opts [lindex [split $item] 0] + regsub {^=} $opts "" opts + set item [lindex [split $item] 1] + } + if {[regexp {^0} $opts]} { + continue; + } + if {[regexp {:$} $item]} { + set bool 0 + } else { + set bool 1 + } + regsub {:$} $item {} item + + set item_opts($item) $opts + set item_case($item) $case + set item_bool($item) $bool + set item_cascade($item) "" + set item_entry($item) $menu_count($case) + +if {$v} { puts "ITEM: $item - $opts - $case - $bool - $menu_count($case)" } + + set mvar 0 + set m $menu_m($case) + + # Create the menu items, its variables, etc., etc. + + if {$item == "--"} { + $m add separator + + } elseif {$item == "Quit"} { + # Quit item must shut us down: + $m add command -label "$item" -underline 0 \ + -command {destroy .; exit 0} + + } elseif {$case == "Help"} { + # Help is simple help: + $m add command -label "$item" \ + -command "menu_help $item" + + } elseif {$item == "current"} { + # Current clients cascade + set subm $m.cascade$menu_count($case) + set item_cascade($item) $subm + update_clients_menu "" + $m add cascade -label "$item" \ + -menu $subm + + } elseif {[is_action $item]} { + # Action + $m add command -label "$item" \ + -command "do_var $item" + set menu_var($item) ""; # for convenience + + } elseif {! $item_bool($item)} { + # String + if {[regexp -- {-C:(.*)} $item_opts($item) m0 m1]} { + # Radiobutton select + set subm $m.cascade$menu_count($case) + menu $subm -tearoff 0 + foreach val [split $m1 ","] { + $subm add radiobutton -label "$val" \ + -command "do_var $item" \ + -value "$val" \ + -variable menu_var($item) + } + $m add cascade -label "$item" \ + -menu $subm + set item_cascade($item) $subm + } else { + # Arbitrary_string + $m add command -label "$item" \ + -command "do_var $item" + } + set mvar 1 + + } else { + # Boolean + $m add checkbutton -label "$item" \ + -command "do_var $item" \ + -variable menu_var($item) + set menu_var($item) 0 + } + + incr menu_count($case) + if {$mvar} { + set menu_var($item) $unset_str + } + } + + # Now make the litte "(?)" help buttons + foreach case [array names menu_m] { + if {$case == "Help"} { + continue; + } + set m $menu_m($case); + set n [$m index end] + +if {$v} { puts "$case end: $n" } + + for {set i 0} {$i <= $n} {incr i} { + set type [$m type $i] + if {$type == "separator"} { + $m add separator + } elseif {$type == "tearoff"} { + continue; + } else { + set label [$m entrycget $i -label] + set str "" + if {[info exists helpremote($label)]} { + set str "(?)" + } elseif {[info exists helptext($label)]} { + set str "(?)" + } + $m add command -label $str \ + -command "menu_help $label"; + +if {$v} { + set ht ""; set hr "" + if {[info exists helptext($label)]} { set ht "YES" } + if {[info exists helpremote($label)]} { set hr "YES" } + puts "'$label'\tht='$ht' hr='$hr'" +} + + if {$str == ""} { + $m entryconfigure end -state disabled + } + set arg "$m,$i" + set helplabel($arg) $label + set j [$m index end] + set arg "$m,$j" + set helplabel($arg) $label + } + if {$i == 0} { + $m entryconfigure end -columnbreak 1 + } + } + } + + # Make the x11 and vnc display label bar: + set df .displayframe + frame $df -bd 1 -relief groove + + set df_x11 "$df.xdisplay" + no_x11_display + label $df_x11 -textvariable x11_display -width 35 -anchor w + + set df_vnc "$df.vdisplay" + no_vnc_display + label $df_vnc -textvariable vnc_display -width 35 -anchor w + + pack $df_x11 $df_vnc -side left + pack $df -side top -fill x + + # text area + text .text -height 11 -relief ridge + set text_area .text + pack .text -side top -fill both -expand 1 + + + set str "Click Help -> gui for overview." + append_text "\n$str\n\n" + + # Make entry box stuff + set ef .entryframe + frame $ef -bd 1 -relief groove + + # Label + set ef_label "$ef.label" + label $ef_label -textvariable entry_str -anchor w -font $bfont + + set entry_str "Set... : " + set ef_entry "$ef.entry" + entry $ef_entry -relief sunken + bind $ef_entry <KeyPress-Return> {set entry_set 1} + bind $ef_entry <KeyPress-Escape> {set entry_set 0} + + # OK button + set ef_ok "$ef.ok" + button $ef_ok -text OK -pady 1 -command {set entry_set 1} \ + -font $bfont + + # Skip button + set ef_skip "$ef.skip" + button $ef_skip -text Skip -pady 0 -command {set entry_set 0} \ + -font $bfont + + # Help button + set ef_help "$ef.help" + button $ef_help -text Help -pady 0 -command \ + {menu_help $entry_dialog_item} -font $bfont + + # Browse button + set ef_browse "$ef.browse" + button $ef_browse -text "Browse..." -pady 0 -font $bfont \ + -command {entry_insert [tk_getOpenFile]} + + pack $ef_label -side left + pack $ef_entry -side left -fill x -expand 1 + pack $ef_ok -side right + pack $ef_skip -side right + pack $ef_help -side right + pack $ef -side bottom -fill x + + set entry_ok $ef_ok + set entry_skip $ef_skip + set entry_help $ef_help + set entry_box $ef_entry + set entry_browse $ef_browse + set entry_label $ef_label + entry_disable + + update + wm minsize . [winfo width .] [winfo height .] +} + +proc menu_bindings {} { + bind Menu <<MenuSelect>> { +#syntax hilite bug \ +MenuSelect>> + set n [%W index active] + set label " " + if {$n != "none"} { + set str %W,$n + set which "" + if {[info exists helplabel($str)]} { + set vname [format %%-16s $helplabel($str)] + set label "Click (?) for help on: $vname" + set which $helplabel($str) + } + if {$which == ""} { + ; + } elseif {[is_action $which]} { + if {[info exists menu_var($which)] + && $menu_var($which) != ""} { + set label "$label value: $menu_var($which)" + } else { + set label "$label (is action)" + } + } elseif {[info exists menu_var($which)]} { + set label "$label value: $menu_var($which)" + } + } + set_info $label + } +} + +proc key_bindings {} { + global env + if {[info exists env(USER)] && $env(USER) == "runge"} { + # quick restart + bind . <Control-KeyPress-c> {exec $argv0 $argv &; destroy .} + } + bind . <Control-KeyPress-p> {try_connect_and_query_all} + bind . <Control-KeyPress-u> {query_all 0} + bind . <Control-KeyPress-r> {query_all 0} + bind . <Control-KeyPress-d> {detach_from_display} + bind . <Control-KeyPress-a> {try_connect_and_query_all} +} + +proc stop_watch {onoff} { + global orig_cursor text_area entry_box + + set widgets [list . $text_area $entry_box] + + if {$onoff == "on"} { + foreach item $widgets { + $item config -cursor {watch} + } + } else { + foreach item $widgets { + $item config -cursor {} + } + } + update +} + +proc double_check_noremote {} { + set msg "\n\n" + append msg "WARNING: setting \"noremote\" will disable ALL remote control commands\n" + append msg "WARNING: (i.e. this gui will be locked out) Do you really want to do this?\n" + append msg "WARNING: If so, press \"OK\", otherwise press \"Skip\"\n" + append msg "\n" + bell + return [warning_dialog $msg "noremote"] +} + +proc double_check_start_x11vnc {} { + global hostname + set msg [get_start_x11vnc_txt] + append msg "\n" + append msg "*** To run the above command on machine \"$hostname\" to\n" + append msg "*** start x11vnc press \"OK\" otherwise press \"Skip\".\n" + return [warning_dialog $msg "start"] +} + +proc get_start_x11vnc_txt {} { + set cmd [get_start_x11vnc_cmd] + set str [join $cmd] + set msg "" + append msg "\n" + append msg "==== The command built so far is: ====\n"; + append msg "\n" + append msg "$str\n" + return $msg +} + +proc get_start_x11vnc_cmd {} { + global menu_var unset_str x11vnc_prog + + set xterm_cmd "xterm -iconic -geometry 80x35 -title x11vnc-console -e" + + set cmd [split $xterm_cmd] + + lappend cmd $x11vnc_prog + + foreach item [lsort [array names menu_var]] { + if {![active_when_starting $item]} { + continue + } + if {[is_action $item]} { + continue + } + + if {[value_is_bool $item]} { + if {[info exists menu_var($item)]} { + if {$menu_var($item)} { + lappend cmd "-$item" + } + } + } elseif {[value_is_string $item]} { + if {[info exists menu_var($item)]} { + if {$menu_var($item) != "" + && $menu_var($item) != $unset_str} { + lappend cmd "-$item" + lappend cmd $menu_var($item) + } + } + } + } + lappend cmd "2>" + lappend cmd "/dev/null" + lappend cmd "&" + + return $cmd +} + +proc start_x11vnc {} { + global menu_var unset_str + global x11vnc_prog x11vnc_xdisplay + global connected_to_x11vnc + + if {$connected_to_x11vnc} { + append_text "\n" + append_text "WARNING: Still connected to an x11vnc server.\n" + append_text "WARNING: Use \"stop\" or \"detach\" first.\n" + return 0 + } + + if {![double_check_start_x11vnc]} { + return + } + + set x11vnc_xdisplay "" + if {[info exists menu_var(display)]} { + if {$menu_var(display) != "" && $menu_var(display) != $unset_str} { + set x11vnc_xdisplay $menu_var(display) + } + } + + set cmd [get_start_x11vnc_cmd] + + set str [join $cmd] + regsub { -e} $str " -e \\\n " str + + if {0} { + puts "running: $str" + foreach word $cmd { + puts " word: $word" + } + } + + append_text "Starting x11vnc in an iconified xterm with command:\n" + append_text " $str\n\n" + catch {[eval exec $cmd]} + after 500 + try_connect_and_query_all 3 +} + +proc run_remote_cmd {opts} { + global menu_var x11vnc_prog x11vnc_cmdline x11vnc_xdisplay + + set debug [in_debug_mode] + + if {[lindex $opts 0] == "-R" && [lindex $opts 1] == "noremote"} { + set str [join $opts] + if ![double_check_noremote] { + append_text "skipping: x11vnc $str" + return "" + } else { + append_text "running: x11vnc $str (please do \"Actions -> detach\" to clean things up)\n" + append_text "subsequent -R/-Q commands should fail..." + } + } + + set cmd "" + + lappend cmd $x11vnc_prog; + + if {$x11vnc_xdisplay != ""} { + lappend cmd "-display" + lappend cmd $x11vnc_xdisplay + } + foreach word $opts { + lappend cmd $word + } + lappend cmd "2>" + lappend cmd "/dev/null" + +if {0} { + set str [join $cmd] + puts "running: $str" + foreach word $cmd { + puts " word: $word" + } +} + + set output "" + stop_watch on + catch {set output [eval exec $cmd]} + stop_watch off + if {$debug} { + append_text "output: $output\n" + } + return $output +} + +proc try_connect_and_query_all {{n 2}} { + for {set i 0} {$i < $n} {incr i} { + if {$i > 0} { + after 500 + append_text "trying again ...\n" + } + if {[try_connect]} { + query_all + break + } + } +} + +proc try_connect {} { + global x11vnc_xdisplay connected_to_x11vnc reply_xdisplay + global menu_var unset_str + + if {! $connected_to_x11vnc} { + if {[info exists menu_var(display)]} { + set d $menu_var(display) + if {$d != "" && $d != $unset_str && $d != $x11vnc_xdisplay} { + set x11vnc_xdisplay $menu_var(display) + append_text "Setting X display to: $x11vnc_xdisplay\n" + } + } + } + + set_info "Pinging $x11vnc_xdisplay ..." + set rargs [list "-Q" "ping"] + set result [run_remote_cmd $rargs] + + if {[regexp {^ans=ping:} $result]} { + regsub {^ans=ping:} $result {} reply_xdisplay + set msg "Connected to $reply_xdisplay" + set_info $msg + append_text "$msg\n" + set_connected yes + fetch_displays + return 1 + } else { + set str "x11vnc server." + if {$x11vnc_xdisplay != ""} { + set str $x11vnc_xdisplay + } + set msg "No reply from $str" + set_info $msg + append_text "$msg\n" + set_connected no + return 0 + } +} + +############################################################################ +# main: + +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 bfont +global connected_to_x11vnc +global delay_sleep extra_sleep extra_sleep_split + +set unset_str "(unset)" +set connected_to_x11vnc 0 +set max_text_height 40 +set max_text_width 90 +set bfont -adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*; +set help_indent 24; +set reply_xdisplay "" +set all_settings "None so far." +set always_update 1 + +#set delay_sleep 500 +#set extra_sleep 1500 +set delay_sleep 350 +set extra_sleep 1000 +set extra_sleep_split 4 + +if {"$argv" == "-spit"} { + set fh [open $argv0 r] + puts "/*" + puts " * tkx11vnc.h: generated by 'tkx11vnc -spit'" + puts " * Abandon all hope, ye who enter here..." + puts " * ...edit tkx11vnc instead." + puts " */" + puts " char gui_code\[\] =" + while {[gets $fh line] > -1} { + regsub -all {\\} $line {\\\\} line + regsub -all {"} $line {\\"} line + puts "\"$line\\n\"" + } + close $fh + puts ";" + exit 0 +} + +# Read environment for clues: +if {[info exists env(X11VNC_PROG)]} { + set x11vnc_prog $env(X11VNC_PROG); +} else { + set x11vnc_prog "x11vnc"; +} + +if {[info exists env(X11VNC_CMDLINE)]} { + set x11vnc_cmdline $env(X11VNC_CMDLINE); +} else { + set x11vnc_cmdline ""; +} + +if {[info exists env(X11VNC_CONNECT)]} { + set x11vnc_connect 1 +} else { + set x11vnc_connect 0; +} + +if {[info exists env(X11VNC_XDISPLAY)]} { + set x11vnc_xdisplay $env(X11VNC_XDISPLAY); + set x11vnc_connect 1 + +} elseif {$argv != "" && [regexp {:[0-9]} $argv]} { + set x11vnc_xdisplay "$argv" + set x11vnc_connect 1 + +} elseif {[info exists env(DISPLAY)]} { + set x11vnc_xdisplay $env(DISPLAY); +} else { + set x11vnc_xdisplay ":0"; +} + +set hostname [exec uname -n] +#puts [exec env] +#puts "x11vnc_xdisplay: $x11vnc_xdisplay" + +set env(X11VNC_STD_HELP) 1 + +# scrape the help output for the text and remote control vars: +parse_help; +parse_remote_help; +parse_query_help; + +# tweaks to duplicate help text: +tweak_remote_help lock deny +tweak_remote_help unlock deny + +tweak_both quiet q +tweak_help logfile o +tweak_both xwarppointer xwarp +tweak_both screen_blank sb + +set_template + +wm title . "tkx11vnc" +make_widgets; + +menu_bindings; +key_bindings; + +if {$x11vnc_connect} { + try_connect_and_query_all +} +set_widgets + +# main loop. |