diff --git a/.circleci/config.yml b/.circleci/config.yml index ab832e39..b247266c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,6 +7,7 @@ jobs: docker: - image: tomaka/cargo-apk steps: + - run: apt-get -qq update && apt-get install -y git - checkout - restore_cache: key: android-test-cache-{{ checksum "Cargo.toml" }} @@ -21,6 +22,7 @@ jobs: docker: - image: tomaka/rustc-emscripten steps: + - run: apt-get -qq update && apt-get install -y git - checkout - restore_cache: key: asmjs-test-cache-{{ checksum "Cargo.toml" }} @@ -35,6 +37,7 @@ jobs: docker: - image: tomaka/rustc-emscripten steps: + - run: apt-get -qq update && apt-get install -y git - checkout - restore_cache: key: wasm-test-cache-{{ checksum "Cargo.toml" }} diff --git a/src/platform/emscripten/ffi.rs b/src/platform/emscripten/ffi.rs index 5543836f..c54e8a40 100644 --- a/src/platform/emscripten/ffi.rs +++ b/src/platform/emscripten/ffi.rs @@ -2,7 +2,6 @@ #![allow(non_snake_case)] #![allow(non_camel_case_types)] -use std::mem; use std::os::raw::{c_int, c_char, c_void, c_ulong, c_double}; pub type EM_BOOL = c_int; @@ -65,6 +64,11 @@ pub const EMSCRIPTEN_EVENT_POINTERLOCKERROR: c_int = 38; pub const EM_HTML5_SHORT_STRING_LEN_BYTES: usize = 32; +pub const DOM_KEY_LOCATION_STANDARD: c_ulong = 0x00; +pub const DOM_KEY_LOCATION_LEFT: c_ulong = 0x01; +pub const DOM_KEY_LOCATION_RIGHT: c_ulong = 0x02; +pub const DOM_KEY_LOCATION_NUMPAD: c_ulong = 0x03; + pub type em_callback_func = Option; pub type em_key_callback_func = Option &'static str { fn key_translate(input: [ffi::EM_UTF8; ffi::EM_HTML5_SHORT_STRING_LEN_BYTES]) -> u8 { use std::str; let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; - let key = unsafe { str::from_utf8(mem::transmute::<&[i8], &[u8]>(slice)).unwrap() }; + let maybe_key = unsafe { str::from_utf8(mem::transmute::<_, &[u8]>(slice)) }; + let key = match maybe_key { + Ok(key) => key, + Err(_) => { return 0; }, + }; if key.chars().count() == 1 { key.as_bytes()[0] } else { @@ -461,9 +465,453 @@ fn key_translate(input: [ffi::EM_UTF8; ffi::EM_HTML5_SHORT_STRING_LEN_BYTES]) -> } } -fn key_translate_virt(_input: [ffi::EM_UTF8; ffi::EM_HTML5_SHORT_STRING_LEN_BYTES], - _location: c_ulong) -> Option<::VirtualKeyCode> +fn key_translate_virt(input: [ffi::EM_UTF8; ffi::EM_HTML5_SHORT_STRING_LEN_BYTES], + location: c_ulong) -> Option<::VirtualKeyCode> { - // TODO - None + use std::str; + let slice = &input[0..input.iter().take_while(|x| **x != 0).count()]; + let maybe_key = unsafe { str::from_utf8(mem::transmute::<_, &[u8]>(slice)) }; + let key = match maybe_key { + Ok(key) => key, + Err(_) => { return None; }, + }; + use VirtualKeyCode::*; + match key { + "Alt" => match location { + ffi::DOM_KEY_LOCATION_LEFT => Some(LAlt), + ffi::DOM_KEY_LOCATION_RIGHT => Some(RAlt), + _ => None, + }, + "AltGraph" => None, + "CapsLock" => None, + "Control" => match location { + ffi::DOM_KEY_LOCATION_LEFT => Some(LControl), + ffi::DOM_KEY_LOCATION_RIGHT => Some(RControl), + _ => None, + }, + "Fn" => None, + "FnLock" => None, + "Hyper" => None, + "Meta" => None, + "NumLock" => Some(Numlock), + "ScrollLock" => Some(Scroll), + "Shift" => match location { + ffi::DOM_KEY_LOCATION_LEFT => Some(LShift), + ffi::DOM_KEY_LOCATION_RIGHT => Some(RShift), + _ => None, + }, + "Super" => None, + "Symbol" => None, + "SymbolLock" => None, + + "Enter" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(NumpadEnter), + _ => Some(Return), + }, + "Tab" => Some(Tab), + " " => Some(Space), + + "ArrowDown" => Some(Down), + "ArrowLeft" => Some(Left), + "ArrowRight" => Some(Right), + "ArrowUp" => Some(Up), + "End" => None, + "Home" => None, + "PageDown" => None, + "PageUp" => None, + + "Backspace" => Some(Back), + "Clear" => None, + "Copy" => None, + "CrSel" => None, + "Cut" => None, + "Delete" => None, + "EraseEof" => None, + "ExSel" => None, + "Insert" => Some(Insert), + "Paste" => None, + "Redo" => None, + "Undo" => None, + + "Accept" => None, + "Again" => None, + "Attn" => None, + "Cancel" => None, + "ContextMenu" => None, + "Escape" => Some(Escape), + "Execute" => None, + "Find" => None, + "Finish" => None, + "Help" => None, + "Pause" => Some(Pause), + "Play" => None, + "Props" => None, + "Select" => None, + "ZoomIn" => None, + "ZoomOut" => None, + + "BrightnessDown" => None, + "BrightnessUp" => None, + "Eject" => None, + "LogOff" => None, + "Power" => Some(Power), + "PowerOff" => None, + "PrintScreen" => Some(Snapshot), + "Hibernate" => None, + "Standby" => Some(Sleep), + "WakeUp" => Some(Wake), + + "AllCandidates" => None, + "Alphanumeric" => None, + "CodeInput" => None, + "Compose" => Some(Compose), + "Convert" => Some(Convert), + "Dead" => None, + "FinalMode" => None, + "GroupFirst" => None, + "GroupLast" => None, + "GroupNext" => None, + "GroupPrevious" => None, + "ModeChange" => None, + "NextCandidate" => None, + "NonConvert" => None, + "PreviousCandidate" => None, + "Process" => None, + "SingleCandidate" => None, + + "HangulMode" => None, + "HanjaMode" => None, + "JunjaMode" => None, + + "Eisu" => None, + "Hankaku" => None, + "Hiragana" => None, + "HiraganaKatakana" => None, + "KanaMode" => Some(Kana), + "KanjiMode" => Some(Kanji), + "Romaji" => None, + "Zenkaku" => None, + "ZenkakuHanaku" => None, + + "F1" => Some(F1), + "F2" => Some(F2), + "F3" => Some(F3), + "F4" => Some(F4), + "F5" => Some(F5), + "F6" => Some(F6), + "F7" => Some(F7), + "F8" => Some(F8), + "F9" => Some(F9), + "F10" => Some(F10), + "F11" => Some(F11), + "F12" => Some(F12), + "F13" => Some(F13), + "F14" => Some(F14), + "F15" => Some(F15), + "F16" => None, + "F17" => None, + "F18" => None, + "F19" => None, + "F20" => None, + "Soft1" => None, + "Soft2" => None, + "Soft3" => None, + "Soft4" => None, + + "AppSwitch" => None, + "Call" => None, + "Camera" => None, + "CameraFocus" => None, + "EndCall" => None, + "GoBack" => None, + "GoHome" => None, + "HeadsetHook" => None, + "LastNumberRedial" => None, + "Notification" => None, + "MannerMode" => None, + "VoiceDial" => None, + + "ChannelDown" => None, + "ChannelUp" => None, + "MediaFastForward" => None, + "MediaPause" => None, + "MediaPlay" => None, + "MediaPlayPause" => Some(PlayPause), + "MediaRecord" => None, + "MediaRewind" => None, + "MediaStop" => Some(MediaStop), + "MediaTrackNext" => Some(NextTrack), + "MediaTrackPrevious" => Some(PrevTrack), + + "AudioBalanceLeft" => None, + "AudioBalanceRight" => None, + "AudioBassDown" => None, + "AudioBassBoostDown" => None, + "AudioBassBoostToggle" => None, + "AudioBassBoostUp" => None, + "AudioBassUp" => None, + "AudioFaderFront" => None, + "AudioFaderRear" => None, + "AudioSurroundModeNext" => None, + "AudioTrebleDown" => None, + "AudioTrebleUp" => None, + "AudioVolumeDown" => Some(VolumeDown), + "AudioVolumeMute" => Some(Mute), + "AudioVolumeUp" => Some(VolumeUp), + "MicrophoneToggle" => None, + "MicrophoneVolumeDown" => None, + "MicrophoneVolumeMute" => None, + "MicrophoneVolumeUp" => None, + + "TV" => None, + "TV3DMode" => None, + "TVAntennaCable" => None, + "TVAudioDescription" => None, + "TVAudioDescriptionMixDown" => None, + "TVAudioDescriptionMixUp" => None, + "TVContentsMenu" => None, + "TVDataService" => None, + "TVInput" => None, + "TVInputComponent1" => None, + "TVInputComponent2" => None, + "TVInputComposite1" => None, + "TVInputComposite2" => None, + "TVInputHDM1" => None, + "TVInputHDM2" => None, + "TVInputHDM3" => None, + "TVInputHDM4" => None, + "TVInputVGA1" => None, + "TVMediaContext" => None, + "TVNetwork" => None, + "TVNumberEntry" => None, + "TVPower" => None, + "TVRadioService" => None, + "TVSatellite" => None, + "TVSatelliteBS" => None, + "TVSatelliteCS" => None, + "TVSatelliteToggle" => None, + "TVTerrestrialAnalog" => None, + "TVTerrestrialDigital" => None, + "TVTimer" => None, + + "AVRInput" => None, + "AVRPower" => None, + "ColorF0Red" => None, + "ColorF1Green" => None, + "ColorF2Yellow" => None, + "ColorF3Blue" => None, + "ColorF4Grey" => None, + "ColorF5Brown" => None, + "ClosedCaptionToggle" => None, + "Dimmer" => None, + "DisplaySwap" => None, + "DVR" => None, + "Exit" => None, + "FavoriteClear0" => None, + "FavoriteClear1" => None, + "FavoriteClear2" => None, + "FavoriteClear3" => None, + "FavoriteRecall0" => None, + "FavoriteRecall1" => None, + "FavoriteRecall2" => None, + "FavoriteRecall3" => None, + "FavoriteStore0" => None, + "FavoriteStore1" => None, + "FavoriteStore2" => None, + "FavoriteStore3" => None, + "FavoriteStore4" => None, + "Guide" => None, + "GuideNextDay" => None, + "GuidePreviousDay" => None, + "Info" => None, + "InstantReplay" => None, + "Link" => None, + "ListProgram" => None, + "LiveContent" => None, + "Lock" => None, + "MediaApps" => None, + "MediaAudioTrack" => None, + "MediaLast" => None, + "MediaSkipBackward" => None, + "MediaSkipForward" => None, + "MediaStepBackward" => None, + "MediaStepForward" => None, + "MediaTopMenu" => None, + "NavigateIn" => None, + "NavigateNext" => None, + "NavigateOut" => None, + "NavigatePrevious" => None, + "NextFavoriteChannel" => None, + "NextUserProfile" => None, + "OnDemand" => None, + "Pairing" => None, + "PinPDown" => None, + "PinPMove" => None, + "PinPToggle" => None, + "PinPUp" => None, + "PlaySpeedDown" => None, + "PlaySpeedReset" => None, + "PlaySpeedUp" => None, + "RandomToggle" => None, + "RcLowBattery" => None, + "RecordSpeedNext" => None, + "RfBypass" => None, + "ScanChannelsToggle" => None, + "ScreenModeNext" => None, + "Settings" => None, + "SplitScreenToggle" => None, + "STBInput" => None, + "STBPower" => None, + "Subtitle" => None, + "Teletext" => None, + "VideoModeNext" => None, + "Wink" => None, + "ZoomToggle" => None, + + "SpeechCorrectionList" => None, + "SpeechInputToggle" => None, + + "Close" => None, + "New" => None, + "Open" => None, + "Print" => None, + "Save" => None, + "SpellCheck" => None, + "MailForward" => None, + "MailReply" => None, + "MailSend" => None, + + "LaunchCalculator" => Some(Calculator), + "LaunchCalendar" => None, + "LaunchContacts" => None, + "LaunchMail" => Some(Mail), + "LaunchMediaPlayer" => None, + "LaunchMusicPlayer" => None, + "LaunchMyComputer" => Some(MyComputer), + "LaunchPhone" => None, + "LaunchScreenSaver" => None, + "LaunchSpreadsheet" => None, + "LaunchWebCam" => None, + "LaunchWordProcessor" => None, + "LaunchApplication1" => None, + "LaunchApplication2" => None, + "LaunchApplication3" => None, + "LaunchApplication4" => None, + "LaunchApplication5" => None, + "LaunchApplication6" => None, + "LaunchApplication7" => None, + "LaunchApplication8" => None, + "LaunchApplication9" => None, + "LaunchApplication10" => None, + "LaunchApplication11" => None, + "LaunchApplication12" => None, + "LaunchApplication13" => None, + "LaunchApplication14" => None, + "LaunchApplication15" => None, + "LaunchApplication16" => None, + + "BrowserBack" => Some(WebBack), + "BrowserFavorites" => Some(WebFavorites), + "BrowserForward" => Some(WebForward), + "BrowserHome" => Some(WebHome), + "BrowserRefresh" => Some(WebRefresh), + "BrowserSearch" => Some(WebSearch), + "BrowserStop" => Some(WebStop), + + "Decimal" => Some(Decimal), + "Key11" => None, + "Key12" => None, + "Multiply" | "*" => Some(Multiply), + "Add" | "+" => Some(Add), + // "Clear" => None, + "Divide" => Some(Divide), + "Subtract" | "-" => Some(Subtract), + "Separator" => None, + "0" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad0), + _ => Some(Key0), + }, + "1" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad1), + _ => Some(Key1), + }, + "2" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad2), + _ => Some(Key2), + }, + "3" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad3), + _ => Some(Key3), + }, + "4" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad4), + _ => Some(Key4), + }, + "5" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad5), + _ => Some(Key5), + }, + "6" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad6), + _ => Some(Key6), + }, + "7" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad7), + _ => Some(Key7), + }, + "8" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad8), + _ => Some(Key8), + }, + "9" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(Numpad9), + _ => Some(Key9), + }, + + "A" | "a" => Some(A), + "B" | "b" => Some(B), + "C" | "c" => Some(C), + "D" | "d" => Some(D), + "E" | "e" => Some(E), + "F" | "f" => Some(F), + "G" | "g" => Some(G), + "H" | "h" => Some(H), + "I" | "i" => Some(I), + "J" | "j" => Some(J), + "K" | "k" => Some(K), + "L" | "l" => Some(L), + "M" | "m" => Some(M), + "N" | "n" => Some(N), + "O" | "o" => Some(O), + "P" | "p" => Some(P), + "Q" | "q" => Some(Q), + "R" | "r" => Some(R), + "S" | "s" => Some(S), + "T" | "t" => Some(T), + "U" | "u" => Some(U), + "V" | "v" => Some(V), + "W" | "w" => Some(W), + "X" | "x" => Some(X), + "Y" | "y" => Some(Y), + "Z" | "z" => Some(Z), + + "'" => Some(Apostrophe), + "\\" => Some(Backslash), + ":" => Some(Colon), + "," => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(NumpadComma), + _ => Some(Comma), + }, + "=" => match location { + ffi::DOM_KEY_LOCATION_NUMPAD => Some(NumpadEquals), + _ => Some(Equals), + }, + "{" => Some(LBracket), + "." => Some(Period), + "}" => Some(RBracket), + ";" => Some(Semicolon), + "/" => Some(Slash), + + _ => None, + } }