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

View File

@ -70,15 +70,18 @@ export default class Display {
this._forcedFrameCnt = 0;
this._missingFlipRect = 0;
this._lateFlipRect = 0;
this._frameStatsInterval = setInterval(function() {
let delta = Date.now() - this._lastFlip;
this._frameStatsInterval = setInterval(() => {
const now = Date.now();
const delta = now - this._lastFlip;
if (delta > 0) {
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);
this._flipCnt = 0;
this._lastFlip = Date.now();
}.bind(this), 5000);
this._lastFlip = now;
}, 5000);
// ===== PROPERTIES =====
@ -586,7 +589,6 @@ export default class Display {
}
// Readjust the viewport as it may be incorrectly sized
// and positioned
const vp = this._screens[0];
@ -657,7 +659,7 @@ export default class Display {
height: height,
color: color,
frame_id: frame_id
}
};
this._processRectScreens(rect);
this._asyncRenderQPush(rect);
} else {
@ -681,7 +683,7 @@ export default class Display {
'width': w,
'height': h,
'frame_id': frame_id
}
};
this._processRectScreens(rect);
this._asyncRenderQPush(rect);
} else {
@ -720,7 +722,7 @@ export default class Display {
'width': width,
'height': height,
'frame_id': frame_id
}
};
this._processRectScreens(rect);
if (rect.inPrimary) {
@ -744,7 +746,7 @@ export default class Display {
return;
}
var rect = {
let rect = {
'type': 'transparent',
'img': null,
'x': x,
@ -754,15 +756,15 @@ export default class Display {
'frame_id': frame_id,
'arr': img,
'hash_id': hashId
}
};
this._processRectScreens(rect);
if (rect.inPrimary) {
let imageBmpPromise = createImageBitmap(img);
imageBmpPromise.then( function(bitmap) {
imageBmpPromise.then((bitmap) => {
this._transparentOverlayImg = bitmap;
this.enableCanvasBuffer = true;
}.bind(this) );
});
}
this._transparentOverlayRect = rect;
@ -778,7 +780,7 @@ export default class Display {
'width': width,
'height': height,
'frame_id': frame_id
}
};
this._processRectScreens(rect);
this._asyncRenderQPush(rect);
}
@ -798,7 +800,7 @@ export default class Display {
'width': width,
'height': height,
'frame_id': frame_id
}
};
this._processRectScreens(rect);
this._asyncRenderQPush(rect);
} else {
@ -811,9 +813,7 @@ export default class Display {
this._drawCtx.putImageData(img, x, y);
} else {
this._targetCtx.putImageData(img, x, y);
}
}
}
@ -827,7 +827,7 @@ export default class Display {
'width': width,
'height': height,
'frame_id': frame_id
}
};
this._processRectScreens(rect);
this._asyncRenderQPush(rect);
} else {
@ -884,10 +884,10 @@ export default class Display {
_handleSecondaryDisplayMessage(event) {
if (!this._isPrimaryDisplay && event.data) {
switch (event.data.eventType) {
case 'rect':
case 'rect': {
let rect = event.data.rect;
//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;
switch (rect.type) {
case 'img':
@ -896,17 +896,18 @@ export default class Display {
rect.img.src = rect.src;
rect.type = 'img';
break;
case 'transparent':
case 'transparent': {
let imageBmpPromise = createImageBitmap(rect.arr);
imageBmpPromise.then( function(img) {
imageBmpPromise.then((img) => {
this._transparentOverlayImg = img;
if (!this.enableCanvasBuffer) {
this._enableCanvasBuffer = true;
}
}.bind(this) );
});
this._transparentOverlayRect = rect;
break;
}
}
this._syncFrameQueue.push(rect);
//if the secondary display is not in focus, the browser may not call requestAnimationFrame, thus we need to limit our buffer
@ -915,8 +916,11 @@ export default class Display {
this._droppedRects++;
}
break;
}
case 'frameComplete':
window.requestAnimationFrame( () => { this._pushSyncRects(); });
window.requestAnimationFrame(() => {
this._pushSyncRects();
});
break;
case 'registered':
if (!this._isPrimaryDisplay) {
@ -1293,8 +1297,8 @@ export default class Display {
Log.Info('Pixel Ratio: ' + window.devicePixelRatio + ', VNC Scale: ' + factor + 'VNC Res: ' + vp.serverWidth + 'x' + vp.serverHeight);
var pixR = Math.abs(Math.ceil(window.devicePixelRatio));
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
let pixR = Math.abs(Math.ceil(window.devicePixelRatio));
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)) {
this._target.style.imageRendering = ((!isFirefox) ? 'pixelated' : 'crisp-edges' );

View File

@ -228,7 +228,7 @@ export default class Keyboard {
// Compare the old string with the new to account for
// text-corrections or other input that modify existing text
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;
backspaces = oldLen - i;
break;