JA
games/xencenter-xenadmin-xcp-jumphp / src / Vnc / Scancodes.php · commit fb1b7c9
<?phpnamespace App\Vnc;/** * Physical keys for the QEMU Extended Key Event of RFB (what XenCenter sends, noVNC too): XCP-ng's consoles are QEMU's VNC * server, which turns a plain key event (a keysym: the character) back into a key of a US keyboard; a VM set to another layout * (AZERTY) then reads that key with its own layout: "a" typed came out as "q". With the extension the client sends the key * itself (where it is on the keyboard) and the VM's own layout makes the character, as on a real keyboard. * * SDL scancodes are USB HID usages (the physical key, whatever the layout: the browser's KeyboardEvent.code too); QEMU wants * XT set 1 codes (0xE0xx for the extended ones). */final class Scancodes{    /** SDL scancode (USB HID usage) => XT set 1 code */    public const XT = [        4 => 0x1E, 5 => 0x30, 6 => 0x2E, 7 => 0x20, 8 => 0x12, 9 => 0x21, 10 => 0x22, 11 => 0x23, 12 => 0x17, 13 => 0x24,      // A..J        14 => 0x25, 15 => 0x26, 16 => 0x32, 17 => 0x31, 18 => 0x18, 19 => 0x19, 20 => 0x10, 21 => 0x13, 22 => 0x1F, 23 => 0x14, // K..T        24 => 0x16, 25 => 0x2F, 26 => 0x11, 27 => 0x2D, 28 => 0x15, 29 => 0x2C,                                                  // U..Z        30 => 0x02, 31 => 0x03, 32 => 0x04, 33 => 0x05, 34 => 0x06, 35 => 0x07, 36 => 0x08, 37 => 0x09, 38 => 0x0A, 39 => 0x0B, // 1..0        40 => 0x1C, 41 => 0x01, 42 => 0x0E, 43 => 0x0F, 44 => 0x39,                          // Return Escape Backspace Tab Space        45 => 0x0C, 46 => 0x0D, 47 => 0x1A, 48 => 0x1B, 49 => 0x2B, 50 => 0x2B, 51 => 0x27, 52 => 0x28, 53 => 0x29,        54 => 0x33, 55 => 0x34, 56 => 0x35, 57 => 0x3A,                                      // , . / CapsLock        58 => 0x3B, 59 => 0x3C, 60 => 0x3D, 61 => 0x3E, 62 => 0x3F, 63 => 0x40, 64 => 0x41, 65 => 0x42, 66 => 0x43, 67 => 0x44, // F1..F10        68 => 0x57, 69 => 0x58,                                                               // F11 F12        70 => 0xE037, 71 => 0x46, 73 => 0xE052, 74 => 0xE047, 75 => 0xE049, 76 => 0xE053, 77 => 0xE04F, 78 => 0xE051,        79 => 0xE04D, 80 => 0xE04B, 81 => 0xE050, 82 => 0xE048,                               // arrows: right left down up        83 => 0x45, 84 => 0xE035, 85 => 0x37, 86 => 0x4A, 87 => 0x4E, 88 => 0xE01C,           // keypad        89 => 0x4F, 90 => 0x50, 91 => 0x51, 92 => 0x4B, 93 => 0x4C, 94 => 0x4D, 95 => 0x47, 96 => 0x48, 97 => 0x49, 98 => 0x52, 99 => 0x53,        100 => 0x56,                                                                          // the < > key of European keyboards        101 => 0xE05D,                                                                        // Menu        224 => 0x1D, 225 => 0x2A, 226 => 0x38, 227 => 0xE05B, 228 => 0xE01D, 229 => 0x36, 230 => 0xE038, 231 => 0xE05C, // modifiers (230 = AltGr)    ];    public const F = 9;    public const LCTRL = 224;    public const LALT = 226;    public const RCTRL = 228;    public const RALT = 230;    /** The XT code as the extended key event carries it: 0xE0xx -> 0x80 | xx (QEMU's and noVNC's encoding). */    public static function rfb(int $xt): int    {        return ($xt >> 8) === 0xE0 ? (($xt & 0x7F) | 0x80) : $xt;    }    /** @param array<int, int|bool> $state SDL_GetKeyboardState(): scancode => 0 / 1 @return list<int> the known keys held */    public static function held(array $state): array    {        $out = [];        foreach (self::XT as $scancode => $xt) {            if (!empty($state[$scancode])) {                $out[] = $scancode;            }        }        return $out;    }}