viewer-side keymap

it's useful when dealing with broken vnc server implementations,
namely qemu/kvm.
This commit is contained in:
Hirokazu Takahashi 2012-12-11 20:05:06 +09:00
parent 77c250c442
commit e37086c1e1
6 changed files with 6487 additions and 4 deletions

View File

@ -17,6 +17,7 @@ is not limited to):
include/vnc.js
include/websock.js
include/webutil.js
include/keymap.js
The HTML, CSS, font and images files that included with the noVNC
source distibution (or repository) are not considered part of the

6407
include/keymap.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -126,7 +126,9 @@ var that = {}, // Public API methods
mouse_buttonMask = 0,
mouse_arr = [],
viewportDragging = false,
viewportDragPos = {};
viewportDragPos = {},
keymap = null;
// Configuration attributes
Util.conf_defaults(conf, that, defaults, [
@ -604,6 +606,11 @@ keyPress = function(keysym, down, km) {
if (conf.view_only) { return; } // View only, skip keyboard events
// Remap the modifiers with apppropriate ones depending on the
// keyboard type of the vnc server if this is a presskey event.
if (!!keymap && down === 2)
km = remapModifiers(km, keysym);
// Generate all modifier keys' events on demand.
// Send key events for modifiers to the vnc server when:
// 1. the status of modifers have been changed
@ -639,10 +646,44 @@ keyPress = function(keysym, down, km) {
// This is a keydown or keyup event.
arr = arr.concat(keyEvent(keysym, down));
}
if (!!keymap && down === 2) {
// Turn off SHIFT and ALTGR every time when emulating modifiers.
if (remote_status.shift) {
arr = arr.concat(keyEvent(0xFFE1, 0)); // SHIFT up
remote_status.shift = false;
}
if (remote_status.altgr) {
arr = arr.concat(keyEvent(0xFE03, 0)); // ALTGR up
remote_status.altgr = false;
}
}
arr = arr.concat(fbUpdateRequests());
ws.send(arr);
};
// Remap the modifiers depending on keyboard types. It depends on keyboards
// whether a certain keycode should be issued with modifiers. For example,
// the US keyboard issues '@' with SHIFT, the Japanese keyboard issues '@'
// without any modifers, and the German keyboard issues '@' with ALTGR.
// When the keyboard types are different between the viewer and the vnc
// server, the server is expected to generate fake modifer key events
// if needed. But unfortunately there are a lot of VNC servers that can't
// handle this. Then there is no choice but to make noVNC take care of it
// on behalf of them.
function remapModifiers(km, keysym)
{
var remap = {'altKey': km.altKey, 'ctrlKey': km.ctrlKey,
'shiftKey': km.shiftKey, 'altgrKey': km.altgrKey};
var key = keymap[keysym];
if (typeof key !== "undefined") {
remap.altgrKey = key.altgr;
remap.shiftKey = key.shift;
}
return remap;
}
mouseButton = function(x, y, down, bmask) {
if (down) {
mouse_buttonMask |= bmask;
@ -1897,6 +1938,14 @@ that.testMode = function(override_send, data_mode) {
};
};
that.setKeymap = function(kb) {
if (!kb || kb === 'default') {
keymap = null;
} else {
keymap = Kmap.getKeymap(kb);
}
};
return constructor(); // Return the public API interface

View File

@ -13,7 +13,8 @@
// Load supporting scripts
window.onscriptsload = function () { UI.load(); };
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
"input.js", "display.js", "jsunzip.js", "rfb.js"]);
"input.js", "display.js", "jsunzip.js", "rfb.js",
"keymap.js"]);
var UI = {
@ -31,7 +32,7 @@ load: function (callback) {
// Render default UI and initialize settings menu
start: function(callback) {
var html = '', i, sheet, sheets, llevels;
var html = '', i, sheet, sheets, llevels, kbtypes;
// Stylesheet selection dropdown
sheet = WebUtil.selectStylesheet();
@ -46,6 +47,19 @@ start: function(callback) {
UI.addOption($D('noVNC_logging'),llevels[i], llevels[i]);
}
// Keyboard type selection dropdown
kbtypes = ['default', 'ar', 'bepo', 'da', 'de', 'de-ch', 'en-gb',
'en-us', 'es', 'et', 'fi', 'fo', 'fr', 'fr-be', 'fr-ca',
'fr-ch', 'hr', 'hu', 'is', 'it', 'ja', 'lt', 'lv', 'mk',
'nl', 'nl-be', 'no', 'pl', 'pt', 'pt-br', 'ru', 'sl',
'sv', 'th', 'tr'];
for (i = 0; i < kbtypes.length; i += 1) {
UI.addOption($D('noVNC_keymap'), kbtypes[i], kbtypes[i]);
}
UI.initSetting('keymap', 'default');
// Settings with immediate effects
UI.initSetting('logging', 'warn');
WebUtil.init_logging(UI.getSetting('logging'));
@ -71,6 +85,7 @@ start: function(callback) {
UI.rfb = RFB({'target': $D('noVNC_canvas'),
'onUpdateState': UI.updateState,
'onClipboard': UI.clipReceive});
UI.rfb.setKeymap(UI.getSetting('keymap'));
UI.updateVisualState();
// Unfocus clipboard when over the VNC area
@ -326,6 +341,7 @@ toggleSettingsPanel: function() {
UI.updateSetting('repeaterID');
UI.updateSetting('stylesheet');
UI.updateSetting('logging');
UI.updateSetting('keymap');
UI.openSettingsMenu();
}
@ -370,8 +386,10 @@ settingsApply: function() {
UI.saveSetting('repeaterID');
UI.saveSetting('stylesheet');
UI.saveSetting('logging');
UI.saveSetting('keymap');
// Settings with immediate (non-connected related) effect
UI.rfb.setKeymap(UI.getSetting('keymap'));
WebUtil.selectStylesheet(UI.getSetting('stylesheet'));
WebUtil.init_logging(UI.getSetting('logging'));
UI.setViewClip();

View File

@ -138,6 +138,12 @@
<select id="noVNC_logging" name="vncLogging">
</select></label>
</li>
<!-- keyboard selection dropdown -->
<li><label><strong>Keyboard: </strong>
<select id="noVNC_keymap" name="vncKeymap">
</select></label>
</li>
<hr>
<li><input type="button" id="noVNC_apply" value="Apply"></li>
</ul>

View File

@ -43,7 +43,8 @@
// Load supporting scripts
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
"input.js", "display.js", "jsunzip.js", "rfb.js"]);
"input.js", "display.js", "jsunzip.js", "rfb.js",
"keymap.js"]);
var rfb;
@ -126,6 +127,7 @@
'view_only': WebUtil.getQueryVar('view_only', false),
'updateState': updateState,
'onPasswordRequired': passwordRequired});
rfb.setKeymap(WebUtil.getQueryVar('keymap', 'default'));
rfb.connect(host, port, password, path);
};
</script>