diff --git a/src/platform_impl/android/keycodes.rs b/src/platform_impl/android/keycodes.rs new file mode 100644 index 00000000..8933e796 --- /dev/null +++ b/src/platform_impl/android/keycodes.rs @@ -0,0 +1,521 @@ +use android_activity::input::Keycode; + +use crate::keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode}; + +pub fn to_physical_keycode(keycode: Keycode) -> KeyCode { + match keycode { + Keycode::A => KeyCode::KeyA, + Keycode::B => KeyCode::KeyB, + Keycode::C => KeyCode::KeyC, + Keycode::D => KeyCode::KeyD, + Keycode::E => KeyCode::KeyE, + Keycode::F => KeyCode::KeyF, + Keycode::G => KeyCode::KeyG, + Keycode::H => KeyCode::KeyH, + Keycode::I => KeyCode::KeyI, + Keycode::J => KeyCode::KeyJ, + Keycode::K => KeyCode::KeyK, + Keycode::L => KeyCode::KeyL, + Keycode::M => KeyCode::KeyM, + Keycode::N => KeyCode::KeyN, + Keycode::O => KeyCode::KeyO, + Keycode::P => KeyCode::KeyP, + Keycode::Q => KeyCode::KeyQ, + Keycode::R => KeyCode::KeyR, + Keycode::S => KeyCode::KeyS, + Keycode::T => KeyCode::KeyT, + Keycode::U => KeyCode::KeyU, + Keycode::V => KeyCode::KeyV, + Keycode::W => KeyCode::KeyW, + Keycode::X => KeyCode::KeyX, + Keycode::Y => KeyCode::KeyY, + Keycode::Z => KeyCode::KeyZ, + + Keycode::Keycode0 => KeyCode::Digit0, + Keycode::Keycode1 => KeyCode::Digit1, + Keycode::Keycode2 => KeyCode::Digit2, + Keycode::Keycode3 => KeyCode::Digit3, + Keycode::Keycode4 => KeyCode::Digit4, + Keycode::Keycode5 => KeyCode::Digit5, + Keycode::Keycode6 => KeyCode::Digit6, + Keycode::Keycode7 => KeyCode::Digit7, + Keycode::Keycode8 => KeyCode::Digit8, + Keycode::Keycode9 => KeyCode::Digit9, + + Keycode::Numpad0 => KeyCode::Numpad0, + Keycode::Numpad1 => KeyCode::Numpad1, + Keycode::Numpad2 => KeyCode::Numpad2, + Keycode::Numpad3 => KeyCode::Numpad3, + Keycode::Numpad4 => KeyCode::Numpad4, + Keycode::Numpad5 => KeyCode::Numpad5, + Keycode::Numpad6 => KeyCode::Numpad6, + Keycode::Numpad7 => KeyCode::Numpad7, + Keycode::Numpad8 => KeyCode::Numpad8, + Keycode::Numpad9 => KeyCode::Numpad9, + + Keycode::NumpadAdd => KeyCode::NumpadAdd, + Keycode::NumpadSubtract => KeyCode::NumpadSubtract, + Keycode::NumpadMultiply => KeyCode::NumpadMultiply, + Keycode::NumpadDivide => KeyCode::NumpadDivide, + Keycode::NumpadEnter => KeyCode::NumpadEnter, + Keycode::NumpadEquals => KeyCode::NumpadEqual, + Keycode::NumpadComma => KeyCode::NumpadComma, + Keycode::NumpadDot => KeyCode::NumpadDecimal, + Keycode::NumLock => KeyCode::NumLock, + + Keycode::DpadLeft => KeyCode::ArrowLeft, + Keycode::DpadRight => KeyCode::ArrowRight, + Keycode::DpadUp => KeyCode::ArrowUp, + Keycode::DpadDown => KeyCode::ArrowDown, + + Keycode::F1 => KeyCode::F1, + Keycode::F2 => KeyCode::F2, + Keycode::F3 => KeyCode::F3, + Keycode::F4 => KeyCode::F4, + Keycode::F5 => KeyCode::F5, + Keycode::F6 => KeyCode::F6, + Keycode::F7 => KeyCode::F7, + Keycode::F8 => KeyCode::F8, + Keycode::F9 => KeyCode::F9, + Keycode::F10 => KeyCode::F10, + Keycode::F11 => KeyCode::F11, + Keycode::F12 => KeyCode::F12, + + Keycode::Space => KeyCode::Space, + Keycode::Escape => KeyCode::Escape, + Keycode::Enter => KeyCode::Enter, // not on the Numpad + Keycode::Tab => KeyCode::Tab, + + Keycode::PageUp => KeyCode::PageUp, + Keycode::PageDown => KeyCode::PageDown, + Keycode::MoveHome => KeyCode::Home, + Keycode::MoveEnd => KeyCode::End, + Keycode::Insert => KeyCode::Insert, + + Keycode::Del => KeyCode::Backspace, // Backspace (above Enter) + Keycode::ForwardDel => KeyCode::Delete, // Delete (below Insert) + + Keycode::Copy => KeyCode::Copy, + Keycode::Paste => KeyCode::Paste, + Keycode::Cut => KeyCode::Cut, + + Keycode::VolumeUp => KeyCode::AudioVolumeUp, + Keycode::VolumeDown => KeyCode::AudioVolumeDown, + Keycode::VolumeMute => KeyCode::AudioVolumeMute, + //Keycode::Mute => None, // Microphone mute + Keycode::MediaPlayPause => KeyCode::MediaPlayPause, + Keycode::MediaStop => KeyCode::MediaStop, + Keycode::MediaNext => KeyCode::MediaTrackNext, + Keycode::MediaPrevious => KeyCode::MediaTrackPrevious, + + Keycode::Plus => KeyCode::Equal, + Keycode::Minus => KeyCode::Minus, + // Winit doesn't differentiate both '+' and '=', considering they are usually + // on the same physical key + Keycode::Equals => KeyCode::Equal, + Keycode::Semicolon => KeyCode::Semicolon, + Keycode::Slash => KeyCode::Slash, + Keycode::Backslash => KeyCode::Backslash, + Keycode::Comma => KeyCode::Comma, + Keycode::Period => KeyCode::Period, + Keycode::Apostrophe => KeyCode::Quote, + Keycode::Grave => KeyCode::Backquote, + + // Winit doesn't expose a SysRq code, so map to PrintScreen since it's + // usually the same physical key + Keycode::Sysrq => KeyCode::PrintScreen, + // These are usually the same (Pause/Break) + Keycode::Break => KeyCode::Pause, + // These are exactly the same + Keycode::ScrollLock => KeyCode::ScrollLock, + + Keycode::Yen => KeyCode::IntlYen, + Keycode::Kana => KeyCode::Lang1, + Keycode::KatakanaHiragana => KeyCode::KanaMode, + + Keycode::CtrlLeft => KeyCode::ControlLeft, + Keycode::CtrlRight => KeyCode::ControlRight, + + Keycode::ShiftLeft => KeyCode::ShiftLeft, + Keycode::ShiftRight => KeyCode::ShiftRight, + + Keycode::AltLeft => KeyCode::AltLeft, + Keycode::AltRight => KeyCode::AltRight, + + Keycode::MetaLeft => KeyCode::SuperLeft, + Keycode::MetaRight => KeyCode::SuperRight, + + Keycode::LeftBracket => KeyCode::BracketLeft, + Keycode::RightBracket => KeyCode::BracketRight, + + Keycode::Power => KeyCode::Power, + Keycode::Sleep => KeyCode::Sleep, // what about SoftSleep? + Keycode::Wakeup => KeyCode::WakeUp, + + keycode => KeyCode::Unidentified(NativeKeyCode::Android(keycode.into())), + } +} + +// TODO: We need to expose getUnicodeChar via android-activity instead of having +// a fixed mapping from key codes +pub fn to_logical(keycode: Keycode, native: NativeKey) -> Key { + use android_activity::input::Keycode::*; + + match keycode { + Unknown => Key::Unidentified(native), + + // Can be added on demand + SoftLeft => Key::Unidentified(native), + SoftRight => Key::Unidentified(native), + + // Using `BrowserHome` instead of `GoHome` according to + // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values + Home => Key::BrowserHome, + Back => Key::BrowserBack, + Call => Key::Call, + Endcall => Key::EndCall, + + //------------------------------------------------------------------------------- + // Reporting unidentified, because the specific character is layout dependent. + // (I'm not sure though) + Keycode0 => Key::Character("0".into()), + Keycode1 => Key::Character("1".into()), + Keycode2 => Key::Character("2".into()), + Keycode3 => Key::Character("3".into()), + Keycode4 => Key::Character("4".into()), + Keycode5 => Key::Character("5".into()), + Keycode6 => Key::Character("6".into()), + Keycode7 => Key::Character("7".into()), + Keycode8 => Key::Character("8".into()), + Keycode9 => Key::Character("9".into()), + Star => Key::Character("*".into()), + Pound => Key::Character("#".into()), + A => Key::Character("a".into()), + B => Key::Character("b".into()), + C => Key::Character("c".into()), + D => Key::Character("d".into()), + E => Key::Character("e".into()), + F => Key::Character("f".into()), + G => Key::Character("g".into()), + H => Key::Character("h".into()), + I => Key::Character("i".into()), + J => Key::Character("j".into()), + K => Key::Character("k".into()), + L => Key::Character("l".into()), + M => Key::Character("m".into()), + N => Key::Character("n".into()), + O => Key::Character("o".into()), + P => Key::Character("p".into()), + Q => Key::Character("q".into()), + R => Key::Character("r".into()), + S => Key::Character("s".into()), + T => Key::Character("t".into()), + U => Key::Character("u".into()), + V => Key::Character("v".into()), + W => Key::Character("w".into()), + X => Key::Character("x".into()), + Y => Key::Character("y".into()), + Z => Key::Character("z".into()), + Comma => Key::Character(",".into()), + Period => Key::Character(".".into()), + Grave => Key::Character("`".into()), + Minus => Key::Character("-".into()), + Equals => Key::Character("=".into()), + LeftBracket => Key::Character("[".into()), + RightBracket => Key::Character("]".into()), + Backslash => Key::Character("\\".into()), + Semicolon => Key::Character(";".into()), + Apostrophe => Key::Character("'".into()), + Slash => Key::Character("/".into()), + At => Key::Character("@".into()), + Plus => Key::Character("+".into()), + //------------------------------------------------------------------------------- + DpadUp => Key::ArrowUp, + DpadDown => Key::ArrowDown, + DpadLeft => Key::ArrowLeft, + DpadRight => Key::ArrowRight, + DpadCenter => Key::Enter, + + VolumeUp => Key::AudioVolumeUp, + VolumeDown => Key::AudioVolumeDown, + Power => Key::Power, + Camera => Key::Camera, + Clear => Key::Clear, + + AltLeft => Key::Alt, + AltRight => Key::Alt, + ShiftLeft => Key::Shift, + ShiftRight => Key::Shift, + Tab => Key::Tab, + Space => Key::Space, + Sym => Key::Symbol, + Explorer => Key::LaunchWebBrowser, + Envelope => Key::LaunchMail, + Enter => Key::Enter, + Del => Key::Backspace, + + // According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM + Num => Key::Alt, + + Headsethook => Key::HeadsetHook, + Focus => Key::CameraFocus, + + Menu => Key::Unidentified(native), + + Notification => Key::Notification, + Search => Key::BrowserSearch, + MediaPlayPause => Key::MediaPlayPause, + MediaStop => Key::MediaStop, + MediaNext => Key::MediaTrackNext, + MediaPrevious => Key::MediaTrackPrevious, + MediaRewind => Key::MediaRewind, + MediaFastForward => Key::MediaFastForward, + Mute => Key::MicrophoneVolumeMute, + PageUp => Key::PageUp, + PageDown => Key::PageDown, + Pictsymbols => Key::Unidentified(native), + SwitchCharset => Key::Unidentified(native), + + // ----------------------------------------------------------------- + // Gamepad events should be exposed through a separate API, not + // keyboard events + ButtonA => Key::Unidentified(native), + ButtonB => Key::Unidentified(native), + ButtonC => Key::Unidentified(native), + ButtonX => Key::Unidentified(native), + ButtonY => Key::Unidentified(native), + ButtonZ => Key::Unidentified(native), + ButtonL1 => Key::Unidentified(native), + ButtonR1 => Key::Unidentified(native), + ButtonL2 => Key::Unidentified(native), + ButtonR2 => Key::Unidentified(native), + ButtonThumbl => Key::Unidentified(native), + ButtonThumbr => Key::Unidentified(native), + ButtonStart => Key::Unidentified(native), + ButtonSelect => Key::Unidentified(native), + ButtonMode => Key::Unidentified(native), + // ----------------------------------------------------------------- + Escape => Key::Escape, + ForwardDel => Key::Delete, + CtrlLeft => Key::Control, + CtrlRight => Key::Control, + CapsLock => Key::CapsLock, + ScrollLock => Key::ScrollLock, + MetaLeft => Key::Super, + MetaRight => Key::Super, + Function => Key::Fn, + Sysrq => Key::PrintScreen, + Break => Key::Pause, + MoveHome => Key::Home, + MoveEnd => Key::End, + Insert => Key::Insert, + Forward => Key::BrowserForward, + MediaPlay => Key::MediaPlay, + MediaPause => Key::MediaPause, + MediaClose => Key::MediaClose, + MediaEject => Key::Eject, + MediaRecord => Key::MediaRecord, + F1 => Key::F1, + F2 => Key::F2, + F3 => Key::F3, + F4 => Key::F4, + F5 => Key::F5, + F6 => Key::F6, + F7 => Key::F7, + F8 => Key::F8, + F9 => Key::F9, + F10 => Key::F10, + F11 => Key::F11, + F12 => Key::F12, + NumLock => Key::NumLock, + Numpad0 => Key::Character("0".into()), + Numpad1 => Key::Character("1".into()), + Numpad2 => Key::Character("2".into()), + Numpad3 => Key::Character("3".into()), + Numpad4 => Key::Character("4".into()), + Numpad5 => Key::Character("5".into()), + Numpad6 => Key::Character("6".into()), + Numpad7 => Key::Character("7".into()), + Numpad8 => Key::Character("8".into()), + Numpad9 => Key::Character("9".into()), + NumpadDivide => Key::Character("/".into()), + NumpadMultiply => Key::Character("*".into()), + NumpadSubtract => Key::Character("-".into()), + NumpadAdd => Key::Character("+".into()), + NumpadDot => Key::Character(".".into()), + NumpadComma => Key::Character(",".into()), + NumpadEnter => Key::Enter, + NumpadEquals => Key::Character("=".into()), + NumpadLeftParen => Key::Character("(".into()), + NumpadRightParen => Key::Character(")".into()), + + VolumeMute => Key::AudioVolumeMute, + Info => Key::Info, + ChannelUp => Key::ChannelUp, + ChannelDown => Key::ChannelDown, + ZoomIn => Key::ZoomIn, + ZoomOut => Key::ZoomOut, + Tv => Key::TV, + Window => Key::Unidentified(native), + Guide => Key::Guide, + Dvr => Key::DVR, + Bookmark => Key::BrowserFavorites, + Captions => Key::ClosedCaptionToggle, + Settings => Key::Settings, + TvPower => Key::TVPower, + TvInput => Key::TVInput, + StbPower => Key::STBPower, + StbInput => Key::STBInput, + AvrPower => Key::AVRPower, + AvrInput => Key::AVRInput, + ProgRed => Key::ColorF0Red, + ProgGreen => Key::ColorF1Green, + ProgYellow => Key::ColorF2Yellow, + ProgBlue => Key::ColorF3Blue, + AppSwitch => Key::AppSwitch, + Button1 => Key::Unidentified(native), + Button2 => Key::Unidentified(native), + Button3 => Key::Unidentified(native), + Button4 => Key::Unidentified(native), + Button5 => Key::Unidentified(native), + Button6 => Key::Unidentified(native), + Button7 => Key::Unidentified(native), + Button8 => Key::Unidentified(native), + Button9 => Key::Unidentified(native), + Button10 => Key::Unidentified(native), + Button11 => Key::Unidentified(native), + Button12 => Key::Unidentified(native), + Button13 => Key::Unidentified(native), + Button14 => Key::Unidentified(native), + Button15 => Key::Unidentified(native), + Button16 => Key::Unidentified(native), + LanguageSwitch => Key::GroupNext, + MannerMode => Key::MannerMode, + Keycode3dMode => Key::TV3DMode, + Contacts => Key::LaunchContacts, + Calendar => Key::LaunchCalendar, + Music => Key::LaunchMusicPlayer, + Calculator => Key::LaunchApplication2, + ZenkakuHankaku => Key::ZenkakuHankaku, + Eisu => Key::Eisu, + Muhenkan => Key::NonConvert, + Henkan => Key::Convert, + KatakanaHiragana => Key::HiraganaKatakana, + Yen => Key::Unidentified(native), + Ro => Key::Unidentified(native), + Kana => Key::KanjiMode, + Assist => Key::Unidentified(native), + BrightnessDown => Key::BrightnessDown, + BrightnessUp => Key::BrightnessUp, + MediaAudioTrack => Key::MediaAudioTrack, + Sleep => Key::Standby, + Wakeup => Key::WakeUp, + Pairing => Key::Pairing, + MediaTopMenu => Key::MediaTopMenu, + Keycode11 => Key::Unidentified(native), + Keycode12 => Key::Unidentified(native), + LastChannel => Key::MediaLast, + TvDataService => Key::TVDataService, + VoiceAssist => Key::VoiceDial, + TvRadioService => Key::TVRadioService, + TvTeletext => Key::Teletext, + TvNumberEntry => Key::TVNumberEntry, + TvTerrestrialAnalog => Key::TVTerrestrialAnalog, + TvTerrestrialDigital => Key::TVTerrestrialDigital, + TvSatellite => Key::TVSatellite, + TvSatelliteBs => Key::TVSatelliteBS, + TvSatelliteCs => Key::TVSatelliteCS, + TvSatelliteService => Key::TVSatelliteToggle, + TvNetwork => Key::TVNetwork, + TvAntennaCable => Key::TVAntennaCable, + TvInputHdmi1 => Key::TVInputHDMI1, + TvInputHdmi2 => Key::TVInputHDMI2, + TvInputHdmi3 => Key::TVInputHDMI3, + TvInputHdmi4 => Key::TVInputHDMI4, + TvInputComposite1 => Key::TVInputComposite1, + TvInputComposite2 => Key::TVInputComposite2, + TvInputComponent1 => Key::TVInputComponent1, + TvInputComponent2 => Key::TVInputComponent2, + TvInputVga1 => Key::TVInputVGA1, + TvAudioDescription => Key::TVAudioDescription, + TvAudioDescriptionMixUp => Key::TVAudioDescriptionMixUp, + TvAudioDescriptionMixDown => Key::TVAudioDescriptionMixDown, + TvZoomMode => Key::ZoomToggle, + TvContentsMenu => Key::TVContentsMenu, + TvMediaContextMenu => Key::TVMediaContext, + TvTimerProgramming => Key::TVTimer, + Help => Key::Help, + NavigatePrevious => Key::NavigatePrevious, + NavigateNext => Key::NavigateNext, + NavigateIn => Key::NavigateIn, + NavigateOut => Key::NavigateOut, + StemPrimary => Key::Unidentified(native), + Stem1 => Key::Unidentified(native), + Stem2 => Key::Unidentified(native), + Stem3 => Key::Unidentified(native), + DpadUpLeft => Key::Unidentified(native), + DpadDownLeft => Key::Unidentified(native), + DpadUpRight => Key::Unidentified(native), + DpadDownRight => Key::Unidentified(native), + MediaSkipForward => Key::MediaSkipForward, + MediaSkipBackward => Key::MediaSkipBackward, + MediaStepForward => Key::MediaStepForward, + MediaStepBackward => Key::MediaStepBackward, + SoftSleep => Key::Unidentified(native), + Cut => Key::Cut, + Copy => Key::Copy, + Paste => Key::Paste, + SystemNavigationUp => Key::Unidentified(native), + SystemNavigationDown => Key::Unidentified(native), + SystemNavigationLeft => Key::Unidentified(native), + SystemNavigationRight => Key::Unidentified(native), + AllApps => Key::Unidentified(native), + Refresh => Key::BrowserRefresh, + ThumbsUp => Key::Unidentified(native), + ThumbsDown => Key::Unidentified(native), + ProfileSwitch => Key::Unidentified(native), + } +} + +pub fn to_location(keycode: Keycode) -> KeyLocation { + use android_activity::input::Keycode::*; + + match keycode { + AltLeft => KeyLocation::Left, + AltRight => KeyLocation::Right, + ShiftLeft => KeyLocation::Left, + ShiftRight => KeyLocation::Right, + + // According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM + Num => KeyLocation::Left, + + CtrlLeft => KeyLocation::Left, + CtrlRight => KeyLocation::Right, + MetaLeft => KeyLocation::Left, + MetaRight => KeyLocation::Right, + + NumLock => KeyLocation::Numpad, + Numpad0 => KeyLocation::Numpad, + Numpad1 => KeyLocation::Numpad, + Numpad2 => KeyLocation::Numpad, + Numpad3 => KeyLocation::Numpad, + Numpad4 => KeyLocation::Numpad, + Numpad5 => KeyLocation::Numpad, + Numpad6 => KeyLocation::Numpad, + Numpad7 => KeyLocation::Numpad, + Numpad8 => KeyLocation::Numpad, + Numpad9 => KeyLocation::Numpad, + NumpadDivide => KeyLocation::Numpad, + NumpadMultiply => KeyLocation::Numpad, + NumpadSubtract => KeyLocation::Numpad, + NumpadAdd => KeyLocation::Numpad, + NumpadDot => KeyLocation::Numpad, + NumpadComma => KeyLocation::Numpad, + NumpadEnter => KeyLocation::Numpad, + NumpadEquals => KeyLocation::Numpad, + NumpadLeftParen => KeyLocation::Numpad, + NumpadRightParen => KeyLocation::Numpad, + + _ => KeyLocation::Standard, + } +} diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 1f8dd8ea..b48d3acc 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -2,7 +2,6 @@ use std::{ collections::VecDeque, - convert::TryInto, hash::Hash, sync::{ atomic::{AtomicBool, Ordering}, @@ -11,7 +10,7 @@ use std::{ time::{Duration, Instant}, }; -use android_activity::input::{InputEvent, KeyAction, MotionAction}; +use android_activity::input::{InputEvent, KeyAction, Keycode, MotionAction}; use android_activity::{ AndroidApp, AndroidAppWaker, ConfigurationRef, InputStatus, MainEvent, Rect, }; @@ -20,21 +19,20 @@ use raw_window_handle::{ AndroidDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; -#[cfg(feature = "android-native-activity")] -use ndk_sys::AKeyEvent_getKeyCode; - use crate::platform_impl::Fullscreen; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, event::{self, StartCause}, event_loop::{self, ControlFlow, EventLoopWindowTarget as RootELW}, - keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode}, + keyboard::NativeKey, window::{ self, CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowButtons, WindowLevel, }, }; +mod keycodes; + static HAS_FOCUS: Lazy> = Lazy::new(|| RwLock::new(true)); struct PeekableReceiver { @@ -408,45 +406,25 @@ impl EventLoop { } InputEvent::KeyEvent(key) => { match key.key_code() { - // Flagg keys related to volume as unhandled. While winit does not have a way for applications + // Flag keys related to volume as unhandled. While winit does not have a way for applications // to configure what keys to flag as handled, this appears to be a good default until winit // can be configured. - ndk::event::Keycode::VolumeUp | - ndk::event::Keycode::VolumeDown | - ndk::event::Keycode::VolumeMute => { + Keycode::VolumeUp | + Keycode::VolumeDown | + Keycode::VolumeMute => { if self.ignore_volume_keys { input_status = InputStatus::Unhandled } }, - _ => { + keycode => { let state = match key.action() { KeyAction::Down => event::ElementState::Pressed, KeyAction::Up => event::ElementState::Released, _ => event::ElementState::Released, }; - #[cfg(feature = "android-native-activity")] - let (keycode_u32, scancode_u32) = unsafe { - // We abuse the fact that `android_activity`'s `KeyEvent` is `repr(transparent)` - let event = (key as *const android_activity::input::KeyEvent<'_>).cast::(); - // We use the unsafe function directly because we want to forward the - // keycode value even if it doesn't have a variant defined in the ndk - // crate. - ( - AKeyEvent_getKeyCode((*event).ptr().as_ptr()) as u32, - (*event).scan_code() as u32 - ) - }; - #[cfg(feature = "android-game-activity")] - let (keycode_u32, scancode_u32) = (key.keyCode as u32, key.scanCode as u32); - let keycode = keycode_u32 - .try_into() - .unwrap_or(ndk::event::Keycode::Unknown); - let physical_key = KeyCode::Unidentified( - NativeKeyCode::Android(scancode_u32), - ); - let native = NativeKey::Android(keycode_u32); - let logical_key = keycode_to_logical(keycode, native); + let native = NativeKey::Android(keycode.into()); + let logical_key = keycodes::to_logical(keycode, native); // TODO: maybe use getUnicodeChar to get the logical key let event = event::Event::WindowEvent { @@ -455,9 +433,9 @@ impl EventLoop { device_id: event::DeviceId(DeviceId), event: event::KeyEvent { state, - physical_key, + physical_key: keycodes::to_physical_keycode(keycode), logical_key, - location: keycode_to_location(keycode), + location: keycodes::to_location(keycode), repeat: key.repeat_count() > 0, text: None, platform_specific: KeyEventExtra {}, @@ -1077,377 +1055,3 @@ impl VideoMode { self.monitor.clone() } } - -fn keycode_to_logical(keycode: ndk::event::Keycode, native: NativeKey) -> Key { - use ndk::event::Keycode::*; - - // The android `Keycode` is sort-of layout dependent. More specifically - // if I press the Z key using a US layout, then I get KEYCODE_Z, - // but if I press the same key after switching to a HUN layout, I get - // KEYCODE_Y. - // - // To prevents us from using this value to determine the `physical_key` - // (also know as winit's `KeyCode`) - // - // Unfortunately the documentation says that the scancode values - // "are not reliable and vary from device to device". Which seems to mean - // that there's no way to reliably get the physical_key on android. - - match keycode { - Unknown => Key::Unidentified(native), - - // Can be added on demand - SoftLeft => Key::Unidentified(native), - SoftRight => Key::Unidentified(native), - - // Using `BrowserHome` instead of `GoHome` according to - // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values - Home => Key::BrowserHome, - Back => Key::BrowserBack, - Call => Key::Call, - Endcall => Key::EndCall, - - //------------------------------------------------------------------------------- - // Reporting unidentified, because the specific character is layout dependent. - // (I'm not sure though) - Keycode0 => Key::Unidentified(native), - Keycode1 => Key::Unidentified(native), - Keycode2 => Key::Unidentified(native), - Keycode3 => Key::Unidentified(native), - Keycode4 => Key::Unidentified(native), - Keycode5 => Key::Unidentified(native), - Keycode6 => Key::Unidentified(native), - Keycode7 => Key::Unidentified(native), - Keycode8 => Key::Unidentified(native), - Keycode9 => Key::Unidentified(native), - Star => Key::Unidentified(native), - Pound => Key::Unidentified(native), - A => Key::Unidentified(native), - B => Key::Unidentified(native), - C => Key::Unidentified(native), - D => Key::Unidentified(native), - E => Key::Unidentified(native), - F => Key::Unidentified(native), - G => Key::Unidentified(native), - H => Key::Unidentified(native), - I => Key::Unidentified(native), - J => Key::Unidentified(native), - K => Key::Unidentified(native), - L => Key::Unidentified(native), - M => Key::Unidentified(native), - N => Key::Unidentified(native), - O => Key::Unidentified(native), - P => Key::Unidentified(native), - Q => Key::Unidentified(native), - R => Key::Unidentified(native), - S => Key::Unidentified(native), - T => Key::Unidentified(native), - U => Key::Unidentified(native), - V => Key::Unidentified(native), - W => Key::Unidentified(native), - X => Key::Unidentified(native), - Y => Key::Unidentified(native), - Z => Key::Unidentified(native), - Comma => Key::Unidentified(native), - Period => Key::Unidentified(native), - Grave => Key::Unidentified(native), - Minus => Key::Unidentified(native), - Equals => Key::Unidentified(native), - LeftBracket => Key::Unidentified(native), - RightBracket => Key::Unidentified(native), - Backslash => Key::Unidentified(native), - Semicolon => Key::Unidentified(native), - Apostrophe => Key::Unidentified(native), - Slash => Key::Unidentified(native), - At => Key::Unidentified(native), - Plus => Key::Unidentified(native), - //------------------------------------------------------------------------------- - DpadUp => Key::ArrowUp, - DpadDown => Key::ArrowDown, - DpadLeft => Key::ArrowLeft, - DpadRight => Key::ArrowRight, - DpadCenter => Key::Enter, - - VolumeUp => Key::AudioVolumeUp, - VolumeDown => Key::AudioVolumeDown, - Power => Key::Power, - Camera => Key::Camera, - Clear => Key::Clear, - - AltLeft => Key::Alt, - AltRight => Key::Alt, - ShiftLeft => Key::Shift, - ShiftRight => Key::Shift, - Tab => Key::Tab, - Space => Key::Space, - Sym => Key::Symbol, - Explorer => Key::LaunchWebBrowser, - Envelope => Key::LaunchMail, - Enter => Key::Enter, - Del => Key::Backspace, - - // According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM - Num => Key::Alt, - - Headsethook => Key::HeadsetHook, - Focus => Key::CameraFocus, - - Menu => Key::Unidentified(native), - - Notification => Key::Notification, - Search => Key::BrowserSearch, - MediaPlayPause => Key::MediaPlayPause, - MediaStop => Key::MediaStop, - MediaNext => Key::MediaTrackNext, - MediaPrevious => Key::MediaTrackPrevious, - MediaRewind => Key::MediaRewind, - MediaFastForward => Key::MediaFastForward, - Mute => Key::MicrophoneVolumeMute, - PageUp => Key::PageUp, - PageDown => Key::PageDown, - Pictsymbols => Key::Unidentified(native), - SwitchCharset => Key::Unidentified(native), - - // ----------------------------------------------------------------- - // Gamepad events should be exposed through a separate API, not - // keyboard events - ButtonA => Key::Unidentified(native), - ButtonB => Key::Unidentified(native), - ButtonC => Key::Unidentified(native), - ButtonX => Key::Unidentified(native), - ButtonY => Key::Unidentified(native), - ButtonZ => Key::Unidentified(native), - ButtonL1 => Key::Unidentified(native), - ButtonR1 => Key::Unidentified(native), - ButtonL2 => Key::Unidentified(native), - ButtonR2 => Key::Unidentified(native), - ButtonThumbl => Key::Unidentified(native), - ButtonThumbr => Key::Unidentified(native), - ButtonStart => Key::Unidentified(native), - ButtonSelect => Key::Unidentified(native), - ButtonMode => Key::Unidentified(native), - // ----------------------------------------------------------------- - Escape => Key::Escape, - ForwardDel => Key::Delete, - CtrlLeft => Key::Control, - CtrlRight => Key::Control, - CapsLock => Key::CapsLock, - ScrollLock => Key::ScrollLock, - MetaLeft => Key::Super, - MetaRight => Key::Super, - Function => Key::Fn, - Sysrq => Key::PrintScreen, - Break => Key::Pause, - MoveHome => Key::Home, - MoveEnd => Key::End, - Insert => Key::Insert, - Forward => Key::BrowserForward, - MediaPlay => Key::MediaPlay, - MediaPause => Key::MediaPause, - MediaClose => Key::MediaClose, - MediaEject => Key::Eject, - MediaRecord => Key::MediaRecord, - F1 => Key::F1, - F2 => Key::F2, - F3 => Key::F3, - F4 => Key::F4, - F5 => Key::F5, - F6 => Key::F6, - F7 => Key::F7, - F8 => Key::F8, - F9 => Key::F9, - F10 => Key::F10, - F11 => Key::F11, - F12 => Key::F12, - NumLock => Key::NumLock, - Numpad0 => Key::Unidentified(native), - Numpad1 => Key::Unidentified(native), - Numpad2 => Key::Unidentified(native), - Numpad3 => Key::Unidentified(native), - Numpad4 => Key::Unidentified(native), - Numpad5 => Key::Unidentified(native), - Numpad6 => Key::Unidentified(native), - Numpad7 => Key::Unidentified(native), - Numpad8 => Key::Unidentified(native), - Numpad9 => Key::Unidentified(native), - NumpadDivide => Key::Unidentified(native), - NumpadMultiply => Key::Unidentified(native), - NumpadSubtract => Key::Unidentified(native), - NumpadAdd => Key::Unidentified(native), - NumpadDot => Key::Unidentified(native), - NumpadComma => Key::Unidentified(native), - NumpadEnter => Key::Unidentified(native), - NumpadEquals => Key::Unidentified(native), - NumpadLeftParen => Key::Unidentified(native), - NumpadRightParen => Key::Unidentified(native), - - VolumeMute => Key::AudioVolumeMute, - Info => Key::Info, - ChannelUp => Key::ChannelUp, - ChannelDown => Key::ChannelDown, - ZoomIn => Key::ZoomIn, - ZoomOut => Key::ZoomOut, - Tv => Key::TV, - Window => Key::Unidentified(native), - Guide => Key::Guide, - Dvr => Key::DVR, - Bookmark => Key::BrowserFavorites, - Captions => Key::ClosedCaptionToggle, - Settings => Key::Settings, - TvPower => Key::TVPower, - TvInput => Key::TVInput, - StbPower => Key::STBPower, - StbInput => Key::STBInput, - AvrPower => Key::AVRPower, - AvrInput => Key::AVRInput, - ProgRed => Key::ColorF0Red, - ProgGreen => Key::ColorF1Green, - ProgYellow => Key::ColorF2Yellow, - ProgBlue => Key::ColorF3Blue, - AppSwitch => Key::AppSwitch, - Button1 => Key::Unidentified(native), - Button2 => Key::Unidentified(native), - Button3 => Key::Unidentified(native), - Button4 => Key::Unidentified(native), - Button5 => Key::Unidentified(native), - Button6 => Key::Unidentified(native), - Button7 => Key::Unidentified(native), - Button8 => Key::Unidentified(native), - Button9 => Key::Unidentified(native), - Button10 => Key::Unidentified(native), - Button11 => Key::Unidentified(native), - Button12 => Key::Unidentified(native), - Button13 => Key::Unidentified(native), - Button14 => Key::Unidentified(native), - Button15 => Key::Unidentified(native), - Button16 => Key::Unidentified(native), - LanguageSwitch => Key::GroupNext, - MannerMode => Key::MannerMode, - Keycode3dMode => Key::TV3DMode, - Contacts => Key::LaunchContacts, - Calendar => Key::LaunchCalendar, - Music => Key::LaunchMusicPlayer, - Calculator => Key::LaunchApplication2, - ZenkakuHankaku => Key::ZenkakuHankaku, - Eisu => Key::Eisu, - Muhenkan => Key::NonConvert, - Henkan => Key::Convert, - KatakanaHiragana => Key::HiraganaKatakana, - Yen => Key::Unidentified(native), - Ro => Key::Unidentified(native), - Kana => Key::KanjiMode, - Assist => Key::Unidentified(native), - BrightnessDown => Key::BrightnessDown, - BrightnessUp => Key::BrightnessUp, - MediaAudioTrack => Key::MediaAudioTrack, - Sleep => Key::Standby, - Wakeup => Key::WakeUp, - Pairing => Key::Pairing, - MediaTopMenu => Key::MediaTopMenu, - Keycode11 => Key::Unidentified(native), - Keycode12 => Key::Unidentified(native), - LastChannel => Key::MediaLast, - TvDataService => Key::TVDataService, - VoiceAssist => Key::VoiceDial, - TvRadioService => Key::TVRadioService, - TvTeletext => Key::Teletext, - TvNumberEntry => Key::TVNumberEntry, - TvTerrestrialAnalog => Key::TVTerrestrialAnalog, - TvTerrestrialDigital => Key::TVTerrestrialDigital, - TvSatellite => Key::TVSatellite, - TvSatelliteBs => Key::TVSatelliteBS, - TvSatelliteCs => Key::TVSatelliteCS, - TvSatelliteService => Key::TVSatelliteToggle, - TvNetwork => Key::TVNetwork, - TvAntennaCable => Key::TVAntennaCable, - TvInputHdmi1 => Key::TVInputHDMI1, - TvInputHdmi2 => Key::TVInputHDMI2, - TvInputHdmi3 => Key::TVInputHDMI3, - TvInputHdmi4 => Key::TVInputHDMI4, - TvInputComposite1 => Key::TVInputComposite1, - TvInputComposite2 => Key::TVInputComposite2, - TvInputComponent1 => Key::TVInputComponent1, - TvInputComponent2 => Key::TVInputComponent2, - TvInputVga1 => Key::TVInputVGA1, - TvAudioDescription => Key::TVAudioDescription, - TvAudioDescriptionMixUp => Key::TVAudioDescriptionMixUp, - TvAudioDescriptionMixDown => Key::TVAudioDescriptionMixDown, - TvZoomMode => Key::ZoomToggle, - TvContentsMenu => Key::TVContentsMenu, - TvMediaContextMenu => Key::TVMediaContext, - TvTimerProgramming => Key::TVTimer, - Help => Key::Help, - NavigatePrevious => Key::NavigatePrevious, - NavigateNext => Key::NavigateNext, - NavigateIn => Key::NavigateIn, - NavigateOut => Key::NavigateOut, - StemPrimary => Key::Unidentified(native), - Stem1 => Key::Unidentified(native), - Stem2 => Key::Unidentified(native), - Stem3 => Key::Unidentified(native), - DpadUpLeft => Key::Unidentified(native), - DpadDownLeft => Key::Unidentified(native), - DpadUpRight => Key::Unidentified(native), - DpadDownRight => Key::Unidentified(native), - MediaSkipForward => Key::MediaSkipForward, - MediaSkipBackward => Key::MediaSkipBackward, - MediaStepForward => Key::MediaStepForward, - MediaStepBackward => Key::MediaStepBackward, - SoftSleep => Key::Unidentified(native), - Cut => Key::Cut, - Copy => Key::Copy, - Paste => Key::Paste, - SystemNavigationUp => Key::Unidentified(native), - SystemNavigationDown => Key::Unidentified(native), - SystemNavigationLeft => Key::Unidentified(native), - SystemNavigationRight => Key::Unidentified(native), - AllApps => Key::Unidentified(native), - Refresh => Key::BrowserRefresh, - ThumbsUp => Key::Unidentified(native), - ThumbsDown => Key::Unidentified(native), - ProfileSwitch => Key::Unidentified(native), - } -} - -fn keycode_to_location(keycode: ndk::event::Keycode) -> KeyLocation { - use ndk::event::Keycode::*; - - match keycode { - AltLeft => KeyLocation::Left, - AltRight => KeyLocation::Right, - ShiftLeft => KeyLocation::Left, - ShiftRight => KeyLocation::Right, - - // According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM - Num => KeyLocation::Left, - - CtrlLeft => KeyLocation::Left, - CtrlRight => KeyLocation::Right, - MetaLeft => KeyLocation::Left, - MetaRight => KeyLocation::Right, - - NumLock => KeyLocation::Numpad, - Numpad0 => KeyLocation::Numpad, - Numpad1 => KeyLocation::Numpad, - Numpad2 => KeyLocation::Numpad, - Numpad3 => KeyLocation::Numpad, - Numpad4 => KeyLocation::Numpad, - Numpad5 => KeyLocation::Numpad, - Numpad6 => KeyLocation::Numpad, - Numpad7 => KeyLocation::Numpad, - Numpad8 => KeyLocation::Numpad, - Numpad9 => KeyLocation::Numpad, - NumpadDivide => KeyLocation::Numpad, - NumpadMultiply => KeyLocation::Numpad, - NumpadSubtract => KeyLocation::Numpad, - NumpadAdd => KeyLocation::Numpad, - NumpadDot => KeyLocation::Numpad, - NumpadComma => KeyLocation::Numpad, - NumpadEnter => KeyLocation::Numpad, - NumpadEquals => KeyLocation::Numpad, - NumpadLeftParen => KeyLocation::Numpad, - NumpadRightParen => KeyLocation::Numpad, - - _ => KeyLocation::Standard, - } -}