VNC-127 Refactor and clean up UI, keyboard, and rendering logic

This commit is contained in:
El 2025-05-13 17:08:35 +05:00
parent 14c8c2af59
commit 67e5541c26
No known key found for this signature in database
GPG Key ID: EB3F4C9EA29CDE59
3 changed files with 57 additions and 61 deletions

View File

@ -655,17 +655,14 @@ const UI = {
* ------v------*/ * ------v------*/
// Ignore clicks that are propogated from child elements in sub panels // Ignore clicks that are propogated from child elements in sub panels
isControlPanelItemClick(e) { isControlPanelItemClick(e) {
if (!(e && e.target && e.target.classList && e.target.parentNode && return e && e.target && e.target.classList && e.target.parentNode &&
( (
e.target.classList.contains('noVNC_button') && e.target.parentNode.id !== 'noVNC_modifiers' || e.target.classList.contains('noVNC_button') && e.target.parentNode.id !== 'noVNC_modifiers' ||
e.target.classList.contains('noVNC_button_div') || e.target.classList.contains('noVNC_button_div') ||
e.target.classList.contains('noVNC_heading') e.target.classList.contains('noVNC_heading')
) );
)) {
return false;
}
return true;
}, },
// Disable/enable controls depending on connection state // Disable/enable controls depending on connection state
@ -741,19 +738,24 @@ const UI = {
showStats() { showStats() {
UI.saveSetting('enable_perf_stats'); UI.saveSetting('enable_perf_stats');
let enable_stats = UI.getSetting('enable_perf_stats'); const element = document.getElementById("noVNC_connection_stats");
if (enable_stats === true && UI.statsInterval == undefined) { const statusElem = document.getElementById('noVNC_status');
document.getElementById("noVNC_connection_stats").style.visibility = "visible"; const enable_stats = UI.getSetting('enable_perf_stats');
UI.statsInterval = setInterval(function() { if (enable_stats === true) {
if (UI.statsInterval !== undefined) {
clearInterval(UI.statsInterval);
}
element.style.visibility = "visible";
UI.statsInterval = setInterval(function () {
if (UI.rfb !== undefined) { if (UI.rfb !== undefined) {
UI.rfb.requestBottleneckStats(); UI.rfb.requestBottleneckStats();
} }
} , 5000); }, 5000);
} else { } else {
document.getElementById("noVNC_connection_stats").style.visibility = "hidden"; element.style.visibility = "hidden";
UI.statsInterval = null; clearInterval(UI.statsInterval);
UI.statsInterval = undefined;
} }
}, },
threading() { threading() {
@ -1681,6 +1683,8 @@ const UI = {
UI.forceReconnect = false; UI.forceReconnect = false;
UI.connect(null, UI.reconnectPassword); UI.connect(null, UI.reconnectPassword);
} }
UI.showStats();
}, },
securityFailed(e) { securityFailed(e) {
@ -2623,11 +2627,7 @@ const UI = {
toggleIMEMode() { toggleIMEMode() {
if (UI.rfb) { if (UI.rfb) {
if (UI.getSetting('enable_ime')) { UI.rfb.keyboard.enableIME = !!UI.getSetting('enable_ime');
UI.rfb.keyboard.enableIME = true;
} else {
UI.rfb.keyboard.enableIME = false;
}
} }
}, },
@ -2638,22 +2638,14 @@ const UI = {
return; return;
} }
if (UI.getSetting('enable_webrtc')) { UI.rfb.enableWebRTC = !!UI.getSetting('enable_webrtc');
UI.rfb.enableWebRTC = true;
} else {
UI.rfb.enableWebRTC = false;
}
UI.updateQuality(); UI.updateQuality();
} }
}, },
enableHiDpi() { enableHiDpi() {
if (UI.rfb) { if (UI.rfb) {
if (UI.getSetting('enable_hidpi')) { UI.rfb.enableHiDpi = !!UI.getSetting('enable_hidpi');
UI.rfb.enableHiDpi = true;
} else {
UI.rfb.enableHiDpi = false;
}
UI.applyResizeMode(); UI.applyResizeMode();
} }
}, },

View File

