Repository: cloudstack
Updated Branches:
refs/heads/4.2-forward 1409ef03a -> 6938b99f8
Add console proxy AltGR support and French keyboard support
Conflicts:
services/console-proxy/server/js/ajaxviewer.js
Signed-off-by: Daan Hoogland <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/6938b99f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/6938b99f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/6938b99f
Branch: refs/heads/4.2-forward
Commit: 6938b99f8bdfc21e323424b009096ae2569e9f32
Parents: 1409ef0
Author: a543197 <[email protected]>
Authored: Mon Mar 3 12:11:27 2014 +0100
Committer: Daan Hoogland <[email protected]>
Committed: Tue Mar 4 10:31:30 2014 +0100
----------------------------------------------------------------------
.../console-proxy/server/css/ajaxviewer.css | 2 +-
services/console-proxy/server/js/ajaxkeys.js | 325 ++++++++++++++++++-
services/console-proxy/server/js/ajaxviewer.js | 30 +-
.../consoleproxy/ConsoleProxyClientBase.java | 1 +
4 files changed, 351 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6938b99f/services/console-proxy/server/css/ajaxviewer.css
----------------------------------------------------------------------
diff --git a/services/console-proxy/server/css/ajaxviewer.css
b/services/console-proxy/server/css/ajaxviewer.css
index fd2fb3c..3e06814 100644
--- a/services/console-proxy/server/css/ajaxviewer.css
+++ b/services/console-proxy/server/css/ajaxviewer.css
@@ -91,7 +91,7 @@ body {
position: absolute;
top:32;
width: 260;
- height: 95;
+ height: 125;
display: block;
display: none;
border-top: 1px solid black;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6938b99f/services/console-proxy/server/js/ajaxkeys.js
----------------------------------------------------------------------
diff --git a/services/console-proxy/server/js/ajaxkeys.js
b/services/console-proxy/server/js/ajaxkeys.js
index 60c9798..abe6f13 100644
--- a/services/console-proxy/server/js/ajaxkeys.js
+++ b/services/console-proxy/server/js/ajaxkeys.js
@@ -164,6 +164,7 @@ KEY_UP = 6;
KEYBOARD_TYPE_COOKED = "us";
KEYBOARD_TYPE_JP = "jp";
KEYBOARD_TYPE_UK = "uk";
+KEYBOARD_TYPE_FR = "fr";
//JP keyboard type
@@ -340,4 +341,326 @@ var keyboardTables = [
}
]
}
- }]
+ },
+ {tindex: 3, keyboardType: KEYBOARD_TYPE_FR, mappingTable:{
+ X11: [
+ // '*' doesn't work
+ {keycode: 220, browser: "Chrome", entry: 0x5c},
+ {keycode: 170, browser: "Firefox", entry: 0x5c},
+//ROW 1 AltGr
+ //[50 = ~]
+ {keycode: 50, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x32, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x32, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[51 = #]
+ {keycode: 51, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x33, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x33, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[52 = {]
+ {keycode: 52, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x34, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x34, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[53 = []
+ {keycode: 53, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x35, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x35, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[54 = |]
+ {keycode: 54, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x36, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x36, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[55 = `]
+ {keycode: 55, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x37, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x37, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[56 = \]
+ {keycode: 56, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x38, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x38, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[57 = ^]
+ {keycode: 57, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x39, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x39, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[48 = @]
+ {keycode: 48, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x30, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x30, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[219 = ]]
+ {keycode: 219, browser: "Chrome", entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x2d, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x2d, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[169 = ]]
+ {keycode: 169, browser: "Firefox", entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x2d, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x2d, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[187 = }]
+ {keycode: 187, browser: "Chrome", entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x3d, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x3d, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[61 = }]
+ {keycode: 61, browser: "Firefox", entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x3d, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x3d, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+//ROW 2 AltGr
+ //[69 = â¬]
+ {keycode: 69, entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x65, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x65, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[186 = ¤]
+ {keycode: 186, browser: "Chrome", entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x5d, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x5d, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]},
+ //[164 = ¤]
+ {keycode: 164, browser: "Firefox", entry: [
+ {type: KEY_DOWN, code: 0xffea, modifiers: 0,
altgr: true},
+ {type: KEY_DOWN, code: 0x5d, modifiers: 0,
altgr: true},
+ {type: KEY_UP, code: 0x5d, modifiers: 0, altgr:
true},
+ {type: KEY_UP, code: 0xffea, modifiers: 0,
altgr: true}
+ ]}
+ ],
+ keyPress: [
+//ROW 1
+ //[178 = ²]
+ {keycode: 178, entry: [
+ {type: KEY_DOWN, code: 0x60, modifiers: 0},
+ {type: KEY_UP, code: 0x60, modifiers: 0}
+ ]},
+ //[38 = &]
+ {keycode: 38, entry: [
+ {type: KEY_DOWN, code: 0x31, modifiers: 0},
+ {type: KEY_UP, code: 0x31, modifiers: 0}
+ ]},
+ //[233 = é]
+ {keycode: 233, entry: [
+ {type: KEY_DOWN, code: 0x32, modifiers: 0},
+ {type: KEY_UP, code: 0x32, modifiers: 0}
+ ]},
+ //[34 = "]
+ {keycode: 34, entry: [
+ {type: KEY_DOWN, code: 0x33, modifiers: 0},
+ {type: KEY_UP, code: 0x33, modifiers: 0}
+ ]},
+ //[39 = ']
+ {keycode: 39, entry: [
+ {type: KEY_DOWN, code: 0x34, modifiers: 0},
+ {type: KEY_UP, code: 0x34, modifiers: 0}
+ ]},
+ //[40 = (]
+ {keycode: 40, entry: [
+ {type: KEY_DOWN, code: 0x35, modifiers: 0},
+ {type: KEY_UP, code: 0x35, modifiers: 0}
+ ]},
+ //[45 = -]
+ {keycode: 45, entry: [
+ {type: KEY_DOWN, code: 0x36, modifiers: 0},
+ {type: KEY_UP, code: 0x36, modifiers: 0}
+ ]},
+ //[232 = è]
+ {keycode: 232, entry: [
+ {type: KEY_DOWN, code: 0x37, modifiers: 0},
+ {type: KEY_UP, code: 0x37, modifiers: 0}
+ ]},
+ //[95 = _]
+ {keycode: 95, entry: [
+ {type: KEY_DOWN, code: 0x38, modifiers: 0},
+ {type: KEY_UP, code: 0x38, modifiers: 0}
+ ]},
+ //[231 = ç]
+ {keycode: 231, entry: [
+ {type: KEY_DOWN, code: 0x39, modifiers: 0},
+ {type: KEY_UP, code: 0x39, modifiers: 0}
+ ]},
+ //[224 = Ã ]
+ {keycode: 224, entry: [
+ {type: KEY_DOWN, code: 0x30, modifiers: 0},
+ {type: KEY_UP, code: 0x30, modifiers: 0}
+ ]},
+ //[41 = )]
+ {keycode: 41, entry: [
+ {type: KEY_DOWN, code: 0x2d, modifiers: 0},
+ {type: KEY_UP, code: 0x2d, modifiers: 0}
+ ]},
+ //[176 = =]
+ {keycode: 176, entry: [
+ {type: KEY_DOWN, code: 0x2d, modifiers: 64},
+ {type: KEY_UP, code: 0x2d, modifiers: 64}
+ ]},
+ //[181 = µ]
+ {keycode: 181, entry: [
+ {type: KEY_DOWN, code: 0x5c, modifiers: 64},
+ {type: KEY_UP, code: 0x5c, modifiers: 64}
+ ]},
+
+//ROW 2
+ //[97 = a]
+ {keycode: 97, entry: [
+ {type: KEY_DOWN, code: 0x71, modifiers: 0},
+ {type: KEY_UP, code: 0x71, modifiers: 0}
+ ]},
+ //[65 = A]
+ {keycode: 65, entry: [
+ {type: KEY_DOWN, code: 0x51, modifiers: 64},
+ {type: KEY_UP, code: 0x51, modifiers: 64}
+ ]},
+ //[122 = z]
+ {keycode: 122, entry: [
+ {type: KEY_DOWN, code: 0x77, modifiers: 0},
+ {type: KEY_UP, code: 0x77, modifiers: 0}
+ ]},
+ //[90 = Z]
+ {keycode: 90, entry: [
+ {type: KEY_DOWN, code: 0x57, modifiers: 64},
+ {type: KEY_UP, code: 0x57, modifiers: 64}
+ ]},
+ //[94 = ^]
+ {keycode: 94, entry: [
+ {type: KEY_DOWN, code: 0x5b, modifiers: 0},
+ {type: KEY_UP, code: 0x5b, modifiers: 0}
+ ]},
+ //[168 = ¨]
+ {keycode: 168, entry: [
+ {type: KEY_DOWN, code: 0x5b, modifiers: 64},
+ {type: KEY_UP, code: 0x5b, modifiers: 64}
+ ]},
+ //[36 = $]
+ {keycode: 36, entry: [
+ {type: KEY_DOWN, code: 0x5d, modifiers: 0},
+ {type: KEY_UP, code: 0x5d, modifiers: 0}
+ ]},
+ //[163 = £]
+ {keycode: 163, entry: [
+ {type: KEY_DOWN, code: 0x5d, modifiers: 64},
+ {type: KEY_UP, code: 0x5d, modifiers: 64}
+ ]},
+
+//ROW 3
+ //[113 = q]
+ {keycode: 113, entry: [
+ {type: KEY_DOWN, code: 0x61, modifiers: 0},
+ {type: KEY_UP, code: 0x61, modifiers: 0}
+ ]},
+ //[81 = Q]
+ {keycode: 81, entry: [
+ {type: KEY_DOWN, code: 0x41, modifiers: 64},
+ {type: KEY_UP, code: 0x41, modifiers: 64}
+ ]},
+ //[109 = m]
+ {keycode: 109, entry: [
+ {type: KEY_DOWN, code: 0x3b, modifiers: 0},
+ {type: KEY_UP, code: 0x3b, modifiers: 0}
+ ]},
+ //[77 = M]
+ {keycode: 77, entry: [
+ {type: KEY_DOWN, code: 0x3b, modifiers: 64},
+ {type: KEY_UP, code: 0x3b, modifiers: 64}
+ ]},
+ //[249 = ù]
+ {keycode: 249, entry: [
+ {type: KEY_DOWN, code: 0x27, modifiers: 0},
+ {type: KEY_UP, code: 0x27, modifiers: 0}
+ ]},
+ //[37 = %]
+ {keycode: 37, entry: [
+ {type: KEY_DOWN, code: 0x27, modifiers: 64},
+ {type: KEY_UP, code: 0x27, modifiers: 64}
+ ]},
+
+//ROW 4
+//need to add "<" ">" key
+ //[119 = w]
+ {keycode: 119, entry: [
+ {type: KEY_DOWN, code: 0x7a, modifiers: 0},
+ {type: KEY_UP, code: 0x7a, modifiers: 0}
+ ]},
+ //[87 = W]
+ {keycode: 87, entry: [
+ {type: KEY_DOWN, code: 0x5a, modifiers: 64},
+ {type: KEY_UP, code: 0x5a, modifiers: 64}
+ ]},
+ //[44 = ,]
+ {keycode: 44, entry: [
+ {type: KEY_DOWN, code: 0x6d, modifiers: 0},
+ {type: KEY_UP, code: 0x6d, modifiers: 0}
+ ]},
+ //[63 = ?]
+ {keycode: 63, entry: [
+ {type: KEY_DOWN, code: 0x4d, modifiers: 64},
+ {type: KEY_UP, code: 0x4d, modifiers: 64}
+ ]},
+ //[59 = ;]
+ {keycode: 59, entry: [
+ {type: KEY_DOWN, code: 0x2c, modifiers: 0},
+ {type: KEY_UP, code: 0x2c, modifiers: 0}
+ ]},
+ //[46 = .]
+ {keycode: 46, entry: [
+ {type: KEY_DOWN, code: 0x2c, modifiers: 64},
+ {type: KEY_UP, code: 0x2c, modifiers: 64}
+ ]},
+ //[58 = :]
+ {keycode: 58, entry: [
+ {type: KEY_DOWN, code: 0x2e, modifiers: 0},
+ {type: KEY_UP, code: 0x2e, modifiers: 0}
+ ]},
+ //[47 = /]
+ {keycode: 47, entry: [
+ {type: KEY_DOWN, code: 0x2e, modifiers: 64},
+ {type: KEY_UP, code: 0x2e, modifiers: 64}
+ ]},
+ //[33 = !]
+ {keycode: 33, entry: [
+ {type: KEY_DOWN, code: 0x2f, modifiers: 0},
+ {type: KEY_UP, code: 0x2f, modifiers: 0}
+ ]},
+ //[167 = §]
+ {keycode: 167, entry: [
+ {type: KEY_DOWN, code: 0x2f, modifiers: 64},
+ {type: KEY_UP, code: 0x2f, modifiers: 64}
+ ]},
+ ]
+ }}
+]
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6938b99f/services/console-proxy/server/js/ajaxviewer.js
----------------------------------------------------------------------
diff --git a/services/console-proxy/server/js/ajaxviewer.js
b/services/console-proxy/server/js/ajaxviewer.js
index 9643204..1d59aee 100644
--- a/services/console-proxy/server/js/ajaxviewer.js
+++ b/services/console-proxy/server/js/ajaxviewer.js
@@ -100,12 +100,13 @@ function KeyboardMapper() {
KeyboardMapper.KEYBOARD_TYPE_RAW = 0;
KeyboardMapper.KEYBOARD_TYPE_COOKED = 1;
KeyboardMapper.KEYBOARD_TYPE_UK = 2;
+KeyboardMapper.KEYBOARD_TYPE_FR = 3;
KeyboardMapper.prototype = {
setKeyboardType : function(keyboardType) {
this.keyboardType = keyboardType;
- if(keyboardType == KeyboardMapper.KEYBOARD_TYPE_COOKED ||
keyboardType == KeyboardMapper.KEYBOARD_TYPE_UK) {
+ if(keyboardType == KeyboardMapper.KEYBOARD_TYPE_COOKED ||
keyboardType == KeyboardMapper.KEYBOARD_TYPE_UK || keyboardType ==
KeyboardMapper.KEYBOARD_TYPE_FR) {
// initialize mapping for COOKED keyboard
this.jsX11KeysymMap[AjaxViewer.JS_KEY_CAPSLOCK]
= AjaxViewer.X11_KEY_CAPSLOCK;
this.jsX11KeysymMap[AjaxViewer.JS_KEY_BACKSPACE]
= AjaxViewer.X11_KEY_BACKSPACE;
@@ -305,7 +306,14 @@ KeyboardMapper.prototype = {
if(entry.shift ^ shift)
return false;
}
-
+
+ // Consider Alt+Ctrl as AltGr
+ if(entry.altgr != undefined){
+ var altgr = ((modifiers &
AjaxViewer.ALT_KEY_MASK) && (modifiers & AjaxViewer.CTRL_KEY_MASK)) != 0 ? true
: false;
+ if(entry.altgr ^ altgr)
+ return false;
+ }
+
if(entry.guestos != undefined) {
if(entry.guestos != guestos)
return false;
@@ -332,7 +340,7 @@ KeyboardMapper.prototype = {
/////////////////////////////////////////////////////////////////////////////
// class AjaxViewer
//
-function AjaxViewer(panelId, imageUrl, updateUrl, tileMap, width, height,
tileWidth, tileHeight) {
+function AjaxViewer(panelId, imageUrl, updateUrl, locale, tileMap, width,
height, tileWidth, tileHeight) {
// logging is disabled by default so that it won't have negative impact
on performance
// however, a back door key-sequence can trigger to open the logger
window, it is designed to help
// trouble-shooting
@@ -358,8 +366,12 @@ function AjaxViewer(panelId, imageUrl, updateUrl, tileMap,
width, height, tileWi
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.maxTileZIndex = 1;
-
- this.currentKeyboard = AjaxViewer.KEYBOARD_TYPE_ENGLISH;
+
+
+ if (locale == AjaxViewer.KEYBOARD_TYPE_UK_ENGLISH || locale ==
AjaxViewer.KEYBOARD_TYPE_JAPANESE || locale == AjaxViewer.KEYBOARD_TYPE_FRENCH)
+ this.currentKeyboard = locale;
+ else
+ this.currentKeyboard = AjaxViewer.KEYBOARD_TYPE_ENGLISH;
this.keyboardMappers = [];
this.timer = 0;
@@ -407,6 +419,7 @@ AjaxViewer.STATUS_SENT = 4;
AjaxViewer.KEYBOARD_TYPE_ENGLISH = "us";
AjaxViewer.KEYBOARD_TYPE_UK_ENGLISH = "uk";
AjaxViewer.KEYBOARD_TYPE_JAPANESE = "jp";
+AjaxViewer.KEYBOARD_TYPE_FRENCH = "fr";
AjaxViewer.JS_KEY_BACKSPACE = 8;
AjaxViewer.JS_KEY_TAB = 9;
@@ -676,6 +689,10 @@ AjaxViewer.prototype = {
this.keyboardMappers[AjaxViewer.KEYBOARD_TYPE_JAPANESE] =
mapper;
mapper.setKeyboardType(KeyboardMapper.KEYBOARD_TYPE_RAW);
+ var mapper = new KeyboardMapper();
+ this.keyboardMappers[AjaxViewer.KEYBOARD_TYPE_FRENCH] = mapper;
+ mapper.setKeyboardType(KeyboardMapper.KEYBOARD_TYPE_FR);
+
// JP keyboard plugged in a English host OS
/*
mapper.jsX11KeysymMap[AjaxViewer.JS_KEY_JP_COLON] =
AjaxViewer.X11_KEY_COLON;
@@ -806,6 +823,9 @@ AjaxViewer.prototype = {
} else if(cmd == "keyboard_uk") {
$("#toolbar").find(".pulldown").find("ul").hide();
this.currentKeyboard =
AjaxViewer.KEYBOARD_TYPE_UK_ENGLISH;
+ } else if(cmd == "keyboard_fr") {
+ $("#toolbar").find(".pulldown").find("ul").hide();
+ this.currentKeyboard = AjaxViewer.KEYBOARD_TYPE_FRENCH;
} else if(cmd == "sendCtrlAltDel") {
this.sendKeyboardEvent(AjaxViewer.KEY_DOWN, 0xffe9, 0);
// X11 Alt
this.sendKeyboardEvent(AjaxViewer.KEY_DOWN, 0xffe3, 0);
// X11 Ctrl
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6938b99f/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
----------------------------------------------------------------------
diff --git
a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
index 07a1b6f..6fa9409 100644
---
a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
+++
b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
@@ -333,6 +333,7 @@ public abstract class ConsoleProxyClientBase implements
ConsoleProxyClient, Cons
"<li><a href=\"#\" cmd=\"keyboard_us\"><span>Standard
(US) keyboard</span></a></li>",
"<li><a href=\"#\" cmd=\"keyboard_uk\"><span>UK
keyboard</span></a></li>",
"<li><a href=\"#\" cmd=\"keyboard_jp\"><span>Japanese
keyboard</span></a></li>",
+ "<li><a href=\"#\" cmd=\"keyboard_fr\"><span>French
AZERTY keyboard</span></a></li>",
"</ul>",
"</li>",
"</ul>",