Feature/kasm 3314 kasmvnc controls (#45)
* KASM-3314 Support for changing framerate / resolution / scaling via iframe message
This commit is contained in:
parent
2f01048bc6
commit
8e5c0e977f
115
app/ui.js
115
app/ui.js
|
@ -243,7 +243,6 @@ const UI = {
|
||||||
UI.initSetting('enable_perf_stats', false);
|
UI.initSetting('enable_perf_stats', false);
|
||||||
UI.initSetting('virtual_keyboard_visible', false);
|
UI.initSetting('virtual_keyboard_visible', false);
|
||||||
UI.initSetting('enable_ime', false);
|
UI.initSetting('enable_ime', false);
|
||||||
UI.initSetting('enable_qoi', false);
|
|
||||||
UI.initSetting('enable_webrtc', false);
|
UI.initSetting('enable_webrtc', false);
|
||||||
UI.toggleKeyboardControls();
|
UI.toggleKeyboardControls();
|
||||||
|
|
||||||
|
@ -557,8 +556,6 @@ const UI = {
|
||||||
UI.addSettingChangeHandler('virtual_keyboard_visible', UI.toggleKeyboardControls);
|
UI.addSettingChangeHandler('virtual_keyboard_visible', UI.toggleKeyboardControls);
|
||||||
UI.addSettingChangeHandler('enable_ime');
|
UI.addSettingChangeHandler('enable_ime');
|
||||||
UI.addSettingChangeHandler('enable_ime', UI.toggleIMEMode);
|
UI.addSettingChangeHandler('enable_ime', UI.toggleIMEMode);
|
||||||
UI.addSettingChangeHandler('enable_qoi');
|
|
||||||
UI.addSettingChangeHandler('enable_qoi', UI.toggleQOI);
|
|
||||||
UI.addSettingChangeHandler('enable_webrtc');
|
UI.addSettingChangeHandler('enable_webrtc');
|
||||||
UI.addSettingChangeHandler('enable_webrtc', UI.toggleWebRTC);
|
UI.addSettingChangeHandler('enable_webrtc', UI.toggleWebRTC);
|
||||||
},
|
},
|
||||||
|
@ -1027,6 +1024,7 @@ const UI = {
|
||||||
} else {
|
} else {
|
||||||
UI.enableSetting(name);
|
UI.enableSetting(name);
|
||||||
}
|
}
|
||||||
|
UI.saveSetting(name);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Update cookie and form control setting. If value is not set, then
|
// Update cookie and form control setting. If value is not set, then
|
||||||
|
@ -1400,7 +1398,6 @@ const UI = {
|
||||||
UI.rfb.clipboardSeamless = UI.getSetting('clipboard_seamless');
|
UI.rfb.clipboardSeamless = UI.getSetting('clipboard_seamless');
|
||||||
UI.rfb.keyboard.enableIME = UI.getSetting('enable_ime');
|
UI.rfb.keyboard.enableIME = UI.getSetting('enable_ime');
|
||||||
UI.rfb.clipboardBinary = supportsBinaryClipboard() && UI.rfb.clipboardSeamless;
|
UI.rfb.clipboardBinary = supportsBinaryClipboard() && UI.rfb.clipboardSeamless;
|
||||||
UI.rfb.enableQOI = UI.getSetting('enable_qoi');
|
|
||||||
UI.rfb.enableWebRTC = UI.getSetting('enable_webrtc');
|
UI.rfb.enableWebRTC = UI.getSetting('enable_webrtc');
|
||||||
UI.rfb.mouseButtonMapper = UI.initMouseButtonMapper();
|
UI.rfb.mouseButtonMapper = UI.initMouseButtonMapper();
|
||||||
|
|
||||||
|
@ -1601,9 +1598,15 @@ const UI = {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'setvideoquality':
|
case 'setvideoquality':
|
||||||
UI.forceSetting('video_quality', parseInt(event.data.value), false);
|
if (event.data.qualityLevel !== undefined) {
|
||||||
UI.forceSetting('enable_qoi', false, false); // QOI controlled via video quality mode when in iframe
|
//apply preset mode values, but don't apply to connection
|
||||||
UI.updateQuality();
|
UI.forceSetting('video_quality', parseInt(event.data.qualityLevel), false);
|
||||||
|
// apply quality preset quality level and override some settings (fps)
|
||||||
|
UI.updateQuality(event.data.frameRate);
|
||||||
|
} else {
|
||||||
|
UI.forceSetting('video_quality', parseInt(event.data.value), false);
|
||||||
|
UI.updateQuality();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'enable_game_mode':
|
case 'enable_game_mode':
|
||||||
if (UI.rfb && !UI.rfb.pointerRelative) {
|
if (UI.rfb && !UI.rfb.pointerRelative) {
|
||||||
|
@ -1649,18 +1652,6 @@ const UI = {
|
||||||
UI.toggleIMEMode();
|
UI.toggleIMEMode();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'disable_qoi':
|
|
||||||
if(UI.getSetting('enable_qoi')) {
|
|
||||||
UI.forceSetting('enable_qoi', false, false);
|
|
||||||
}
|
|
||||||
UI.toggleQOI();
|
|
||||||
break;
|
|
||||||
case 'enable_qoi':
|
|
||||||
if(!UI.getSetting('enable_qoi')) {
|
|
||||||
UI.forceSetting('enable_qoi', true, false);
|
|
||||||
}
|
|
||||||
UI.toggleQOI();
|
|
||||||
break;
|
|
||||||
case 'enable_webrtc':
|
case 'enable_webrtc':
|
||||||
if (!UI.getSetting('enable_webrtc')) {
|
if (!UI.getSetting('enable_webrtc')) {
|
||||||
UI.forceSetting('enable_webrtc', true, false);
|
UI.forceSetting('enable_webrtc', true, false);
|
||||||
|
@ -1673,7 +1664,23 @@ const UI = {
|
||||||
UI.toggleWebRTC();
|
UI.toggleWebRTC();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'resize':
|
||||||
|
UI.forceSetting('resize', event.data.value, false);
|
||||||
|
UI.applyResizeMode();
|
||||||
|
break;
|
||||||
|
case 'set_resolution':
|
||||||
|
if (UI.rfb) {
|
||||||
|
UI.rfb.forcedResolutionX = event.data.value_x;
|
||||||
|
UI.rfb.forcedResolutionY = event.data.value_y;
|
||||||
|
UI.applyResizeMode();
|
||||||
|
UI.rfb.forcedResolutionX = null;
|
||||||
|
UI.rfb.forcedResolutionY = null;
|
||||||
|
UI.rfb._resizeSession = UI.getSetting('resize') === 'remote';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'set_perf_stats':
|
||||||
|
UI.forceSetting('enable_perf_stats', event.data.value, false);
|
||||||
|
UI.showStats();
|
||||||
case 'set_idle_timeout':
|
case 'set_idle_timeout':
|
||||||
//message value in seconds
|
//message value in seconds
|
||||||
const idle_timeout_min = Math.ceil(event.data.value / 60);
|
const idle_timeout_min = Math.ceil(event.data.value / 60);
|
||||||
|
@ -1815,7 +1822,7 @@ const UI = {
|
||||||
if (!UI.rfb) return;
|
if (!UI.rfb) return;
|
||||||
|
|
||||||
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
|
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
|
||||||
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
|
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote' || UI.rfb.forcedResolutionX && UI.rfb.forcedResolutionY;
|
||||||
UI.rfb.idleDisconnect = UI.getSetting('idle_disconnect');
|
UI.rfb.idleDisconnect = UI.getSetting('idle_disconnect');
|
||||||
UI.rfb.videoQuality = UI.getSetting('video_quality');
|
UI.rfb.videoQuality = UI.getSetting('video_quality');
|
||||||
UI.rfb.enableWebP = UI.getSetting('enable_webp');
|
UI.rfb.enableWebP = UI.getSetting('enable_webp');
|
||||||
|
@ -1959,8 +1966,9 @@ const UI = {
|
||||||
* QUALITY
|
* QUALITY
|
||||||
* ------v------*/
|
* ------v------*/
|
||||||
|
|
||||||
updateQuality() {
|
updateQuality(fps) {
|
||||||
let present_mode = parseInt(UI.getSetting('video_quality'));
|
let present_mode = parseInt(UI.getSetting('video_quality'));
|
||||||
|
let enable_qoi = false;
|
||||||
|
|
||||||
// video_quality preset values
|
// video_quality preset values
|
||||||
switch (present_mode) {
|
switch (present_mode) {
|
||||||
|
@ -1977,20 +1985,31 @@ const UI = {
|
||||||
UI.enableSetting('framerate');
|
UI.enableSetting('framerate');
|
||||||
UI.enableSetting('video_scaling');
|
UI.enableSetting('video_scaling');
|
||||||
UI.enableSetting('video_out_time');
|
UI.enableSetting('video_out_time');
|
||||||
UI.showStatus("Refresh or reconnect to apply changes.");
|
break;
|
||||||
return;
|
case 5: //lossless
|
||||||
case 5: //extreme+lossless
|
enable_qoi = true;
|
||||||
UI.forceSetting('enable_qoi', true, false);
|
fps = (fps && Number.isFinite(fps)) ? fps : 60;
|
||||||
case 4: //extreme
|
|
||||||
UI.forceSetting('dynamic_quality_min', 9);
|
UI.forceSetting('dynamic_quality_min', 9);
|
||||||
UI.forceSetting('dynamic_quality_max', 9);
|
UI.forceSetting('dynamic_quality_max', 9);
|
||||||
UI.forceSetting('framerate', 60);
|
UI.forceSetting('framerate', fps);
|
||||||
|
UI.forceSetting('treat_lossless', 9);
|
||||||
|
UI.forceSetting('video_time', 100);
|
||||||
|
UI.forceSetting('video_area', 100);
|
||||||
|
UI.forceSetting('max_video_resolution_x', 1920);
|
||||||
|
UI.forceSetting('max_video_resolution_y', 1080);
|
||||||
|
UI.forceSetting('jpeg_video_quality', 9);
|
||||||
|
UI.forceSetting('webp_video_quality', 9);
|
||||||
|
UI.forceSetting('video_scaling', 0);
|
||||||
|
UI.forceSetting('video_out_time', 3);
|
||||||
|
break;
|
||||||
|
case 4: //extreme
|
||||||
|
fps = (fps && Number.isFinite(fps)) ? fps : 60;
|
||||||
|
UI.forceSetting('dynamic_quality_min', 9);
|
||||||
|
UI.forceSetting('dynamic_quality_max', 9);
|
||||||
|
UI.forceSetting('framerate', fps);
|
||||||
UI.forceSetting('treat_lossless', 9);
|
UI.forceSetting('treat_lossless', 9);
|
||||||
|
|
||||||
// effectively disables video mode
|
|
||||||
UI.forceSetting('video_time', 100);
|
UI.forceSetting('video_time', 100);
|
||||||
UI.forceSetting('video_area', 100);
|
UI.forceSetting('video_area', 100);
|
||||||
// go ahead and set video mode settings, won't be used
|
|
||||||
UI.forceSetting('max_video_resolution_x', 1920);
|
UI.forceSetting('max_video_resolution_x', 1920);
|
||||||
UI.forceSetting('max_video_resolution_y', 1080);
|
UI.forceSetting('max_video_resolution_y', 1080);
|
||||||
UI.forceSetting('jpeg_video_quality', 9);
|
UI.forceSetting('jpeg_video_quality', 9);
|
||||||
|
@ -1999,13 +2018,14 @@ const UI = {
|
||||||
UI.forceSetting('video_out_time', 3);
|
UI.forceSetting('video_out_time', 3);
|
||||||
break;
|
break;
|
||||||
case 3: // high
|
case 3: // high
|
||||||
|
fps = (fps && Number.isFinite(fps)) ? fps : 60;
|
||||||
UI.forceSetting('jpeg_video_quality', 8);
|
UI.forceSetting('jpeg_video_quality', 8);
|
||||||
UI.forceSetting('webp_video_quality', 8);
|
UI.forceSetting('webp_video_quality', 8);
|
||||||
UI.forceSetting('dynamic_quality_min', 7);
|
UI.forceSetting('dynamic_quality_min', 7);
|
||||||
UI.forceSetting('dynamic_quality_max', 9);
|
UI.forceSetting('dynamic_quality_max', 9);
|
||||||
UI.forceSetting('max_video_resolution_x', 1920);
|
UI.forceSetting('max_video_resolution_x', 1920);
|
||||||
UI.forceSetting('max_video_resolution_y', 1080);
|
UI.forceSetting('max_video_resolution_y', 1080);
|
||||||
UI.forceSetting('framerate', 60);
|
UI.forceSetting('framerate', fps);
|
||||||
UI.forceSetting('treat_lossless', 8);
|
UI.forceSetting('treat_lossless', 8);
|
||||||
UI.forceSetting('video_time', 5);
|
UI.forceSetting('video_time', 5);
|
||||||
UI.forceSetting('video_area', 65);
|
UI.forceSetting('video_area', 65);
|
||||||
|
@ -2013,13 +2033,14 @@ const UI = {
|
||||||
UI.forceSetting('video_out_time', 3);
|
UI.forceSetting('video_out_time', 3);
|
||||||
break;
|
break;
|
||||||
case 1: // low, resolution capped at 720p keeping aspect ratio
|
case 1: // low, resolution capped at 720p keeping aspect ratio
|
||||||
|
fps = (fps && Number.isFinite(fps)) ? fps : 24;
|
||||||
UI.forceSetting('jpeg_video_quality', 5);
|
UI.forceSetting('jpeg_video_quality', 5);
|
||||||
UI.forceSetting('webp_video_quality', 4);
|
UI.forceSetting('webp_video_quality', 4);
|
||||||
UI.forceSetting('dynamic_quality_min', 3);
|
UI.forceSetting('dynamic_quality_min', 3);
|
||||||
UI.forceSetting('dynamic_quality_max', 7);
|
UI.forceSetting('dynamic_quality_max', 7);
|
||||||
UI.forceSetting('max_video_resolution_x', 960);
|
UI.forceSetting('max_video_resolution_x', 960);
|
||||||
UI.forceSetting('max_video_resolution_y', 540);
|
UI.forceSetting('max_video_resolution_y', 540);
|
||||||
UI.forceSetting('framerate', 22);
|
UI.forceSetting('framerate', fps);
|
||||||
UI.forceSetting('treat_lossless', 7);
|
UI.forceSetting('treat_lossless', 7);
|
||||||
UI.forceSetting('video_time', 5);
|
UI.forceSetting('video_time', 5);
|
||||||
UI.forceSetting('video_area', 65);
|
UI.forceSetting('video_area', 65);
|
||||||
|
@ -2029,13 +2050,14 @@ const UI = {
|
||||||
case 2: // medium
|
case 2: // medium
|
||||||
case 0: // static resolution, but same settings as medium
|
case 0: // static resolution, but same settings as medium
|
||||||
default:
|
default:
|
||||||
|
fps = (fps && Number.isFinite(fps)) ? fps : 24;
|
||||||
UI.forceSetting('jpeg_video_quality', 7);
|
UI.forceSetting('jpeg_video_quality', 7);
|
||||||
UI.forceSetting('webp_video_quality', 7);
|
UI.forceSetting('webp_video_quality', 7);
|
||||||
UI.forceSetting('dynamic_quality_min', 4);
|
UI.forceSetting('dynamic_quality_min', 4);
|
||||||
UI.forceSetting('dynamic_quality_max', 9);
|
UI.forceSetting('dynamic_quality_max', 9);
|
||||||
UI.forceSetting('max_video_resolution_x', 960);
|
UI.forceSetting('max_video_resolution_x', 960);
|
||||||
UI.forceSetting('max_video_resolution_y', 540);
|
UI.forceSetting('max_video_resolution_y', 540);
|
||||||
UI.forceSetting('framerate', 24);
|
UI.forceSetting('framerate', (fps) ? fps : 24);
|
||||||
UI.forceSetting('treat_lossless', 7);
|
UI.forceSetting('treat_lossless', 7);
|
||||||
UI.forceSetting('video_time', 5);
|
UI.forceSetting('video_time', 5);
|
||||||
UI.forceSetting('video_area', 65);
|
UI.forceSetting('video_area', 65);
|
||||||
|
@ -2044,12 +2066,6 @@ const UI = {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//force QOI off if mode is below extreme
|
|
||||||
if (present_mode < 4 && UI.getSetting('enable_qoi')) {
|
|
||||||
UI.showStatus("Lossless QOI disabled when not in extreme quality mode.");
|
|
||||||
UI.forceSetting('enable_qoi', false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UI.rfb) {
|
if (UI.rfb) {
|
||||||
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
|
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
|
||||||
UI.rfb.antiAliasing = parseInt(UI.getSetting('anti_aliasing'));
|
UI.rfb.antiAliasing = parseInt(UI.getSetting('anti_aliasing'));
|
||||||
|
@ -2067,7 +2083,7 @@ const UI = {
|
||||||
UI.rfb.frameRate = parseInt(UI.getSetting('framerate'));
|
UI.rfb.frameRate = parseInt(UI.getSetting('framerate'));
|
||||||
UI.rfb.enableWebP = UI.getSetting('enable_webp');
|
UI.rfb.enableWebP = UI.getSetting('enable_webp');
|
||||||
UI.rfb.videoQuality = parseInt(UI.getSetting('video_quality'));
|
UI.rfb.videoQuality = parseInt(UI.getSetting('video_quality'));
|
||||||
UI.rfb.enableQOI = UI.getSetting('enable_qoi');
|
UI.rfb.enableQOI = enable_qoi;
|
||||||
|
|
||||||
// Gracefully update settings server side
|
// Gracefully update settings server side
|
||||||
UI.rfb.updateConnectionSettings();
|
UI.rfb.updateConnectionSettings();
|
||||||
|
@ -2127,23 +2143,6 @@ const UI = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleQOI() {
|
|
||||||
if(UI.rfb) {
|
|
||||||
if(UI.getSetting('enable_qoi')) {
|
|
||||||
UI.rfb.enableQOI = true;
|
|
||||||
if (!UI.rfb.enableQOI) {
|
|
||||||
UI.showStatus("Enabling QOI failed, browser may not be compatible with WASM and/or Workers.");
|
|
||||||
UI.forceSetting('enable_qoi', false, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UI.forceSetting('video_quality', 4, false); //force into extreme quality mode
|
|
||||||
} else {
|
|
||||||
UI.rfb.enableQOI = false;
|
|
||||||
}
|
|
||||||
UI.updateQuality();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
showKeyboardControls() {
|
showKeyboardControls() {
|
||||||
document.getElementById('noVNC_keyboard_control').classList.add("is-visible");
|
document.getElementById('noVNC_keyboard_control').classList.add("is-visible");
|
||||||
},
|
},
|
||||||
|
|
11
core/rfb.js
11
core/rfb.js
|
@ -139,6 +139,8 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._frameRate = 30;
|
this._frameRate = 30;
|
||||||
this._maxVideoResolutionX = 960;
|
this._maxVideoResolutionX = 960;
|
||||||
this._maxVideoResolutionY = 540;
|
this._maxVideoResolutionY = 540;
|
||||||
|
this._forcedResolutionX = null;
|
||||||
|
this._forcedResolutionY = null;
|
||||||
this._clipboardBinary = true;
|
this._clipboardBinary = true;
|
||||||
this._useUdp = true;
|
this._useUdp = true;
|
||||||
this._enableQOI = false;
|
this._enableQOI = false;
|
||||||
|
@ -693,6 +695,11 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._pendingApplyVideoRes = true;
|
this._pendingApplyVideoRes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get forcedResolutionX() { return this._forcedResolutionX; }
|
||||||
|
set forcedResolutionX(value) {this._forcedResolutionX = value;}
|
||||||
|
get forcedResolutionY() { return this._forcedResolutionY; }
|
||||||
|
set forcedResolutionY(value) {this._forcedResolutionY = value;}
|
||||||
|
|
||||||
get qualityLevel() {
|
get qualityLevel() {
|
||||||
return this._qualityLevel;
|
return this._qualityLevel;
|
||||||
}
|
}
|
||||||
|
@ -1320,8 +1327,8 @@ export default class RFB extends EventTargetMixin {
|
||||||
if (limited === undefined) {
|
if (limited === undefined) {
|
||||||
limited = true;
|
limited = true;
|
||||||
}
|
}
|
||||||
var x = this._screen.offsetWidth;
|
var x = this.forcedResolutionX || this._screen.offsetWidth;
|
||||||
var y = this._screen.offsetHeight;
|
var y = this.forcedResolutionY || this._screen.offsetHeight;
|
||||||
var scale = 0; // 0=auto
|
var scale = 0; // 0=auto
|
||||||
try {
|
try {
|
||||||
if (x > 1280 && limited && this.videoQuality == 1) {
|
if (x > 1280 && limited && this.videoQuality == 1) {
|
||||||
|
|
7
vnc.html
7
vnc.html
|
@ -277,12 +277,6 @@
|
||||||
<span class="slider-label">IME Input Mode</span>
|
<span class="slider-label">IME Input Mode</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<label class="switch"><input id="noVNC_setting_enable_qoi" type="checkbox" />
|
|
||||||
<span class="slider round"></span>
|
|
||||||
<span class="slider-label">QOI Lossless</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<label class="switch"><input id="noVNC_setting_virtual_keyboard_visible" type="checkbox" />
|
<label class="switch"><input id="noVNC_setting_virtual_keyboard_visible" type="checkbox" />
|
||||||
<span class="slider round"></span>
|
<span class="slider round"></span>
|
||||||
|
@ -352,6 +346,7 @@
|
||||||
<option value=2>Medium</option>
|
<option value=2>Medium</option>
|
||||||
<option value=3>High</option>
|
<option value=3>High</option>
|
||||||
<option value=4>Extreme</option>
|
<option value=4>Extreme</option>
|
||||||
|
<option value=5>Lossless</option>
|
||||||
<option value=10>Custom</option>
|
<option value=10>Custom</option>
|
||||||
</select>
|
</select>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue