]>
Commit | Line | Data |
---|---|---|
c4164bda JM |
1 | /* |
2 | * noVNC: HTML5 VNC client | |
af6b17ce JM |
3 | * Copyright (C) 2010 Joel Martin |
4 | * Licensed under LGPL-3 (see LICENSE.LGPL-3) | |
c4164bda JM |
5 | * |
6 | * See README.md for usage and integration instructions. | |
7 | */ | |
c4164bda | 8 | |
15046f00 JM |
9 | "use strict"; |
10 | /*jslint white: false, bitwise: false */ | |
11 | /*global window, console, $, Util */ | |
c4164bda | 12 | |
d93d3e09 JM |
13 | var Canvas, Canvas_native; |
14 | ||
15 | (function () { | |
48eed1ac | 16 | var pre, start = "<script src='", end = "'><\/script>"; |
d93d3e09 JM |
17 | if (document.createElement('canvas').getContext) { |
18 | Canvas_native = true; | |
19 | } else { | |
48eed1ac JM |
20 | pre = (typeof VNC_uri_prefix !== "undefined") ? |
21 | VNC_uri_prefix : "include/"; | |
22 | document.write(start + pre + "excanvas.js" + end); | |
d93d3e09 | 23 | Canvas_native = false; |
d93d3e09 JM |
24 | } |
25 | }()); | |
26 | ||
c4164bda | 27 | // Everything namespaced inside Canvas |
d93d3e09 | 28 | Canvas = { |
c8460b03 | 29 | |
d93d3e09 | 30 | prefer_js : false, |
5235b29d | 31 | force_canvas : false, |
97763d0e | 32 | |
d41c33e4 JM |
33 | true_color : false, |
34 | colourMap : [], | |
35 | ||
c8460b03 JM |
36 | c_wx : 0, |
37 | c_wy : 0, | |
64ab5c4d | 38 | ctx : null, |
c8460b03 | 39 | |
48ebcdb1 JM |
40 | prevStyle: "", |
41 | ||
15046f00 | 42 | focused : true, |
e2e7c224 JM |
43 | keyPress : null, |
44 | mouseButton : null, | |
45 | mouseMove : null, | |
46 | ||
e2e7c224 | 47 | onMouseButton: function(e, down) { |
61dd52c9 | 48 | var evt, pos, bmask; |
15046f00 JM |
49 | evt = (e ? e : window.event); |
50 | pos = Util.getEventPosition(e, $(Canvas.id)); | |
e2e7c224 | 51 | bmask = 1 << evt.button; |
15046f00 | 52 | //console.log('mouse ' + pos.x + "," + pos.y + " down: " + down + " bmask: " + bmask); |
e2e7c224 | 53 | if (Canvas.mouseButton) { |
61dd52c9 | 54 | Canvas.mouseButton(pos.x, pos.y, down, bmask); |
e2e7c224 | 55 | } |
15046f00 | 56 | Util.stopEvent(e); |
e2e7c224 | 57 | return false; |
c8460b03 | 58 | }, |
f272267b | 59 | |
e2e7c224 JM |
60 | onMouseDown: function (e) { |
61 | Canvas.onMouseButton(e, 1); | |
c8460b03 | 62 | }, |
f272267b | 63 | |
e2e7c224 JM |
64 | onMouseUp: function (e) { |
65 | Canvas.onMouseButton(e, 0); | |
8cf20615 JM |
66 | }, |
67 | ||
e2e7c224 | 68 | onMouseWheel: function (e) { |
15046f00 JM |
69 | var evt, pos, bmask, wheelData; |
70 | evt = (e ? e : window.event); | |
71 | pos = Util.getEventPosition(e, $(Canvas.id)); | |
72 | wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40; | |
e2e7c224 JM |
73 | if (wheelData > 0) { |
74 | bmask = 1 << 3; | |
75 | } else { | |
76 | bmask = 1 << 4; | |
77 | } | |
61dd52c9 | 78 | //console.log('mouse scroll by ' + wheelData + ':' + pos.x + "," + pos.y); |
e2e7c224 | 79 | if (Canvas.mouseButton) { |
61dd52c9 JM |
80 | Canvas.mouseButton(pos.x, pos.y, 1, bmask); |
81 | Canvas.mouseButton(pos.x, pos.y, 0, bmask); | |
e2e7c224 | 82 | } |
15046f00 | 83 | Util.stopEvent(e); |
e2e7c224 | 84 | return false; |
a575a383 JM |
85 | }, |
86 | ||
8cf20615 | 87 | |
e2e7c224 | 88 | onMouseMove: function (e) { |
61dd52c9 | 89 | var evt, pos; |
15046f00 JM |
90 | evt = (e ? e : window.event); |
91 | pos = Util.getEventPosition(e, $(Canvas.id)); | |
61dd52c9 JM |
92 | //console.log('mouse ' + evt.which + '/' + evt.button + ' up:' + pos.x + "," + pos.y); |
93 | if (Canvas.mouseMove) { | |
94 | Canvas.mouseMove(pos.x, pos.y); | |
e2e7c224 JM |
95 | } |
96 | }, | |
97 | ||
98 | onKeyDown: function (e) { | |
15046f00 JM |
99 | //console.log("keydown: " + Canvas.getKeysym(e)); |
100 | if (! Canvas.focused) { | |
101 | return true; | |
102 | } | |
e2e7c224 JM |
103 | if (Canvas.keyPress) { |
104 | Canvas.keyPress(Canvas.getKeysym(e), 1); | |
105 | } | |
15046f00 | 106 | Util.stopEvent(e); |
e2e7c224 | 107 | return false; |
c8460b03 | 108 | }, |
f272267b | 109 | |
e2e7c224 | 110 | onKeyUp : function (e) { |
d93d3e09 | 111 | //console.log("keyup: " + Canvas.getKeysym(e)); |
15046f00 JM |
112 | if (! Canvas.focused) { |
113 | return true; | |
114 | } | |
e2e7c224 JM |
115 | if (Canvas.keyPress) { |
116 | Canvas.keyPress(Canvas.getKeysym(e), 0); | |
117 | } | |
15046f00 | 118 | Util.stopEvent(e); |
e2e7c224 | 119 | return false; |
c8460b03 | 120 | }, |
f272267b | 121 | |
e2e7c224 | 122 | onMouseDisable: function (e) { |
61dd52c9 | 123 | var evt, pos; |
15046f00 JM |
124 | evt = (e ? e : window.event); |
125 | pos = Util.getPosition($(Canvas.id)); | |
f272267b | 126 | /* Stop propagation if inside canvas area */ |
61dd52c9 JM |
127 | if ((evt.clientX >= pos.x) && |
128 | (evt.clientY >= pos.y) && | |
129 | (evt.clientX < (pos.x + Canvas.c_wx)) && | |
130 | (evt.clientY < (pos.y + Canvas.c_wy))) { | |
15046f00 JM |
131 | //console.log("mouse event disabled"); |
132 | Util.stopEvent(e); | |
f272267b | 133 | return false; |
c4164bda | 134 | } |
15046f00 JM |
135 | //console.log("mouse event not disabled"); |
136 | return true; | |
c8460b03 | 137 | }, |
f272267b JM |
138 | |
139 | ||
d93d3e09 JM |
140 | init: function (id) { |
141 | var c, imgTest, arora; | |
15046f00 | 142 | console.log(">> Canvas.init"); |
f272267b | 143 | |
532a9fd9 | 144 | Canvas.id = id; |
d93d3e09 JM |
145 | c = $(Canvas.id); |
146 | ||
147 | if (Canvas_native) { | |
148 | console.log("Using native canvas"); | |
149 | // Use default Canvas functions | |
150 | } else { | |
151 | console.warn("Using excanvas canvas emulation"); | |
48eed1ac | 152 | //G_vmlCanvasManager.init(c); |
d93d3e09 JM |
153 | G_vmlCanvasManager.initElement(c); |
154 | } | |
155 | ||
156 | if (! c.getContext) { throw("No getContext method"); } | |
157 | Canvas.ctx = c.getContext('2d'); | |
158 | ||
159 | Canvas.clear(); | |
160 | ||
d93d3e09 | 161 | /* |
48eed1ac JM |
162 | * Determine browser Canvas feature support |
163 | * and select fastest rendering methods | |
d93d3e09 JM |
164 | */ |
165 | tval = 0; | |
48eed1ac | 166 | Canvas.has_imageData = false; |
d93d3e09 JM |
167 | try { |
168 | imgTest = Canvas.ctx.getImageData(0, 0, 1,1); | |
169 | imgTest.data[0] = 123; | |
170 | imgTest.data[3] = 255; | |
171 | Canvas.ctx.putImageData(imgTest, 0, 0); | |
172 | tval = Canvas.ctx.getImageData(0, 0, 1, 1).data[0]; | |
48eed1ac JM |
173 | if (tval === 123) { |
174 | Canvas.has_imageData = true; | |
175 | } | |
176 | } catch (exc) {} | |
177 | ||
178 | if (Canvas.has_imageData) { | |
179 | console.log("Canvas supports imageData"); | |
5235b29d | 180 | Canvas.force_canvas = false; |
d93d3e09 JM |
181 | if (Canvas.ctx.createImageData) { |
182 | // If it's there, it's faster | |
183 | console.log("Using Canvas createImageData"); | |
184 | Canvas._imageData = Canvas._imageDataCreate; | |
185 | } else if (Canvas.ctx.getImageData) { | |
186 | console.log("Using Canvas getImageData"); | |
187 | Canvas._imageData = Canvas._imageDataGet; | |
d93d3e09 | 188 | } |
67134184 JM |
189 | console.log("Prefering javascript operations"); |
190 | Canvas.prefer_js = true; | |
5235b29d JM |
191 | Canvas._rgbxImage = Canvas._rgbxImageData; |
192 | Canvas._cmapImage = Canvas._cmapImageData; | |
d93d3e09 | 193 | } else { |
48eed1ac | 194 | console.log("Canvas lacks imageData, using fillRect (slow)"); |
5235b29d JM |
195 | Canvas.force_canvas = true; |
196 | Canvas.prefer_js = false; | |
d93d3e09 JM |
197 | Canvas._rgbxImage = Canvas._rgbxImageFill; |
198 | Canvas._cmapImage = Canvas._cmapImageFill; | |
d93d3e09 | 199 | } |
532a9fd9 | 200 | |
d93d3e09 JM |
201 | Canvas.colourMap = []; |
202 | Canvas.prevStyle = ""; | |
203 | Canvas.focused = true; | |
204 | ||
205 | //console.log("<< Canvas.init"); | |
206 | return true; | |
207 | }, | |
208 | ||
209 | ||
210 | start: function (keyPress, mouseButton, mouseMove) { | |
211 | var c; | |
212 | console.log(">> Canvas.start"); | |
213 | ||
214 | c = $(Canvas.id); | |
e2e7c224 JM |
215 | Canvas.keyPress = keyPress || null; |
216 | Canvas.mouseButton = mouseButton || null; | |
217 | Canvas.mouseMove = mouseMove || null; | |
64ab5c4d | 218 | |
15046f00 JM |
219 | Util.addEvent(document, 'keydown', Canvas.onKeyDown); |
220 | Util.addEvent(document, 'keyup', Canvas.onKeyUp); | |
221 | Util.addEvent(c, 'mousedown', Canvas.onMouseDown); | |
222 | Util.addEvent(c, 'mouseup', Canvas.onMouseUp); | |
223 | Util.addEvent(c, 'mousemove', Canvas.onMouseMove); | |
224 | Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', | |
225 | Canvas.onMouseWheel); | |
f272267b JM |
226 | |
227 | /* Work around right and middle click browser behaviors */ | |
15046f00 JM |
228 | Util.addEvent(document, 'click', Canvas.onMouseDisable); |
229 | Util.addEvent(document.body, 'contextmenu', Canvas.onMouseDisable); | |
f272267b | 230 | |
d93d3e09 | 231 | //console.log("<< Canvas.start"); |
532a9fd9 JM |
232 | }, |
233 | ||
234 | clear: function () { | |
4b4496ad | 235 | Canvas.resize(640, 20); |
d93d3e09 | 236 | Canvas.ctx.clearRect(0, 0, Canvas.c_wx, Canvas.c_wy); |
4b4496ad JM |
237 | }, |
238 | ||
d93d3e09 | 239 | resize: function (width, height, true_color) { |
31af85b9 | 240 | var c = $(Canvas.id); |
d93d3e09 JM |
241 | |
242 | if (typeof true_color !== "undefined") { | |
243 | Canvas.true_color = true_color; | |
244 | } | |
245 | ||
4b4496ad JM |
246 | c.width = width; |
247 | c.height = height; | |
d93d3e09 JM |
248 | |
249 | Canvas.c_wx = c.offsetWidth; | |
250 | Canvas.c_wy = c.offsetHeight; | |
31af85b9 JM |
251 | }, |
252 | ||
253 | stop: function () { | |
532a9fd9 | 254 | var c = $(Canvas.id); |
15046f00 JM |
255 | Util.removeEvent(document, 'keydown', Canvas.onKeyDown); |
256 | Util.removeEvent(document, 'keyup', Canvas.onKeyUp); | |
257 | Util.removeEvent(c, 'mousedown', Canvas.onMouseDown); | |
258 | Util.removeEvent(c, 'mouseup', Canvas.onMouseUp); | |
259 | Util.removeEvent(c, 'mousemove', Canvas.onMouseMove); | |
260 | Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', | |
261 | Canvas.onMouseWheel); | |
2bcb2d5b JM |
262 | |
263 | /* Work around right and middle click browser behaviors */ | |
15046f00 JM |
264 | Util.removeEvent(document, 'click', Canvas.onMouseDisable); |
265 | Util.removeEvent(document.body, 'contextmenu', Canvas.onMouseDisable); | |
532a9fd9 JM |
266 | }, |
267 | ||
3875f847 JM |
268 | /* |
269 | * Tile rendering functions optimized for rendering engines. | |
270 | * | |
271 | * - In Chrome/webkit, Javascript image data array manipulations are | |
272 | * faster than direct Canvas fillStyle, fillRect rendering. In | |
273 | * gecko, Javascript array handling is much slower. | |
274 | */ | |
275 | getTile: function(x, y, width, height, color) { | |
d41c33e4 | 276 | var img, data, p, rgb, red, green, blue, j, i; |
c4164bda JM |
277 | img = {'x': x, 'y': y, 'width': width, 'height': height, |
278 | 'data': []}; | |
97763d0e JM |
279 | if (Canvas.prefer_js) { |
280 | data = img.data; | |
d41c33e4 JM |
281 | if (Canvas.true_color) { |
282 | rgb = color; | |
283 | } else { | |
284 | rgb = Canvas.colourMap[color[0]]; | |
285 | } | |
286 | red = rgb[0]; | |
287 | green = rgb[1]; | |
288 | blue = rgb[2]; | |
15046f00 JM |
289 | for (j = 0; j < height; j += 1) { |
290 | for (i = 0; i < width; i += 1) { | |
3875f847 | 291 | p = (i + (j * width) ) * 4; |
d41c33e4 JM |
292 | data[p + 0] = red; |
293 | data[p + 1] = green; | |
294 | data[p + 2] = blue; | |
295 | //data[p + 3] = 255; // Set Alpha | |
3875f847 JM |
296 | } |
297 | } | |
298 | } else { | |
299 | Canvas.fillRect(x, y, width, height, color); | |
300 | } | |
301 | return img; | |
302 | }, | |
303 | ||
d93d3e09 | 304 | setSubTile: function(img, x, y, w, h, color) { |
d41c33e4 | 305 | var data, p, rgb, red, green, blue, width, j, i; |
97763d0e JM |
306 | if (Canvas.prefer_js) { |
307 | data = img.data; | |
c4164bda | 308 | width = img.width; |
d41c33e4 JM |
309 | if (Canvas.true_color) { |
310 | rgb = color; | |
311 | } else { | |
312 | rgb = Canvas.colourMap[color[0]]; | |
313 | } | |
314 | red = rgb[0]; | |
315 | green = rgb[1]; | |
316 | blue = rgb[2]; | |
15046f00 JM |
317 | for (j = 0; j < h; j += 1) { |
318 | for (i = 0; i < w; i += 1) { | |
3875f847 | 319 | p = (x + i + ((y + j) * width) ) * 4; |
97763d0e JM |
320 | data[p + 0] = red; |
321 | data[p + 1] = green; | |
322 | data[p + 2] = blue; | |
3875f847 JM |
323 | //img.data[p + 3] = 255; // Set Alpha |
324 | } | |
325 | } | |
326 | } else { | |
327 | Canvas.fillRect(img.x + x, img.y + y, w, h, color); | |
328 | } | |
329 | }, | |
330 | ||
331 | putTile: function(img) { | |
97763d0e | 332 | if (Canvas.prefer_js) { |
d93d3e09 | 333 | Canvas._rgbxImage(img.x, img.y, img.width, img.height, img.data, 0); |
3875f847 | 334 | } else { |
d93d3e09 | 335 | // No-op, under gecko already done by setSubTile |
3875f847 JM |
336 | } |
337 | }, | |
338 | ||
d93d3e09 JM |
339 | _imageDataGet: function(width, height) { |
340 | return Canvas.ctx.getImageData(0, 0, width, height); | |
341 | }, | |
342 | _imageDataCreate: function(width, height) { | |
343 | return Canvas.ctx.createImageData(width, height); | |
344 | }, | |
345 | _imageDataRaw: function(width, height) { | |
346 | return {'data': [], 'width': width, 'height': height}; | |
347 | }, | |
3875f847 | 348 | |
d93d3e09 | 349 | _rgbxImageData: function(x, y, width, height, arr, offset) { |
7f4f41b0 | 350 | var img, i, j, data; |
d93d3e09 | 351 | img = Canvas._imageData(width, height); |
97763d0e | 352 | data = img.data; |
d41c33e4 | 353 | for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) { |
7f4f41b0 JM |
354 | data[i + 0] = arr[j + 0]; |
355 | data[i + 1] = arr[j + 1]; | |
356 | data[i + 2] = arr[j + 2]; | |
357 | data[i + 3] = 255; // Set Alpha | |
64ab5c4d JM |
358 | } |
359 | Canvas.ctx.putImageData(img, x, y); | |
d41c33e4 | 360 | }, |
64ab5c4d | 361 | |
d93d3e09 JM |
362 | // really slow fallback if we don't have imageData |
363 | _rgbxImageFill: function(x, y, width, height, arr, offset) { | |
364 | var sx = 0, sy = 0; | |
365 | for (i=0, j=offset; i < (width * height); i+=1, j+=4) { | |
366 | Canvas.fillRect(x+sx, y+sy, 1, 1, [arr[j+0], arr[j+1], arr[j+2]]); | |
367 | sx += 1; | |
368 | if ((sx % width) === 0) { | |
369 | sx = 0; | |
370 | sy += 1; | |
371 | } | |
372 | } | |
373 | }, | |
374 | ||
375 | _cmapImageData: function(x, y, width, height, arr, offset) { | |
15046f00 | 376 | var img, i, j, data, rgb, cmap; |
d93d3e09 | 377 | img = Canvas._imageData(width, height); |
d41c33e4 JM |
378 | data = img.data; |
379 | cmap = Canvas.colourMap; | |
d93d3e09 | 380 | for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) { |
d41c33e4 JM |
381 | rgb = cmap[arr[j]]; |
382 | data[i + 0] = rgb[0]; | |
383 | data[i + 1] = rgb[1]; | |
384 | data[i + 2] = rgb[2]; | |
385 | data[i + 3] = 255; // Set Alpha | |
386 | } | |
387 | Canvas.ctx.putImageData(img, x, y); | |
388 | }, | |
389 | ||
d93d3e09 JM |
390 | _cmapImageFill: function(x, y, width, height, arr, offset) { |
391 | var sx = 0, sy = 0; | |
392 | cmap = Canvas.colourMap; | |
393 | console.log("here1: arr[2]: " + arr[2] + ", cmap[arr[2]]: " + cmap[arr[2]]); | |
394 | for (i=0, j=offset; i < (width * height); i+=1, j+=1) { | |
395 | Canvas.fillRect(x+sx, y+sy, 1, 1, [arr[j]]); | |
396 | sx += 1; | |
397 | if ((sx % width) === 0) { | |
398 | sx = 0; | |
399 | sy += 1; | |
400 | } | |
401 | } | |
402 | }, | |
403 | ||
404 | ||
d41c33e4 JM |
405 | blitImage: function(x, y, width, height, arr, offset) { |
406 | if (Canvas.true_color) { | |
d93d3e09 | 407 | Canvas._rgbxImage(x, y, width, height, arr, offset); |
d41c33e4 | 408 | } else { |
d93d3e09 | 409 | Canvas._cmapImage(x, y, width, height, arr, offset); |
d41c33e4 | 410 | } |
d9cbdc7d JM |
411 | }, |
412 | ||
d93d3e09 JM |
413 | blitStringImage: function(str, x, y) { |
414 | var img = new Image(); | |
415 | img.onload = function () { Canvas.ctx.drawImage(img, x, y); }; | |
416 | img.src = str; | |
417 | }, | |
418 | ||
419 | setFillColor: function(color) { | |
d41c33e4 JM |
420 | var rgb, newStyle; |
421 | if (Canvas.true_color) { | |
422 | rgb = color; | |
423 | } else { | |
424 | rgb = Canvas.colourMap[color[0]]; | |
425 | } | |
c4164bda | 426 | if (newStyle !== Canvas.prevStyle) { |
d41c33e4 | 427 | newStyle = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; |
48ebcdb1 | 428 | Canvas.ctx.fillStyle = newStyle; |
c4164bda | 429 | Canvas.prevStyle = newStyle; |
48ebcdb1 | 430 | } |
d93d3e09 JM |
431 | }, |
432 | ||
433 | fillRect: function(x, y, width, height, color) { | |
434 | Canvas.setFillColor(color); | |
ed7e776d JM |
435 | Canvas.ctx.fillRect(x, y, width, height); |
436 | }, | |
437 | ||
48617e27 JM |
438 | copyImage: function(old_x, old_y, new_x, new_y, width, height) { |
439 | Canvas.ctx.drawImage($(Canvas.id), old_x, old_y, width, height, | |
440 | new_x, new_y, width, height); | |
441 | }, | |
442 | ||
d9cbdc7d JM |
443 | /* Translate DOM key event to keysym value */ |
444 | getKeysym: function(e) { | |
c4164bda | 445 | var evt, keysym; |
15046f00 | 446 | evt = (e ? e : window.event); |
d9cbdc7d JM |
447 | |
448 | /* Remap modifier and special keys */ | |
449 | switch ( evt.keyCode ) { | |
450 | case 8 : keysym = 0xFF08; break; // BACKSPACE | |
451 | case 9 : keysym = 0xFF09; break; // TAB | |
452 | case 13 : keysym = 0xFF0D; break; // ENTER | |
453 | case 27 : keysym = 0xFF1B; break; // ESCAPE | |
454 | case 45 : keysym = 0xFF63; break; // INSERT | |
455 | case 46 : keysym = 0xFFFF; break; // DELETE | |
456 | case 36 : keysym = 0xFF50; break; // HOME | |
457 | case 35 : keysym = 0xFF57; break; // END | |
458 | case 33 : keysym = 0xFF55; break; // PAGE_UP | |
459 | case 34 : keysym = 0xFF56; break; // PAGE_DOWN | |
460 | case 37 : keysym = 0xFF51; break; // LEFT | |
461 | case 38 : keysym = 0xFF52; break; // UP | |
462 | case 39 : keysym = 0xFF53; break; // RIGHT | |
463 | case 40 : keysym = 0xFF54; break; // DOWN | |
464 | case 112 : keysym = 0xFFBE; break; // F1 | |
465 | case 113 : keysym = 0xFFBF; break; // F2 | |
466 | case 114 : keysym = 0xFFC0; break; // F3 | |
467 | case 115 : keysym = 0xFFC1; break; // F4 | |
468 | case 116 : keysym = 0xFFC2; break; // F5 | |
469 | case 117 : keysym = 0xFFC3; break; // F6 | |
470 | case 118 : keysym = 0xFFC4; break; // F7 | |
471 | case 119 : keysym = 0xFFC5; break; // F8 | |
472 | case 120 : keysym = 0xFFC6; break; // F9 | |
473 | case 121 : keysym = 0xFFC7; break; // F10 | |
474 | case 122 : keysym = 0xFFC8; break; // F11 | |
475 | case 123 : keysym = 0xFFC9; break; // F12 | |
476 | case 16 : keysym = 0xFFE1; break; // SHIFT | |
477 | case 17 : keysym = 0xFFE3; break; // CONTROL | |
2e041cf2 JM |
478 | //case 18 : keysym = 0xFFE7; break; // Left Meta (Mac Option) |
479 | case 18 : keysym = 0xFFE9; break; // Left ALT (Mac Command) | |
d9cbdc7d JM |
480 | default : keysym = evt.keyCode; break; |
481 | } | |
482 | ||
483 | /* Remap symbols */ | |
484 | switch (keysym) { | |
485 | case 186 : keysym = 59; break; // ; (IE) | |
486 | case 187 : keysym = 61; break; // = (IE) | |
487 | case 188 : keysym = 44; break; // , (Mozilla, IE) | |
9fec75c0 | 488 | case 109 : // - (Mozilla) |
15046f00 | 489 | if (Util.Engine.gecko) { |
c4164bda JM |
490 | keysym = 45; } |
491 | break; | |
d9cbdc7d JM |
492 | case 189 : keysym = 45; break; // - (IE) |
493 | case 190 : keysym = 46; break; // . (Mozilla, IE) | |
494 | case 191 : keysym = 47; break; // / (Mozilla, IE) | |
495 | case 192 : keysym = 96; break; // ` (Mozilla, IE) | |
496 | case 219 : keysym = 91; break; // [ (Mozilla, IE) | |
497 | case 220 : keysym = 92; break; // \ (Mozilla, IE) | |
498 | case 221 : keysym = 93; break; // ] (Mozilla, IE) | |
499 | case 222 : keysym = 39; break; // ' (Mozilla, IE) | |
500 | } | |
501 | ||
502 | /* Remap shifted and unshifted keys */ | |
503 | if (!!evt.shiftKey) { | |
504 | switch (keysym) { | |
505 | case 48 : keysym = 41 ; break; // ) (shifted 0) | |
506 | case 49 : keysym = 33 ; break; // ! (shifted 1) | |
507 | case 50 : keysym = 64 ; break; // @ (shifted 2) | |
508 | case 51 : keysym = 35 ; break; // # (shifted 3) | |
509 | case 52 : keysym = 36 ; break; // $ (shifted 4) | |
510 | case 53 : keysym = 37 ; break; // % (shifted 5) | |
511 | case 54 : keysym = 94 ; break; // ^ (shifted 6) | |
512 | case 55 : keysym = 38 ; break; // & (shifted 7) | |
513 | case 56 : keysym = 42 ; break; // * (shifted 8) | |
514 | case 57 : keysym = 40 ; break; // ( (shifted 9) | |
515 | ||
516 | case 59 : keysym = 58 ; break; // : (shifted `) | |
517 | case 61 : keysym = 43 ; break; // + (shifted ;) | |
518 | case 44 : keysym = 60 ; break; // < (shifted ,) | |
519 | case 45 : keysym = 95 ; break; // _ (shifted -) | |
520 | case 46 : keysym = 62 ; break; // > (shifted .) | |
521 | case 47 : keysym = 63 ; break; // ? (shifted /) | |
522 | case 96 : keysym = 126; break; // ~ (shifted `) | |
523 | case 91 : keysym = 123; break; // { (shifted [) | |
524 | case 92 : keysym = 124; break; // | (shifted \) | |
525 | case 93 : keysym = 125; break; // } (shifted ]) | |
526 | case 39 : keysym = 34 ; break; // " (shifted ') | |
527 | } | |
528 | } else if ((keysym >= 65) && (keysym <=90)) { | |
529 | /* Remap unshifted A-Z */ | |
530 | keysym += 32; | |
531 | } | |
532 | ||
533 | return keysym; | |
f272267b JM |
534 | } |
535 | ||
d9cbdc7d | 536 | |
c8460b03 JM |
537 | }; |
538 |