mirror of
				https://github.com/retspen/webvirtcloud
				synced 2025-07-31 12:41:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			208 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
| import KeyTable from "./keysym.js";
 | |
| import keysyms from "./keysymdef.js";
 | |
| import vkeys from "./vkeys.js";
 | |
| import fixedkeys from "./fixedkeys.js";
 | |
| import DOMKeyTable from "./domkeytable.js";
 | |
| import * as browser from "../util/browser.js";
 | |
| 
 | |
| // Get 'KeyboardEvent.code', handling legacy browsers
 | |
| export function getKeycode(evt) {
 | |
|     // Are we getting proper key identifiers?
 | |
|     // (unfortunately Firefox and Chrome are crappy here and gives
 | |
|     // us an empty string on some platforms, rather than leaving it
 | |
|     // undefined)
 | |
|     if (evt.code) {
 | |
|         // Mozilla isn't fully in sync with the spec yet
 | |
|         switch (evt.code) {
 | |
|             case 'OSLeft': return 'MetaLeft';
 | |
|             case 'OSRight': return 'MetaRight';
 | |
|         }
 | |
| 
 | |
|         return evt.code;
 | |
|     }
 | |
| 
 | |
|     // The de-facto standard is to use Windows Virtual-Key codes
 | |
|     // in the 'keyCode' field for non-printable characters. However
 | |
|     // Webkit sets it to the same as charCode in 'keypress' events.
 | |
|     if ((evt.type !== 'keypress') && (evt.keyCode in vkeys)) {
 | |
|         let code = vkeys[evt.keyCode];
 | |
| 
 | |
|         // macOS has messed up this code for some reason
 | |
|         if (browser.isMac() && (code === 'ContextMenu')) {
 | |
|             code = 'MetaRight';
 | |
|         }
 | |
| 
 | |
|         // The keyCode doesn't distinguish between left and right
 | |
|         // for the standard modifiers
 | |
|         if (evt.location === 2) {
 | |
|             switch (code) {
 | |
|                 case 'ShiftLeft': return 'ShiftRight';
 | |
|                 case 'ControlLeft': return 'ControlRight';
 | |
|                 case 'AltLeft': return 'AltRight';
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Nor a bunch of the numpad keys
 | |
|         if (evt.location === 3) {
 | |
|             switch (code) {
 | |
|                 case 'Delete': return 'NumpadDecimal';
 | |
|                 case 'Insert': return 'Numpad0';
 | |
|                 case 'End': return 'Numpad1';
 | |
|                 case 'ArrowDown': return 'Numpad2';
 | |
|                 case 'PageDown': return 'Numpad3';
 | |
|                 case 'ArrowLeft': return 'Numpad4';
 | |
|                 case 'ArrowRight': return 'Numpad6';
 | |
|                 case 'Home': return 'Numpad7';
 | |
|                 case 'ArrowUp': return 'Numpad8';
 | |
|                 case 'PageUp': return 'Numpad9';
 | |
|                 case 'Enter': return 'NumpadEnter';
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return code;
 | |
|     }
 | |
| 
 | |
|     return 'Unidentified';
 | |
| }
 | |
| 
 | |
| // Get 'KeyboardEvent.key', handling legacy browsers
 | |
| export function getKey(evt) {
 | |
|     // Are we getting a proper key value?
 | |
|     if (evt.key !== undefined) {
 | |
|         // IE and Edge use some ancient version of the spec
 | |
|         // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
 | |
|         switch (evt.key) {
 | |
|             case 'Spacebar': return ' ';
 | |
|             case 'Esc': return 'Escape';
 | |
|             case 'Scroll': return 'ScrollLock';
 | |
|             case 'Win': return 'Meta';
 | |
|             case 'Apps': return 'ContextMenu';
 | |
|             case 'Up': return 'ArrowUp';
 | |
|             case 'Left': return 'ArrowLeft';
 | |
|             case 'Right': return 'ArrowRight';
 | |
|             case 'Down': return 'ArrowDown';
 | |
|             case 'Del': return 'Delete';
 | |
|             case 'Divide': return '/';
 | |
|             case 'Multiply': return '*';
 | |
|             case 'Subtract': return '-';
 | |
|             case 'Add': return '+';
 | |
|             case 'Decimal': return evt.char;
 | |
|         }
 | |
| 
 | |
|         // Mozilla isn't fully in sync with the spec yet
 | |
|         switch (evt.key) {
 | |
|             case 'OS': return 'Meta';
 | |
|             case 'LaunchMyComputer': return 'LaunchApplication1';
 | |
|             case 'LaunchCalculator': return 'LaunchApplication2';
 | |
|         }
 | |
| 
 | |
|         // iOS leaks some OS names
 | |
|         switch (evt.key) {
 | |
|             case 'UIKeyInputUpArrow': return 'ArrowUp';
 | |
|             case 'UIKeyInputDownArrow': return 'ArrowDown';
 | |
|             case 'UIKeyInputLeftArrow': return 'ArrowLeft';
 | |
|             case 'UIKeyInputRightArrow': return 'ArrowRight';
 | |
|             case 'UIKeyInputEscape': return 'Escape';
 | |
|         }
 | |
| 
 | |
|         // Broken behaviour in Chrome
 | |
|         if ((evt.key === '\x00') && (evt.code === 'NumpadDecimal')) {
 | |
|             return 'Delete';
 | |
|         }
 | |
| 
 | |
|         // IE and Edge need special handling, but for everyone else we
 | |
|         // can trust the value provided
 | |
|         if (!browser.isIE() && !browser.isEdge()) {
 | |
|             return evt.key;
 | |
|         }
 | |
| 
 | |
|         // IE and Edge have broken handling of AltGraph so we can only
 | |
|         // trust them for non-printable characters (and unfortunately
 | |
|         // they also specify 'Unidentified' for some problem keys)
 | |
|         if ((evt.key.length !== 1) && (evt.key !== 'Unidentified')) {
 | |
|             return evt.key;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Try to deduce it based on the physical key
 | |
|     const code = getKeycode(evt);
 | |
|     if (code in fixedkeys) {
 | |
|         return fixedkeys[code];
 | |
|     }
 | |
| 
 | |
|     // If that failed, then see if we have a printable character
 | |
|     if (evt.charCode) {
 | |
|         return String.fromCharCode(evt.charCode);
 | |
|     }
 | |
| 
 | |
|     // At this point we have nothing left to go on
 | |
|     return 'Unidentified';
 | |
| }
 | |
| 
 | |
| // Get the most reliable keysym value we can get from a key event
 | |
| export function getKeysym(evt) {
 | |
|     const key = getKey(evt);
 | |
| 
 | |
|     if (key === 'Unidentified') {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     // First look up special keys
 | |
|     if (key in DOMKeyTable) {
 | |
|         let location = evt.location;
 | |
| 
 | |
|         // Safari screws up location for the right cmd key
 | |
|         if ((key === 'Meta') && (location === 0)) {
 | |
|             location = 2;
 | |
|         }
 | |
| 
 | |
|         // And for Clear
 | |
|         if ((key === 'Clear') && (location === 3)) {
 | |
|             let code = getKeycode(evt);
 | |
|             if (code === 'NumLock') {
 | |
|                 location = 0;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ((location === undefined) || (location > 3)) {
 | |
|             location = 0;
 | |
|         }
 | |
| 
 | |
|         // The original Meta key now gets confused with the Windows key
 | |
|         // https://bugs.chromium.org/p/chromium/issues/detail?id=1020141
 | |
|         // https://bugzilla.mozilla.org/show_bug.cgi?id=1232918
 | |
|         if (key === 'Meta') {
 | |
|             let code = getKeycode(evt);
 | |
|             if (code === 'AltLeft') {
 | |
|                 return KeyTable.XK_Meta_L;
 | |
|             } else if (code === 'AltRight') {
 | |
|                 return KeyTable.XK_Meta_R;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // macOS has Clear instead of NumLock, but the remote system is
 | |
|         // probably not macOS, so lying here is probably best...
 | |
|         if (key === 'Clear') {
 | |
|             let code = getKeycode(evt);
 | |
|             if (code === 'NumLock') {
 | |
|                 return KeyTable.XK_Num_Lock;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return DOMKeyTable[key][location];
 | |
|     }
 | |
| 
 | |
|     // Now we need to look at the Unicode symbol instead
 | |
| 
 | |
|     // Special key? (FIXME: Should have been caught earlier)
 | |
|     if (key.length !== 1) {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     const codepoint = key.charCodeAt();
 | |
|     if (codepoint) {
 | |
|         return keysyms.lookup(codepoint);
 | |
|     }
 | |
| 
 | |
|     return null;
 | |
| }
 |