Merge pull request #2 from DomenGaber/display-mouse-position
Add info panel
This commit is contained in:
commit
b5b0500d4f
|
|
@ -847,7 +847,7 @@ select:active {
|
|||
|
||||
/* Main container */
|
||||
#noVNC_container {
|
||||
width: 100%;
|
||||
width: 80%;
|
||||
height: 100%;
|
||||
background-color: #313131;
|
||||
border-bottom-right-radius: 800px 600px;
|
||||
|
|
@ -866,6 +866,65 @@ select:active {
|
|||
ime-mode: disabled;
|
||||
}
|
||||
|
||||
#noVNC_info_panel {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 0 20px;
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.noVNC_info_item {
|
||||
width: 100%;
|
||||
padding: 20px 0;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, .15);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.noVNC_info_item_label {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
color: rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
.noVNC_info_item button {
|
||||
display: inline-block;
|
||||
padding: 4px 4px;
|
||||
margin: 10px 5px 20px 0;
|
||||
vertical-align: middle;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
#noVNC_mouse_coordinates,
|
||||
#noVNC_click_stack {
|
||||
width: 100%;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#noVNC_mouse_coordinates {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#noVNC_click_stack {
|
||||
text-align: left;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
height: 400px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/*Default noVNC logo.*/
|
||||
/* From: http://fonts.googleapis.com/css?family=Orbitron:700 */
|
||||
@font-face {
|
||||
|
|
|
|||
88
app/ui.js
88
app/ui.js
|
|
@ -37,6 +37,8 @@ const UI = {
|
|||
lastKeyboardinput: null,
|
||||
defaultKeyboardinputLen: 100,
|
||||
|
||||
canvasInteractionEvents: Array(),
|
||||
|
||||
inhibit_reconnect: true,
|
||||
reconnect_callback: null,
|
||||
reconnect_password: null,
|
||||
|
|
@ -165,6 +167,7 @@ const UI = {
|
|||
UI.initSetting('view_only', false);
|
||||
UI.initSetting('img_bgrx_mode', false);
|
||||
UI.initSetting('show_dot', false);
|
||||
UI.initSetting('show_pointer', false);
|
||||
UI.initSetting('path', 'websockify');
|
||||
UI.initSetting('repeaterID', '');
|
||||
UI.initSetting('reconnect', false);
|
||||
|
|
@ -357,6 +360,8 @@ const UI = {
|
|||
UI.addSettingChangeHandler('img_bgrx_mode', UI.applyBGRXMode);
|
||||
UI.addSettingChangeHandler('show_dot');
|
||||
UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor);
|
||||
UI.addSettingChangeHandler('show_pointer');
|
||||
UI.addSettingChangeHandler('show_pointer', UI.updateShowPointerCursor);
|
||||
UI.addSettingChangeHandler('host');
|
||||
UI.addSettingChangeHandler('port');
|
||||
UI.addSettingChangeHandler('path');
|
||||
|
|
@ -707,6 +712,79 @@ const UI = {
|
|||
}
|
||||
},
|
||||
|
||||
trackMouse() {
|
||||
UI.rfb.canvas.addEventListener('mousemove', function(e) {
|
||||
let scaleRatioX = UI.rfb.canvas.width / UI.rfb.canvas.clientWidth;
|
||||
let scaleRatioY = UI.rfb.canvas.height / UI.rfb.canvas.clientHeight;
|
||||
let x = Math.floor(e.offsetX * scaleRatioX);
|
||||
let y = Math.floor(e.offsetY * scaleRatioY);
|
||||
document.getElementById('noVNC_mouse_coordinates').innerHTML = "(" + x + ", " + y + ")"
|
||||
});
|
||||
},
|
||||
|
||||
trackClicks() {
|
||||
document.getElementById('noVNC_click_stack_copy').addEventListener('click', function() {
|
||||
let text = JSON.stringify(UI.canvasInteractionEvents);
|
||||
if (!navigator.clipboard) {
|
||||
var textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
textArea.style.position="fixed"; //avoid scrolling to bottom
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
var successful = document.execCommand('copy');
|
||||
var msg = successful ? 'successful' : 'unsuccessful';
|
||||
console.log('Fallback: Copying text command was ' + msg);
|
||||
} catch (err) {
|
||||
console.error('Fallback: Oops, unable to copy', err);
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
return;
|
||||
}
|
||||
navigator.clipboard.writeText(text).then(function() {
|
||||
console.log('Async: Copying to clipboard was successful!');
|
||||
}, function(err) {
|
||||
console.error('Async: Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('noVNC_click_stack_clear').addEventListener('click', function() {
|
||||
UI.canvasInteractionEvents = Array();
|
||||
UI.updateInteractionStackUI();
|
||||
});
|
||||
|
||||
UI.rfb.canvas.addEventListener('mouseup', function(e) {
|
||||
let scaleRatioX = UI.rfb.canvas.width / UI.rfb.canvas.clientWidth;
|
||||
let scaleRatioY = UI.rfb.canvas.height / UI.rfb.canvas.clientHeight;
|
||||
let x = Math.floor(e.offsetX * scaleRatioX);
|
||||
let y = Math.floor(e.offsetY * scaleRatioY);
|
||||
UI.canvasInteractionEvents.push({name: e.type, x: x, y: y})
|
||||
UI.updateInteractionStackUI();
|
||||
});
|
||||
},
|
||||
|
||||
attachDownloadScreenshotButton() {
|
||||
document.getElementById('noVNC_download_screenshot').addEventListener('click', function() {
|
||||
let link = document.createElement('a');
|
||||
link.download = 'screenshot.png';
|
||||
link.href = UI.rfb.canvas.toDataURL("image/png");
|
||||
link.click();
|
||||
});
|
||||
},
|
||||
|
||||
updateInteractionStackUI() {
|
||||
document.getElementById('noVNC_click_stack').innerHTML = '';
|
||||
for (var i = 0; i < UI.canvasInteractionEvents.length; i++) {
|
||||
let e = UI.canvasInteractionEvents[i];
|
||||
let el = document.createElement('li');
|
||||
el.innerText = e.name + ' at (' + e.x + ', ' + e.y + ')';
|
||||
document.getElementById('noVNC_click_stack').append(el);
|
||||
}
|
||||
},
|
||||
|
||||
/* ------^-------
|
||||
* /VISUAL
|
||||
* ==============
|
||||
|
|
@ -1035,6 +1113,11 @@ const UI = {
|
|||
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
|
||||
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
|
||||
UI.rfb.showDotCursor = UI.getSetting('show_dot');
|
||||
UI.rfb.showPointerCursor = UI.getSetting('show_pointer');
|
||||
|
||||
UI.trackMouse();
|
||||
UI.trackClicks();
|
||||
UI.attachDownloadScreenshotButton();
|
||||
|
||||
UI.updateViewOnly(); // requires UI.rfb
|
||||
},
|
||||
|
|
@ -1653,6 +1736,11 @@ const UI = {
|
|||
UI.rfb.showDotCursor = UI.getSetting('show_dot');
|
||||
},
|
||||
|
||||
updateShowPointerCursor() {
|
||||
if (!UI.rfb) return;
|
||||
UI.rfb.showPointerCursor = UI.getSetting('show_pointer');
|
||||
},
|
||||
|
||||
updateLogging() {
|
||||
WebUtil.init_logging(UI.getSetting('logging'));
|
||||
},
|
||||
|
|
|
|||
27
core/rfb.js
27
core/rfb.js
|
|
@ -251,6 +251,10 @@ export default class RFB extends EventTargetMixin {
|
|||
Log.Warn("Specifying showDotCursor as a RFB constructor argument is deprecated");
|
||||
this._showDotCursor = options.showDotCursor;
|
||||
}
|
||||
this._showPointerCursor = false;
|
||||
if (options.showPointerCursor !== undefined) {
|
||||
this._showPointerCursor = options.showPointerCursor;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== PROPERTIES =====
|
||||
|
|
@ -271,6 +275,8 @@ export default class RFB extends EventTargetMixin {
|
|||
}
|
||||
}
|
||||
|
||||
get canvas() { return this._canvas; }
|
||||
|
||||
get capabilities() { return this._capabilities; }
|
||||
|
||||
get touchButton() { return this._mouse.touchButton; }
|
||||
|
|
@ -313,6 +319,12 @@ export default class RFB extends EventTargetMixin {
|
|||
this._refreshCursor();
|
||||
}
|
||||
|
||||
get showPointerCursor() { return this._showPointerCursor; }
|
||||
set showPointerCursor(show) {
|
||||
this._showPointerCursor = show;
|
||||
this._refreshCursor();
|
||||
}
|
||||
|
||||
get background() { return this._screen.style.background; }
|
||||
set background(cssValue) { this._screen.style.background = cssValue; }
|
||||
|
||||
|
|
@ -1882,11 +1894,16 @@ export default class RFB extends EventTargetMixin {
|
|||
this._rfb_connection_state !== "connected") {
|
||||
return;
|
||||
}
|
||||
const image = this._shouldShowDotCursor() ? RFB.cursors.dot : this._cursorImage;
|
||||
this._cursor.change(image.rgbaPixels,
|
||||
image.hotx, image.hoty,
|
||||
image.w, image.h
|
||||
);
|
||||
|
||||
if (this._showPointerCursor) {
|
||||
this._cursor.changeToDefaultCursor();
|
||||
} else {
|
||||
const image = this._shouldShowDotCursor() ? RFB.cursors.dot : this._cursorImage;
|
||||
this._cursor.change(image.rgbaPixels,
|
||||
image.hotx, image.hoty,
|
||||
image.w, image.h
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static genDES(password, challenge) {
|
||||
|
|
|
|||
|
|
@ -121,6 +121,10 @@ export default class Cursor {
|
|||
}
|
||||
}
|
||||
|
||||
changeToDefaultCursor() {
|
||||
this._target.style.cursor = 'default';
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._target.style.cursor = 'none';
|
||||
this._canvas.width = 0;
|
||||
|
|
|
|||
25
vnc.html
25
vnc.html
|
|
@ -16,7 +16,7 @@
|
|||
<title>noVNC</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
|
||||
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
|
||||
Remove this if you use the .htaccess -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
|
@ -243,6 +243,9 @@
|
|||
<input id="noVNC_setting_reconnect_delay" type="number">
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_show_pointer" type="checkbox"> Show Default when No Cursor</label>
|
||||
</li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No Cursor</label>
|
||||
</li>
|
||||
|
|
@ -328,6 +331,26 @@
|
|||
autocomplete="off" spellcheck="false" tabindex="-1"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="noVNC_info_panel">
|
||||
<div class="noVNC_info_item">
|
||||
<span class="noVNC_info_item_label">Mouse coordinates</span>
|
||||
<div id="noVNC_mouse_coordinates">
|
||||
(0, 0)
|
||||
</div>
|
||||
</div>
|
||||
<div class="noVNC_info_item">
|
||||
<span class="noVNC_info_item_label">Screenshot</span>
|
||||
<button id="noVNC_download_screenshot">Download screenshot</button>
|
||||
</div>
|
||||
<div class="noVNC_info_item">
|
||||
<span class="noVNC_info_item_label">Interaction stack</span>
|
||||
<button id="noVNC_click_stack_copy">Copy stack to clipboard</button>
|
||||
<button id="noVNC_click_stack_clear">Clear stack</button>
|
||||
<ol id="noVNC_click_stack">
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<audio id="noVNC_bell">
|
||||
<source src="app/sounds/bell.oga" type="audio/ogg">
|
||||
<source src="app/sounds/bell.mp3" type="audio/mpeg">
|
||||
|
|
|
|||
Loading…
Reference in New Issue