Cleanup:
- remove unused changeViewportMeta function from include/ui.js
- remove some debug output and debug CSS.
- rename panel toggle functions and put them in same location in the
code.
- refactor some code from updateState to updateVisualState routine
(renamed from updateSettingsState).
API changes (forward compatible):
- Display: add 'viewport' conf option to turn on and off viewport
mode.
- RFB: add 'viewportDrag' option to enable/disable viewport dragging
mode.
Other:
- Add clip mode setting to default UI. For touch devices, clipping is
forced on.
- Use CSS media queries to adjust visual elements based on screen
size. Especially disconnected logo size/position and button text size.
- Catch page unload while connected and give a confirm dialog.
- Change mouse button selector to a single button that changes between
' ', 'L', 'M', 'R' when clicked (empty means mouse is just being
moved and doesn't send clicks).
- include/ui.js:setViewClip() routine sets the clipping of the
viewport to the current size of the viewport area (if clipping is
enabled).
- include/ui.js:setViewDrag() toggles/enables/disables viewport
dragging mode.
- Add several images for the UI and for Apple devices:
- images/clipboard.png: clipboard menu icon
- images/connect.png: connect menu icon
- images/disconnect.png: disconnect button icon
- images/keyboard.png: show keyboard button
- images/move.png: viewport drag/move toggle button
- images/settings.png: settings menu icon
- images/screen_320x460.png: iOS app/desktop link start image
- images/screen_57x57.png: iOS app icon
- images/screen_700x700.png: full size noVNC image
New routine fbUpdateRequests that builds the update request messages
based on the result of display.getCleanDirtyReset().
- Also, fix fbUpdateRequest to properly accept x,y,xw,yw parameters.
Another firefox issue is that height: 100% is calculated as 100% of
the containing element even when the containing element is the window.
This means that the size of any sibling element shifts the window size
down by that much and causes the vertical scroll bars to appear. This
doesn't happen in Chrome.
- So instead, put a pad element inside the noVNC_screen element that
is the size of the control bar. This is hidden by the control bar,
however, it causes things to be sized correctly.
- Also, rename noVNC_defaultScreen to noVNC_logo.
- Clean some style specification out of the HTML.
For some reason, the position calculation is broken in firefox when
a DOM object in the ancestry change uses padding. So use margin to
shift the view area down.
Part of mobile device support:
https://github.com/kanaka/noVNC/issues/48
The Display object is redefined as a larger display region with
an equal or smaller visible viewport. The size of the full display
region is set/changed using resize(). The viewport is set/changed
using viewportChange().
All exposed routines that draw on the display now take coordinates
that are absolute (relative to the full display region). For example,
the result of fillRect(100, 100, 10, 10, [255,0,0]) will appear in the
canvas at (0,0) if the viewport is set to (100,100).
Details:
- Move the generic part of the viewport code from tests/viewport.html
into include/display.
- Add two new routines to the Display interface:
- viewportChange(deltaX, deltaY, width, height)
- This adjusts the position of the visible viewport and/or the
size of the viewport.
- deltaX and deltaY specify how the position of the viewport
should be shifted. The position of the viewport is clamped
to the full region size (i.e. cannot outside the display
region).
- The clean and dirty regions of the display are updated based
on calls to this routine. For example, if the viewport width
is increased, then there is now a dirty box on the right
side of the viewport. Another example, if the viewport is
shifted down and to the left over the display region, there
are now two dirty boxes: one on the left side and one
on the bottom of the viewport.
- getCleanDirtyReset()
- This returns an object with the clean box and a list of
dirty boxes (that need to be redrawn).
{'cleanBox':
{'x': x, 'y': y, 'w': w, 'h': h},
'dirtyBoxes':
[{'x': x, 'y': y, 'w': w, 'h': h}, ...]
}
- The coordinates in the clean and dirty boxes are absolute
coordinates (relative to the full display region) but they
are clipped to the visible viewport.
- Calling this function also resets the clean rectangle to be
the whole viewport (i.e. nothing visible needs to be redrawn
dirty) so the caller of this routine is responsible for
redrawing any
Tested on iOS (iPhone and iPad).
The viewport is correctly clipped to the screen/browser size and
resizing works correctly.
This uses the CSS3 Flexible Box Layout model.
First crack at supporting touch screen for devices like Android and
iOS tablets. Part of https://github.com/kanaka/noVNC/issues/48.
This change detects touch screen support and uses the touchstart,
touchmove, touchend events in place of the normal mouse events.
In order to support middle and right mouse clicks, if the device is
a touch device, then three toggle buttons are added to the UI
representing the left, middle and right mouse buttons. These select
which mouse button will be sent when the screen is touched. All the
buttons can be toggled off, in which case then the touch events only
move the mouse cursor rather than sending a mouse down and mouse up
for touchstart and touchend events respectively. This allows fairly
full control with the mouse on touch screens.
Instead of R,G,B (red-shift of 0, green-shift of 8, and blue-shift
of 16), use the default ordering of B,G,R (red-shift of 16, green-shift of 8, and blue-shift
of 0) that tightvncserver uses (and that VMWare's VNC server seems to
require). Also, warn in the console if the server does not default to
the new format.
Fix the tests/canvas.html test. This is a general fix with regards to
the rename/refactor of canvas.js into display.js and not specific to
the color re-ordering.
noVNC version 0.1
Add debian packaging directory loosely based on
http://trac.zentyal.org/browser/trunk/extra/novnc/debian
Show web root directory on startup (pulled from websockify f1c8223).
Lintian fixups:
- Some license text clarifications.
- remove executable permission on utils/launch.sh and
include/web-socket-js/web_socket.js
- Add executable permission to utils/launch.sh
This addresses issue #65:
https://github.com/kanaka/noVNC/issues/65
When tightPNG encoded rects were received, any fill types were
immediately drawn to the canvas while images (PNG, JPEGs) were queued
for loading. This can cause screen corruption when things are changing
rapidly due to the misordering of fills vs images.
Also, remove the onload setting in each image on the queue and instead
decrease the tight image queue scanning interval (to 40ms or 25
scans per second).
- Add conf_defaults which accepts an array of configuration
attributes.
- Split out user configuration defaults from the actual configuration
object.
- Add mode field and enforce read-only, write-once, read-write modes.
API changes:
- include/canvas.js renamed to include/display.js
- Display.rescale() method removed from API. Use Display.set_scale() instead.
- Make logo configuration attribute of Display and display it when
clear() is called if it is set.
API deprecations:
- use RFB onUpdateState instead of updateState.
- use RFB onClipboard instead of clipboardReceive.
See https://github.com/kanaka/noVNC/wiki/ModuleAPI for detailed noVNC
modules and API description.
Expand and normalize the event/callback interfaces. Standize on
"onEventName" form for callbacks.
Callback Renames:
- RFB updateState -> onUpdateState
- RFB clipboardReceive -> onClipboard
- Keyboard keyPress -> onKeyPress
- Mouse mouseButton -> onMouseButton
- Mouse mouseMove -> onMouseMove
Callback Additions:
- RFB onPasswordRequired
- RFB onBell
- RFB onFBUReceive
- RFB onFBUComplete
Other:
- Add array type support to Util.conf_default()
- Removed a bunch of routines from the Display API that were just used
internally and not actually by noVNC: flush, setFillColor,
imageDataGet, imageDataCreate, rgbxImageData, rgbxImageFill,
cmapImageData, cmapImageFill.
- More keyboard/mouse logging when debug turned on.
- Some JSLinting
Issue #21 - non-US keyboard layouts.
The code section for tab, backspace and enter was commented out for
testing but got checked in that way. Fix that.
Issue #21 - non-US keyboard layouts.
Only identify some keys as special during the keyDown event so that
when using non-US keyboards the values don't overlap with the values
for normal keys.
Some keys have to still be identified in both keyDown and keyPress
since they generate both: backspace and enter for Firefox and Opera,
tab for Opera.
This is part of addressing issue #21 - non-US keyboard layouts.
There are several challenges when dealing with keyboard events:
- The meaning and use of keyCode, charCode and which depends on
both the browser and the event type (keyDown/Up vs keyPress).
- We cannot automatically determine the keyboard layout
- The keyDown and keyUp events have a keyCode value that has not
been translated by modifier keys.
- The keyPress event has a translated (for layout and modifiers)
character code but the attribute containing it differs. keyCode
contains the translated value in WebKit (Chrome/Safari), Opera
11 and IE9. charCode contains the value in WebKit and Firefox.
The which attribute contains the value on WebKit, Firefox and
Opera 11.
- The keyDown/Up keyCode value indicates (sort of) the physical
key was pressed but only for standard US layout. On a US
keyboard, the '-' and '_' characters are on the same key and
generate a keyCode value of 189. But on an AZERTY keyboard even
though they are different physical keys they both still
generate a keyCode of 189!
- To prevent a key event from propagating to the browser and
causing unwanted default actions (such as closing a tab,
opening a menu, shifting focus, etc) we must suppress this
event in both keyDown and keyPress because not all key strokes
generate on a keyPress event. Also, in WebKit and IE9
suppressing the keyDown prevents a keyPress but other browsers
still generated a keyPress even if keyDown is suppressed.
For safe key events, we wait until the keyPress event before
reporting a key down event. For unsafe key events, we report a key
down event when the keyDown event fires and we suppress any further
actions (including keyPress).
In order to report a key up event that matches what we reported
for the key down event, we keep a list of keys that are currently
down. When the keyDown event happens, we add the key event to the
list. If it is a safe key event, then we update the which attribute
in the most recent item on the list when we received a keyPress
event (keyPress should immediately follow keyDown). When we
received a keyUp event we search for the event on the list with
a matching keyCode and we report the character code using the value
in the 'which' attribute that was stored with that key.
For character codes above 255 we use a character code to keysym lookup
table. This is generated using the util/u2x11 script contributed by
Colin Dean (xvpsource.org).
API change: for intergrators that explicitly include the Javascript
files (that do not use include/vnc.js)js, include/input.js is a new
file that must also be included.
The mouse and keyboard handling could be useful on its own so split it
out into a Keyboard and Mouse class in include/input.js.
This refactoring is preparation to deal with issue #21 - non-US
keyboard layouts.
Fix mouse button mapping in IE9. All browsers have converged on
a standard left=0, middle=1, right=2 ... all except IE that is.
Add html5 doctype to tests.
In vnc_perf test, use do_test instead of start for function name since
start is a keyword in IE.
In error about Flash give a link to Adobe's download page.
Current timeout is 2 seconds for connect timeout. Use 5 seconds if
web-socket-js (Flash WebSockets emulator) is being used. On Windows XP
with Flash 10.2.152.26, connecting seems to take quite a bit longer
than it probably should. This should make it work more consistently.
Syncs with same change to websockify (7534574a2f).
Primary change is removal of FABridge interface.
Seems to improve overall latency by perhaps 10%. Also, the slowdown
over time in Opera is about half as bad (but still there).
Thanks to Michael Sersen for creating images/Logo.svg.
- Add images directory with original SVG logo, favicon, and some
derivative PNGs of the logo for different purpose.
- Note that license on images/* is CC BY-SA.
- Add utils/img2js.py to take an image and generate a base64 encoded
data URI string.
- Add base64 encoded data URI screen logo to display in canvas when
disconnected.
API change: changed include path variable from VNC_uri_prefix to
URI_INCLUDE since websock.js uses the variable and websock.js is no
longer just for noVNC (i.e. websockify is really the canonical
location for websock.js).
Changes to get web-socket-js to work. Right now it's a hack to get
around: https://github.com/gimite/web-socket-js/issues#issue/41. The
hack is to disable caching of the flash objects by appending
"?" + Math.random() to the end of the flash object path (but only when
using IE).
Opera 11 native WebSockets (if enabled) seems to have bad behavior for
the bufferedAmount so add change from websockify project to allow max
bufferedAmount (before send queue is delay) to be configured.
Also, Opera 11 and 10.60 behave like Mozilla regarding the '-' key so
translate it correctly.
If all send data was flushed from the send queue then return true,
otherwise false. This doesn't mean the data won't be sent, just that
it wasn't sent this time and is queued.
Only delay sending data if bufferedAmount is greater than 1000.
This seems to match the intention of the spec better. bufferedAmount
does not mean that we can't send, it's just an indication that the
network is becoming saturated. But Opera 11 native WebSockets seems to
have a bug that bufferedAmount isn't set back to zero correctly so
we'll be a bit more tolerant.
Related to this issue:
https://github.com/gimite/web-socket-js/issues/#issue/50
This prevents the "Uncaught exception: TypeError:
'this.__handleEvents' is not a function" everytime the timer fires.
Yay, one of Javascript's worst behaviors; the way it sets "this".
Issues #27 (safari cursor rendering messed up) and #29 (firefox 3.6.10
segault).
Finally found some better reference on the icon/cursor format which is
added to the docs/links file.
It seems like I was missing the XOR section. So setting the cursor
would cause corruptin in Safari rendering or the segfault for firefox.
Update to a build based on 20f837425d4 from gimite/web-socket-js.
This changes the event handling code and fixes the frequent recursive
call into Flash errors.
wswrapper:
Getting the wswrapper.c LD_PRELOAD model working has turned out to
involve too many dark corners of the glibc/POSIX file descriptor
space. I realized that 95% of what I want can be accomplished by
adding a "wrap command" mode to wsproxy.
The code is still there for now, but consider it experimental at
best. Minor fix to dup2 and add dup and dup3 logging.
wsproxy Wrap Command:
In wsproxy wrap command mode, a command line is specified instead
of a target address and port. wsproxy then uses a much simpler
LD_PRELOAD library, rebind.so, to move intercept any bind() system
calls made by the program. If the bind() call is for the wsproxy
listen port number then the real bind() system call is issued for
an alternate (free high) port on loopback/localhost. wsproxy then
forwards from the listen address/port to the moved port.
The --wrap-mode argument takes three options that determine the
behavior of wsproxy when the wrapped command returns an exit code
(exit or daemonizing): ignore, exit, respawn.
For example, this runs vncserver on turns port 5901 into
a WebSockets port (rebind.so must be built first):
./utils/wsproxy.py --wrap-mode=ignore 5901 -- vncserver :1
The vncserver command backgrounds itself so the wrap mode is set
to "ignore" so that wsproxy keeps running even after it receives
an exit code from vncserver.
wstelnet:
To demonstrate the wrap command mode, I added WebSockets telnet
client.
For example, this runs telnetd (krb5-telnetd) on turns port 2023
into a WebSockets port (using "respawn" mode since telnetd exits
after each connection closes):
sudo ./utils/wsproxy.py --wrap-mode=respawn 2023 -- telnetd -debug 2023
Then the utils/wstelnet.html page can be used to connect to the
telnetd server on port 2023. The telnet client includes VT100.js
(from http://code.google.com/p/sshconsole) which handles the
terminal emulation and rendering.
rebind:
The rebind LD_PRELOAD library is used by wsproxy in wrap command
mode to intercept bind() system calls and move the port to
a different port on loopback/localhost. The rebind.so library can
be built by running make in the utils directory.
The rebind library can be used separately from wsproxy by setting
the REBIND_OLD_PORT and REBIND_NEW_PORT environment variables
prior to executing a command. For example:
export export REBIND_PORT_OLD="23"
export export REBIND_PORT_NEW="65023"
LD_PRELOAD=./rebind.so telnetd -debug 23
Alternately, the rebind script does the same thing:
rebind 23 65023 telnetd -debug 23
Other changes/notes:
- wsproxy no longer daemonizes by default. Remove -f/--foreground
option and add -D/--deamon option.
- When wsproxy is used to wrap a command in "respawn" mode, the
command will not be respawn more often than 3 times within 10
seconds.
- Move getKeysym routine out of Canvas object so that it can be called
directly.
Rename the $() selector to $D() so that it doesn't collide with
the jQuery name.
The API change is that the 'target' option for Canvas and RFB objects
must now be a DOM Canvas element. A string is no longer accepted
because this requires that a DOM lookup is done and the Canvas and RFB
should have no UI code in them. Modularity.
Only call encode_message when the WebSockets object is actually
ready to send. Otherwise multiple base64 encode sequences can be
encoded into the same WebSockets frame. This causes the C version of
wsproxy to crash and the python version to ignore the subsequent
base64 sequence(s).
Thanks to Colin Dean (xvpsource.org) for finding this and helping
track it down.
- Add meta tag to vnc.html and vnc_auto.html so that if Chrome Frame
is installed, it is used.
- Add detection to default_controls.js that shows a message with
a Chrome Frame install link if the user is using a version of IE
without Canvas support.
- Fix web.py so that requests have their connection closed after they
are completed. This has been a bug for a while but it prevents
Chrome Frame from working because Chrome Frame doesn't activate
until the initial request connection closes.
This is WebKit bug https://bugs.webkit.org/show_bug.cgi?id=46319
The workaround is to wrap Canvas render functions with a function that
sets a flush timer. The flush function sets the right margin and then
1ms later sets it back. This triggers the canvas to redraw with the
correct contents.
Two downsides:
- rendering is slower, but only on the busted versions of webkit.
Correct and useful is better than fast and useless.
- There is a barely perceptible jitter of the control buttons because
the canvas size is changing by one pixel.
To support this functionality, we also have to read out the exact
webkit version from the user agent in the render engine detection code
in include/util.js.
- Make sure that canvas exists (i.e. didn't throw an error) before
trying to call canvas method get_canvas_uri.
- Typos in HTML render engine debug output.
- Split out ClientInitialisation state.
- In version 3.3 and 3.7, when the server has no auth (scheme
1), then we should skip from Authentication to ClientInitialisation.
- rQwait checks the receive queue to see if there is enough data to
satisfy the following request. If not it returns true (which is
almost always translated into an immediate return false by the
caller).
- rQwait is called quite a bit and this generally allows 4 lines to
become 1 line where it is called.
- rQwait allows simplification of cuttext processing. No global
tracking needed anymore.
Overall, about 60 lines less code.
DES is just used once during authentication and is not performance
sensitive so we save some space by generating and/or removing some
lookup tables. Also, shorten some very frequently used variables.
Shaves off about 100 lines.
- util.js that contains essential functions
- webutils.js that contains the GUI utility function.js
this helps to include noVNC in other project, especially Cappuccino Application
i
The decrypt functionality is never used so remove it. Also, we can
assume that we are always DES encrypting 16 characters which allows
several things to be simplified in DES.
Overall this removes about 80 lines of code.
- include/rfb.js: Keep track of the number of rects of each encoding
type and print them out when we close a connection (if 'info'
logging level).
- tests/vnc_perf.html: first pass at a noVNC based performance
benchmark.
- utils/wsproxy.py: Fix the output of the record filename.
- include/util.js: Add type and desc field to conf_default routine.
Make comment descriptions of settings into desc parameters that can
be queried. Also, use set_FOO in conf_default to set or coerce the
current setting so that we always have the right type for the value.
- include/rfb.js, include/default_config.js: add connectTimeout
setting to address situations with slow connections that may need
more than 2 seconds.
Yet another weird VNC server behavior: sending a failure and length
before the reason message. To calculated the length, the reason string
is already available, why not just send everything as one packet. Oh
well.
- include/canvas.js: When 'debug' logging, show browser detection
values.
- test/canvas.html: Only restore the canvas to it's starting state if
the logging level is not 'debug'.
- wsproxy.py: Append the session number to the record filename so that
multiple sessions don't stomp on each other.