@ -70,15 +70,18 @@ export default class Display {
this._forcedFrameCnt = 0; this._forcedFrameCnt = 0;
this._missingFlipRect = 0; this._missingFlipRect = 0;
this._lateFlipRect = 0; this._lateFlipRect = 0;
this._frameStatsInterval = setInterval(function() { this._frameStatsInterval = setInterval(() => {
let delta = Date.now() - this._lastFlip; const now = Date.now();
const delta = now - this._lastFlip;
if (delta > 0) { if (delta > 0) {
this._fps = (this._flipCnt / (delta / 1000)).toFixed(2); this._fps = (this._flipCnt / (delta / 1000)).toFixed(2);
} }
Log.Debug('Dropped Frames: ' + this._droppedFrames + ' Dropped Rects: ' + this._droppedRects + ' Forced Frames: ' + this._forcedFrameCnt + ' Missing Flips: ' + this._missingFlipRect + ' Late Flips: ' + this._lateFlipRect); Log.Debug('Dropped Frames: ' + this._droppedFrames + ' Dropped Rects: ' + this._droppedRects + ' Forced Frames: ' + this._forcedFrameCnt + ' Missing Flips: ' + this._missingFlipRect + ' Late Flips: ' + this._lateFlipRect);
this._flipCnt = 0; this._flipCnt = 0;
this._lastFlip = Date.now(); this._lastFlip = now;
}.bind(this), 5000);
}, 5000);
// ===== PROPERTIES ===== // ===== PROPERTIES =====
@ -585,7 +588,6 @@ export default class Display {
} }
} }
// Readjust the viewport as it may be incorrectly sized // Readjust the viewport as it may be incorrectly sized
// and positioned // and positioned
@ -604,7 +606,7 @@ export default class Display {
'type': 'flip', 'type': 'flip',
'frame_id': frame_id, 'frame_id': frame_id,
'rect_cnt': rect_cnt, 'rect_cnt': rect_cnt,
'screenLocations': [ { screenIndex: 0, x: 0, y: 0 } ] 'screenLocations': [{screenIndex: 0, x: 0, y: 0}]
}); });
} }
@ -657,7 +659,7 @@ export default class Display {
height: height, height: height,
color: color, color: color,
frame_id: frame_id frame_id: frame_id
} };
this._processRectScreens(rect); this._processRectScreens(rect);
this._asyncRenderQPush(rect); this._asyncRenderQPush(rect);
} else { } else {
@ -681,7 +683,7 @@ export default class Display {
'width': w, 'width': w,
'height': h, 'height': h,
'frame_id': frame_id 'frame_id': frame_id
} };
this._processRectScreens(rect); this._processRectScreens(rect);
this._asyncRenderQPush(rect); this._asyncRenderQPush(rect);
} else { } else {
@ -711,7 +713,7 @@ export default class Display {
if ((width === 0) || (height === 0)) { if ((width === 0) || (height === 0)) {
return; return;
} }
let rect = { let rect = {
'type': 'img', 'type': 'img',
'img': null, 'img': null,
@ -720,7 +722,7 @@ export default class Display {
'width': width, 'width': width,
'height': height, 'height': height,
'frame_id': frame_id 'frame_id': frame_id
} };
this._processRectScreens(rect); this._processRectScreens(rect);
if (rect.inPrimary) { if (rect.inPrimary) {
@ -744,7 +746,7 @@ export default class Display {
return; return;
} }
var rect = { let rect = {
'type': 'transparent', 'type': 'transparent',
'img': null, 'img': null,
'x': x, 'x': x,
@ -754,15 +756,15 @@ export default class Display {
'frame_id': frame_id, 'frame_id': frame_id,
'arr': img, 'arr': img,
'hash_id': hashId 'hash_id': hashId
} };
this._processRectScreens(rect); this._processRectScreens(rect);
if (rect.inPrimary) { if (rect.inPrimary) {
let imageBmpPromise = createImageBitmap(img); let imageBmpPromise = createImageBitmap(img);
imageBmpPromise.then( function(bitmap) { imageBmpPromise.then((bitmap) => {
this._transparentOverlayImg = bitmap; this._transparentOverlayImg = bitmap;
this.enableCanvasBuffer = true; this.enableCanvasBuffer = true;
}.bind(this) ); });
} }
this._transparentOverlayRect = rect; this._transparentOverlayRect = rect;
@ -778,7 +780,7 @@ export default class Display {
'width': width, 'width': width,
'height': height, 'height': height,
'frame_id': frame_id 'frame_id': frame_id
} };
this._processRectScreens(rect); this._processRectScreens(rect);
this._asyncRenderQPush(rect); this._asyncRenderQPush(rect);
} }
@ -798,7 +800,7 @@ export default class Display {
'width': width, 'width': width,
'height': height, 'height': height,
'frame_id': frame_id 'frame_id': frame_id
} };
this._processRectScreens(rect); this._processRectScreens(rect);
this._asyncRenderQPush(rect); this._asyncRenderQPush(rect);
} else { } else {
@ -811,9 +813,7 @@ export default class Display {
this._drawCtx.putImageData(img, x, y); this._drawCtx.putImageData(img, x, y);
} else { } else {
this._targetCtx.putImageData(img, x, y); this._targetCtx.putImageData(img, x, y);
} }
} }
} }
@ -827,7 +827,7 @@ export default class Display {
'width': width, 'width': width,
'height': height, 'height': height,
'frame_id': frame_id 'frame_id': frame_id
} };
this._processRectScreens(rect); this._processRectScreens(rect);
this._asyncRenderQPush(rect); this._asyncRenderQPush(rect);
} else { } else {
@ -884,10 +884,10 @@ export default class Display {
_handleSecondaryDisplayMessage(event) { _handleSecondaryDisplayMessage(event) {
if (!this._isPrimaryDisplay && event.data) { if (!this._isPrimaryDisplay && event.data) {
switch (event.data.eventType) { switch (event.data.eventType) {
case 'rect': case 'rect': {
let rect = event.data.rect; let rect = event.data.rect;
//overwrite screen locations when received on the secondary display //overwrite screen locations when received on the secondary display
rect.screenLocations = [ rect.screenLocations[event.data.screenLocationIndex] ] rect.screenLocations = [rect.screenLocations[event.data.screenLocationIndex]];
rect.screenLocations[0].screenIndex = 0; rect.screenLocations[0].screenIndex = 0;
switch (rect.type) { switch (rect.type) {
case 'img': case 'img':
@ -896,16 +896,17 @@ export default class Display {
rect.img.src = rect.src; rect.img.src = rect.src;
rect.type = 'img'; rect.type = 'img';
break; break;
case 'transparent': case 'transparent': {
let imageBmpPromise = createImageBitmap(rect.arr); let imageBmpPromise = createImageBitmap(rect.arr);
imageBmpPromise.then( function(img) { imageBmpPromise.then((img) => {
this._transparentOverlayImg = img; this._transparentOverlayImg = img;
if (!this.enableCanvasBuffer) { if (!this.enableCanvasBuffer) {
this._enableCanvasBuffer = true; this._enableCanvasBuffer = true;
} }
}.bind(this) ); });
this._transparentOverlayRect = rect; this._transparentOverlayRect = rect;
break; break;
}
} }
this._syncFrameQueue.push(rect); this._syncFrameQueue.push(rect);
@ -915,9 +916,12 @@ export default class Display {
this._droppedRects++; this._droppedRects++;
} }
break; break;
}
case 'frameComplete': case 'frameComplete':
window.requestAnimationFrame( () => { this._pushSyncRects(); }); window.requestAnimationFrame(() => {
break; this._pushSyncRects();
});
break;
case 'registered': case 'registered':
if (!this._isPrimaryDisplay) { if (!this._isPrimaryDisplay) {
this._screens[0].screenIndex = event.data.screenIndex; this._screens[0].screenIndex = event.data.screenIndex;
@ -1293,8 +1297,8 @@ export default class Display {
Log.Info('Pixel Ratio: ' + window.devicePixelRatio + ', VNC Scale: ' + factor + 'VNC Res: ' + vp.serverWidth + 'x' + vp.serverHeight); Log.Info('Pixel Ratio: ' + window.devicePixelRatio + ', VNC Scale: ' + factor + 'VNC Res: ' + vp.serverWidth + 'x' + vp.serverHeight);
var pixR = Math.abs(Math.ceil(window.devicePixelRatio)); let pixR = Math.abs(Math.ceil(window.devicePixelRatio));
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (this.antiAliasing === 2 || (this.antiAliasing === 0 && factor === 1 && this._target.style.imageRendering !== 'pixelated' && pixR === window.devicePixelRatio && vp.width > 0)) { if (this.antiAliasing === 2 || (this.antiAliasing === 0 && factor === 1 && this._target.style.imageRendering !== 'pixelated' && pixR === window.devicePixelRatio && vp.width > 0)) {
this._target.style.imageRendering = ((!isFirefox) ? 'pixelated' : 'crisp-edges' ); this._target.style.imageRendering = ((!isFirefox) ? 'pixelated' : 'crisp-edges' );

View File

@ -221,14 +221,14 @@ export default class Keyboard {
newLen = newValue.length; newLen = newValue.length;
} }
const oldLen = oldValue.length; const oldLen = oldValue.length;
let inputs = newLen - oldLen; let inputs = newLen - oldLen;
let backspaces = inputs < 0 ? -inputs : 0; let backspaces = inputs < 0 ? -inputs : 0;
// Compare the old string with the new to account for // Compare the old string with the new to account for
// text-corrections or other input that modify existing text // text-corrections or other input that modify existing text
for (let i = 0; i < Math.min(oldLen, newLen); i++) { for (let i = 0; i < Math.min(oldLen, newLen); i++) {
if (newValue.charAt(i) != oldValue.charAt(i)) { if (newValue.charAt(i) !== oldValue.charAt(i)) {
inputs = newLen - i; inputs = newLen - i;
backspaces = oldLen - i; backspaces = oldLen - i;
break; break;
@ -273,7 +273,7 @@ export default class Keyboard {
const code = this._getKeyCode(e); const code = this._getKeyCode(e);
let keysym = KeyboardUtil.getKeysym(e); let keysym = KeyboardUtil.getKeysym(e);
this.clearKeysDown(e); this.clearKeysDown(e);
if (this._isIMEInteraction(e)) { if (this._isIMEInteraction(e)) {
//skip event if IME related //skip event if IME related
Log.Debug("Skipping keydown, IME interaction, code: " + code + " keysym: " + keysym + " keycode: " + e.keyCode); Log.Debug("Skipping keydown, IME interaction, code: " + code + " keysym: " + keysym + " keycode: " + e.keyCode);