Merge ddc634fff8 into 832c744578
This commit is contained in:
commit
83a86dfa28
|
|
@ -23,7 +23,7 @@ var that = {}, // Public API methods
|
|||
|
||||
// Predefine function variables (jslint)
|
||||
imageDataCreate, imageDataGet, rgbxImageData, cmapImageData,
|
||||
rgbxImageFill, cmapImageFill, setFillColor, rescale, flush,
|
||||
rgbxImageFill, cmapImageFill, setFillColor, rescale, rescaleAuto, flush,
|
||||
|
||||
// The full frame buffer (logical canvas) size
|
||||
fb_width = 0,
|
||||
|
|
@ -232,13 +232,52 @@ rescale = function(factor) {
|
|||
|
||||
if (conf.scale === factor) {
|
||||
//Util.Debug("Display already scaled to '" + factor + "'");
|
||||
UI.message("Display already scaled to '" + factor + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
conf.scale = factor;
|
||||
x = c.width - c.width * factor;
|
||||
y = c.height - c.height * factor;
|
||||
c.style[tp] = "scale(" + conf.scale + ") translate(-" + x + "px, -" + y + "px)";
|
||||
UI.message("scale: "+conf.scale+", x: "+x+", y: "+y);
|
||||
};
|
||||
|
||||
rescaleAuto = function() {
|
||||
var c, tp, x, y, xFactor, yFactor, factor,
|
||||
properties = ['transform', 'WebkitTransform', 'MozTransform', null];
|
||||
|
||||
c = conf.target;
|
||||
tp = properties.shift();
|
||||
while (tp) {
|
||||
if (typeof c.style[tp] !== 'undefined') {
|
||||
break;
|
||||
}
|
||||
tp = properties.shift();
|
||||
}
|
||||
|
||||
if (tp === null) {
|
||||
Util.Debug("No scaling support");
|
||||
return;
|
||||
}
|
||||
|
||||
xFactor=viewport.w/fb_width;
|
||||
yFactor=viewport.h/fb_height;
|
||||
UI.message("xFactor: "+xFactor+", yFactor: "+yFactor+", viewport.h: "+viewport.h+", fb_height: "+fb_height);
|
||||
|
||||
if (xFactor > 1.0) {xFactor = 1.0;}
|
||||
else if (xFactor < 0.1) {xFactor = 0.1;}
|
||||
|
||||
if (yFactor > 1.0) {yFactor = 1.0;}
|
||||
else if (yFactor < 0.1) {yFactor = 0.1;}
|
||||
|
||||
/* Rescale screen to whichever factor that is smaller (so we get to see the whole screen). */
|
||||
factor=xFactor<yFactor?xFactor:yFactor;
|
||||
factor-=0.01;
|
||||
|
||||
c.style[tp] = "scale(" + factor + ")";
|
||||
c.style[tp+'Origin'] = "top left";
|
||||
|
||||
UI.rfb.get_mouse().set_scale(factor);
|
||||
};
|
||||
|
||||
that.viewportChange = function(deltaX, deltaY, width, height) {
|
||||
|
|
@ -439,7 +478,6 @@ setFillColor = function(color) {
|
|||
//
|
||||
// Public API interface functions
|
||||
//
|
||||
|
||||
that.resize = function(width, height) {
|
||||
c_prevStyle = "";
|
||||
|
||||
|
|
@ -450,8 +488,65 @@ that.resize = function(width, height) {
|
|||
that.viewportChange();
|
||||
};
|
||||
|
||||
that.clear = function() {
|
||||
that.resizeAuto = function(canvas) {
|
||||
var c=canvas;
|
||||
var v = viewport,
|
||||
cw=window.innerWidth,
|
||||
ch=window.innerHeight;
|
||||
|
||||
UI.message("container: " + cw + "," + ch);
|
||||
|
||||
if (cw > fb_width) {
|
||||
cw = fb_width;
|
||||
}
|
||||
if (ch > fb_height) {
|
||||
ch = fb_height;
|
||||
}
|
||||
if ((cw !== v.w) || (ch !== v.h)) {
|
||||
v.w = cw;
|
||||
v.h = ch;
|
||||
UI.message("new viewport: " + v.w + "," + v.h);
|
||||
|
||||
c = conf.target;
|
||||
c.width = v.w;
|
||||
c.height = v.h;
|
||||
|
||||
rescaleAuto();
|
||||
that.refresh();
|
||||
}
|
||||
UI.message("framebuffer: "+fb_width+","+fb_height+"; viewport: "+v.w+","+v.h);
|
||||
};
|
||||
|
||||
/* Test graphics (repeating pattern). */
|
||||
that.drawArea = function(x, y, w, h) {
|
||||
UI.message("draw "+x+","+y+" ("+w+","+h+")");
|
||||
var imgData = ctx.createImageData(w, h),
|
||||
data = imgData.data, pixel, realX, realY;
|
||||
|
||||
for (var i = 0; i < w; i++) {
|
||||
realX = viewport.x + x + i;
|
||||
for (var j = 0; j < h; j++) {
|
||||
realY = viewport.y + y + j;
|
||||
pixel = (j * w * 4 + i * 4);
|
||||
data[pixel + 0] = ((realX * realY) / 13) % 256;
|
||||
data[pixel + 1] = ((realX * realY) + 392) % 256;
|
||||
data[pixel + 2] = ((realX + realY) + 256) % 256;
|
||||
data[pixel + 3] = 255;
|
||||
}
|
||||
}
|
||||
//UI.message("i: " + i + ", j: " + j + ", pixel: " + pixel);
|
||||
ctx.putImageData(imgData, x, y);
|
||||
};
|
||||
|
||||
/* Screen refresh. */
|
||||
that.refresh = function() {
|
||||
if (UI.rfb) {UI.rfb.refresh();}
|
||||
|
||||
UI.message('screen refreshed.');
|
||||
Util.Debug('screen refreshed.');
|
||||
};
|
||||
|
||||
that.clear = function() {
|
||||
if (conf.logo) {
|
||||
that.resize(conf.logo.width, conf.logo.height);
|
||||
that.viewportChange(0, 0, conf.logo.width, conf.logo.height);
|
||||
|
|
|
|||
|
|
@ -80,10 +80,11 @@
|
|||
}
|
||||
|
||||
/* Do not set width/height for VNC_screen or VNC_canvas or incorrect
|
||||
* scaling will occur. Canvas resizes to remote VNC settings */
|
||||
* scaling will occur. Canvas resizes to client browser size (viewport). */
|
||||
#VNC_screen {
|
||||
text-align: center;
|
||||
display: table;
|
||||
/* display: table; */
|
||||
display: block;
|
||||
}
|
||||
#VNC_canvas {
|
||||
background: #eee;
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ Util.conf_defaults(conf, that, defaults, [
|
|||
|
||||
['connectTimeout', 'rw', 'int', def_con_timeout, 'Time (s) to wait for connection'],
|
||||
['disconnectTimeout', 'rw', 'int', 3, 'Time (s) to wait for disconnection'],
|
||||
['refreshTimeout', 'rw', 'int', 2, 'Time (s) to wait for a refresh'],
|
||||
|
||||
['check_rate', 'rw', 'int', 217, 'Timing (ms) of send/receive check'],
|
||||
['fbu_req_rate', 'rw', 'int', 1413, 'Timing (ms) of frameBufferUpdate requests'],
|
||||
|
|
@ -428,7 +429,6 @@ updateState = function(state, statusMsg) {
|
|||
|
||||
|
||||
case 'connect':
|
||||
|
||||
connTimer = setTimeout(function () {
|
||||
fail("Connect timeout");
|
||||
}, conf.connectTimeout * 1000);
|
||||
|
|
@ -441,7 +441,8 @@ updateState = function(state, statusMsg) {
|
|||
|
||||
|
||||
case 'disconnect':
|
||||
|
||||
rfb_password='';
|
||||
|
||||
if (! test_mode) {
|
||||
disconnTimer = setTimeout(function () {
|
||||
fail("Disconnect timeout");
|
||||
|
|
@ -449,7 +450,8 @@ updateState = function(state, statusMsg) {
|
|||
}
|
||||
|
||||
print_stats();
|
||||
|
||||
display.clear();
|
||||
|
||||
// WebSocket.onclose transitions to 'disconnected'
|
||||
break;
|
||||
|
||||
|
|
@ -1527,6 +1529,17 @@ that.sendPassword = function(passwd) {
|
|||
setTimeout(init_msg, 1);
|
||||
};
|
||||
|
||||
that.refresh = function() {
|
||||
// Refresh only when already connected, i.e. don't refresh during disconnected or loaded states.
|
||||
if (rfb_state!='loaded' && rfb_password.length>0) {
|
||||
updateState('connect','refreshing...');
|
||||
setTimeout(function () {
|
||||
if (rfb_state!=='normal') {that.refresh();}
|
||||
}, conf.refreshTimeout * 1000);
|
||||
}
|
||||
UI.message('state: '+rfb_state);
|
||||
};
|
||||
|
||||
that.sendCtrlAltDel = function() {
|
||||
if (rfb_state !== "normal") { return false; }
|
||||
Util.Info("Sending Ctrl-Alt-Del");
|
||||
|
|
|
|||
142
include/ui.js
142
include/ui.js
|
|
@ -10,13 +10,31 @@
|
|||
/*jslint white: false, browser: true */
|
||||
/*global window, $D, Util, WebUtil, RFB, Display */
|
||||
|
||||
var msg_cnt = 0, iterations,
|
||||
//fb_width = 800,
|
||||
//fb_height = 768,
|
||||
fb_width=1920,
|
||||
fb_height=1200,
|
||||
viewport = {'x': 0, 'y': 0, 'w' : 0, 'h' : 0 },
|
||||
cleanRect = {},
|
||||
penDown = false, doMove = false,
|
||||
inMove = false, lastPos = {},
|
||||
canvas, ctx, keyboard, mouse;
|
||||
|
||||
var newline = "\n";
|
||||
|
||||
|
||||
var UI = {
|
||||
|
||||
settingsOpen : false,
|
||||
|
||||
// Render default UI and initialize settings menu
|
||||
load: function(target) {
|
||||
var html = '', i, sheet, sheets, llevels;
|
||||
if (Util.Engine.trident) {
|
||||
var newline = "<br>\n";
|
||||
}
|
||||
|
||||
var html = '', i, val, sheet, sheets, llevels;
|
||||
|
||||
/* Populate the 'target' DOM element with default UI */
|
||||
if (!target) {
|
||||
|
|
@ -39,17 +57,18 @@ load: function(target) {
|
|||
target.innerHTML = html;
|
||||
return;
|
||||
}
|
||||
|
||||
html += '<div id="VNC_controls">';
|
||||
html += ' <ul>';
|
||||
html += ' <li>Host: <input id="VNC_host"></li>';
|
||||
html += ' <li>Port: <input id="VNC_port"></li>';
|
||||
html += ' <li>Password: <input id="VNC_password"';
|
||||
html += ' type="password"></li>';
|
||||
html += ' <li><input id="VNC_connect_button" type="button"';
|
||||
html += ' value="Loading" disabled></li>';
|
||||
html += ' </ul>';
|
||||
html += '</div>';
|
||||
|
||||
html+='<table border="0"><tr>';
|
||||
html+=' <td width="150pt">Host: <input id="VNC_host"/></td>';
|
||||
html+=' <td width="100pt">Port: <input id="VNC_port"/></td>';
|
||||
html+=' <td><div id="VNC_passwdField">';
|
||||
html+=' <form onsubmit="return UI.connect();">';
|
||||
html+=' Password: <input id="VNC_password" type="password"/>';
|
||||
html+=' </form>';
|
||||
html+=' <input id="VNC_connect_button" type="button"/>';
|
||||
html+=' </div></td>';
|
||||
html+='</tr></table>';
|
||||
|
||||
html += '<div id="VNC_screen">';
|
||||
html += ' <div id="VNC_status_bar" class="VNC_status_bar" style="margin-top: 0px;">';
|
||||
html += ' <table border=0 width=100%><tr>';
|
||||
|
|
@ -86,7 +105,15 @@ load: function(target) {
|
|||
html += ' <li><input id="VNC_connectTimeout"';
|
||||
html += ' type="input"> Connect Timeout (s)</li>';
|
||||
html += ' <hr>';
|
||||
|
||||
|
||||
// Scale selection dropdown
|
||||
html += ' <li><select id="VNC_scale">';
|
||||
for (i = 10; i >= 1; i -= 1) {
|
||||
val = (i/10).toFixed(1);
|
||||
html += '<option value="' + val + '">' + val + '</option>';
|
||||
}
|
||||
html += ' </select> Scale</li>';
|
||||
|
||||
// Stylesheet selection dropdown
|
||||
html += ' <li><select id="VNC_stylesheet" name="vncStyle">';
|
||||
html += ' <option value="default">default</option>';
|
||||
|
|
@ -140,6 +167,7 @@ load: function(target) {
|
|||
// Settings with immediate effects
|
||||
UI.initSetting('logging', 'warn');
|
||||
WebUtil.init_logging(UI.getSetting('logging'));
|
||||
UI.initSetting('scale', 1.0);
|
||||
UI.initSetting('stylesheet', 'default');
|
||||
|
||||
WebUtil.selectStylesheet(null); // call twice to get around webkit bug
|
||||
|
|
@ -149,6 +177,7 @@ load: function(target) {
|
|||
UI.initSetting('host', '');
|
||||
UI.initSetting('port', '');
|
||||
UI.initSetting('password', '');
|
||||
//TODO: Dynamically detect URI to determine encryption mode.
|
||||
UI.initSetting('encrypt', false);
|
||||
UI.initSetting('true_color', true);
|
||||
UI.initSetting('cursor', false);
|
||||
|
|
@ -158,7 +187,7 @@ load: function(target) {
|
|||
UI.rfb = RFB({'target': $D('VNC_canvas'),
|
||||
'onUpdateState': UI.updateState,
|
||||
'onClipboard': UI.clipReceive});
|
||||
|
||||
|
||||
// Unfocus clipboard when over the VNC area
|
||||
$D('VNC_screen').onmousemove = function () {
|
||||
var keyboard = UI.rfb.get_keyboard();
|
||||
|
|
@ -172,7 +201,9 @@ load: function(target) {
|
|||
$D('VNC_mouse_buttons').style.display = "inline";
|
||||
UI.setMouseButton();
|
||||
}
|
||||
|
||||
|
||||
ctx=UI.rfb.get_display().get_context();
|
||||
UI.rfb.get_display().resizeAuto(target);
|
||||
},
|
||||
|
||||
// Read form control compatible setting from cookie
|
||||
|
|
@ -264,6 +295,7 @@ clickSettingsMenu: function() {
|
|||
UI.updateSetting('shared');
|
||||
UI.updateSetting('connectTimeout');
|
||||
UI.updateSetting('stylesheet');
|
||||
UI.updateSetting('scale');
|
||||
UI.updateSetting('logging');
|
||||
|
||||
UI.openSettingsMenu();
|
||||
|
|
@ -300,6 +332,7 @@ settingsDisabled: function(disabled, rfb) {
|
|||
|
||||
// Save/apply settings when 'Apply' button is pressed
|
||||
settingsApply: function() {
|
||||
var scale = UI.getSetting('scale');
|
||||
//Util.Debug(">> settingsApply");
|
||||
UI.saveSetting('encrypt');
|
||||
UI.saveSetting('true_color');
|
||||
|
|
@ -308,18 +341,24 @@ settingsApply: function() {
|
|||
}
|
||||
UI.saveSetting('shared');
|
||||
UI.saveSetting('connectTimeout');
|
||||
UI.saveSetting('scale');
|
||||
UI.saveSetting('stylesheet');
|
||||
UI.saveSetting('logging');
|
||||
|
||||
// Settings with immediate (non-connected related) effect
|
||||
if (UI.rfb) {
|
||||
//Util.Debug("scale: " + scale);
|
||||
UI.rfb.get_display().set_scale(UI.getSetting('scale'));
|
||||
UI.rfb.get_mouse().set_scale(UI.getSetting('scale'));
|
||||
//UI.rfb.get_display().resize();
|
||||
UI.rfb.get_display().resizeAuto($D('vnc'));
|
||||
}
|
||||
WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
|
||||
WebUtil.init_logging(UI.getSetting('logging'));
|
||||
|
||||
//Util.Debug("<< settingsApply");
|
||||
},
|
||||
|
||||
|
||||
|
||||
setPassword: function() {
|
||||
UI.rfb.sendPassword($D('VNC_password').value);
|
||||
return false;
|
||||
|
|
@ -359,22 +398,25 @@ setMouseButton: function(num) {
|
|||
},
|
||||
|
||||
updateState: function(rfb, state, oldstate, msg) {
|
||||
var s, sb, c, cad, klass;
|
||||
//var link, host, port, password;
|
||||
var html, s, sb, cad, klass;
|
||||
s = $D('VNC_status');
|
||||
sb = $D('VNC_status_bar');
|
||||
c = $D('VNC_connect_button');
|
||||
cad = $D('sendCtrlAltDelButton');
|
||||
|
||||
switch (state) {
|
||||
case 'failed':
|
||||
case 'fatal':
|
||||
c.disabled = true;
|
||||
cad.disabled = true;
|
||||
UI.settingsDisabled(true, rfb);
|
||||
klass = "VNC_status_error";
|
||||
break;
|
||||
case 'normal':
|
||||
c.value = "Disconnect";
|
||||
c.onclick = UI.disconnect;
|
||||
$D('VNC_passwdField').innerHTML='<input id="VNC_connect_button" type="button"/>';
|
||||
var c=$D('VNC_connect_button');
|
||||
|
||||
c.value="Disconnect";
|
||||
c.onclick=UI.disconnect;
|
||||
c.disabled = false;
|
||||
cad.disabled = false;
|
||||
UI.settingsDisabled(true, rfb);
|
||||
|
|
@ -382,25 +424,21 @@ updateState: function(rfb, state, oldstate, msg) {
|
|||
break;
|
||||
case 'disconnected':
|
||||
case 'loaded':
|
||||
c.value = "Connect";
|
||||
c.onclick = UI.connect;
|
||||
|
||||
c.disabled = false;
|
||||
html='<form onsubmit="return UI.connect();">';
|
||||
html+=' Password: <input id="VNC_password" type="password"/>';
|
||||
html+='</form>';
|
||||
$D('VNC_passwdField').innerHTML=html;
|
||||
|
||||
cad.disabled = true;
|
||||
UI.settingsDisabled(false, rfb);
|
||||
klass = "VNC_status_normal";
|
||||
break;
|
||||
case 'password':
|
||||
c.value = "Send Password";
|
||||
c.onclick = UI.setPassword;
|
||||
|
||||
c.disabled = false;
|
||||
cad.disabled = true;
|
||||
UI.settingsDisabled(true, rfb);
|
||||
klass = "VNC_status_warn";
|
||||
break;
|
||||
default:
|
||||
c.disabled = true;
|
||||
cad.disabled = true;
|
||||
UI.settingsDisabled(true, rfb);
|
||||
klass = "VNC_status_warn";
|
||||
|
|
@ -412,21 +450,42 @@ updateState: function(rfb, state, oldstate, msg) {
|
|||
sb.setAttribute("class", klass);
|
||||
s.innerHTML = msg;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/* updateState: function(rfb, state, oldstate, msg) {
|
||||
var link, s, sb, cad, level;
|
||||
s = $D('VNC_status');
|
||||
sb = $D('VNC_status_bar');
|
||||
cad = $D('sendCtrlAltDelButton');
|
||||
switch (state) {
|
||||
case 'failed': level = "error"; break;
|
||||
case 'fatal': level = "error"; break;
|
||||
case 'normal': level = "normal"; break;
|
||||
case 'disconnected': level = "normal"; break;
|
||||
case 'loaded': level = "normal"; break;
|
||||
default: level = "warn"; break;
|
||||
}
|
||||
|
||||
if (state === "normal") { cad.disabled = false; }
|
||||
else { cad.disabled = true; }
|
||||
|
||||
if (typeof(msg) !== 'undefined') {
|
||||
sb.setAttribute("class", "VNC_status_" + level);
|
||||
s.innerHTML = msg;
|
||||
}
|
||||
}, */
|
||||
|
||||
clipReceive: function(rfb, text) {
|
||||
Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "...");
|
||||
$D('VNC_clipboard_text').value = text;
|
||||
Util.Debug("<< UI.clipReceive");
|
||||
},
|
||||
|
||||
|
||||
connect: function() {
|
||||
var host, port, password;
|
||||
|
||||
UI.closeSettingsMenu();
|
||||
|
||||
|
||||
host = $D('VNC_host').value;
|
||||
port = $D('VNC_port').value;
|
||||
password = $D('VNC_password').value;
|
||||
|
|
@ -439,13 +498,14 @@ connect: function() {
|
|||
UI.rfb.set_local_cursor(UI.getSetting('cursor'));
|
||||
UI.rfb.set_shared(UI.getSetting('shared'));
|
||||
UI.rfb.set_connectTimeout(UI.getSetting('connectTimeout'));
|
||||
|
||||
|
||||
UI.rfb.connect(host, port, password);
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
disconnect: function() {
|
||||
UI.closeSettingsMenu();
|
||||
|
||||
UI.rfb.disconnect();
|
||||
},
|
||||
|
||||
|
|
@ -469,6 +529,14 @@ clipSend: function() {
|
|||
Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "...");
|
||||
UI.rfb.clipboardPasteFrom(text);
|
||||
Util.Debug("<< UI.clipSend");
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
message: function(str) {
|
||||
console.log(str);
|
||||
var cell = $D('messages');
|
||||
cell.innerHTML += msg_cnt + ": " + str + newline;
|
||||
cell.scrollTop = cell.scrollHeight;
|
||||
msg_cnt++;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
15
vnc.html
15
vnc.html
|
|
@ -8,6 +8,7 @@
|
|||
<head>
|
||||
<title>noVNC</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<link rel="stylesheet" href="../include/mobile.css">
|
||||
<link rel="stylesheet" href="include/plain.css">
|
||||
<link rel="alternate stylesheet" href="include/black.css" TITLE="Black">
|
||||
<!--
|
||||
|
|
@ -19,13 +20,17 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<div id='vnc'>Loading</div>
|
||||
<div id="vnc" class="flex-box">Loading...</div>
|
||||
<div>
|
||||
<br>
|
||||
Log:<br>
|
||||
<textarea id="messages" font="9pt" cols=80 rows=8></textarea>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function () {
|
||||
UI.load('vnc');
|
||||
};
|
||||
//window.onresize=function() {UI.rfb.get_display().resize(); UI.rfb.get_display().refresh();};
|
||||
window.onresize=function() {UI.rfb.get_display().resizeAuto($D('vnc'));};
|
||||
window.onload=function() {UI.load('vnc');};
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue